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