os/kernelhwsrv/kernel/eka/drivers/pbus/pccard/spccard.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32\drivers\pbus\pccard\spccard.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include <pccard.h>
sl@0
    19
#include "cis.h"
sl@0
    20
sl@0
    21
LOCAL_D const TPccdAccessSpeed CisDevSpeedTable[8] =
sl@0
    22
	{EAcSpeedInValid,EAcSpeed250nS,EAcSpeed200nS,EAcSpeed150nS,
sl@0
    23
	EAcSpeed100nS,EAcSpeedInValid,EAcSpeedInValid,EAcSpeedInValid};
sl@0
    24
LOCAL_D const TUint32 CisDevSizeInBytesTable[8] =
sl@0
    25
	{0x00000200,0x00000800,0x00002000,0x00008000,0x00020000,0x00080000,0x00200000,0};
sl@0
    26
LOCAL_D const TInt CisMantisaTable[0x10] =
sl@0
    27
	{10,12,13,15,20,25,30,35,40,45,50,55,60,70,80,90};
sl@0
    28
LOCAL_D const TInt CisSpeedExponentTable[8] =
sl@0
    29
	{0,1,10,100,1000,10000,100000,1000000};
sl@0
    30
sl@0
    31
GLDEF_C void PcCardPanic(TPcCardPanic aPanic)
sl@0
    32
	{
sl@0
    33
	Kern::Fault("PCCARD",aPanic);
sl@0
    34
	}
sl@0
    35
sl@0
    36
LOCAL_C TPccdAccessSpeed DevSpeedFromExtended(TInt aSpeedInNanoSecs)
sl@0
    37
	{
sl@0
    38
sl@0
    39
	if (aSpeedInNanoSecs<=100) return(EAcSpeed100nS);
sl@0
    40
	if (aSpeedInNanoSecs<=150) return(EAcSpeed150nS);
sl@0
    41
	if (aSpeedInNanoSecs<=200) return(EAcSpeed200nS);
sl@0
    42
	if (aSpeedInNanoSecs<=250) return(EAcSpeed250nS);
sl@0
    43
	if (aSpeedInNanoSecs<=300) return(EAcSpeed300nS);
sl@0
    44
	if (aSpeedInNanoSecs<=450) return(EAcSpeed450nS);
sl@0
    45
	if (aSpeedInNanoSecs<=600) return(EAcSpeed600nS);
sl@0
    46
	if (aSpeedInNanoSecs<=750) return(EAcSpeed750nS);
sl@0
    47
	return(EAcSpeedExtended);
sl@0
    48
	}
sl@0
    49
sl@0
    50
LOCAL_C TMemDeviceType DevType(TInt aTypeCode)
sl@0
    51
	{
sl@0
    52
	if ( aTypeCode>=KTpDiDTypeNull && aTypeCode<=KTpDiDTypeDram )
sl@0
    53
		return( (TMemDeviceType)aTypeCode );
sl@0
    54
	else if (aTypeCode>=KTpDiDTypeFuncSpec)
sl@0
    55
		return(EDeviceFunSpec);
sl@0
    56
	else
sl@0
    57
		return(EDeviceInvalid);
sl@0
    58
	}
sl@0
    59
sl@0
    60
LOCAL_C TInt ExtendedSpeedToNanoSeconds(TUint8 aVal)
sl@0
    61
//
sl@0
    62
// Converts extended device speed field to speed in nS.
sl@0
    63
//
sl@0
    64
	{
sl@0
    65
sl@0
    66
	TInt mant=(aVal&KCisTplMantM)>>KCisTplMantFO;
sl@0
    67
	TInt s=(mant==0)?0:CisMantisaTable[mant-1];
sl@0
    68
	s*=CisSpeedExponentTable[aVal&KCisTplExponM];
sl@0
    69
	return(s);
sl@0
    70
	}
sl@0
    71
	 
sl@0
    72
LOCAL_C TInt PwrTplToMicroAmps(TUint aVal,TUint anExt)
sl@0
    73
//
sl@0
    74
// Converts a power tuple into an integer value - units uA.
sl@0
    75
//
sl@0
    76
	{
sl@0
    77
	TInt p=CisMantisaTable[(aVal&KCisTplMantM)>>KCisTplMantFO];
sl@0
    78
	p*=10;
sl@0
    79
	if (anExt<=99)
sl@0
    80
		p+=anExt;	// Add on the extension
sl@0
    81
	switch ( aVal&KCisTplExponM )
sl@0
    82
		{
sl@0
    83
		case 7: return(p*=10000);   case 6: return(p*=1000); 
sl@0
    84
		case 5: return(p*=100);	 	case 4: return(p*=10); 
sl@0
    85
		case 3: return(p);  		case 2: return(p/=10);
sl@0
    86
		case 1: return(p/=100);
sl@0
    87
		default: return(0); // Anything else is too small to worry about 
sl@0
    88
		}
sl@0
    89
	}
sl@0
    90
sl@0
    91
LOCAL_C TInt PwrTplToMilliVolts(TUint aVal,TUint anExt)
sl@0
    92
//
sl@0
    93
// Converts a power tuple into a integer value - units mV.
sl@0
    94
//
sl@0
    95
	{
sl@0
    96
	return(PwrTplToMicroAmps(aVal,anExt)/10);
sl@0
    97
	}
sl@0
    98
sl@0
    99
LOCAL_C TInt ParseConfigTuple(TDes8 &configTpl,TPcCardConfig &anInfo,TInt &aLastEntry)
sl@0
   100
//
sl@0
   101
// Parse a KCisTplConfig tuple.
sl@0
   102
// (Always alters iConfigBaseAddr and iRegPresent).  
sl@0
   103
//
sl@0
   104
	{
sl@0
   105
sl@0
   106
	anInfo.iConfigBaseAddr=0;
sl@0
   107
	anInfo.iRegPresent=0;
sl@0
   108
sl@0
   109
	// Get the sizes of the ConfReg base addr & ConfReg present fields
sl@0
   110
	TInt rasz=((configTpl[2]&KTpCcRaszM)>>KTpCcRaszFO)+1;
sl@0
   111
	TInt rmsz=((configTpl[2]&KTpCcRmszM)>>KTpCcRmszFO)+1;
sl@0
   112
	if ( (configTpl.Size()-4) < (rasz+rmsz) )
sl@0
   113
		return(KErrNotSupported); // Size of fields longer than tuple length.
sl@0
   114
	aLastEntry=configTpl[3];
sl@0
   115
sl@0
   116
	// Read Config. Reg. base address.
sl@0
   117
	TInt i;
sl@0
   118
	for (i=0;i<rasz;i++)
sl@0
   119
		anInfo.iConfigBaseAddr += (configTpl[4+i]<<(8*i));
sl@0
   120
sl@0
   121
	// Read Config. Reg. present mask
sl@0
   122
	if (rmsz>4) rmsz=4;	  // We only have 32bit field
sl@0
   123
	for (i=0;i<rmsz;i++)
sl@0
   124
		anInfo.iRegPresent += (configTpl[4+rasz+i]<<(8*i));
sl@0
   125
	return(KErrNone); // Ignore custom interface subtuples
sl@0
   126
	}
sl@0
   127
sl@0
   128
LOCAL_C TInt ParsePowerEntry(const TUint8 *aTplPtr,TInt *aVMax,TInt *aVMin,TInt *aPeakI,TInt *aPdwnI)
sl@0
   129
//
sl@0
   130
// Parse a Power descriptor in a KCisTplCfTableEntry tuple. Returns the 
sl@0
   131
// number of bytes we have parsed. 
sl@0
   132
//
sl@0
   133
	{
sl@0
   134
	const TUint8 *initPtr = aTplPtr;
sl@0
   135
	TUint8 present = *aTplPtr++;
sl@0
   136
	TBuf8<16> pwr;
sl@0
   137
	pwr.FillZ(16);	  // Important
sl@0
   138
sl@0
   139
	TInt i;
sl@0
   140
	for (i=0;i<16;i+=2,present>>=1)
sl@0
   141
		{
sl@0
   142
		if (present&0x01)
sl@0
   143
			{
sl@0
   144
			pwr[i]=(TUint8)((*aTplPtr)&(~KCisTplExt));
sl@0
   145
			if (*aTplPtr++ & KCisTplExt)
sl@0
   146
				{
sl@0
   147
				pwr[i+1]=(TUint8)((*aTplPtr)&(~KCisTplExt));	// Extension tuple
sl@0
   148
				while( *aTplPtr++ & KCisTplExt );				// Jump past any more extensions
sl@0
   149
				}
sl@0
   150
			}
sl@0
   151
		}
sl@0
   152
sl@0
   153
	if (aVMin && aVMax)
sl@0
   154
		{
sl@0
   155
		if (pwr[0])						 // NomV (assume +/-5%)
sl@0
   156
			{
sl@0
   157
			(*aVMin)=(*aVMax)=PwrTplToMilliVolts(pwr[0],pwr[1]);
sl@0
   158
			(*aVMin) = ((*aVMin)*95)/100;
sl@0
   159
			(*aVMax) = ((*aVMax)*105)/100;
sl@0
   160
			}
sl@0
   161
		if (pwr[2])							// MinV
sl@0
   162
			*aVMin=PwrTplToMilliVolts(pwr[2],pwr[3]);
sl@0
   163
  		if (pwr[4])							// MaxV
sl@0
   164
			*aVMax=PwrTplToMilliVolts(pwr[4],pwr[5]);
sl@0
   165
		}
sl@0
   166
	// We'll settle for average/static if no peak.
sl@0
   167
	if (aPeakI && (pwr[10]||pwr[8]||pwr[6]) )
sl@0
   168
		{
sl@0
   169
		if (pwr[6])
sl@0
   170
			*aPeakI = PwrTplToMicroAmps(pwr[6],pwr[7]);
sl@0
   171
		if (pwr[8])
sl@0
   172
			*aPeakI = PwrTplToMicroAmps(pwr[8],pwr[9]);
sl@0
   173
		if (pwr[10])
sl@0
   174
			*aPeakI = PwrTplToMicroAmps(pwr[10],pwr[11]); // Last one overides others
sl@0
   175
		}
sl@0
   176
	if (aPdwnI && pwr[12])
sl@0
   177
		*aPdwnI = PwrTplToMicroAmps(pwr[12],pwr[13]); 
sl@0
   178
sl@0
   179
	return(aTplPtr-initPtr);
sl@0
   180
	}
sl@0
   181
sl@0
   182
LOCAL_C TInt ParseTimingEntry(const TUint8 *aTplPtr)
sl@0
   183
//
sl@0
   184
// Parse a timing descriptor in a KCisTplCfTableEntry tuple. Returns the 
sl@0
   185
// number of bytes we have parsed. 
sl@0
   186
//
sl@0
   187
	{
sl@0
   188
	// We ignore this information - just jump past this field
sl@0
   189
	const TUint8 *initPtr=aTplPtr;
sl@0
   190
sl@0
   191
	TUint8 present=*aTplPtr++;	  // First the timing present field
sl@0
   192
sl@0
   193
	if ((present & KTpCeTimWaitM) != KTpCeTimWaitM)
sl@0
   194
		while( *aTplPtr++ & KCisTplExt ); // Wait time (jump past any extensions)
sl@0
   195
	if ((present & KTpCeTimRdyM) != KTpCeTimRdyM)
sl@0
   196
		while( *aTplPtr++ & KCisTplExt ); // Ready time (jump past any extensions)
sl@0
   197
	if ((present & KTpCeTimResM) != KTpCeTimResM)
sl@0
   198
		while( *aTplPtr++ & KCisTplExt ); // Reserved time (jump past any extensions)
sl@0
   199
	return(aTplPtr-initPtr);
sl@0
   200
	}
sl@0
   201
sl@0
   202
LOCAL_C TInt ParseIoEntry(const TUint8 *aTplPtr,TPccdChnk *aChnk,TInt &aNextChnkNum)
sl@0
   203
//
sl@0
   204
// Parse an IO space descriptor in a KCisTplCfTableEntry tuple. Returns the 
sl@0
   205
// number of bytes we have parsed (or a negative error value). Also returns the 
sl@0
   206
// number of config chunk entries used ('aNextChunkNum').
sl@0
   207
//
sl@0
   208
	{
sl@0
   209
	TPccdMemType memType;
sl@0
   210
	TInt bytesParsed = 1; // Must be a minimum of a single byte descriptor here.
sl@0
   211
sl@0
   212
	// Always at least one I/O space descriptor
sl@0
   213
	switch( (*aTplPtr & KTpCeBus16_8M) >> KTpCeBus16_8FO )
sl@0
   214
		{
sl@0
   215
		case 1: case 2:
sl@0
   216
			memType = EPccdIo8Mem;	 // Card supports 8bit I/O only.
sl@0
   217
			break;
sl@0
   218
		case 3:
sl@0
   219
			memType = EPccdIo16Mem;	// Card supports 8 & 16 bit I/O.
sl@0
   220
			break;
sl@0
   221
		default:
sl@0
   222
			return(KErrCorrupt);	
sl@0
   223
		}
sl@0
   224
	TUint ioLines = (*aTplPtr & KTpCeIoLinesM) >> KTpCeIoLinesFO;
sl@0
   225
sl@0
   226
	TInt ranges=1; // We always specify one chunk even if no range descriptors follow
sl@0
   227
	TInt addrInBytes=0; 
sl@0
   228
	TInt lenInBytes=0;
sl@0
   229
	// Are there any IO Range description bytes to follow
sl@0
   230
	if (*aTplPtr++ & KTpCeRangePresM)
sl@0
   231
		{
sl@0
   232
		ranges = ((*aTplPtr & KTpCeIoRangesM) >> KTpCeIoRangesFO)+1;
sl@0
   233
		addrInBytes = (*aTplPtr & KTpCeIoAddrSzM) >> KTpCeIoAddrSzFO;
sl@0
   234
		lenInBytes = (*aTplPtr & KTpCeIoAddrLenM) >> KTpCeIoAddrLenFO;
sl@0
   235
		aTplPtr++;
sl@0
   236
sl@0
   237
		// There could be multiple range descriptors
sl@0
   238
		if ((ranges+aNextChnkNum)<=KMaxChunksPerConfig)
sl@0
   239
			bytesParsed += (ranges * (addrInBytes + lenInBytes))+1;
sl@0
   240
		else
sl@0
   241
			return(KErrNotSupported);	// Too many descriptors for us
sl@0
   242
		}
sl@0
   243
sl@0
   244
	aChnk+=aNextChnkNum;
sl@0
   245
	for (;ranges>0;ranges--,aChnk++,aNextChnkNum++)
sl@0
   246
		{
sl@0
   247
		TInt j;
sl@0
   248
		aChnk->iMemType=memType;	 // I/O memory type
sl@0
   249
sl@0
   250
		// Lets get the IO start address
sl@0
   251
		aChnk->iMemBaseAddr=0;
sl@0
   252
		if (addrInBytes)
sl@0
   253
			{
sl@0
   254
			for (j=0;j<addrInBytes;j++)
sl@0
   255
				aChnk->iMemBaseAddr += (*aTplPtr++) << (8*j);
sl@0
   256
			}
sl@0
   257
sl@0
   258
		// Finally, lets get the IO length
sl@0
   259
		if (lenInBytes)
sl@0
   260
			{
sl@0
   261
			for (j=0,aChnk->iMemLen=0;j<lenInBytes;j++)
sl@0
   262
		   		aChnk->iMemLen += (*aTplPtr++) << (8*j);
sl@0
   263
			(aChnk->iMemLen)++;
sl@0
   264
			}
sl@0
   265
		else
sl@0
   266
			{
sl@0
   267
			if (ioLines)
sl@0
   268
				aChnk->iMemLen = 0x01<<ioLines;
sl@0
   269
			else
sl@0
   270
				return(KErrCorrupt); // No ioLines and no length, it's invalid.   
sl@0
   271
			}
sl@0
   272
		}
sl@0
   273
	return(bytesParsed);
sl@0
   274
	}
sl@0
   275
sl@0
   276
LOCAL_C TInt ParseMemEntry(const TUint8 *aTplPtr,TInt aFeatureVal,TPccdChnk *aChnk,TInt &aNextChnkNum)
sl@0
   277
//
sl@0
   278
// Parse a memory space descriptor in a KCisTplCfTableEntry tuple. Returns
sl@0
   279
// the number of bytes we have parsed (or a negative error value). Also returns the 
sl@0
   280
// number of config chunk entries used ('aNextChunkNum').
sl@0
   281
//
sl@0
   282
	{
sl@0
   283
sl@0
   284
	const TUint8 *initPtr=aTplPtr;
sl@0
   285
	TInt windows=0; 		
sl@0
   286
	TInt lenInBytes=0;  	
sl@0
   287
	TInt addrInBytes=0;		
sl@0
   288
	TBool hostAddr=EFalse;
sl@0
   289
	switch (aFeatureVal)
sl@0
   290
		{
sl@0
   291
		case 3:   // Memory space descriptor
sl@0
   292
			windows=(*aTplPtr & KTpCeMemWindowsM)+1;
sl@0
   293
			lenInBytes=(*aTplPtr & KTpCeMemLenSzM) >> KTpCeMemLenSzFO;
sl@0
   294
			addrInBytes=(*aTplPtr & KTpCeMemAddrSzM) >> KTpCeMemAddrSzFO;
sl@0
   295
			hostAddr=(*aTplPtr & KTpCeMemHostAddrM);
sl@0
   296
			aTplPtr++;
sl@0
   297
			break;
sl@0
   298
		case 2:			// Length(2byte) and base address(2byte) specified.
sl@0
   299
			addrInBytes=2; 
sl@0
   300
		case 1:			// Single 2-byte length specified.
sl@0
   301
			lenInBytes=2;
sl@0
   302
			windows=1;
sl@0
   303
			break;
sl@0
   304
		}
sl@0
   305
sl@0
   306
	if ((windows+aNextChnkNum)>KMaxChunksPerConfig)
sl@0
   307
		return(KErrNotSupported);	// Too many descriptors for us
sl@0
   308
sl@0
   309
	aChnk+=aNextChnkNum;
sl@0
   310
	TInt i;
sl@0
   311
	for (;windows>0;windows--,aChnk++,aNextChnkNum++)
sl@0
   312
		{
sl@0
   313
		aChnk->iMemType=EPccdCommon16Mem;
sl@0
   314
		aChnk->iMemLen=0;
sl@0
   315
		if (lenInBytes)
sl@0
   316
			{
sl@0
   317
			for (i=0;i<lenInBytes;i++)
sl@0
   318
				aChnk->iMemLen += (*aTplPtr++) << ((8*i)+8);  	// in 256 byte pages
sl@0
   319
			}
sl@0
   320
		aChnk->iMemBaseAddr=0;
sl@0
   321
		if (addrInBytes)
sl@0
   322
			{
sl@0
   323
			for (i=0;i<addrInBytes;i++)
sl@0
   324
				aChnk->iMemBaseAddr += (*aTplPtr++) << ((8*i)+8);// in 256 byte pages
sl@0
   325
			}
sl@0
   326
		if (hostAddr)
sl@0
   327
			{
sl@0
   328
			for (i=0;i<addrInBytes;i++)
sl@0
   329
				aTplPtr++; // Dont record this, just advance the tuple pointer
sl@0
   330
			}
sl@0
   331
		}
sl@0
   332
	return(aTplPtr-initPtr);
sl@0
   333
	}
sl@0
   334
sl@0
   335
LOCAL_C TInt ParseMiscEntry(const TUint8 *aTplPtr, TBool &aPwrDown)
sl@0
   336
//
sl@0
   337
// Parse a miscellaneous features field in a KCisTplCfTableEntry tuple.
sl@0
   338
// Returns the number of bytes we have parsed. 
sl@0
   339
//
sl@0
   340
	{
sl@0
   341
	aPwrDown=(*aTplPtr&KTpCePwrDownM);
sl@0
   342
sl@0
   343
	TInt i;
sl@0
   344
	for (i=1;*aTplPtr & KCisTplExt;i++,aTplPtr++);
sl@0
   345
	return(i);
sl@0
   346
	}
sl@0
   347
sl@0
   348
LOCAL_C TInt ParseConfigEntTuple(TDes8 &cTpl,TPcCardConfig &anInfo)
sl@0
   349
//
sl@0
   350
// Parse a KCisTplCfTableEntry tuple. anInfo contains default values on 
sl@0
   351
// entry so this routine only adds data it finds in the tuple.
sl@0
   352
//
sl@0
   353
	{
sl@0
   354
sl@0
   355
	// Parse the Index byte.
sl@0
   356
	const TUint8 *tplPtr=cTpl.Ptr()+2; // First tuple after link
sl@0
   357
	anInfo.iConfigOption=(*tplPtr & KTpCeOptionM);
sl@0
   358
	anInfo.iIsDefault=(*tplPtr & KTpCeIsDefaultM);
sl@0
   359
sl@0
   360
	// Check if there is an interface description field to follow
sl@0
   361
	if (*tplPtr++ & KTpCeIntfPresM)
sl@0
   362
		{
sl@0
   363
 		anInfo.iIsIoAndMem=(*tplPtr&KTpCeIntfTypeM);
sl@0
   364
		anInfo.iActiveSignals=*tplPtr&(KTpCeBvdM|KTpCeWpM|KTpCeReadyM|KTpCeWaitM);
sl@0
   365
		tplPtr++;
sl@0
   366
		}
sl@0
   367
sl@0
   368
	// Next byte should be the feature selection byte.
sl@0
   369
	TUint8 features=*tplPtr++;
sl@0
   370
sl@0
   371
	// Next might be 0-3 power description structures. 1st one is always VCC info.
sl@0
   372
	TInt entry=(features & KTpCePwrPresM)>>KTpCePwrPresFO;
sl@0
   373
	if (entry)
sl@0
   374
		{
sl@0
   375
		tplPtr += ParsePowerEntry(tplPtr,&anInfo.iVccMaxInMilliVolts,&anInfo.iVccMinInMilliVolts,
sl@0
   376
							      &anInfo.iOperCurrentInMicroAmps,&anInfo.iPwrDwnCurrentInMicroAmps);
sl@0
   377
		entry--;
sl@0
   378
		}
sl@0
   379
	
sl@0
   380
	// We only support a single Vpp supply. However we need to parse both (Vpp1+Vpp2)
sl@0
   381
	// in order to advance the tuple pointer.
sl@0
   382
	while ( entry-- )
sl@0
   383
		tplPtr += ParsePowerEntry(tplPtr,&anInfo.iVppMaxInMilliVolts,&anInfo.iVppMinInMilliVolts,NULL,NULL);
sl@0
   384
sl@0
   385
	// Next might be timing info.
sl@0
   386
	if (features & KTpCeTimPresM)
sl@0
   387
		tplPtr += ParseTimingEntry(tplPtr);
sl@0
   388
sl@0
   389
	// Next might be IO space description.
sl@0
   390
	TInt ret;
sl@0
   391
	TInt nextFreeChunk=0;
sl@0
   392
	if (features & KTpCeIoPresM)
sl@0
   393
		{
sl@0
   394
		if((ret=ParseIoEntry(tplPtr,&(anInfo.iChnk[0]),nextFreeChunk))<0)
sl@0
   395
			return(ret);
sl@0
   396
		anInfo.iValidChunks=nextFreeChunk;
sl@0
   397
		tplPtr += ret;
sl@0
   398
		}
sl@0
   399
sl@0
   400
	// Next might be IRQ description.
sl@0
   401
	if (features & KTpCeIrqPresM)
sl@0
   402
		{
sl@0
   403
		anInfo.iInterruptInfo=*tplPtr&(KPccdIntShare|KPccdIntPulse|KPccdIntLevel);
sl@0
   404
		tplPtr+=(*tplPtr&KTpCeIrqMaskM)?3:1; // Ignore mask bytes if present
sl@0
   405
		}
sl@0
   406
sl@0
   407
	// Next might be memory space description.
sl@0
   408
	entry=((features & KTpCeMemPresM) >> KTpCeMemPresFO);
sl@0
   409
	if (entry)
sl@0
   410
		{
sl@0
   411
		if ((ret=ParseMemEntry(tplPtr,entry,&(anInfo.iChnk[0]),nextFreeChunk))<0)
sl@0
   412
			return(ret);
sl@0
   413
		anInfo.iValidChunks=nextFreeChunk;
sl@0
   414
		tplPtr+=ret;
sl@0
   415
		}
sl@0
   416
sl@0
   417
	// And finally there might be a miscellaneous features field
sl@0
   418
	if (features & KTpCeMiscPresM)
sl@0
   419
		tplPtr+=ParseMiscEntry(tplPtr,anInfo.iPwrDown);
sl@0
   420
sl@0
   421
	// Check that we haven't been reading beyond the tuple.
sl@0
   422
	if ((tplPtr-cTpl.Ptr()) > (cTpl[1]+2))
sl@0
   423
		return(KErrCorrupt);
sl@0
   424
sl@0
   425
	return(KErrNone);
sl@0
   426
	}
sl@0
   427
sl@0
   428
LOCAL_C TInt ParseDeviceInfo(const TUint8 *aTplPtr,TPcCardRegion &anInfo)
sl@0
   429
//
sl@0
   430
// Parse a device info field in a KCisTplDeviceX tuple.
sl@0
   431
// Returns the number of bytes we have parsed (or a negative error value). 
sl@0
   432
//
sl@0
   433
	{
sl@0
   434
sl@0
   435
	const TUint8 *initPtr=aTplPtr;
sl@0
   436
	TInt val;
sl@0
   437
	// Device ID - device type field
sl@0
   438
	val=((*aTplPtr & KTpDiDTypeM) >> KTpDiDTypeFO);
sl@0
   439
	if (val==KTpDiDTypeExtend)
sl@0
   440
		return(KErrNotSupported);	   // Don't support extended device type
sl@0
   441
	anInfo.iDeviceType=DevType(val);
sl@0
   442
sl@0
   443
	// Device ID - write protect field
sl@0
   444
	if (!(*aTplPtr&KTpDiWpsM))
sl@0
   445
		anInfo.iActiveSignals|=KSigWpActive;
sl@0
   446
sl@0
   447
	// Device ID - device speed field
sl@0
   448
	val=(*aTplPtr & KTpDiDSpeedM);
sl@0
   449
	if (val==KTpDiDSpeedExt)
sl@0
   450
		{
sl@0
   451
		aTplPtr++;
sl@0
   452
		anInfo.iExtendedAccSpeedInNanoSecs=ExtendedSpeedToNanoSeconds(*aTplPtr);
sl@0
   453
		anInfo.iAccessSpeed=DevSpeedFromExtended(anInfo.iExtendedAccSpeedInNanoSecs);
sl@0
   454
		while(*aTplPtr++ & KCisTplExt); // Jump past any (further) extended speed fields
sl@0
   455
		}
sl@0
   456
	else
sl@0
   457
		{
sl@0
   458
		anInfo.iExtendedAccSpeedInNanoSecs=0;
sl@0
   459
		anInfo.iAccessSpeed=CisDevSpeedTable[val];
sl@0
   460
		aTplPtr++;
sl@0
   461
		}
sl@0
   462
sl@0
   463
	// Now the Device size
sl@0
   464
	TInt size,numUnits;
sl@0
   465
	size=((*aTplPtr & KTpDiDSizeM) >> KTpDiDSizeFO);
sl@0
   466
	numUnits=((*aTplPtr++ & KTpDiDUnitsM) >> KTpDiDUnitsFO)+1;
sl@0
   467
	if (size>KTpDiDSize2M)
sl@0
   468
		return(KErrCorrupt);	 
sl@0
   469
	anInfo.iChnk.iMemLen=numUnits*CisDevSizeInBytesTable[size];
sl@0
   470
	return(aTplPtr-initPtr);
sl@0
   471
	}
sl@0
   472
/*
sl@0
   473
LOCAL_C TInt SocketIsInRange(TSocket aSocket)
sl@0
   474
//
sl@0
   475
// Check socket is valid for this machine
sl@0
   476
//
sl@0
   477
	{
sl@0
   478
sl@0
   479
//	return(aSocket>=0&&aSocket<ThePcCardController->TotalSupportedBuses());
sl@0
   480
	return (aSocket>=0 && aSocket<KMaxPBusSockets && TheSockets[aSocket]!=NULL);
sl@0
   481
	}
sl@0
   482
*/
sl@0
   483
EXPORT_C TCisReader::TCisReader()
sl@0
   484
//
sl@0
   485
// Constructor.
sl@0
   486
//
sl@0
   487
	: iFunc(0),iCisOffset(0),iLinkOffset(0),iMemType(EPccdAttribMem),
sl@0
   488
	  iLinkFlags(0),iRestarted(EFalse),iRegionCount(0),
sl@0
   489
	  iConfigCount(0)
sl@0
   490
	{
sl@0
   491
	iSocket=NULL;
sl@0
   492
	}
sl@0
   493
sl@0
   494
EXPORT_C TInt TCisReader::SelectCis(TSocket aSocket,TInt aCardFunc)
sl@0
   495
//
sl@0
   496
//  Assign the CIS reader to a socket and function.
sl@0
   497
//
sl@0
   498
	{
sl@0
   499
	// We need to have read the CIS format
sl@0
   500
	__KTRACE_OPT(KPBUS1,Kern::Printf(">CisReader:SelectCis(S:%d F:%d)",aSocket,aCardFunc));
sl@0
   501
	DPcCardSocket* pS=(DPcCardSocket*)TheSockets[aSocket];
sl@0
   502
	if (pS->CardIsReadyAndVerified()!=KErrNone)
sl@0
   503
		return KErrNotReady;
sl@0
   504
	iSocket=pS;
sl@0
   505
	return(DoSelectCis(aCardFunc));
sl@0
   506
	}
sl@0
   507
sl@0
   508
TInt TCisReader::DoSelectCis(TInt aCardFunc)
sl@0
   509
//
sl@0
   510
//  Actually assign the CIS reader to a socket and function.
sl@0
   511
//
sl@0
   512
	{
sl@0
   513
sl@0
   514
	// Check that the function is valid
sl@0
   515
	TInt r;
sl@0
   516
	if (!iSocket->IsValidCardFunc(aCardFunc))
sl@0
   517
		{
sl@0
   518
		iSocket=NULL;
sl@0
   519
		r=KErrNotFound;
sl@0
   520
		}
sl@0
   521
	else
sl@0
   522
		{
sl@0
   523
		iFunc=aCardFunc;
sl@0
   524
		DoRestart();
sl@0
   525
		iConfigCount=0;
sl@0
   526
		r=KErrNone;
sl@0
   527
		}
sl@0
   528
	__KTRACE_OPT(KPBUS1,Kern::Printf("<CisReader:DoSelectCis(F:%d)-%d",aCardFunc,r));
sl@0
   529
	return(r);
sl@0
   530
	}
sl@0
   531
sl@0
   532
EXPORT_C TInt TCisReader::Restart()
sl@0
   533
//
sl@0
   534
// Restart the CIS reader back to the start of the CIS, and re-initialise
sl@0
   535
// config entry parsing.
sl@0
   536
