sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\drivers\pbus\pccard\socket.cpp sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include "cis.h" sl@0: sl@0: const TInt KFuncGranularity=(KMaxFuncPerCard+1); sl@0: const TInt KMemGranularity=2; sl@0: sl@0: TPccdFuncType FuncType(TUint aFuncCode) sl@0: { sl@0: sl@0: if (aFuncCode<=KCisTplFuncIdScsi) sl@0: return((TPccdFuncType)(aFuncCode+1)); sl@0: else if (aFuncCode==KCisTplFuncIdVendorSpecific) sl@0: return(EVendorSpecificCard); sl@0: else sl@0: return(EUnknownCard); sl@0: } sl@0: sl@0: /******************************************** sl@0: * PC card power supply sl@0: ********************************************/ sl@0: DPcCardVcc::DPcCardVcc(TInt aPsuNum, TInt aMediaChangeNum) sl@0: : DPBusPsuBase(aPsuNum, aMediaChangeNum) sl@0: { sl@0: } sl@0: sl@0: TInt DPcCardVcc::SocketVccToMilliVolts(TPccdSocketVcc aVcc) sl@0: // sl@0: // Converts a TPccdSocketVcc into a integer value - units mV. sl@0: // sl@0: { sl@0: switch (aVcc) sl@0: { sl@0: case EPccdSocket_5V0: return(5000); sl@0: case EPccdSocket_3V3: return(3300); sl@0: default: return(0); sl@0: } sl@0: } sl@0: sl@0: TBool DPcCardVcc::IsLocked() sl@0: { sl@0: /* TInt i; sl@0: Kern::EnterCS(); sl@0: for (i=0; iiVcc==this) sl@0: { sl@0: if (pS->iClientWindows || pS->iActiveConfigs) sl@0: break; sl@0: } sl@0: } sl@0: Kern::LeaveCS(); sl@0: return (iiClientWindows || pS->iActiveConfigs); sl@0: } sl@0: sl@0: void DPcCardVcc::ReceiveVoltageCheckResult(TInt anError) sl@0: { sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf("DPcCardVcc(%d)::ReceiveVoltageCheckResult(%d)",iPsuNum,anError)); sl@0: DPcCardSocket* pS=(DPcCardSocket*)iSocket; sl@0: TInt s=pS->iCardPowerUpState; sl@0: if (s==DPcCardSocket::EWaitForVccReading) sl@0: { sl@0: if (anError==KErrNone) sl@0: { sl@0: SetState(EPsuOnFull); sl@0: pS->iCardPowerUpState=DPcCardSocket::EWaitForReady; sl@0: } sl@0: else sl@0: pS->TerminatePowerUpSequence(KErrCorrupt); sl@0: } sl@0: else if (s!=DPcCardSocket::EInit && s!=DPcCardSocket::EApplyingReset && s!=DPcCardSocket::ECheckVcc) sl@0: DPBusPsuBase::ReceiveVoltageCheckResult(anError); sl@0: } sl@0: sl@0: /******************************************** sl@0: * PC card media change sl@0: ********************************************/ sl@0: DPcCardMediaChange::DPcCardMediaChange(TInt aMediaChangeNum) sl@0: : DMediaChangeBase(aMediaChangeNum) sl@0: { sl@0: } sl@0: sl@0: TInt DPcCardMediaChange::Create() sl@0: { sl@0: return DMediaChangeBase::Create(); sl@0: } sl@0: sl@0: /******************************************** sl@0: * PC card socket sl@0: ********************************************/ sl@0: void cardPowerUpTick(TAny* aPtr) sl@0: { sl@0: ((DPcCardSocket*)aPtr)->iCardPowerUpDfc.Enque(); sl@0: } sl@0: sl@0: void cardPowerUpDfc(TAny* aPtr) sl@0: { sl@0: ((DPcCardSocket*)aPtr)->CardPowerUpTick(); sl@0: } sl@0: sl@0: DPcCardSocket::DPcCardSocket(TSocket aSocketNum) sl@0: // sl@0: // Constructor. sl@0: // sl@0: : DPBusSocket(aSocketNum), sl@0: iCardFuncArray(KFuncGranularity), sl@0: iMemChunks(KMemGranularity), sl@0: iCardPowerUpDfc(cardPowerUpDfc, this, 1) sl@0: { sl@0: sl@0: iType=EPBusTypePcCard; sl@0: // iCardPowerUpState=EIdle; sl@0: // iClientWindows=0; sl@0: // iActiveConfigs=0; sl@0: } sl@0: sl@0: TInt DPcCardSocket::Create(const TDesC* aName) sl@0: // sl@0: // Create a new Socket. Only created once on kernel initialization so don't sl@0: // worry about cleanup if it fails. sl@0: // sl@0: { sl@0: sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):Create(%lS)",iSocketNumber,aName)); sl@0: sl@0: TInt r=DPBusSocket::Create(aName); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: iCardPowerUpDfc.SetDfcQ(&iDfcQ); sl@0: sl@0: // Create card function array - add and remove a dummy function to pre-allocate array memory. sl@0: // This way, adding new functions to array never causes any memory allocation. sl@0: r=AddNewFunc(0,EPccdAttribMem); // Add dummy function sl@0: if (r!=KErrNone) sl@0: return r; sl@0: delete iCardFuncArray[0]; // Destroy dummy function sl@0: iCardFuncArray.Remove(0); // Remove pointer to dummy from array sl@0: sl@0: // Now allocate the permanent attribute memory chunk. Don't bother about what sl@0: // access speed we asign, it gets set each time we subsequently access the chunk. sl@0: TPccdChnk chnk(EPccdAttribMem,0,KDefaultAttribMemSize); sl@0: r=iAttribWin.Create(this,chnk,EAcSpeed300nS,KPccdChunkPermanent|KPccdChunkShared|KPccdChunkSystemOwned); sl@0: return r; sl@0: } sl@0: sl@0: void DPcCardSocket::ResetPowerUpState() sl@0: { sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):ResetPowerUpState",iSocketNumber)); sl@0: if (iCardPowerUpState!=EIdle) sl@0: { sl@0: iCardPowerUpTimer.Cancel(); sl@0: iCardPowerUpDfc.Cancel(); sl@0: iCardPowerUpState=EIdle; sl@0: } sl@0: } sl@0: sl@0: void DPcCardSocket::Reset1() sl@0: { sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):Reset1",iSocketNumber)); sl@0: ResetPowerUpState(); sl@0: } sl@0: sl@0: void DPcCardSocket::Reset2() sl@0: // sl@0: // Reset the socket (called to remove any allocated memory following a sl@0: // media change event). sl@0: // sl@0: { sl@0: sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):Rst2",iSocketNumber)); sl@0: // Destroy all the function objects sl@0: TInt i; sl@0: for (i=CardFuncCount()-1;i>=0;i--) sl@0: { sl@0: delete iCardFuncArray[i]; sl@0: iCardFuncArray.Remove(i); // Now remove from array (doesn't cause memory dealloc). sl@0: } sl@0: iActiveConfigs=0; sl@0: sl@0: // Destroy all the non-permanent Pc Card chunks sl@0: for (i=(iMemChunks.Count()-1);i>=0;i--) sl@0: { sl@0: if ( iMemChunks[i]->IsRemovable() ) sl@0: iMemChunks[i]->Close(); sl@0: } sl@0: iMemChunks.Compress(); sl@0: } sl@0: sl@0: void DPcCardSocket::Restore() sl@0: // sl@0: // Restore the socket. Normally called when restoring a socket after it has been powered sl@0: // down due to inactivity (but not media change) sl@0: // sl@0: { sl@0: TInt i; sl@0: TPcCardFunction *cf; sl@0: for (i=CardFuncCount()-1;i>=0;i--) sl@0: { sl@0: cf=iCardFuncArray[i]; sl@0: sl@0: TUint8 index; sl@0: if ((index=(TUint8)cf->ConfigOption())!=KInvalidConfOpt && cf->IsRestorableConfig()) sl@0: WriteConfigReg(i,KConfigOptionReg,index); sl@0: } sl@0: } sl@0: sl@0: void DPcCardSocket::RemoveChunk(DPccdChunkBase *aChunk) sl@0: // sl@0: // Remove a chunk from this socket. sl@0: // sl@0: { sl@0: TInt i; sl@0: for (i=0;iSkt(%d):RequestConfig(F:%d O:%xH B:%xH L:%xH)",iSocketNumber,aCardFunc,\ sl@0: anInfo.iConfigOption,anInfo.iConfigBaseAddr,anInfo.iRegPresent)); sl@0: if (!IsValidCardFunc(aCardFunc)) sl@0: return(KErrArgument); sl@0: // Check that this function isn't configured already sl@0: TPcCardFunction *cf=iCardFuncArray[aCardFunc]; sl@0: if (cf->IsConfigured()) sl@0: return(KErrInUse); // Its already configured. sl@0: sl@0: // If configuration registers are within attribute chunk then configure the sl@0: // card (rather than use the registers present info, assume all registers are sl@0: // present - ie size of mask). sl@0: if (anInfo.iConfigBaseAddr+(sizeof(anInfo.iRegPresent)<<1)>KDefaultAttribMemSize) sl@0: return(KErrNotSupported); sl@0: anInfo.iConfigOption&=(KConfOptLevIReqM|KConfOptConfM); // Mustn't allow msb - KInvalidConfOpt sl@0: TPccdAccessSpeed sp=(VccSetting()==EPccdSocket_3V3)?EAcSpeed600nS:EAcSpeed300nS; sl@0: iAttribWin.SetAccessSpeed(sp); sl@0: iAttribWin.SetupChunkHw(); sl@0: iAttribWin.Write(anInfo.iConfigBaseAddr,(TUint8*)&anInfo.iConfigOption,1); sl@0: sl@0: cf->SetConfigRegMask(anInfo.iRegPresent); sl@0: cf->SetConfigBaseAddr(anInfo.iConfigBaseAddr); sl@0: cf->SetConfigOption(anInfo.iConfigOption,aClientID,aFlag); sl@0: __e32_atomic_add_ord32(&iActiveConfigs, 1); sl@0: return(KErrNone); sl@0: } sl@0: sl@0: EXPORT_C void DPcCardSocket::ReleaseConfig(TInt aCardFunc,DBase *aClientID) sl@0: // sl@0: // Return card to memory only config. sl@0: // sl@0: { sl@0: sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):ReleaseConfig(F:%d)",iSocketNumber,aCardFunc)); sl@0: if (IsValidCardFunc(aCardFunc)) sl@0: { sl@0: TPcCardFunction *cf=iCardFuncArray[aCardFunc]; sl@0: if (cf->IsConfiguredByClient(aClientID)) sl@0: { sl@0: if (iState==EPBusOn && Kern::PowerGood()) sl@0: WriteConfigReg(aCardFunc,KConfigOptionReg,0); // Restore Config. Option register sl@0: sl@0: cf->SetConfigRegMask(0); sl@0: cf->SetConfigBaseAddr(0); sl@0: cf->SetConfigOption(KInvalidConfOpt,NULL,0); sl@0: __e32_atomic_add_ord32(&iActiveConfigs, TUint32(-1)); sl@0: } sl@0: } sl@0: } sl@0: sl@0: EXPORT_C TInt DPcCardSocket::ReadConfigReg(TInt aCardFunc,TInt aRegOffset,TUint8 &aVal) sl@0: // sl@0: // Read from a specified configuration register. (We return an error if the RegPres mask sl@0: // indicates the register isn't present but still attempt the read). sl@0: // sl@0: { sl@0: TInt offset, err; sl@0: if (!IsValidCardFunc(aCardFunc)|| iState!=EPBusOn || !Kern::PowerGood()) sl@0: err=KErrArgument; sl@0: else sl@0: { sl@0: if ((err=iCardFuncArray[aCardFunc]->ConfigRegAddress(aRegOffset,offset))==KErrNone||err==KErrNotSupported) sl@0: { sl@0: TPccdAccessSpeed sp=(VccSetting()==EPccdSocket_3V3)?EAcSpeed600nS:EAcSpeed300nS; sl@0: iAttribWin.SetAccessSpeed(sp); sl@0: iAttribWin.SetupChunkHw(); sl@0: iAttribWin.Read(offset,&aVal,1); sl@0: } sl@0: } sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf("ConfigRegAddress(aRegOffset,offset))==KErrNone||err==KErrNotSupported) sl@0: { sl@0: TPccdAccessSpeed sp=(VccSetting()==EPccdSocket_3V3)?EAcSpeed600nS:EAcSpeed300nS; sl@0: iAttribWin.SetAccessSpeed(sp); sl@0: iAttribWin.SetupChunkHw(); sl@0: iAttribWin.Write(offset,&aVal,1); sl@0: } sl@0: } sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf("Skt(%d):ReadCis(LE:%xH PO:%d TY:%d)",iSocketNumber,aLen,aPos,aMemType)); sl@0: RPccdWindow newWin; sl@0: RPccdWindow* win=&newWin; sl@0: TBool needNewChunk=ETrue; sl@0: TInt cisE=(aPos+aLen); sl@0: TInt incrm=1; sl@0: if (aMemType==EPccdAttribMem) sl@0: { sl@0: incrm=2; // Read every other byte sl@0: cisE<<=1; sl@0: aPos<<=1; sl@0: if (cisE<=(TInt)KDefaultAttribMemSize) sl@0: { sl@0: needNewChunk=EFalse; sl@0: win=&iAttribWin; sl@0: } sl@0: } sl@0: sl@0: if (needNewChunk) sl@0: { sl@0: TPccdChnk chnk(aMemType,aPos,(cisE-aPos)); sl@0: TInt r=newWin.Create(this,chnk,EAcSpeed300nS,KPccdChunkShared|KPccdChunkSystemOwned); sl@0: if (r!=KErrNone) sl@0: return(r); sl@0: cisE-=aPos; sl@0: aPos=0; sl@0: } sl@0: sl@0: TPccdAccessSpeed sp=(VccSetting()==EPccdSocket_3V3)?EAcSpeed600nS:EAcSpeed300nS; sl@0: win->SetAccessSpeed(sp); sl@0: win->SetupChunkHw(); sl@0: aDes.Zero(); sl@0: TText8 buf[KReadCisBufferSize]; sl@0: TInt s; sl@0: for (;aPosRead(aPos,&buf[0],s); sl@0: for (TInt i=0;iSkt(%d):AddNewFunc(T:%d)",iSocketNumber,aMemType)); sl@0: TInt r=KErrNoMemory; sl@0: TPcCardFunction* cf=new TPcCardFunction(anOffset,aMemType); sl@0: if (cf) sl@0: { sl@0: r=iCardFuncArray.Append(cf); sl@0: if (r!=KErrNone) sl@0: delete cf; sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: TPcCardFunction *DPcCardSocket::CardFunc(TInt aCardFunc) sl@0: // sl@0: // Get a reference to a specific card function from the function array sl@0: // sl@0: { sl@0: sl@0: __ASSERT_ALWAYS(IsValidCardFunc(aCardFunc),PcCardPanic(EPcCardBadFunctionNumber)); sl@0: return iCardFuncArray[aCardFunc]; sl@0: } sl@0: sl@0: TBool DPcCardSocket::IsConfigLocked() sl@0: // sl@0: // Returns ETrue if this socket contains a card function which is currently configured. sl@0: // sl@0: { sl@0: // TInt i; sl@0: // for (i=CardFuncCount()-1;i>=0;i--) sl@0: // { sl@0: // if (iCardFuncArray[i]->IsConfigured()) sl@0: // return(ETrue); sl@0: // } sl@0: // return(EFalse); sl@0: return (iActiveConfigs!=0); sl@0: } sl@0: sl@0: TBool DPcCardSocket::IsMemoryLocked() sl@0: // sl@0: // Returns ETrue if any PC Card memory chunks are allocated on this socket. sl@0: // sl@0: { sl@0: sl@0: // TInt i; sl@0: // for (i=iMemChunks.Count()-1;i>=0;i--) sl@0: // { sl@0: // if ( iMemChunks[i]->IsLocked() ) sl@0: // return(ETrue); sl@0: // } sl@0: // return(EFalse); sl@0: return (iClientWindows!=0); sl@0: } sl@0: sl@0: TPccdSocketVcc DPcCardSocket::VccSetting() sl@0: // sl@0: // Return voltage setting that this socket is currently set for sl@0: // sl@0: { sl@0: sl@0: return ((DPcCardVcc*)iVcc)->VoltageSetting(); sl@0: } sl@0: sl@0: EXPORT_C TInt DPcCardSocket::VerifyCard(TPccdType &aType) sl@0: // sl@0: // Return information about the type of card present sl@0: // sl@0: { sl@0: sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf(">Cntrl:VerifyCard(S:%d)",iSocketNumber)); sl@0: // The data we want is stored off-card, so it doesn't actually need to be sl@0: // powered but we need to have read CIS format. sl@0: TInt err=KErrNone; sl@0: if (CardIsReadyAndVerified()==KErrNone) sl@0: { sl@0: aType.iFuncCount=CardFuncCount(); sl@0: for (TInt i=(aType.iFuncCount-1);i>=0;i--) sl@0: aType.iFuncType[i]=CardFunc(i)->FuncType(); sl@0: } sl@0: else sl@0: err=KErrNotReady; sl@0: sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf("IsOff(); sl@0: } sl@0: sl@0: TInt DPcCardSocket::GetCisFormat() sl@0: // sl@0: // Determine the type of card present by parsing the entire CIS. If a sl@0: // Multi-function card is present then parse each CIS. sl@0: // sl@0: { sl@0: sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf(">GetCisFormat (S:%d)",iSocketNumber)); sl@0: sl@0: TInt r=AddNewFunc(0,EPccdAttribMem); // We always have 1st CIS sl@0: if (r!=KErrNone) sl@0: return r; sl@0: if (ValidateCis(0)!=KErrNone) // Can't use this until func added sl@0: return KErrCorrupt; sl@0: TCisReader cisRd; sl@0: cisRd.iSocket=this; sl@0: cisRd.DoSelectCis(0); sl@0: TPccdFuncType firstFuncType; sl@0: // Check for a multi-function card, search the global CIS (attribute sl@0: // memory - addr 0) for a KCisTplLongLinkMfc tuple. sl@0: TBuf8 tpl; sl@0: if (cisRd.DoFindReadTuple(KCisTplLongLinkMfc,tpl,KPccdReturnLinkTpl)==KErrNone) sl@0: { sl@0: // Multi-Function card sl@0: firstFuncType=EGlobalCard; sl@0: const TUint8 *tplPtr=tpl.Ptr()+2; // First tuple after link sl@0: TInt funcCount=*tplPtr++; sl@0: sl@0: // Add a card function object to the socket for each entry in KCisTplLongLinkMfc tuple sl@0: TPccdMemType memType; sl@0: TUint32 lnkAdr; sl@0: TInt i; sl@0: for (i=0;iSetFuncType(ft); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // Single Function card sl@0: cisRd.Restart(); sl@0: if (cisRd.DoFindReadTuple(KCisTplFuncId,tpl,0)==KErrNone) sl@0: firstFuncType=FuncType(tpl[2]); sl@0: else sl@0: firstFuncType=EUnknownCard; sl@0: } sl@0: sl@0: CardFunc(0)->SetFuncType(firstFuncType); sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf(" tpl; sl@0: TInt j=0,err; sl@0: if ((err=cisRd.DoSelectCis(aCardFunc))==KErrNone) sl@0: { sl@0: for (j=0;j=KMaxTuplesPerCis) sl@0: err=KErrCorrupt; sl@0: if (err==KErrNotFound) sl@0: err=KErrNone; sl@0: } sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf("SetSocketStatus(ESocketBatTooLow); sl@0: // rs=KErrBadPower; sl@0: // break; sl@0: // } sl@0: // } sl@0: sl@0: // Check the state of the Voltage sense line sl@0: TSocketIndicators ind; sl@0: Indicators(ind); sl@0: TUint v=(TUint)ind.iVoltSense & ((DPcCardVcc*)iVcc)->VoltageSupported(); sl@0: if (v==0) sl@0: { sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf("InitiatePowerUpSequence(S:%d)-Voltage sense problem(%d)",iSocketNumber,ind.iVoltSense)); sl@0: iVcc->SetCurrLimited(); // Not totally true but has effect. sl@0: PowerUpSequenceComplete(KErrCorrupt); sl@0: return; sl@0: } sl@0: TPccdSocketVcc sVcc=(v&KPccdVcc_3V3)?EPccdSocket_3V3:EPccdSocket_5V0; // ??? What about xVx / yVy sl@0: ((DPcCardVcc*)iVcc)->SetVoltage(sVcc); sl@0: sl@0: // Power up card (current limited). sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf("InitiatePowerUpSequence(S:%d)-Apply Vcc",iSocketNumber)); sl@0: if (iVcc->SetState(EPsuOnCurLimit) != KErrNone) sl@0: { sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf("InitiatePowerUpSequence(S:%d)-Vcc problem",iSocketNumber)); sl@0: iVcc->SetState(EPsuOff); sl@0: iVcc->SetCurrLimited(); sl@0: PowerUpSequenceComplete(KErrGeneral); sl@0: return; sl@0: } sl@0: iCardPowerUpState=EInit; sl@0: iCardPowerUpTickCount=0; sl@0: iCardPowerUpResetLen=KResetOnDefaultLen; sl@0: iCardPowerUpPauseLen=KResetOffDefaultLen; sl@0: iCardPowerUpTimer.Periodic(KPccdPowerUpReqInterval,cardPowerUpTick,this); sl@0: } sl@0: sl@0: void DPcCardSocket::TerminatePowerUpSequence(TInt aResult) sl@0: { sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf("DPcCardSocket(%d)::TerminatePowerUpSequence result %d",iSocketNumber,aResult)); sl@0: ResetPowerUpState(); sl@0: if (aResult==KErrNone) sl@0: Restore(); sl@0: PowerUpSequenceComplete(aResult); sl@0: } sl@0: sl@0: void DPcCardSocket::CardPowerUpTick() sl@0: { sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf("CardPowerUpTick S:%d Elapsed %d State %d",iSocketNumber,iCardPowerUpTickCount,iCardPowerUpState)); sl@0: if (++iCardPowerUpTickCount>KPwrUpTimeOut) sl@0: { sl@0: iVcc->SetState(EPsuOff); // should leave this to timeout sl@0: TerminatePowerUpSequence(KErrTimedOut); sl@0: return; sl@0: } sl@0: switch (iCardPowerUpState) sl@0: { sl@0: case EInit: sl@0: HwReset(ETrue); // Apply reset - Turns on interface sl@0: iCardPowerUpState=EApplyingReset; sl@0: break; sl@0: case EApplyingReset: sl@0: if (iCardPowerUpTickCount>iCardPowerUpResetLen) sl@0: { sl@0: HwReset(EFalse); // remove reset sl@0: iCardPowerUpState=ECheckVcc; sl@0: } sl@0: break; sl@0: case ECheckVcc: sl@0: { sl@0: iCardPowerUpState=EWaitForVccReading; sl@0: TInt cv=iVcc->CheckVoltage(KPsuChkOnPwrUp); sl@0: if (cv==KErrNotSupported) sl@0: iCardPowerUpState=EWaitForReady; sl@0: else if (cv!=KErrNone) sl@0: TerminatePowerUpSequence(cv); sl@0: break; sl@0: } sl@0: case EWaitForVccReading: sl@0: break; sl@0: case EWaitForReady: sl@0: if (Ready()) sl@0: { sl@0: iCardPowerUpState=EPauseAfterReady; // Card is ready sl@0: // Its effectively powered up now so reset the elapsed time and use it sl@0: // to measure pause after reset (ie this is limited to KPwrUpTimeOut too). sl@0: iCardPowerUpTickCount=0; sl@0: } sl@0: break; sl@0: case EPauseAfterReady: sl@0: if (iCardPowerUpTickCount>=iCardPowerUpPauseLen) sl@0: { sl@0: // power-up sequence is complete sl@0: TerminatePowerUpSequence(KErrNone); sl@0: } sl@0: break; sl@0: } sl@0: } sl@0: sl@0: /******************************************** sl@0: * PC card memory chunk sl@0: ********************************************/ sl@0: DPccdChunkBase::DPccdChunkBase() sl@0: // sl@0: // Constructor sl@0: // sl@0: { sl@0: // iSocket=NULL; sl@0: // iCacheable=EFalse; sl@0: } sl@0: sl@0: TInt DPccdChunkBase::Create(DPcCardSocket* aSocket, TPccdChnk aChunk, TUint aFlag) sl@0: // sl@0: // Create a chunk of Pc Card h/w. sl@0: // sl@0: { sl@0: iSocket=aSocket; sl@0: iChnk=aChunk; sl@0: iCacheable=(aFlag&KPccdChunkCacheable); sl@0: return DoCreate(aChunk,aFlag); sl@0: } sl@0: sl@0: DPccdChunkBase::~DPccdChunkBase() sl@0: // sl@0: // Destructor sl@0: // sl@0: { sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf(">DPccdChunkBase destruct %08x",this)); sl@0: } sl@0: sl@0: void DPccdChunkBase::Close() sl@0: // sl@0: // Destructor sl@0: // sl@0: { sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf(">DPccdChunkBase::Close() %08x",this)); sl@0: sl@0: // Disconnect all the Pc Card windows and then delete chunk sl@0: SDblQueLink* pW=iWindowQ.iA.iNext; sl@0: while (pW!=&iWindowQ.iA) sl@0: { sl@0: RPccdWindow& w=*(RPccdWindow*)pW; sl@0: pW=pW->iNext; sl@0: w.Close(); // closing last window deletes chunk sl@0: } sl@0: __KTRACE_OPT(KPBUS1,Kern::Printf("iSystemWindows); sl@0: } sl@0: sl@0: TInt DPccdChunkBase::AllocateWinCheck(TPccdChnk aWin,TUint aFlag) sl@0: // sl@0: // Check if it is possible to create the specified window from this chunk. sl@0: // sl@0: { sl@0: // Check if they are of compatible type sl@0: if (!IsTypeCompatible(aWin.iMemType)) sl@0: return(KErrNotFound); sl@0: sl@0: // For a success, the requested window must lie entirely within this chunk. sl@0: TUint32 chnkEnd=(iChnk.iMemBaseAddr+iChnk.iMemLen-1); sl@0: TUint32 winEnd=(aWin.iMemBaseAddr+aWin.iMemLen-1); sl@0: TBool startIsInChnk=(aWin.iMemBaseAddr>=iChnk.iMemBaseAddr && aWin.iMemBaseAddr<=chnkEnd); sl@0: TBool endIsInChnk=(winEnd>=iChnk.iMemBaseAddr && winEnd<=chnkEnd); sl@0: if (startIsInChnk&&endIsInChnk) sl@0: { sl@0: // Possible success - first check the cache options are compatible sl@0: if (!(aFlag|KPccdChunkCacheable)&&iCacheable) sl@0: return(KErrAccessDenied); sl@0: sl@0: // Now check that the requested window isn't already allocated sl@0: SDblQueLink* pW=iWindowQ.iA.iNext; sl@0: while (pW!=&iWindowQ.iA) sl@0: { sl@0: RPccdWindow& w=*(RPccdWindow*)pW; sl@0: pW=pW->iNext; sl@0: if (w.Overlap(aWin.iMemBaseAddr-iChnk.iMemBaseAddr,aWin.iMemLen) ) sl@0: return(KErrAccessDenied); sl@0: } sl@0: return(KErrNone); sl@0: } sl@0: if (startIsInChnk||endIsInChnk) sl@0: return(KErrAccessDenied); // Requested window is partly in this chunk. sl@0: return(KErrNotFound); sl@0: } sl@0: sl@0: void DPccdChunkBase::AddWindow(RPccdWindow *aWindow) sl@0: // sl@0: // Add a window to this chunk. sl@0: // sl@0: { sl@0: iWindowQ.Add(aWindow); sl@0: // Kern::EnterCS(); Not needed since a single thread is used sl@0: iWindows++; sl@0: if (aWindow->IsPermanent()) sl@0: iPermanentWindows++; sl@0: if (aWindow->IsShareable()) sl@0: iShareableWindows++; sl@0: if (aWindow->IsSystemOwned()) sl@0: iSystemWindows++; sl@0: else sl@0: iSocket->iClientWindows++; sl@0: // Kern::LeaveCS(); sl@0: aWindow->iChunk=this; sl@0: } sl@0: sl@0: void DPccdChunkBase::RemoveWindow(RPccdWindow *aWindow) sl@0: // sl@0: // Remove a window from this chunk (even if it's permanent). sl@0: // sl@0: { sl@0: sl@0: if (aWindow->iNext && aWindow->iChunk==this) sl@0: { sl@0: aWindow->Deque(); sl@0: aWindow->iNext=NULL; sl@0: // Kern::EnterCS(); Not needed since a single thread is used sl@0: iWindows--; sl@0: if (aWindow->IsPermanent()) sl@0: iPermanentWindows--; sl@0: if (aWindow->IsShareable()) sl@0: iShareableWindows--; sl@0: if (aWindow->IsSystemOwned()) sl@0: iSystemWindows--; sl@0: else sl@0: iSocket->iClientWindows--; sl@0: // Kern::LeaveCS(); sl@0: if (iWindows==0) sl@0: { sl@0: iSocket->RemoveChunk(this); sl@0: delete this; sl@0: } sl@0: } sl@0: } sl@0: sl@0: /******************************************** sl@0: * PC card memory window sl@0: ********************************************/ sl@0: EXPORT_C RPccdWindow::RPccdWindow() sl@0: // sl@0: // Constructor sl@0: // sl@0: : iAccessSpeed(EAcSpeedInValid),iMemType(EPccdAttribMem),iOffset(0),iLen(0),iType(0) sl@0: { sl@0: iNext=NULL; sl@0: iChunk=NULL; sl@0: } sl@0: sl@0: EXPORT_C TInt RPccdWindow::Create(DPcCardSocket* aSocket, TPccdChnk aChnk, TPccdAccessSpeed aSpeed, TUint aFlag) sl@0: // sl@0: // Create a block of memory (IO, Common or Attribute memory). sl@0: // sl@0: { sl@0: sl@0: DPccdChunkBase *chunk=NULL; sl@0: TBool chunkExists=EFalse; sl@0: TInt r; sl@0: sl@0: // See if requested window is actually part of a chunk already created sl@0: TInt i; sl@0: for (i=0;iiMemChunks.Count();i++) sl@0: { sl@0: if ((r=aSocket->iMemChunks[i]->AllocateWinCheck(aChnk,aFlag))==KErrNone) sl@0: { sl@0: chunk=aSocket->iMemChunks[i]; sl@0: chunkExists=ETrue; sl@0: break; sl@0: } sl@0: if (r==KErrAccessDenied) sl@0: return r; sl@0: } sl@0: sl@0: // If necesary, create a chunk sl@0: if (!chunkExists) sl@0: { sl@0: // Create the memory chunk sl@0: chunk=aSocket->NewPccdChunk(aChnk.iMemType); sl@0: if (!chunk) sl@0: return KErrNoMemory; sl@0: TInt r=chunk->Create(aSocket, aChnk, aFlag); sl@0: if (r==KErrNone) sl@0: r=aSocket->iMemChunks.Append(chunk); sl@0: if (r!=KErrNone) sl@0: { sl@0: delete chunk; sl@0: return r; sl@0: } sl@0: } sl@0: __KTRACE_OPT(KPBUS2,Kern::Printf("Skt:CreateMemWindowL-got chunk(existing-%d)",chunkExists)); sl@0: sl@0: // Create the memory window sl@0: iOffset=aChnk.iMemBaseAddr-chunk->BaseAddr(); sl@0: iLen=aChnk.iMemLen; sl@0: iAccessSpeed=aSpeed; sl@0: iMemType=aChnk.iMemType; sl@0: iWaitSig=(aFlag&KPccdRequestWait); sl@0: iType=aFlag&(KPccdChunkShared|KPccdChunkPermanent|KPccdChunkSystemOwned); // Save flag settings sl@0: chunk->AddWindow(this); sl@0: __KTRACE_OPT(KPBUS2,Kern::Printf("Skt:CreateMemWindowL-created window")); sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C void RPccdWindow::Close() sl@0: { sl@0: if (iNext && iChunk) sl@0: iChunk->RemoveWindow(this); sl@0: } sl@0: sl@0: EXPORT_C TInt RPccdWindow::SetupChunkHw(TUint aFlag) sl@0: // sl@0: // Config h/w in preparation for accessing window. Flag is for platform dependant info. sl@0: // sl@0: { sl@0: sl@0: if (!iChunk) sl@0: return(KErrNotReady); sl@0: iChunk->SetupChunkHw(iAccessSpeed,iMemType,iWaitSig,aFlag); sl@0: // iVcc->ResetInactivityTimer(); sl@0: return(KErrNone); sl@0: } sl@0: sl@0: EXPORT_C TLinAddr RPccdWindow::LinearAddress() sl@0: // sl@0: // Return linear address of window sl@0: // sl@0: { sl@0: return iChunk->LinearAddress()+iOffset; sl@0: } sl@0: sl@0: TBool RPccdWindow::Overlap(TUint32 anOffset,TUint aLen) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: // If this window is sharable then it doesn't matter if they overlap or not. sl@0: if (IsShareable()) sl@0: return(EFalse); sl@0: sl@0: TUint32 winEnd=(anOffset+aLen-1); sl@0: TUint32 thisEnd=(iOffset+iLen-1); sl@0: if ((anOffset>=iOffset && anOffset<=thisEnd) || sl@0: (winEnd>=iOffset && winEnd<=thisEnd) ) sl@0: return(ETrue); sl@0: sl@0: return(EFalse); sl@0: } sl@0: