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\socket.cpp
21 const TInt KFuncGranularity=(KMaxFuncPerCard+1);
22 const TInt KMemGranularity=2;
24 TPccdFuncType FuncType(TUint aFuncCode)
27 if (aFuncCode<=KCisTplFuncIdScsi)
28 return((TPccdFuncType)(aFuncCode+1));
29 else if (aFuncCode==KCisTplFuncIdVendorSpecific)
30 return(EVendorSpecificCard);
35 /********************************************
36 * PC card power supply
37 ********************************************/
38 DPcCardVcc::DPcCardVcc(TInt aPsuNum, TInt aMediaChangeNum)
39 : DPBusPsuBase(aPsuNum, aMediaChangeNum)
43 TInt DPcCardVcc::SocketVccToMilliVolts(TPccdSocketVcc aVcc)
45 // Converts a TPccdSocketVcc into a integer value - units mV.
50 case EPccdSocket_5V0: return(5000);
51 case EPccdSocket_3V3: return(3300);
56 TBool DPcCardVcc::IsLocked()
60 for (i=0; i<KMaxPccdSockets; i++)
62 DPcCardSocket* pS=(DPcCardSocket*)TheSockets[i];
63 if (pS && pS->iVcc==this)
65 if (pS->iClientWindows || pS->iActiveConfigs)
70 return (i<KMaxPccdSockets);
72 DPcCardSocket* pS=(DPcCardSocket*)iSocket;
73 return (pS->iClientWindows || pS->iActiveConfigs);
76 void DPcCardVcc::ReceiveVoltageCheckResult(TInt anError)
78 __KTRACE_OPT(KPBUS1,Kern::Printf("DPcCardVcc(%d)::ReceiveVoltageCheckResult(%d)",iPsuNum,anError));
79 DPcCardSocket* pS=(DPcCardSocket*)iSocket;
80 TInt s=pS->iCardPowerUpState;
81 if (s==DPcCardSocket::EWaitForVccReading)
83 if (anError==KErrNone)
86 pS->iCardPowerUpState=DPcCardSocket::EWaitForReady;
89 pS->TerminatePowerUpSequence(KErrCorrupt);
91 else if (s!=DPcCardSocket::EInit && s!=DPcCardSocket::EApplyingReset && s!=DPcCardSocket::ECheckVcc)
92 DPBusPsuBase::ReceiveVoltageCheckResult(anError);
95 /********************************************
96 * PC card media change
97 ********************************************/
98 DPcCardMediaChange::DPcCardMediaChange(TInt aMediaChangeNum)
99 : DMediaChangeBase(aMediaChangeNum)
103 TInt DPcCardMediaChange::Create()
105 return DMediaChangeBase::Create();
108 /********************************************
110 ********************************************/
111 void cardPowerUpTick(TAny* aPtr)
113 ((DPcCardSocket*)aPtr)->iCardPowerUpDfc.Enque();
116 void cardPowerUpDfc(TAny* aPtr)
118 ((DPcCardSocket*)aPtr)->CardPowerUpTick();
121 DPcCardSocket::DPcCardSocket(TSocket aSocketNum)
125 : DPBusSocket(aSocketNum),
126 iCardFuncArray(KFuncGranularity),
127 iMemChunks(KMemGranularity),
128 iCardPowerUpDfc(cardPowerUpDfc, this, 1)
131 iType=EPBusTypePcCard;
132 // iCardPowerUpState=EIdle;
137 TInt DPcCardSocket::Create(const TDesC* aName)
139 // Create a new Socket. Only created once on kernel initialization so don't
140 // worry about cleanup if it fails.
144 __KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):Create(%lS)",iSocketNumber,aName));
146 TInt r=DPBusSocket::Create(aName);
149 iCardPowerUpDfc.SetDfcQ(&iDfcQ);
151 // Create card function array - add and remove a dummy function to pre-allocate array memory.
152 // This way, adding new functions to array never causes any memory allocation.
153 r=AddNewFunc(0,EPccdAttribMem); // Add dummy function
156 delete iCardFuncArray[0]; // Destroy dummy function
157 iCardFuncArray.Remove(0); // Remove pointer to dummy from array
159 // Now allocate the permanent attribute memory chunk. Don't bother about what
160 // access speed we asign, it gets set each time we subsequently access the chunk.
161 TPccdChnk chnk(EPccdAttribMem,0,KDefaultAttribMemSize);
162 r=iAttribWin.Create(this,chnk,EAcSpeed300nS,KPccdChunkPermanent|KPccdChunkShared|KPccdChunkSystemOwned);
166 void DPcCardSocket::ResetPowerUpState()
168 __KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):ResetPowerUpState",iSocketNumber));
169 if (iCardPowerUpState!=EIdle)
171 iCardPowerUpTimer.Cancel();
172 iCardPowerUpDfc.Cancel();
173 iCardPowerUpState=EIdle;
177 void DPcCardSocket::Reset1()
179 __KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):Reset1",iSocketNumber));
183 void DPcCardSocket::Reset2()
185 // Reset the socket (called to remove any allocated memory following a
186 // media change event).
190 __KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):Rst2",iSocketNumber));
191 // Destroy all the function objects
193 for (i=CardFuncCount()-1;i>=0;i--)
195 delete iCardFuncArray[i];
196 iCardFuncArray.Remove(i); // Now remove from array (doesn't cause memory dealloc).
200 // Destroy all the non-permanent Pc Card chunks
201 for (i=(iMemChunks.Count()-1);i>=0;i--)
203 if ( iMemChunks[i]->IsRemovable() )
204 iMemChunks[i]->Close();
206 iMemChunks.Compress();
209 void DPcCardSocket::Restore()
211 // Restore the socket. Normally called when restoring a socket after it has been powered
212 // down due to inactivity (but not media change)
217 for (i=CardFuncCount()-1;i>=0;i--)
219 cf=iCardFuncArray[i];
222 if ((index=(TUint8)cf->ConfigOption())!=KInvalidConfOpt && cf->IsRestorableConfig())
223 WriteConfigReg(i,KConfigOptionReg,index);
227 void DPcCardSocket::RemoveChunk(DPccdChunkBase *aChunk)
229 // Remove a chunk from this socket.
233 for (i=0;i<iMemChunks.Count();i++)
235 if (iMemChunks[i]==aChunk)
237 iMemChunks.Remove(i);
238 iMemChunks.Compress();
244 EXPORT_C TInt DPcCardSocket::RequestConfig(TInt aCardFunc,DBase *aClientID,TPcCardConfig &anInfo,TUint aFlag)
246 // Configure the card.
250 __KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):RequestConfig(F:%d O:%xH B:%xH L:%xH)",iSocketNumber,aCardFunc,\
251 anInfo.iConfigOption,anInfo.iConfigBaseAddr,anInfo.iRegPresent));
252 if (!IsValidCardFunc(aCardFunc))
253 return(KErrArgument);
254 // Check that this function isn't configured already
255 TPcCardFunction *cf=iCardFuncArray[aCardFunc];
256 if (cf->IsConfigured())
257 return(KErrInUse); // Its already configured.
259 // If configuration registers are within attribute chunk then configure the
260 // card (rather than use the registers present info, assume all registers are
261 // present - ie size of mask).
262 if (anInfo.iConfigBaseAddr+(sizeof(anInfo.iRegPresent)<<1)>KDefaultAttribMemSize)
263 return(KErrNotSupported);
264 anInfo.iConfigOption&=(KConfOptLevIReqM|KConfOptConfM); // Mustn't allow msb - KInvalidConfOpt
265 TPccdAccessSpeed sp=(VccSetting()==EPccdSocket_3V3)?EAcSpeed600nS:EAcSpeed300nS;
266 iAttribWin.SetAccessSpeed(sp);
267 iAttribWin.SetupChunkHw();
268 iAttribWin.Write(anInfo.iConfigBaseAddr,(TUint8*)&anInfo.iConfigOption,1);
270 cf->SetConfigRegMask(anInfo.iRegPresent);
271 cf->SetConfigBaseAddr(anInfo.iConfigBaseAddr);
272 cf->SetConfigOption(anInfo.iConfigOption,aClientID,aFlag);
273 __e32_atomic_add_ord32(&iActiveConfigs, 1);
277 EXPORT_C void DPcCardSocket::ReleaseConfig(TInt aCardFunc,DBase *aClientID)
279 // Return card to memory only config.
283 __KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):ReleaseConfig(F:%d)",iSocketNumber,aCardFunc));
284 if (IsValidCardFunc(aCardFunc))
286 TPcCardFunction *cf=iCardFuncArray[aCardFunc];
287 if (cf->IsConfiguredByClient(aClientID))
289 if (iState==EPBusOn && Kern::PowerGood())
290 WriteConfigReg(aCardFunc,KConfigOptionReg,0); // Restore Config. Option register
292 cf->SetConfigRegMask(0);
293 cf->SetConfigBaseAddr(0);
294 cf->SetConfigOption(KInvalidConfOpt,NULL,0);
295 __e32_atomic_add_ord32(&iActiveConfigs, TUint32(-1));
300 EXPORT_C TInt DPcCardSocket::ReadConfigReg(TInt aCardFunc,TInt aRegOffset,TUint8 &aVal)
302 // Read from a specified configuration register. (We return an error if the RegPres mask
303 // indicates the register isn't present but still attempt the read).
307 if (!IsValidCardFunc(aCardFunc)|| iState!=EPBusOn || !Kern::PowerGood())
311 if ((err=iCardFuncArray[aCardFunc]->ConfigRegAddress(aRegOffset,offset))==KErrNone||err==KErrNotSupported)
313 TPccdAccessSpeed sp=(VccSetting()==EPccdSocket_3V3)?EAcSpeed600nS:EAcSpeed300nS;
314 iAttribWin.SetAccessSpeed(sp);
315 iAttribWin.SetupChunkHw();
316 iAttribWin.Read(offset,&aVal,1);
319 __KTRACE_OPT(KPBUS1,Kern::Printf("<Skt(%d):ReadConfigReg-%d",iSocketNumber,err));
323 EXPORT_C TInt DPcCardSocket::WriteConfigReg(TInt aCardFunc,TInt aRegOffset,const TUint8 aVal)
325 // Write to a specified configuration register. (We return an error if the RegPres mask
326 // indicates the register isn't present but still attempt the write).
330 if (!IsValidCardFunc(aCardFunc)|| iState!=EPBusOn || !Kern::PowerGood())
334 if ((err=iCardFuncArray[aCardFunc]->ConfigRegAddress(aRegOffset,offset))==KErrNone||err==KErrNotSupported)
336 TPccdAccessSpeed sp=(VccSetting()==EPccdSocket_3V3)?EAcSpeed600nS:EAcSpeed300nS;
337 iAttribWin.SetAccessSpeed(sp);
338 iAttribWin.SetupChunkHw();
339 iAttribWin.Write(offset,&aVal,1);
342 __KTRACE_OPT(KPBUS1,Kern::Printf("<Skt(%d):WriteConfigReg-%d",iSocketNumber,err));
346 const TInt KReadCisBufferSize=0x80; // 128 Bytes
347 TInt DPcCardSocket::ReadCis(TPccdMemType aMemType,TInt aPos,TDes8 &aDes,TInt aLen)
353 __KTRACE_OPT(KPBUS2,Kern::Printf(">Skt(%d):ReadCis(LE:%xH PO:%d TY:%d)",iSocketNumber,aLen,aPos,aMemType));
355 RPccdWindow* win=&newWin;
356 TBool needNewChunk=ETrue;
357 TInt cisE=(aPos+aLen);
359 if (aMemType==EPccdAttribMem)
361 incrm=2; // Read every other byte
364 if (cisE<=(TInt)KDefaultAttribMemSize)
373 TPccdChnk chnk(aMemType,aPos,(cisE-aPos));
374 TInt r=newWin.Create(this,chnk,EAcSpeed300nS,KPccdChunkShared|KPccdChunkSystemOwned);
381 TPccdAccessSpeed sp=(VccSetting()==EPccdSocket_3V3)?EAcSpeed600nS:EAcSpeed300nS;
382 win->SetAccessSpeed(sp);
385 TText8 buf[KReadCisBufferSize];
387 for (;aPos<cisE;aPos+=s)
389 s=Min(KReadCisBufferSize,(cisE-aPos));
390 win->Read(aPos,&buf[0],s);
391 for (TInt i=0;i<s;i+=incrm)
392 aDes.Append((TChar)buf[i]);
400 TInt DPcCardSocket::AddNewFunc(TUint32 anOffset,TPccdMemType aMemType)
402 // Create a new card function and append it to the function array
406 __KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):AddNewFunc(T:%d)",iSocketNumber,aMemType));
408 TPcCardFunction* cf=new TPcCardFunction(anOffset,aMemType);
411 r=iCardFuncArray.Append(cf);
418 TPcCardFunction *DPcCardSocket::CardFunc(TInt aCardFunc)
420 // Get a reference to a specific card function from the function array
424 __ASSERT_ALWAYS(IsValidCardFunc(aCardFunc),PcCardPanic(EPcCardBadFunctionNumber));
425 return iCardFuncArray[aCardFunc];
428 TBool DPcCardSocket::IsConfigLocked()
430 // Returns ETrue if this socket contains a card function which is currently configured.
434 // for (i=CardFuncCount()-1;i>=0;i--)
436 // if (iCardFuncArray[i]->IsConfigured())
440 return (iActiveConfigs!=0);
443 TBool DPcCardSocket::IsMemoryLocked()
445 // Returns ETrue if any PC Card memory chunks are allocated on this socket.
450 // for (i=iMemChunks.Count()-1;i>=0;i--)
452 // if ( iMemChunks[i]->IsLocked() )
456 return (iClientWindows!=0);
459 TPccdSocketVcc DPcCardSocket::VccSetting()
461 // Return voltage setting that this socket is currently set for
465 return ((DPcCardVcc*)iVcc)->VoltageSetting();
468 EXPORT_C TInt DPcCardSocket::VerifyCard(TPccdType &aType)
470 // Return information about the type of card present
474 __KTRACE_OPT(KPBUS1,Kern::Printf(">Cntrl:VerifyCard(S:%d)",iSocketNumber));
475 // The data we want is stored off-card, so it doesn't actually need to be
476 // powered but we need to have read CIS format.
478 if (CardIsReadyAndVerified()==KErrNone)
480 aType.iFuncCount=CardFuncCount();
481 for (TInt i=(aType.iFuncCount-1);i>=0;i--)
482 aType.iFuncType[i]=CardFunc(i)->FuncType();
487 __KTRACE_OPT(KPBUS1,Kern::Printf("<Cntrl:VerifyCard(S:%d T:%d)-%d",iSocketNumber,(TInt)aType.iFuncType[0],err));
491 TInt DPcCardSocket::CardIsReadyAndVerified()
493 // Returns KErrNone when specified card is powered and ready (ie has had h/w reset) and
494 // a basic parsing of CIS has been performed (card functions detected).
502 // Check if card function(s) have been determined (there is always at
503 // least a global function record if basic parsing performed).
508 __KTRACE_OPT(KPBUS1,Kern::Printf("<Cntrl:CardRdyAndVerif(S:%d)-%xH",iSocketNumber,r));
512 TBool DPcCardSocket::CardIsReady()
514 TBool r=(iState==EPBusOn && Kern::PowerGood());
515 __KTRACE_OPT(KPBUS1,Kern::Printf("CardIsReady: %d",r));
519 TBool DPcCardSocket::CardIsPowered()
521 return !iVcc->IsOff();
524 TInt DPcCardSocket::GetCisFormat()
526 // Determine the type of card present by parsing the entire CIS. If a
527 // Multi-function card is present then parse each CIS.
531 __KTRACE_OPT(KPBUS1,Kern::Printf(">GetCisFormat (S:%d)",iSocketNumber));
533 TInt r=AddNewFunc(0,EPccdAttribMem); // We always have 1st CIS
536 if (ValidateCis(0)!=KErrNone) // Can't use this until func added
540 cisRd.DoSelectCis(0);
541 TPccdFuncType firstFuncType;
542 // Check for a multi-function card, search the global CIS (attribute
543 // memory - addr 0) for a KCisTplLongLinkMfc tuple.
544 TBuf8<KLargeTplBufSize> tpl;
545 if (cisRd.DoFindReadTuple(KCisTplLongLinkMfc,tpl,KPccdReturnLinkTpl)==KErrNone)
547 // Multi-Function card
548 firstFuncType=EGlobalCard;
549 const TUint8 *tplPtr=tpl.Ptr()+2; // First tuple after link
550 TInt funcCount=*tplPtr++;
552 // Add a card function object to the socket for each entry in KCisTplLongLinkMfc tuple
553 TPccdMemType memType;
556 for (i=0;i<funcCount;i++)
558 memType=(*tplPtr++)?EPccdCommon8Mem:EPccdAttribMem;
560 for (lnkAdr=0,j=0;j<4;j++) // Convert link address from string to unsigned long
561 lnkAdr += (*tplPtr++) << (8*j);
562 r=AddNewFunc(lnkAdr,memType);
565 if (ValidateCis(i+1)!=KErrNone) // Can't use this until func added
568 // Parse the CIS of each card function looking for a KCisTplFuncId tuple
569 for (i=1;i<=funcCount;i++)
571 cisRd.DoSelectCis(i);
573 if (cisRd.DoFindReadTuple(KCisTplFuncId,tpl,0)==KErrNone)
577 CardFunc(i)->SetFuncType(ft);
582 // Single Function card
584 if (cisRd.DoFindReadTuple(KCisTplFuncId,tpl,0)==KErrNone)
585 firstFuncType=FuncType(tpl[2]);
587 firstFuncType=EUnknownCard;
590 CardFunc(0)->SetFuncType(firstFuncType);
591 __KTRACE_OPT(KPBUS1,Kern::Printf("<GetCisFormat(T:%d)",firstFuncType));
595 TInt DPcCardSocket::ValidateCis(TInt aCardFunc)
597 // Attempt to walk though entire CIS.
603 TBuf8<KLargeTplBufSize> tpl;
605 if ((err=cisRd.DoSelectCis(aCardFunc))==KErrNone)
607 for (j=0;j<KMaxTuplesPerCis;j++)
609 err=cisRd.DoFindReadTuple(KPccdNonSpecificTpl,tpl,(KPccdFindOnly|KPccdReturnLinkTpl|KPccdReportErrors));
613 if (j>=KMaxTuplesPerCis)
615 if (err==KErrNotFound)
618 __KTRACE_OPT(KPBUS1,Kern::Printf("<Skt:ValidateCis(S:%d F:%d Tuples:%d)-%d",iSocketNumber,aCardFunc,j,err));
622 void DPcCardSocket::InitiatePowerUpSequence()
624 __KTRACE_OPT(KPBUS1,Kern::Printf("DPcCardSocket(%d)::InitiatePowerUpSequence",iSocketNumber));
625 // Check if battery is too low
626 // TSupplyStatus ss=(TSupplyStatus)iMachineInfo.iDisableOnLowBattery;
629 // TSupplyInfoV1 info;
630 // Hal::SupplyInfo(info);
631 // if (info.iMainBatteryStatus<ss && !info.iExternalPowerPresent)
633 // iSocket[aSocket]->SetSocketStatus(ESocketBatTooLow);
639 // Check the state of the Voltage sense line
640 TSocketIndicators ind;
642 TUint v=(TUint)ind.iVoltSense & ((DPcCardVcc*)iVcc)->VoltageSupported();
645 __KTRACE_OPT(KPBUS1,Kern::Printf("InitiatePowerUpSequence(S:%d)-Voltage sense problem(%d)",iSocketNumber,ind.iVoltSense));
646 iVcc->SetCurrLimited(); // Not totally true but has effect.
647 PowerUpSequenceComplete(KErrCorrupt);
650 TPccdSocketVcc sVcc=(v&KPccdVcc_3V3)?EPccdSocket_3V3:EPccdSocket_5V0; // ??? What about xVx / yVy
651 ((DPcCardVcc*)iVcc)->SetVoltage(sVcc);
653 // Power up card (current limited).
654 __KTRACE_OPT(KPBUS1,Kern::Printf("InitiatePowerUpSequence(S:%d)-Apply Vcc",iSocketNumber));
655 if (iVcc->SetState(EPsuOnCurLimit) != KErrNone)
657 __KTRACE_OPT(KPBUS1,Kern::Printf("InitiatePowerUpSequence(S:%d)-Vcc problem",iSocketNumber));
658 iVcc->SetState(EPsuOff);
659 iVcc->SetCurrLimited();
660 PowerUpSequenceComplete(KErrGeneral);
663 iCardPowerUpState=EInit;
664 iCardPowerUpTickCount=0;
665 iCardPowerUpResetLen=KResetOnDefaultLen;
666 iCardPowerUpPauseLen=KResetOffDefaultLen;
667 iCardPowerUpTimer.Periodic(KPccdPowerUpReqInterval,cardPowerUpTick,this);
670 void DPcCardSocket::TerminatePowerUpSequence(TInt aResult)
672 __KTRACE_OPT(KPBUS1,Kern::Printf("DPcCardSocket(%d)::TerminatePowerUpSequence result %d",iSocketNumber,aResult));
674 if (aResult==KErrNone)
676 PowerUpSequenceComplete(aResult);
679 void DPcCardSocket::CardPowerUpTick()
681 __KTRACE_OPT(KPBUS1,Kern::Printf("CardPowerUpTick S:%d Elapsed %d State %d",iSocketNumber,iCardPowerUpTickCount,iCardPowerUpState));
682 if (++iCardPowerUpTickCount>KPwrUpTimeOut)
684 iVcc->SetState(EPsuOff); // should leave this to timeout
685 TerminatePowerUpSequence(KErrTimedOut);
688 switch (iCardPowerUpState)
691 HwReset(ETrue); // Apply reset - Turns on interface
692 iCardPowerUpState=EApplyingReset;
695 if (iCardPowerUpTickCount>iCardPowerUpResetLen)
697 HwReset(EFalse); // remove reset
698 iCardPowerUpState=ECheckVcc;
703 iCardPowerUpState=EWaitForVccReading;
704 TInt cv=iVcc->CheckVoltage(KPsuChkOnPwrUp);
705 if (cv==KErrNotSupported)
706 iCardPowerUpState=EWaitForReady;
707 else if (cv!=KErrNone)
708 TerminatePowerUpSequence(cv);
711 case EWaitForVccReading:
716 iCardPowerUpState=EPauseAfterReady; // Card is ready
717 // Its effectively powered up now so reset the elapsed time and use it
718 // to measure pause after reset (ie this is limited to KPwrUpTimeOut too).
719 iCardPowerUpTickCount=0;
722 case EPauseAfterReady:
723 if (iCardPowerUpTickCount>=iCardPowerUpPauseLen)
725 // power-up sequence is complete
726 TerminatePowerUpSequence(KErrNone);
732 /********************************************
733 * PC card memory chunk
734 ********************************************/
735 DPccdChunkBase::DPccdChunkBase()
741 // iCacheable=EFalse;
744 TInt DPccdChunkBase::Create(DPcCardSocket* aSocket, TPccdChnk aChunk, TUint aFlag)
746 // Create a chunk of Pc Card h/w.
751 iCacheable=(aFlag&KPccdChunkCacheable);
752 return DoCreate(aChunk,aFlag);
755 DPccdChunkBase::~DPccdChunkBase()
760 __KTRACE_OPT(KPBUS1,Kern::Printf(">DPccdChunkBase destruct %08x",this));
763 void DPccdChunkBase::Close()
768 __KTRACE_OPT(KPBUS1,Kern::Printf(">DPccdChunkBase::Close() %08x",this));
770 // Disconnect all the Pc Card windows and then delete chunk
771 SDblQueLink* pW=iWindowQ.iA.iNext;
772 while (pW!=&iWindowQ.iA)
774 RPccdWindow& w=*(RPccdWindow*)pW;
776 w.Close(); // closing last window deletes chunk
778 __KTRACE_OPT(KPBUS1,Kern::Printf("<DPccdChunkBase::Close() %08x",this));
781 TBool DPccdChunkBase::IsRemovable()
783 // Check if this chunk has any permanent windows.
786 return (iPermanentWindows==0);
789 TBool DPccdChunkBase::IsLocked()
791 // Check if this chunk has any windows which are allocated to clients of the PC Card
792 // Controller (as opposed to the Controller itself).
795 return (iWindows>iSystemWindows);
798 TInt DPccdChunkBase::AllocateWinCheck(TPccdChnk aWin,TUint aFlag)
800 // Check if it is possible to create the specified window from this chunk.
803 // Check if they are of compatible type
804 if (!IsTypeCompatible(aWin.iMemType))
805 return(KErrNotFound);
807 // For a success, the requested window must lie entirely within this chunk.
808 TUint32 chnkEnd=(iChnk.iMemBaseAddr+iChnk.iMemLen-1);
809 TUint32 winEnd=(aWin.iMemBaseAddr+aWin.iMemLen-1);
810 TBool startIsInChnk=(aWin.iMemBaseAddr>=iChnk.iMemBaseAddr && aWin.iMemBaseAddr<=chnkEnd);
811 TBool endIsInChnk=(winEnd>=iChnk.iMemBaseAddr && winEnd<=chnkEnd);
812 if (startIsInChnk&&endIsInChnk)
814 // Possible success - first check the cache options are compatible
815 if (!(aFlag|KPccdChunkCacheable)&&iCacheable)
816 return(KErrAccessDenied);
818 // Now check that the requested window isn't already allocated
819 SDblQueLink* pW=iWindowQ.iA.iNext;
820 while (pW!=&iWindowQ.iA)
822 RPccdWindow& w=*(RPccdWindow*)pW;
824 if (w.Overlap(aWin.iMemBaseAddr-iChnk.iMemBaseAddr,aWin.iMemLen) )
825 return(KErrAccessDenied);
829 if (startIsInChnk||endIsInChnk)
830 return(KErrAccessDenied); // Requested window is partly in this chunk.
831 return(KErrNotFound);
834 void DPccdChunkBase::AddWindow(RPccdWindow *aWindow)
836 // Add a window to this chunk.
839 iWindowQ.Add(aWindow);
840 // Kern::EnterCS(); Not needed since a single thread is used
842 if (aWindow->IsPermanent())
844 if (aWindow->IsShareable())
846 if (aWindow->IsSystemOwned())
849 iSocket->iClientWindows++;
851 aWindow->iChunk=this;
854 void DPccdChunkBase::RemoveWindow(RPccdWindow *aWindow)
856 // Remove a window from this chunk (even if it's permanent).
860 if (aWindow->iNext && aWindow->iChunk==this)
864 // Kern::EnterCS(); Not needed since a single thread is used
866 if (aWindow->IsPermanent())
868 if (aWindow->IsShareable())
870 if (aWindow->IsSystemOwned())
873 iSocket->iClientWindows--;
877 iSocket->RemoveChunk(this);
883 /********************************************
884 * PC card memory window
885 ********************************************/
886 EXPORT_C RPccdWindow::RPccdWindow()
890 : iAccessSpeed(EAcSpeedInValid),iMemType(EPccdAttribMem),iOffset(0),iLen(0),iType(0)
896 EXPORT_C TInt RPccdWindow::Create(DPcCardSocket* aSocket, TPccdChnk aChnk, TPccdAccessSpeed aSpeed, TUint aFlag)
898 // Create a block of memory (IO, Common or Attribute memory).
902 DPccdChunkBase *chunk=NULL;
903 TBool chunkExists=EFalse;
906 // See if requested window is actually part of a chunk already created
908 for (i=0;i<aSocket->iMemChunks.Count();i++)
910 if ((r=aSocket->iMemChunks[i]->AllocateWinCheck(aChnk,aFlag))==KErrNone)
912 chunk=aSocket->iMemChunks[i];
916 if (r==KErrAccessDenied)
920 // If necesary, create a chunk
923 // Create the memory chunk
924 chunk=aSocket->NewPccdChunk(aChnk.iMemType);
927 TInt r=chunk->Create(aSocket, aChnk, aFlag);
929 r=aSocket->iMemChunks.Append(chunk);
936 __KTRACE_OPT(KPBUS2,Kern::Printf("Skt:CreateMemWindowL-got chunk(existing-%d)",chunkExists));
938 // Create the memory window
939 iOffset=aChnk.iMemBaseAddr-chunk->BaseAddr();
942 iMemType=aChnk.iMemType;
943 iWaitSig=(aFlag&KPccdRequestWait);
944 iType=aFlag&(KPccdChunkShared|KPccdChunkPermanent|KPccdChunkSystemOwned); // Save flag settings
945 chunk->AddWindow(this);
946 __KTRACE_OPT(KPBUS2,Kern::Printf("Skt:CreateMemWindowL-created window"));
950 EXPORT_C void RPccdWindow::Close()
953 iChunk->RemoveWindow(this);
956 EXPORT_C TInt RPccdWindow::SetupChunkHw(TUint aFlag)
958 // Config h/w in preparation for accessing window. Flag is for platform dependant info.
963 return(KErrNotReady);
964 iChunk->SetupChunkHw(iAccessSpeed,iMemType,iWaitSig,aFlag);
965 // iVcc->ResetInactivityTimer();
969 EXPORT_C TLinAddr RPccdWindow::LinearAddress()
971 // Return linear address of window
974 return iChunk->LinearAddress()+iOffset;
977 TBool RPccdWindow::Overlap(TUint32 anOffset,TUint aLen)
982 // If this window is sharable then it doesn't matter if they overlap or not.
986 TUint32 winEnd=(anOffset+aLen-1);
987 TUint32 thisEnd=(iOffset+iLen-1);
988 if ((anOffset>=iOffset && anOffset<=thisEnd) ||
989 (winEnd>=iOffset && winEnd<=thisEnd) )