//
sl@0
   537
	{
sl@0
   538
	if (iSocket==NULL)
sl@0
   539
		return(KErrGeneral);
sl@0
   540
	DoRestart();
sl@0
   541
	iConfigCount=0;
sl@0
   542
	return(KErrNone);
sl@0
   543
	}
sl@0
   544
sl@0
   545
void TCisReader::DoRestart()
sl@0
   546
//
sl@0
   547
//  Restart the CIS reader back to the start of the CIS
sl@0
   548
//
sl@0
   549
	{
sl@0
   550
sl@0
   551
	TPcCardFunction *func=iSocket->CardFunc(iFunc);
sl@0
   552
	iCisOffset=func->InitCisOffset();	
sl@0
   553
	iLinkOffset=0;	
sl@0
   554
	iMemType=func->InitCisMemType();
sl@0
   555
	iLinkFlags=0;
sl@0
   556
	iRestarted=ETrue;
sl@0
   557
	iRegionCount=0;
sl@0
   558
	__KTRACE_OPT(KPBUS1,Kern::Printf("<CisReader:DoRestart"));
sl@0
   559
	}
sl@0
   560
sl@0
   561
EXPORT_C TInt TCisReader::FindReadTuple(TUint8 aDesiredTpl,TDes8 &aDes,TUint aFlag)
sl@0
   562
//
sl@0
   563
// Find a specified tuple from the CIS and read it.
sl@0
   564
//
sl@0
   565
	{                                 
sl@0
   566
	__ASSERT_ALWAYS(iSocket!=NULL,PcCardPanic(EPcCardCisReaderUnInit)); 
sl@0
   567
sl@0
   568
	// We're going to read the card itself so it must be ready.
sl@0
   569
	if ( iSocket->CardIsReadyAndVerified()!=KErrNone )
sl@0
   570
		return(KErrNotReady);
sl@0
   571
sl@0
   572
	return(DoFindReadTuple(aDesiredTpl,aDes,aFlag));
sl@0
   573
	}
sl@0
   574
sl@0
   575
TInt TCisReader::DoFindReadTuple(TUint8 aDesiredTpl,TDes8 &aDes,TUint aFlag)
sl@0
   576
//
sl@0
   577
// Actually find a specified tuple from the CIS and read it.
sl@0
   578
//
sl@0
   579
	{
sl@0
   580
sl@0
   581
	__KTRACE_OPT(KPBUS1,Kern::Printf(">CisReader:DoFindReadTuple(T:%xH)",aDesiredTpl));
sl@0
   582
sl@0
   583
	TBuf8<KSmallTplBufSize> tpl;
sl@0
   584
	TBuf8<KSmallTplBufSize> linkAddr;
sl@0
   585
	TInt i,j,err;
sl@0
   586
sl@0
   587
	// Read the previous tuple
sl@0
   588
	if ((err=iSocket->ReadCis(iMemType,iCisOffset,tpl,2))!=KErrNone)
sl@0
   589
		return(err);
sl@0
   590
sl@0
   591
	for (j=0;j<KMaxTuplesPerCis;j++)
sl@0
   592
		{
sl@0
   593
		// Adjust CIS offset beyond last tuple read (unless we've just restarted)
sl@0
   594
		if (iRestarted)
sl@0
   595
			iRestarted=EFalse;
sl@0
   596
		else
sl@0
   597
			{
sl@0
   598
			if (tpl[0]!=KCisTplEnd && tpl[1]!=0xff)
sl@0
   599
				iCisOffset+=(tpl[0]==KCisTplNull)?1:(tpl[1]+2); // A null tuple has no link field
sl@0
   600
			else
sl@0
   601
				{
sl@0
   602
				// End of chain tuple
sl@0
   603
				if ((err=FollowLink(aFlag&KPccdReportErrors))!=KErrNone)
sl@0
   604
					return(err);
sl@0
   605
				}
sl@0
   606
			}
sl@0
   607
sl@0
   608
		// Read the next tuple
sl@0
   609
		if ((err=iSocket->ReadCis(iMemType,iCisOffset,tpl,2))!=KErrNone)
sl@0
   610
			return(err);
sl@0
   611
sl@0
   612
		// Check for a link tuple (need to store next chain addr. for later)
sl@0
   613
		switch(tpl[0])
sl@0
   614
			{
sl@0
   615
			case KCisTplLongLinkA:
sl@0
   616
				iLinkFlags |= KPccdLinkA;
sl@0
   617
				if ((err= iSocket->ReadCis(iMemType,iCisOffset+2,linkAddr,4)) != KErrNone)
sl@0
   618
					return(err);
sl@0
   619
				for (iLinkOffset=0,i=0 ; i<4 ; i++)
sl@0
   620
					iLinkOffset += linkAddr[i] << (8*i);
sl@0
   621
				break;
sl@0
   622
			case KCisTplLongLinkC:
sl@0
   623
				iLinkFlags |= KPccdLinkC;
sl@0
   624
				if ((err= iSocket->ReadCis(iMemType,iCisOffset+2,linkAddr,4)) != KErrNone)
sl@0
   625
					return(err);
sl@0
   626
				for (iLinkOffset=0,i=0 ; i<4 ; i++)
sl@0
   627
					iLinkOffset += linkAddr[i] << (8*i);
sl@0
   628
				break;
sl@0
   629
			case KCisTplLongLinkMfc:
sl@0
   630
				iLinkFlags |= KPccdLinkMFC;
sl@0
   631
				break;
sl@0
   632
			case KCisTplNoLink:
sl@0
   633
				iLinkFlags |= KPccdNoLink;
sl@0
   634
			default:
sl@0
   635
				break;
sl@0
   636
			}
sl@0
   637
sl@0
   638
		// Check if we have found the specified tuple
sl@0
   639
		if (aDesiredTpl==KPccdNonSpecificTpl || aDesiredTpl==tpl[0])
sl@0
   640
			{
sl@0
   641
			// The following are ignored unless KPccdReturnLinkTpl is set. 
sl@0
   642
			if ((tpl[0]==KCisTplNull)||
sl@0
   643
				(tpl[0]==KCisTplEnd)||
sl@0
   644
				(tpl[0]==KCisTplLongLinkA)||
sl@0
   645
				(tpl[0]==KCisTplLongLinkC)||
sl@0
   646
				(tpl[0]==KCisTplLongLinkMfc)||
sl@0
   647
				(tpl[0]==KCisTplNoLink)||
sl@0
   648
				(tpl[0]==KCisTplLinkTarget))
sl@0
   649
				{
sl@0
   650
				if (aFlag&KPccdReturnLinkTpl)
sl@0
   651
					break;
sl@0
   652
				}
sl@0
   653
			else
sl@0
   654
				break;
sl@0
   655
			}
sl@0
   656
		}
sl@0
   657
sl@0
   658
	// We got a result (or we've wandered off into the weeds)
sl@0
   659
	if (j>=KMaxTuplesPerCis)
sl@0
   660
		return( (aFlag&KPccdReportErrors)?KErrCorrupt:KErrNotFound );
sl@0
   661
	else
sl@0
   662
		return((aFlag&KPccdFindOnly)?KErrNone:DoReadTuple(aDes));
sl@0
   663
	}
sl@0
   664
sl@0
   665
EXPORT_C TInt TCisReader::ReadTuple(TDes8 &aDes)
sl@0
   666
//
sl@0
   667
// Read the tuple at the current CIS offset.
sl@0
   668
//
sl@0
   669
	{
sl@0
   670
	__ASSERT_ALWAYS(iSocket!=NULL,PcCardPanic(EPcCardCisReaderUnInit)); 
sl@0
   671
sl@0
   672
	// We're going to read the card itself so it must be ready.
sl@0
   673
	if ( iSocket->CardIsReadyAndVerified()!=KErrNone )
sl@0
   674
		return(KErrNotReady);
sl@0
   675
sl@0
   676
	return(DoReadTuple(aDes));
sl@0
   677
	}
sl@0
   678
sl@0
   679
TInt TCisReader::DoReadTuple(TDes8 &aDes)
sl@0
   680
//
sl@0
   681
