Update contrib.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\drivers\pbus\pccard\spccard.cpp
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};
31 GLDEF_C void PcCardPanic(TPcCardPanic aPanic)
33 Kern::Fault("PCCARD",aPanic);
36 LOCAL_C TPccdAccessSpeed DevSpeedFromExtended(TInt aSpeedInNanoSecs)
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);
50 LOCAL_C TMemDeviceType DevType(TInt aTypeCode)
52 if ( aTypeCode>=KTpDiDTypeNull && aTypeCode<=KTpDiDTypeDram )
53 return( (TMemDeviceType)aTypeCode );
54 else if (aTypeCode>=KTpDiDTypeFuncSpec)
55 return(EDeviceFunSpec);
57 return(EDeviceInvalid);
60 LOCAL_C TInt ExtendedSpeedToNanoSeconds(TUint8 aVal)
62 // Converts extended device speed field to speed in nS.
66 TInt mant=(aVal&KCisTplMantM)>>KCisTplMantFO;
67 TInt s=(mant==0)?0:CisMantisaTable[mant-1];
68 s*=CisSpeedExponentTable[aVal&KCisTplExponM];
72 LOCAL_C TInt PwrTplToMicroAmps(TUint aVal,TUint anExt)
74 // Converts a power tuple into an integer value - units uA.
77 TInt p=CisMantisaTable[(aVal&KCisTplMantM)>>KCisTplMantFO];
80 p+=anExt; // Add on the extension
81 switch ( aVal&KCisTplExponM )
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
91 LOCAL_C TInt PwrTplToMilliVolts(TUint aVal,TUint anExt)
93 // Converts a power tuple into a integer value - units mV.
96 return(PwrTplToMicroAmps(aVal,anExt)/10);
99 LOCAL_C TInt ParseConfigTuple(TDes8 &configTpl,TPcCardConfig &anInfo,TInt &aLastEntry)
101 // Parse a KCisTplConfig tuple.
102 // (Always alters iConfigBaseAddr and iRegPresent).
106 anInfo.iConfigBaseAddr=0;
107 anInfo.iRegPresent=0;
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];
116 // Read Config. Reg. base address.
119 anInfo.iConfigBaseAddr += (configTpl[4+i]<<(8*i));
121 // Read Config. Reg. present mask
122 if (rmsz>4) rmsz=4; // We only have 32bit field
124 anInfo.iRegPresent += (configTpl[4+rasz+i]<<(8*i));
125 return(KErrNone); // Ignore custom interface subtuples
128 LOCAL_C TInt ParsePowerEntry(const TUint8 *aTplPtr,TInt *aVMax,TInt *aVMin,TInt *aPeakI,TInt *aPdwnI)
130 // Parse a Power descriptor in a KCisTplCfTableEntry tuple. Returns the
131 // number of bytes we have parsed.
134 const TUint8 *initPtr = aTplPtr;
135 TUint8 present = *aTplPtr++;
137 pwr.FillZ(16); // Important
140 for (i=0;i<16;i+=2,present>>=1)
144 pwr[i]=(TUint8)((*aTplPtr)&(~KCisTplExt));
145 if (*aTplPtr++ & KCisTplExt)
147 pwr[i+1]=(TUint8)((*aTplPtr)&(~KCisTplExt)); // Extension tuple
148 while( *aTplPtr++ & KCisTplExt ); // Jump past any more extensions
155 if (pwr[0]) // NomV (assume +/-5%)
157 (*aVMin)=(*aVMax)=PwrTplToMilliVolts(pwr[0],pwr[1]);
158 (*aVMin) = ((*aVMin)*95)/100;
159 (*aVMax) = ((*aVMax)*105)/100;
162 *aVMin=PwrTplToMilliVolts(pwr[2],pwr[3]);
164 *aVMax=PwrTplToMilliVolts(pwr[4],pwr[5]);
166 // We'll settle for average/static if no peak.
167 if (aPeakI && (pwr[10]||pwr[8]||pwr[6]) )
170 *aPeakI = PwrTplToMicroAmps(pwr[6],pwr[7]);
172 *aPeakI = PwrTplToMicroAmps(pwr[8],pwr[9]);
174 *aPeakI = PwrTplToMicroAmps(pwr[10],pwr[11]); // Last one overides others
176 if (aPdwnI && pwr[12])
177 *aPdwnI = PwrTplToMicroAmps(pwr[12],pwr[13]);
179 return(aTplPtr-initPtr);
182 LOCAL_C TInt ParseTimingEntry(const TUint8 *aTplPtr)
184 // Parse a timing descriptor in a KCisTplCfTableEntry tuple. Returns the
185 // number of bytes we have parsed.
188 // We ignore this information - just jump past this field
189 const TUint8 *initPtr=aTplPtr;
191 TUint8 present=*aTplPtr++; // First the timing present field
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);
202 LOCAL_C TInt ParseIoEntry(const TUint8 *aTplPtr,TPccdChnk *aChnk,TInt &aNextChnkNum)
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').
209 TPccdMemType memType;
210 TInt bytesParsed = 1; // Must be a minimum of a single byte descriptor here.
212 // Always at least one I/O space descriptor
213 switch( (*aTplPtr & KTpCeBus16_8M) >> KTpCeBus16_8FO )
216 memType = EPccdIo8Mem; // Card supports 8bit I/O only.
219 memType = EPccdIo16Mem; // Card supports 8 & 16 bit I/O.
224 TUint ioLines = (*aTplPtr & KTpCeIoLinesM) >> KTpCeIoLinesFO;
226 TInt ranges=1; // We always specify one chunk even if no range descriptors follow
229 // Are there any IO Range description bytes to follow
230 if (*aTplPtr++ & KTpCeRangePresM)
232 ranges = ((*aTplPtr & KTpCeIoRangesM) >> KTpCeIoRangesFO)+1;
233 addrInBytes = (*aTplPtr & KTpCeIoAddrSzM) >> KTpCeIoAddrSzFO;
234 lenInBytes = (*aTplPtr & KTpCeIoAddrLenM) >> KTpCeIoAddrLenFO;
237 // There could be multiple range descriptors
238 if ((ranges+aNextChnkNum)<=KMaxChunksPerConfig)
239 bytesParsed += (ranges * (addrInBytes + lenInBytes))+1;
241 return(KErrNotSupported); // Too many descriptors for us
245 for (;ranges>0;ranges--,aChnk++,aNextChnkNum++)
248 aChnk->iMemType=memType; // I/O memory type
250 // Lets get the IO start address
251 aChnk->iMemBaseAddr=0;
254 for (j=0;j<addrInBytes;j++)
255 aChnk->iMemBaseAddr += (*aTplPtr++) << (8*j);
258 // Finally, lets get the IO length
261 for (j=0,aChnk->iMemLen=0;j<lenInBytes;j++)
262 aChnk->iMemLen += (*aTplPtr++) << (8*j);
268 aChnk->iMemLen = 0x01<<ioLines;
270 return(KErrCorrupt); // No ioLines and no length, it's invalid.
276 LOCAL_C TInt ParseMemEntry(const TUint8 *aTplPtr,TInt aFeatureVal,TPccdChnk *aChnk,TInt &aNextChnkNum)
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').
284 const TUint8 *initPtr=aTplPtr;
288 TBool hostAddr=EFalse;
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);
298 case 2: // Length(2byte) and base address(2byte) specified.
300 case 1: // Single 2-byte length specified.
306 if ((windows+aNextChnkNum)>KMaxChunksPerConfig)
307 return(KErrNotSupported); // Too many descriptors for us
311 for (;windows>0;windows--,aChnk++,aNextChnkNum++)
313 aChnk->iMemType=EPccdCommon16Mem;
317 for (i=0;i<lenInBytes;i++)
318 aChnk->iMemLen += (*aTplPtr++) << ((8*i)+8); // in 256 byte pages
320 aChnk->iMemBaseAddr=0;
323 for (i=0;i<addrInBytes;i++)
324 aChnk->iMemBaseAddr += (*aTplPtr++) << ((8*i)+8);// in 256 byte pages
328 for (i=0;i<addrInBytes;i++)
329 aTplPtr++; // Dont record this, just advance the tuple pointer
332 return(aTplPtr-initPtr);
335 LOCAL_C TInt ParseMiscEntry(const TUint8 *aTplPtr, TBool &aPwrDown)
337 // Parse a miscellaneous features field in a KCisTplCfTableEntry tuple.
338 // Returns the number of bytes we have parsed.
341 aPwrDown=(*aTplPtr&KTpCePwrDownM);
344 for (i=1;*aTplPtr & KCisTplExt;i++,aTplPtr++);
348 LOCAL_C TInt ParseConfigEntTuple(TDes8 &cTpl,TPcCardConfig &anInfo)
350 // Parse a KCisTplCfTableEntry tuple. anInfo contains default values on
351 // entry so this routine only adds data it finds in the tuple.
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);
360 // Check if there is an interface description field to follow
361 if (*tplPtr++ & KTpCeIntfPresM)
363 anInfo.iIsIoAndMem=(*tplPtr&KTpCeIntfTypeM);
364 anInfo.iActiveSignals=*tplPtr&(KTpCeBvdM|KTpCeWpM|KTpCeReadyM|KTpCeWaitM);
368 // Next byte should be the feature selection byte.
369 TUint8 features=*tplPtr++;
371 // Next might be 0-3 power description structures. 1st one is always VCC info.
372 TInt entry=(features & KTpCePwrPresM)>>KTpCePwrPresFO;
375 tplPtr += ParsePowerEntry(tplPtr,&anInfo.iVccMaxInMilliVolts,&anInfo.iVccMinInMilliVolts,
376 &anInfo.iOperCurrentInMicroAmps,&anInfo.iPwrDwnCurrentInMicroAmps);
380 // We only support a single Vpp supply. However we need to parse both (Vpp1+Vpp2)
381 // in order to advance the tuple pointer.
383 tplPtr += ParsePowerEntry(tplPtr,&anInfo.iVppMaxInMilliVolts,&anInfo.iVppMinInMilliVolts,NULL,NULL);
385 // Next might be timing info.
386 if (features & KTpCeTimPresM)
387 tplPtr += ParseTimingEntry(tplPtr);
389 // Next might be IO space description.
391 TInt nextFreeChunk=0;
392 if (features & KTpCeIoPresM)
394 if((ret=ParseIoEntry(tplPtr,&(anInfo.iChnk[0]),nextFreeChunk))<0)
396 anInfo.iValidChunks=nextFreeChunk;
400 // Next might be IRQ description.
401 if (features & KTpCeIrqPresM)
403 anInfo.iInterruptInfo=*tplPtr&(KPccdIntShare|KPccdIntPulse|KPccdIntLevel);
404 tplPtr+=(*tplPtr&KTpCeIrqMaskM)?3:1; // Ignore mask bytes if present
407 // Next might be memory space description.
408 entry=((features & KTpCeMemPresM) >> KTpCeMemPresFO);
411 if ((ret=ParseMemEntry(tplPtr,entry,&(anInfo.iChnk[0]),nextFreeChunk))<0)
413 anInfo.iValidChunks=nextFreeChunk;
417 // And finally there might be a miscellaneous features field
418 if (features & KTpCeMiscPresM)
419 tplPtr+=ParseMiscEntry(tplPtr,anInfo.iPwrDown);
421 // Check that we haven't been reading beyond the tuple.
422 if ((tplPtr-cTpl.Ptr()) > (cTpl[1]+2))
428 LOCAL_C TInt ParseDeviceInfo(const TUint8 *aTplPtr,TPcCardRegion &anInfo)
430 // Parse a device info field in a KCisTplDeviceX tuple.
431 // Returns the number of bytes we have parsed (or a negative error value).
435 const TUint8 *initPtr=aTplPtr;
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);
443 // Device ID - write protect field
444 if (!(*aTplPtr&KTpDiWpsM))
445 anInfo.iActiveSignals|=KSigWpActive;
447 // Device ID - device speed field
448 val=(*aTplPtr & KTpDiDSpeedM);
449 if (val==KTpDiDSpeedExt)
452 anInfo.iExtendedAccSpeedInNanoSecs=ExtendedSpeedToNanoSeconds(*aTplPtr);
453 anInfo.iAccessSpeed=DevSpeedFromExtended(anInfo.iExtendedAccSpeedInNanoSecs);
454 while(*aTplPtr++ & KCisTplExt); // Jump past any (further) extended speed fields
458 anInfo.iExtendedAccSpeedInNanoSecs=0;
459 anInfo.iAccessSpeed=CisDevSpeedTable[val];
463 // Now the Device size
465 size=((*aTplPtr & KTpDiDSizeM) >> KTpDiDSizeFO);
466 numUnits=((*aTplPtr++ & KTpDiDUnitsM) >> KTpDiDUnitsFO)+1;
467 if (size>KTpDiDSize2M)
469 anInfo.iChnk.iMemLen=numUnits*CisDevSizeInBytesTable[size];
470 return(aTplPtr-initPtr);
473 LOCAL_C TInt SocketIsInRange(TSocket aSocket)
475 // Check socket is valid for this machine
479 // return(aSocket>=0&&aSocket<ThePcCardController->TotalSupportedBuses());
480 return (aSocket>=0 && aSocket<KMaxPBusSockets && TheSockets[aSocket]!=NULL);
483 EXPORT_C TCisReader::TCisReader()
487 : iFunc(0),iCisOffset(0),iLinkOffset(0),iMemType(EPccdAttribMem),
488 iLinkFlags(0),iRestarted(EFalse),iRegionCount(0),
494 EXPORT_C TInt TCisReader::SelectCis(TSocket aSocket,TInt aCardFunc)
496 // Assign the CIS reader to a socket and function.
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)
505 return(DoSelectCis(aCardFunc));
508 TInt TCisReader::DoSelectCis(TInt aCardFunc)
510 // Actually assign the CIS reader to a socket and function.
514 // Check that the function is valid
516 if (!iSocket->IsValidCardFunc(aCardFunc))
528 __KTRACE_OPT(KPBUS1,Kern::Printf("<CisReader:DoSelectCis(F:%d)-%d",aCardFunc,r));
532 EXPORT_C TInt TCisReader::Restart()
534 // Restart the CIS reader back to the start of the CIS, and re-initialise
535 // config entry parsing.
545 void TCisReader::DoRestart()
547 // Restart the CIS reader back to the start of the CIS
551 TPcCardFunction *func=iSocket->CardFunc(iFunc);
552 iCisOffset=func->InitCisOffset();
554 iMemType=func->InitCisMemType();
558 __KTRACE_OPT(KPBUS1,Kern::Printf("<CisReader:DoRestart"));
561 EXPORT_C TInt TCisReader::FindReadTuple(TUint8 aDesiredTpl,TDes8 &aDes,TUint aFlag)
563 // Find a specified tuple from the CIS and read it.
566 __ASSERT_ALWAYS(iSocket!=NULL,PcCardPanic(EPcCardCisReaderUnInit));
568 // We're going to read the card itself so it must be ready.
569 if ( iSocket->CardIsReadyAndVerified()!=KErrNone )
570 return(KErrNotReady);
572 return(DoFindReadTuple(aDesiredTpl,aDes,aFlag));
575 TInt TCisReader::DoFindReadTuple(TUint8 aDesiredTpl,TDes8 &aDes,TUint aFlag)
577 // Actually find a specified tuple from the CIS and read it.
581 __KTRACE_OPT(KPBUS1,Kern::Printf(">CisReader:DoFindReadTuple(T:%xH)",aDesiredTpl));
583 TBuf8<KSmallTplBufSize> tpl;
584 TBuf8<KSmallTplBufSize> linkAddr;
587 // Read the previous tuple
588 if ((err=iSocket->ReadCis(iMemType,iCisOffset,tpl,2))!=KErrNone)
591 for (j=0;j<KMaxTuplesPerCis;j++)
593 // Adjust CIS offset beyond last tuple read (unless we've just restarted)
598 if (tpl[0]!=KCisTplEnd && tpl[1]!=0xff)
599 iCisOffset+=(tpl[0]==KCisTplNull)?1:(tpl[1]+2); // A null tuple has no link field
602 // End of chain tuple
603 if ((err=FollowLink(aFlag&KPccdReportErrors))!=KErrNone)
608 // Read the next tuple
609 if ((err=iSocket->ReadCis(iMemType,iCisOffset,tpl,2))!=KErrNone)
612 // Check for a link tuple (need to store next chain addr. for later)
615 case KCisTplLongLinkA:
616 iLinkFlags |= KPccdLinkA;
617 if ((err= iSocket->ReadCis(iMemType,iCisOffset+2,linkAddr,4)) != KErrNone)
619 for (iLinkOffset=0,i=0 ; i<4 ; i++)
620 iLinkOffset += linkAddr[i] << (8*i);
622 case KCisTplLongLinkC:
623 iLinkFlags |= KPccdLinkC;
624 if ((err= iSocket->ReadCis(iMemType,iCisOffset+2,linkAddr,4)) != KErrNone)
626 for (iLinkOffset=0,i=0 ; i<4 ; i++)
627 iLinkOffset += linkAddr[i] << (8*i);
629 case KCisTplLongLinkMfc:
630 iLinkFlags |= KPccdLinkMFC;
633 iLinkFlags |= KPccdNoLink;
638 // Check if we have found the specified tuple
639 if (aDesiredTpl==KPccdNonSpecificTpl || aDesiredTpl==tpl[0])
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))
650 if (aFlag&KPccdReturnLinkTpl)
658 // We got a result (or we've wandered off into the weeds)
659 if (j>=KMaxTuplesPerCis)
660 return( (aFlag&KPccdReportErrors)?KErrCorrupt:KErrNotFound );
662 return((aFlag&KPccdFindOnly)?KErrNone:DoReadTuple(aDes));
665 EXPORT_C TInt TCisReader::ReadTuple(TDes8 &aDes)
667 // Read the tuple at the current CIS offset.
670 __ASSERT_ALWAYS(iSocket!=NULL,PcCardPanic(EPcCardCisReaderUnInit));
672 // We're going to read the card itself so it must be ready.
673 if ( iSocket->CardIsReadyAndVerified()!=KErrNone )
674 return(KErrNotReady);
676 return(DoReadTuple(aDes));
679 TInt TCisReader::DoReadTuple(TDes8 &aDes)
681 // Actually read the tuple at the current CIS offset.
685 __KTRACE_OPT(KPBUS1,Kern::Printf(">CisReader:DoReadTuple"));
688 // Read the tuple type and link
689 TBuf8<KSmallTplBufSize> tpl;
690 if ((err= iSocket->ReadCis(iMemType,iCisOffset,tpl,2)) != KErrNone)
694 if ((tpl[0] == KCisTplNull) || (tpl[0] == KCisTplEnd))
695 tplLen = 1 ; // These tuples dont have a link.
697 tplLen = (tpl[1]+2) ;
698 if ( tplLen>aDes.MaxLength() ) // We dont want a panic if aDes too small
699 return(KErrArgument);
701 // Lets copy the tuple
702 if ((err= iSocket->ReadCis(iMemType,iCisOffset,aDes,tplLen)) != KErrNone)
708 TInt TCisReader::FollowLink(TUint aFullErrorReport)
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.
718 case 0: // Haven't found anything so assume longlink to 0 in common.
721 iCisOffset=iLinkOffset;
722 iMemType=EPccdCommon8Mem;
724 if ((err=VerifyLinkTarget())!=KErrNone)
726 DoRestart(); // Leave pointers somewhere safe.
727 if (iLinkFlags==0||!aFullErrorReport)
728 err=KErrNotFound; // Above assumption wrong
732 iCisOffset=iLinkOffset;
733 iMemType=EPccdAttribMem;
735 if ((err=VerifyLinkTarget())!=KErrNone)
737 iCisOffset>>=1; // Check if the link offset is wrong
738 if (VerifyLinkTarget()!=KErrNone)
740 DoRestart(); // Leave pointers somewhere safe.
741 if (!aFullErrorReport)
749 case KPccdLinkMFC: // Can't follow a multi-function link
750 DoRestart(); // Leave pointers somewhere safe.
753 default: // Shouldn't have more than 1 link per chain
754 DoRestart(); // Leave pointers somewhere safe.
755 err=(aFullErrorReport)?KErrCorrupt:KErrNotFound;
761 TInt TCisReader::VerifyLinkTarget()
763 // Verify a new tuple chain starts with a valid link target tuple
766 TBuf8<KSmallTplBufSize> tpl;
768 if ((err=iSocket->ReadCis(iMemType,iCisOffset,tpl,5))!=KErrNone)
770 if ( (tpl[0]!=KCisTplLinkTarget) || (tpl[1]<3) || (tpl.Find(_L8("CIS"))!=2) )
775 EXPORT_C TInt TCisReader::FindReadRegion(TPccdSocketVcc aSocketVcc,TPcCardRegion &anInfo,TUint8 aDesiredTpl)
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.
785 aDesiredTpl=(aSocketVcc==EPccdSocket_5V0)?KCisTplDevice:KCisTplDeviceOC;
786 __KTRACE_OPT(KPBUS1,Kern::Printf(">CisReader:FindReadRegion(TPL:%xH)",aDesiredTpl));
789 TBuf8<KLargeTplBufSize> devTpl;
790 if (!iRegionCount) // Count of regions processed in tuple
791 ret=FindReadTuple(aDesiredTpl,devTpl);
793 ret=ReadTuple(devTpl);
796 const TUint8 *tplPtr=devTpl.Ptr();
797 const TUint8 *tplE=tplPtr+devTpl.Length();
798 tplPtr+=2; // First tuple after link
800 if (aDesiredTpl==KCisTplDeviceOC||aDesiredTpl==KCisTplDeviceOA)
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 )
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;
812 while (*tplPtr++ & KCisTplExt); // Ignore any extensions
816 anInfo.iChnk.iMemType=(aDesiredTpl==KCisTplDeviceA)?EPccdAttribMem:EPccdCommon16Mem;
817 anInfo.iVcc=EPccdSocket_5V0;
818 anInfo.iActiveSignals=0;
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++)
826 // Add length of previous region to give new base address.
827 anInfo.iChnk.iMemBaseAddr+=anInfo.iChnk.iMemLen;
829 if ((ret=ParseDeviceInfo(tplPtr,anInfo)) < 0)
832 // Check if we have new region to report (dont report null regions)
833 if (anInfo.iDeviceType!=EDeviceNull && regions>iRegionCount)
835 iRegionCount=regions; // Save for next time
839 return(KErrNotFound);
842 EXPORT_C TInt TCisReader::FindReadConfig(TPcCardConfig &anInfo)
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.
852 __KTRACE_OPT(KPBUS1,Kern::Printf(">CisReader:FindReadConfig(%d)",iConfigCount));
853 __ASSERT_ALWAYS(iSocket!=NULL,PcCardPanic(EPcCardCisReaderUnInit));
855 DoRestart(); // Start from beginning of CIS each time (dont reset iConfigCount though).
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;
864 TBuf8<KLargeTplBufSize> configTpl;
866 TBool foundLast=EFalse;
870 (err=FindReadTuple(KCisTplConfig,configTpl))==KErrNone &&
871 (err=ParseConfigTuple(configTpl,defaultConfInfo,lastEntryIndex))==KErrNone
874 // Start of new configuration table
875 for (; (err=FindReadTuple(KCisTplCfTableEntry,configTpl))==KErrNone && i<KMaxCfEntriesPerCis ; i++)
877 anInfo=defaultConfInfo; // Entries assume values from last default entry
878 err=ParseConfigEntTuple(configTpl,anInfo);
879 if (anInfo.iConfigOption==lastEntryIndex)
885 err=KErrNotFound; // We've passed the last entry
891 if (err==KErrNone && anInfo.iIsDefault)
892 defaultConfInfo=anInfo;
895 if (i>=KMaxCfEntriesPerCis)
899 __KTRACE_OPT(KPBUS1,Kern::Printf("<CisReader:FindReadConfig-%d",err));
903 TPcCardFunction::TPcCardFunction(TUint32 anOffset,TPccdMemType aMemType)
907 : iFuncType(EUnknownCard),iInitCisOffset(anOffset),iInitCisMemType(aMemType),
908 iConfigBaseAddr(0),iConfigRegMask(0),iConfigIndex(KInvalidConfOpt),iConfigFlags(0)
913 void TPcCardFunction::SetConfigOption(TInt anIndex,DBase *aClientID,TUint aConfigFlags)
915 // Save configuration index and client ID
919 iConfigIndex=anIndex;
921 iConfigFlags=aConfigFlags;
924 TInt TPcCardFunction::ConfigRegAddress(TInt aRegOffset,TInt &anAddr)
926 // Provide the specified configuration register address.
930 // Must be configured or we wont have the ConfigReg base address
933 anAddr=(iConfigBaseAddr + (aRegOffset<<1));
935 // Return an error if the register isn't present
936 if ( !(iConfigRegMask & (0x01<<aRegOffset)) )
937 return(KErrNotSupported);
942 EXPORT_C TPccdChnk::TPccdChnk()
946 : iMemType(EPccdAttribMem),iMemBaseAddr(0),iMemLen(0)
949 EXPORT_C TPccdChnk::TPccdChnk(TPccdMemType aType,TUint32 aBaseAddr,TUint32 aLen)
953 : iMemType(aType),iMemBaseAddr(aBaseAddr),iMemLen(aLen)
956 EXPORT_C TPcCardConfig::TPcCardConfig()
958 // Constructor (iConfigOption to KInvalidConfOpt guarentees that we start with
959 // 1st configuration entry).
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),
968 EXPORT_C TBool TPcCardConfig::IsMachineCompatible(TSocket aSocket,TInt aFlag)
970 // Return ETrue if this configuration is compatible with this machine
974 DPcCardSocket* pS=(DPcCardSocket*)TheSockets[aSocket];
975 DPcCardVcc* pV=(DPcCardVcc*)pS->iVcc;
976 TInt nomSocketVcc=DPcCardVcc::SocketVccToMilliVolts(pV->VoltageSetting());
977 if (!(aFlag&KPccdCompatNoVccCheck))
979 // Check Vcc level compatibility
980 if (iVccMaxInMilliVolts<nomSocketVcc||iVccMinInMilliVolts>nomSocketVcc)
982 __KTRACE_OPT(KPBUS1,Kern::Printf("MachineCompatible-Bad Vcc"));
987 TPcCardSocketInfo si;
989 if (!(aFlag&KPccdCompatNoVppCheck))
991 // Check Vpp level compatibility
992 if (iVppMaxInMilliVolts<si.iNomVppInMilliVolts||iVppMinInMilliVolts>si.iNomVppInMilliVolts)
994 __KTRACE_OPT(KPBUS1,Kern::Printf("MachineCompatible-Bad Vpp"));
999 if (!(aFlag&KPccdCompatNoPwrCheck))
1001 // Check the configurations power requirements can be supported
1002 if (iOperCurrentInMicroAmps>pV->MaxCurrentInMicroAmps())
1004 __KTRACE_OPT(KPBUS1,Kern::Printf("MachineCompatible-Bad Pwr"));
1009 // If wait requested then check its supported
1010 if ((iActiveSignals&KSigWaitRequired)&&!(si.iSupportedSignals&KSigWaitSupported))
1012 __KTRACE_OPT(KPBUS1,Kern::Printf("MachineCompatible-Bad Wait-sig"));
1015 // Dealt with WAIT - mask out any other signls which aren't supported - not reason to reject though
1016 iActiveSignals&=si.iSupportedSignals;
1020 EXPORT_C TPcCardRegion::TPcCardRegion()
1022 // Constructor (iDeviceType to EDeviceInvalid guarentees that we start with
1023 // 1st device information entry).
1025 : iAccessSpeed(EAcSpeedInValid),iActiveSignals(0),iVcc(EPccdSocket_Invalid),
1026 iDeviceType(EDeviceInvalid),iExtendedAccSpeedInNanoSecs(0)
1029 EXPORT_C TBool TPcCardRegion::IsMachineCompatible(TSocket aSocket)
1031 // Return ETrue if this configuration is compatible with this machine
1035 DPcCardSocket* pS=(DPcCardSocket*)TheSockets[aSocket];
1036 TPccdSocketVcc vcc=pS->VccSetting();
1037 // Check Vcc level compatibility
1040 __KTRACE_OPT(KPBUS1,Kern::Printf("MachineCompatible-Bad Vcc"));
1044 // If wait requested then check its supported
1045 TPcCardSocketInfo si;
1047 TBool waitReq=(iActiveSignals&KSigWaitRequired);
1048 if (waitReq&&!(si.iSupportedSignals&KSigWaitSupported))
1050 __KTRACE_OPT(KPBUS1,Kern::Printf("MachineCompatible-Bad Wait-sig"));
1053 // Dealt with WAIT - mask out any other signls which aren't supported - not reason to reject though
1054 iActiveSignals&=si.iSupportedSignals;
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)
1060 __KTRACE_OPT(KPBUS1,Kern::Printf("MachineCompatible-Bad speed"));
1066 EXPORT_C TPccdType::TPccdType()
1072 for (TInt i=0;i<(TInt)KMaxFuncPerCard;i++)
1073 iFuncType[i]=EUnknownCard;