// Actually read the tuple at the current CIS offset.
sl@0
   682
//
sl@0
   683
	{
sl@0
   684
sl@0
   685
	__KTRACE_OPT(KPBUS1,Kern::Printf(">CisReader:DoReadTuple"));
sl@0
   686
	TInt err;
sl@0
   687
sl@0
   688
	// Read the tuple type and link
sl@0
   689
	TBuf8<KSmallTplBufSize> tpl;
sl@0
   690
	if ((err= iSocket->ReadCis(iMemType,iCisOffset,tpl,2)) != KErrNone)
sl@0
   691
		return(err);
sl@0
   692
sl@0
   693
	TInt tplLen ;
sl@0
   694
	if ((tpl[0] == KCisTplNull) || (tpl[0] == KCisTplEnd))
sl@0
   695
		tplLen = 1 ;			// These tuples dont have a link.
sl@0
   696
	else
sl@0
   697
		tplLen = (tpl[1]+2) ;
sl@0
   698
	if ( tplLen>aDes.MaxLength() )   // We dont want a panic if aDes too small
sl@0
   699
		return(KErrArgument);
sl@0
   700
sl@0
   701
	// Lets copy the tuple
sl@0
   702
	if ((err= iSocket->ReadCis(iMemType,iCisOffset,aDes,tplLen)) != KErrNone)
sl@0
   703
		return(err);
sl@0
   704
	else
sl@0
   705
		return(KErrNone);
sl@0
   706
	}
sl@0
   707
sl@0
   708
TInt TCisReader::FollowLink(TUint aFullErrorReport)
sl@0
   709
//
sl@0
   710
// Called at the end of a tuple chain, this moves CIS pointer to the next
sl@0
   711
// CIS chain if a long link has been detected.
sl@0
   712
//
sl@0
   713
	{
sl@0
   714
sl@0
   715
	TInt err;
sl@0
   716
	switch (iLinkFlags)
sl@0
   717
		{
sl@0
   718
		case 0: // Haven't found anything so assume longlink to 0 in common.
sl@0
   719
			iLinkOffset=0;
sl@0
   720
		case KPccdLinkC:
sl@0
   721
			iCisOffset=iLinkOffset;
sl@0
   722
			iMemType=EPccdCommon8Mem;
sl@0
   723
			iLinkOffset=0;
sl@0
   724
			if ((err=VerifyLinkTarget())!=KErrNone)
sl@0
   725
				{
sl@0
   726
				DoRestart(); // Leave pointers somewhere safe.
sl@0
   727
				if (iLinkFlags==0||!aFullErrorReport)
sl@0
   728
					err=KErrNotFound; // Above assumption wrong
sl@0
   729
				}
sl@0
   730
			break;
sl@0
   731
		case KPccdLinkA:
sl@0
   732
			iCisOffset=iLinkOffset;
sl@0
   733
			iMemType=EPccdAttribMem;
sl@0
   734
			iLinkOffset=0;
sl@0
   735
			if ((err=VerifyLinkTarget())!=KErrNone)
sl@0
   736
				{
sl@0
   737
				iCisOffset>>=1; // Check if the link offset is wrong
sl@0
   738
				if (VerifyLinkTarget()!=KErrNone)
sl@0
   739
					{
sl@0
   740
					DoRestart(); // Leave pointers somewhere safe.
sl@0
   741
					if (!aFullErrorReport)
sl@0
   742
						err=KErrNotFound;
sl@0
   743
					}
sl@0
   744
				else
sl@0
   745
					err=KErrNone;
sl@0
   746
				}
sl@0
   747
			break;
sl@0
   748
		case KPccdNoLink:
sl@0
   749
		case KPccdLinkMFC: // Can't follow a multi-function link
sl@0
   750
			DoRestart(); // Leave pointers somewhere safe.
sl@0
   751
			err=KErrNotFound;
sl@0
   752
			break;
sl@0
   753
		default:	// Shouldn't have more than 1 link per chain
sl@0
   754
			DoRestart(); // Leave pointers somewhere safe.
sl@0
   755
			err=(aFullErrorReport)?KErrCorrupt:KErrNotFound;   
sl@0
   756
		}
sl@0
   757
	iLinkFlags=0;
sl@0
   758
	return(err);
sl@0
   759
	}
sl@0
   760
sl@0
   761
TInt TCisReader::VerifyLinkTarget()
sl@0
   762
//
sl@0
   763
//	Verify a new tuple chain starts with a valid link target tuple
sl@0
   764
//
sl@0
   765
	{
sl@0
   766
	TBuf8<KSmallTplBufSize> tpl;
sl@0
   767
	TInt err;
sl@0
   768
	if ((err=iSocket->ReadCis(iMemType,iCisOffset,tpl,5))!=KErrNone)
sl@0
   769
		return(err);
sl@0
   770
	if ( (tpl[0]!=KCisTplLinkTarget) || (tpl[1]<3) || (tpl.Find(_L8("CIS"))!=2) )
sl@0
   771
		return(KErrCorrupt);
sl@0
   772
	return(KErrNone);
sl@0
   773
	}
sl@0
   774
sl@0
   775
EXPORT_C TInt TCisReader::FindReadRegion(TPccdSocketVcc aSocketVcc,TPcCardRegion &anInfo,TUint8 aDesiredTpl)
sl@0
   776
//
sl@0
   777
// Read region info from the CIS on the specified Socket/Function. Can
sl@0
   778
// be called multiple times to read all regions (eventually
sl@0
   779
// returns KErrNotFound). 
sl@0
   780
// If the function returns an error value then ignore anInfo.
sl@0
   781
//
sl@0
   782
	{
sl@0
   783
sl@0
   784
	if (!aDesiredTpl)
sl@0
   785
		aDesiredTpl=(aSocketVcc==EPccdSocket_5V0)?KCisTplDevice:KCisTplDeviceOC;
sl@0
   786
	__KTRACE_OPT(KPBUS1,Kern::Printf(">CisReader:FindReadRegion(TPL:%xH)",aDesiredTpl));
sl@0
   787
sl@0
   788
	TInt ret;
sl@0
   789
	TBuf8<KLargeTplBufSize> devTpl;
sl@0
   790
	if (!iRegionCount)				 // Count of regions processed in tuple
sl@0
   791
		ret=FindReadTuple(aDesiredTpl,devTpl);
sl@0
   792
	else
sl@0
   793
		ret=ReadTuple(devTpl);
sl@0
   794
	if (ret!=KErrNone)
sl@0
   795
		return(ret);
sl@0
   796
	const TUint8 *tplPtr=devTpl.Ptr();
sl@0
   797
	const TUint8 *tplE=tplPtr+devTpl.Length(); 
sl@0
   798
	tplPtr+=2; // First tuple after link
sl@0
   799
sl@0
   800
	if (aDesiredTpl==KCisTplDeviceOC||aDesiredTpl==KCisTplDeviceOA)
sl@0
   801
		{
sl@0
   802
		// Process the Other Conditions info.
sl@0
   803
		anInfo.iChnk.iMemType=(aDesiredTpl==KCisTplDeviceOA)?EPccdAttribMem:EPccdCommon16Mem;
sl@0
   804
		anInfo.iActiveSignals=(*tplPtr & KTpDoMWaitM)?KSigWaitRequired:0;
sl@0
   805
		switch( (*tplPtr & KTpDoVccUsedM) >> KTpDoVccUsedFO )
sl@0
   806
			{
sl@0
   807
			case 3: anInfo.iVcc=EPccdSocket_yVy; break;
sl@0
   808
			case 2: anInfo.iVcc=EPccdSocket_xVx; break;
sl@0
   809
			case 1: anInfo.iVcc=EPccdSocket_3V3; break;
sl@0
   810
			default: anInfo.iVcc=EPccdSocket_5V0; break;
sl@0
   811
			}
sl@0
   812
		while (*tplPtr++ & KCisTplExt);	 // Ignore any extensions
sl@0
   813
		}
sl@0
   814
	else
sl@0
   815
		{ // KCisTplDevice
sl@0
   816
		anInfo.iChnk.iMemType=(aDesiredTpl==KCisTplDeviceA)?EPccdAttribMem:EPccdCommon16Mem;
sl@0
   817
		anInfo.iVcc=EPccdSocket_5V0;
sl@0
   818
		anInfo.iActiveSignals=0;
sl@0
   819
		}
sl@0
   820
sl@0
   821
	// Now start on the Device Info fields
sl@0
   822
	anInfo.iAccessSpeed=EAcSpeedInValid;
sl@0
   823
	anInfo.iChnk.iMemBaseAddr = anInfo.iChnk.iMemLen = 0;
sl@0
   824
	for (TInt regions=1;*tplPtr!=0xFF&&tplPtr<tplE;tplPtr+=ret,regions++)
sl@0
   825
		{
sl@0
   826
		// Add length of previous region to give new base address.
sl@0
   827
		anInfo.iChnk.iMemBaseAddr+=anInfo.iChnk.iMemLen;
sl@0
   828
sl@0
   829
		if ((ret=ParseDeviceInfo(tplPtr,anInfo)) < 0)
sl@0
   830
			return(ret);
sl@0
   831
sl@0
   832
		// Check if we have new region to report (dont report null regions)
sl@0
   833
		if (anInfo.iDeviceType!=EDeviceNull && regions>iRegionCount)
sl@0
   834
			{
sl@0
   835
			iRegionCount=regions; // Save for next time
sl@0
   836
			return(KErrNone);
sl@0
   837
			}
sl@0
   838
		}
sl@0
   839
	return(KErrNotFound); 
sl@0
   840
	}
sl@0
   841
sl@0
   842
EXPORT_C TInt TCisReader::FindReadConfig(TPcCardConfig &anInfo)
sl@0
   843
//
sl@0
   844
// Read configuration info from the CIS on the specified Socket/Function. Can
sl@0
   845
// be called multiple times to read all configuration options (eventually
sl@0
   846
// returns KErrNotFound). Uses previous configuration option value to mark
sl@0
   847
// where we are in a configuration table.
sl@0
   848
// If the function returns an error value then ignore anInfo.
sl@0
   849
//
sl@0
   850
	{
sl@0
   851
sl@0
   852
	__KTRACE_OPT(KPBUS1,Kern::Printf(">CisReader:FindReadConfig(%d)",iConfigCount));
sl@0
   853
	__ASSERT_ALWAYS(iSocket!=NULL,PcCardPanic(EPcCardCisReaderUnInit)); 
sl@0
   854
sl@0
   855
	DoRestart();	  // Start from beginning of CIS each time (dont reset iConfigCount though).
sl@0
   856
sl@0
   857
	// Create an initial default configuration
sl@0
   858
	TPcCardConfig defaultConfInfo;
sl@0
   859
	defaultConfInfo.iVccMaxInMilliVolts=5250;	// 5V+5%		
sl@0
   860
	defaultConfInfo.iVccMinInMilliVolts=4750;	// 5V-5%					
sl@0
   861
	defaultConfInfo.iAccessSpeed=DEF_IO_ACSPEED;
sl@0
   862
	defaultConfInfo.iActiveSignals=0;
sl@0
   863
					  
sl@0
   864
	TBuf8<KLargeTplBufSize> configTpl;
sl@0
   865
	TInt lastEntryIndex;
sl@0
   866
	TBool foundLast=EFalse;
sl@0
   867
	TInt err;
sl@0
   868
	TInt i=0;
sl@0
   869
	if (
sl@0
   870
		 (err=FindReadTuple(KCisTplConfig,configTpl))==KErrNone &&
sl@0
   871
		 (err=ParseConfigTuple(configTpl,defaultConfInfo,lastEntryIndex))==KErrNone
sl@0
   872
	   )
sl@0
   873
		{
sl@0
   874
		// Start of new configuration table
sl@0
   875
		for (; (err=FindReadTuple(KCisTplCfTableEntry,configTpl))==KErrNone && i<KMaxCfEntriesPerCis ; i++)
sl@0
   876
			{
sl@0
   877
			anInfo=defaultConfInfo; 		// Entries assume values from last default entry
sl@0
   878
			err=ParseConfigEntTuple(configTpl,anInfo);
sl@0
   879
			if (anInfo.iConfigOption==lastEntryIndex)
sl@0
   880
				foundLast=ETrue;
sl@0
   881
			else
sl@0
   882
				{
sl@0
   883
				if (foundLast)
sl@0
   884
					{
sl@0
   885
					err=KErrNotFound; // We've passed the last entry
sl@0
   886
					break;
sl@0
   887
					}
sl@0
   888
				}
sl@0
   889
			if (iConfigCount==i)
sl@0
   890
				break;
sl@0
   891
			if (err==KErrNone && anInfo.iIsDefault)
sl@0
   892
				defaultConfInfo=anInfo;
sl@0
   893
			}
sl@0
   894
		}
sl@0
   895
	if (i>=KMaxCfEntriesPerCis)
sl@0
   896
		err=KErrCorrupt;
sl@0
   897
	if (err==KErrNone)
sl@0
   898
		iConfigCount++;
sl@0
   899
	__KTRACE_OPT(KPBUS1,Kern::Printf("<CisReader:FindReadConfig-%d",err));
sl@0
   900
	return(err);
sl@0
   901
	}
sl@0
   902
sl@0
   903
TPcCardFunction::TPcCardFunction(TUint32 anOffset,TPccdMemType aMemType)
sl@0
   904
//
sl@0
   905
// Constructor
sl@0
   906
//
sl@0
   907
	: iFuncType(EUnknownCard),iInitCisOffset(anOffset),iInitCisMemType(aMemType),
sl@0
   908
	  iConfigBaseAddr(0),iConfigRegMask(0),iConfigIndex(KInvalidConfOpt),iConfigFlags(0)
sl@0
   909
	{
sl@0
   910
	iClientID=NULL;
sl@0
   911
	}
sl@0
   912
sl@0
   913
void TPcCardFunction::SetConfigOption(TInt anIndex,DBase *aClientID,TUint aConfigFlags)
sl@0
   914
//
sl@0
   915
// Save configuration index and client ID
sl@0
   916
//
sl@0
   917
	{
sl@0
   918
sl@0
   919
	iConfigIndex=anIndex;
sl@0
   920
	iClientID=aClientID;
sl@0
   921
	iConfigFlags=aConfigFlags;
sl@0
   922
	}
sl@0
   923
sl@0
   924
TInt TPcCardFunction::ConfigRegAddress(TInt aRegOffset,TInt &anAddr)
sl@0
   925
//
sl@0
   926
// Provide the specified configuration register address.
sl@0
   927
//
sl@0
   928
	{
sl@0
   929
sl@0
   930
	// Must be configured or we wont have the ConfigReg base address
sl@0
   931
	if (!IsConfigured())
sl@0
   932
		return(KErrGeneral);
sl@0
   933
	anAddr=(iConfigBaseAddr + (aRegOffset<<1));
sl@0
   934
sl@0
   935
	// Return an error if the register isn't present
sl@0
   936
	if ( !(iConfigRegMask & (0x01<<aRegOffset)) )
sl@0
   937
		return(KErrNotSupported);
sl@0
   938
	else
sl@0
   939
		return(KErrNone);
sl@0
   940
	}
sl@0
   941
sl@0
   942
EXPORT_C TPccdChnk::TPccdChnk()
sl@0
   943
//
sl@0
   944
// Constructor
sl@0
   945
//
sl@0
   946
	: iMemType(EPccdAttribMem),iMemBaseAddr(0),iMemLen(0)
sl@0
   947
	{}
sl@0
   948
sl@0
   949
EXPORT_C TPccdChnk::TPccdChnk(TPccdMemType aType,TUint32 aBaseAddr,TUint32 aLen)
sl@0
   950
//
sl@0
   951
// Constructor
sl@0
   952
//
sl@0
   953
	: iMemType(aType),iMemBaseAddr(aBaseAddr),iMemLen(aLen)
sl@0
   954
	{}
sl@0
   955
sl@0
   956
EXPORT_C TPcCardConfig::TPcCardConfig()
sl@0
   957
//
sl@0
   958
// Constructor (iConfigOption to KInvalidConfOpt guarentees that we start with
sl@0
   959
// 1st configuration entry).
sl@0
   960
//
sl@0
   961
	: iAccessSpeed(EAcSpeedInValid),iActiveSignals(0),iVccMaxInMilliVolts(0),
sl@0
   962
	  iVccMinInMilliVolts(0),iValidChunks(0),iIsIoAndMem(FALSE),iIsDefault(FALSE),
sl@0
   963
	  iPwrDown(FALSE),iVppMaxInMilliVolts(0),iVppMinInMilliVolts(0),iOperCurrentInMicroAmps(0),
sl@0
   964
	  iPwrDwnCurrentInMicroAmps(0),iInterruptInfo(0),iConfigOption(KInvalidConfOpt),iConfigBaseAddr(0),
sl@0
   965
	  iRegPresent(0)
sl@0
   966
	{}
sl@0
   967
sl@0
   968
EXPORT_C TBool TPcCardConfig::IsMachineCompatible(TSocket aSocket,TInt aFlag)
sl@0
   969
//
sl@0
   970
// Return ETrue if this configuration is compatible with this machine
sl@0
   971
//
sl@0
   972
	{
sl@0
   973
sl@0
   974
	DPcCardSocket* pS=(DPcCardSocket*)TheSockets[aSocket];
sl@0
   975
	DPcCardVcc* pV=(DPcCardVcc*)pS->iVcc;
sl@0
   976
	TInt nomSocketVcc=DPcCardVcc::SocketVccToMilliVolts(pV->VoltageSetting());
sl@0
   977
    if (!(aFlag&KPccdCompatNoVccCheck))
sl@0
   978
        {
sl@0
   979
	    // Check Vcc level compatibility
sl@0
   980
	    if (iVccMaxInMilliVolts<nomSocketVcc||iVccMinInMilliVolts>nomSocketVcc)
sl@0
   981
		    {
sl@0
   982
		    __KTRACE_OPT(KPBUS1,Kern::Printf("MachineCompatible-Bad Vcc"));
sl@0
   983
		    return(EFalse);
sl@0
   984
		    }
sl@0
   985
        }
sl@0
   986
sl@0
   987
	TPcCardSocketInfo si;
sl@0
   988
	pS->SocketInfo(si);
sl@0
   989
    if (!(aFlag&KPccdCompatNoVppCheck))
sl@0
   990
		{
sl@0
   991
		// Check Vpp level compatibility
sl@0
   992
		if (iVppMaxInMilliVolts<si.iNomVppInMilliVolts||iVppMinInMilliVolts>si.iNomVppInMilliVolts) 
sl@0
   993
			{
sl@0
   994
			__KTRACE_OPT(KPBUS1,Kern::Printf("MachineCompatible-Bad Vpp"));
sl@0
   995
			return(EFalse);
sl@0
   996
			} 
sl@0
   997
		}
sl@0
   998
sl@0
   999
    if (!(aFlag&KPccdCompatNoPwrCheck))
sl@0
  1000
		{
sl@0
  1001
		// Check the configurations power requirements can be supported
sl@0
  1002
		if (iOperCurrentInMicroAmps>pV->MaxCurrentInMicroAmps())
sl@0
  1003
			{
sl@0
  1004
			__KTRACE_OPT(KPBUS1,Kern::Printf("MachineCompatible-Bad Pwr"));
sl@0
  1005
			return(EFalse);
sl@0
  1006
			}
sl@0
  1007
		}
sl@0
  1008
sl@0
  1009
	// If wait requested then check its supported
sl@0
  1010
	if ((iActiveSignals&KSigWaitRequired)&&!(si.iSupportedSignals&KSigWaitSupported))
sl@0
  1011
		{
sl@0
  1012
		__KTRACE_OPT(KPBUS1,Kern::Printf("MachineCompatible-Bad Wait-sig"));
sl@0
  1013
		return(EFalse);
sl@0
  1014
		}
sl@0
  1015
	// Dealt with WAIT - mask out any other signls which aren't supported - not reason to reject though
sl@0
  1016
	iActiveSignals&=si.iSupportedSignals;
sl@0
  1017
	return(ETrue);
sl@0
  1018
	}
sl@0
  1019
sl@0
  1020
EXPORT_C TPcCardRegion::TPcCardRegion()
sl@0
  1021
//
sl@0
  1022
// Constructor (iDeviceType to EDeviceInvalid guarentees that we start with
sl@0
  1023
// 1st device information entry).
sl@0
  1024
//
sl@0
  1025
	: iAccessSpeed(EAcSpeedInValid),iActiveSignals(0),iVcc(EPccdSocket_Invalid),
sl@0
  1026
	  iDeviceType(EDeviceInvalid),iExtendedAccSpeedInNanoSecs(0)
sl@0
  1027
	{}
sl@0
  1028
sl@0
  1029
EXPORT_C TBool TPcCardRegion::IsMachineCompatible(TSocket aSocket)
sl@0
  1030
//
sl@0
  1031
// Return ETrue if this configuration is compatible with this machine
sl@0
  1032
//
sl@0
  1033
	{
sl@0
  1034
sl@0
  1035
	DPcCardSocket* pS=(DPcCardSocket*)TheSockets[aSocket];
sl@0
  1036
	TPccdSocketVcc vcc=pS->VccSetting();
sl@0
  1037
	// Check Vcc level compatibility
sl@0
  1038
	if (iVcc!=vcc)
sl@0
  1039
		{
sl@0
  1040
		__KTRACE_OPT(KPBUS1,Kern::Printf("MachineCompatible-Bad Vcc"));
sl@0
  1041
		return(EFalse);
sl@0
  1042
		}
sl@0
  1043
sl@0
  1044
	// If wait requested then check its supported
sl@0
  1045
	TPcCardSocketInfo si;
sl@0
  1046
	pS->SocketInfo(si);
sl@0
  1047
	TBool waitReq=(iActiveSignals&KSigWaitRequired);
sl@0
  1048
	if (waitReq&&!(si.iSupportedSignals&KSigWaitSupported))
sl@0
  1049
		{
sl@0
  1050
		__KTRACE_OPT(KPBUS1,Kern::Printf("MachineCompatible-Bad Wait-sig"));
sl@0
  1051
		return(EFalse);
sl@0
  1052
		}
sl@0
  1053
	// Dealt with WAIT - mask out any other signls which aren't supported - not reason to reject though
sl@0
  1054
	iActiveSignals&=si.iSupportedSignals;
sl@0
  1055
sl@0
  1056
	// Check requested access speed (ie not too slow for us)
sl@0
  1057
	TPccdAccessSpeed as=__IS_ATTRIB_MEM(iChnk.iMemType)?si.iMaxAttribAccSpeed:si.iMaxCommonIoAccSpeed;
sl@0
  1058
	if (iAccessSpeed>as && !waitReq)
sl@0
  1059
		{
sl@0
  1060
		__KTRACE_OPT(KPBUS1,Kern::Printf("MachineCompatible-Bad speed"));
sl@0
  1061
		return(EFalse);
sl@0
  1062
		}
sl@0
  1063
	return(ETrue);
sl@0
  1064
	}
sl@0
  1065
sl@0
  1066
EXPORT_C TPccdType::TPccdType()
sl@0
  1067
//
sl@0
  1068
// Constructor
sl@0
  1069
//
sl@0
  1070
	: iFuncCount(0)
sl@0
  1071
	{
sl@0
  1072
	for (TInt i=0;i<(TInt)KMaxFuncPerCard;i++)
sl@0
  1073
		iFuncType[i]=EUnknownCard;
sl@0
  1074
	}
sl@0
  1075
sl@0
  1076