os/kernelhwsrv/kernel/eka/drivers/pbus/pccard/socket.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32\drivers\pbus\pccard\socket.cpp
    15 // 
    16 //
    17 
    18 #include <pccard.h>
    19 #include "cis.h"
    20 
    21 const TInt KFuncGranularity=(KMaxFuncPerCard+1);
    22 const TInt KMemGranularity=2;
    23 
    24 TPccdFuncType FuncType(TUint aFuncCode)
    25 	{
    26 
    27 	if (aFuncCode<=KCisTplFuncIdScsi)
    28 		return((TPccdFuncType)(aFuncCode+1));
    29 	else if (aFuncCode==KCisTplFuncIdVendorSpecific)
    30 		return(EVendorSpecificCard);
    31 	else
    32 		return(EUnknownCard);
    33 	}
    34 
    35 /********************************************
    36  * PC card power supply
    37  ********************************************/
    38 DPcCardVcc::DPcCardVcc(TInt aPsuNum, TInt aMediaChangeNum)
    39 	:	DPBusPsuBase(aPsuNum, aMediaChangeNum)
    40 	{
    41 	}
    42 
    43 TInt DPcCardVcc::SocketVccToMilliVolts(TPccdSocketVcc aVcc)
    44 //
    45 // Converts a TPccdSocketVcc into a integer value - units mV.
    46 //
    47 	{
    48 	switch (aVcc)
    49 		{
    50 		case EPccdSocket_5V0: return(5000);
    51 		case EPccdSocket_3V3: return(3300);
    52 		default: return(0);
    53 		}
    54 	}
    55 
    56 TBool DPcCardVcc::IsLocked()
    57 	{
    58 /*	TInt i;
    59 	Kern::EnterCS();
    60 	for (i=0; i<KMaxPccdSockets; i++)
    61 		{
    62 		DPcCardSocket* pS=(DPcCardSocket*)TheSockets[i];
    63 		if (pS && pS->iVcc==this)
    64 			{
    65 			if (pS->iClientWindows || pS->iActiveConfigs)
    66 				break;
    67 			}
    68 		}
    69 	Kern::LeaveCS();
    70 	return (i<KMaxPccdSockets);
    71 */
    72 	DPcCardSocket* pS=(DPcCardSocket*)iSocket;
    73 	return (pS->iClientWindows || pS->iActiveConfigs);
    74 	}
    75 
    76 void DPcCardVcc::ReceiveVoltageCheckResult(TInt anError)
    77 	{
    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)
    82 		{
    83 		if (anError==KErrNone)
    84 			{
    85 			SetState(EPsuOnFull);
    86 			pS->iCardPowerUpState=DPcCardSocket::EWaitForReady;
    87 			}
    88 		else
    89 			pS->TerminatePowerUpSequence(KErrCorrupt);
    90 		}
    91 	else if (s!=DPcCardSocket::EInit && s!=DPcCardSocket::EApplyingReset && s!=DPcCardSocket::ECheckVcc)
    92 		DPBusPsuBase::ReceiveVoltageCheckResult(anError);
    93 	}
    94 
    95 /********************************************
    96  * PC card media change
    97  ********************************************/
    98 DPcCardMediaChange::DPcCardMediaChange(TInt aMediaChangeNum)
    99 	: DMediaChangeBase(aMediaChangeNum)
   100 	{
   101 	}
   102 
   103 TInt DPcCardMediaChange::Create()
   104 	{
   105 	return DMediaChangeBase::Create();
   106 	}
   107 
   108 /********************************************
   109  * PC card socket
   110  ********************************************/
   111 void cardPowerUpTick(TAny* aPtr)
   112 	{
   113 	((DPcCardSocket*)aPtr)->iCardPowerUpDfc.Enque();
   114 	}
   115 
   116 void cardPowerUpDfc(TAny* aPtr)
   117 	{
   118 	((DPcCardSocket*)aPtr)->CardPowerUpTick();
   119 	}
   120 
   121 DPcCardSocket::DPcCardSocket(TSocket aSocketNum)
   122 //
   123 // Constructor.
   124 //
   125 	:	DPBusSocket(aSocketNum),
   126 		iCardFuncArray(KFuncGranularity),
   127 		iMemChunks(KMemGranularity),
   128 		iCardPowerUpDfc(cardPowerUpDfc, this, 1)
   129 	{
   130 
   131 	iType=EPBusTypePcCard;
   132 //	iCardPowerUpState=EIdle;
   133 //	iClientWindows=0;
   134 //	iActiveConfigs=0;
   135 	}
   136 
   137 TInt DPcCardSocket::Create(const TDesC* aName)
   138 //
   139 // Create a new Socket. Only created once on kernel initialization so don't
   140 // worry about cleanup if it fails.
   141 //
   142 	{
   143 
   144 	__KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):Create(%lS)",iSocketNumber,aName));
   145 
   146 	TInt r=DPBusSocket::Create(aName);
   147 	if (r!=KErrNone)
   148 		return r;
   149 	iCardPowerUpDfc.SetDfcQ(&iDfcQ);
   150 
   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
   154 	if (r!=KErrNone)
   155 		return r;
   156 	delete iCardFuncArray[0];					// Destroy dummy function
   157 	iCardFuncArray.Remove(0);					// Remove pointer to dummy from array
   158 
   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);
   163 	return r;
   164 	}
   165 
   166 void DPcCardSocket::ResetPowerUpState()
   167 	{
   168 	__KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):ResetPowerUpState",iSocketNumber));
   169 	if (iCardPowerUpState!=EIdle)
   170 		{
   171 		iCardPowerUpTimer.Cancel();
   172 		iCardPowerUpDfc.Cancel();
   173 		iCardPowerUpState=EIdle;
   174 		}
   175 	}
   176 
   177 void DPcCardSocket::Reset1()
   178 	{
   179 	__KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):Reset1",iSocketNumber));
   180 	ResetPowerUpState();
   181 	}
   182 
   183 void DPcCardSocket::Reset2()
   184 //
   185 // Reset the socket (called to remove any allocated memory following a
   186 // media change event).
   187 //
   188 	{
   189 
   190 	__KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):Rst2",iSocketNumber));
   191 	// Destroy all the function objects
   192 	TInt i;
   193 	for (i=CardFuncCount()-1;i>=0;i--)
   194 		{
   195 		delete iCardFuncArray[i];
   196 		iCardFuncArray.Remove(i);		// Now remove from array (doesn't cause memory dealloc).
   197 		}
   198 	iActiveConfigs=0;
   199 
   200 	// Destroy all the non-permanent Pc Card chunks
   201 	for (i=(iMemChunks.Count()-1);i>=0;i--)
   202 		{
   203 		if ( iMemChunks[i]->IsRemovable() )
   204 			iMemChunks[i]->Close();
   205 		}
   206 	iMemChunks.Compress();
   207 	}
   208 
   209 void DPcCardSocket::Restore()
   210 //
   211 // Restore the socket. Normally called when restoring a socket after it has been powered 
   212 // down due to inactivity (but not media change)
   213 //
   214 	{	
   215 	TInt i;
   216 	TPcCardFunction *cf;
   217 	for (i=CardFuncCount()-1;i>=0;i--)
   218 		{
   219 		cf=iCardFuncArray[i];
   220 
   221 		TUint8 index;
   222 		if ((index=(TUint8)cf->ConfigOption())!=KInvalidConfOpt && cf->IsRestorableConfig())
   223 			WriteConfigReg(i,KConfigOptionReg,index);
   224 		}
   225 	}
   226 
   227 void DPcCardSocket::RemoveChunk(DPccdChunkBase *aChunk)
   228 //
   229 // Remove a chunk from this socket. 
   230 //	
   231 	{
   232 	TInt i;
   233 	for (i=0;i<iMemChunks.Count();i++)
   234 		{
   235 		if (iMemChunks[i]==aChunk)
   236 			{
   237 			iMemChunks.Remove(i);
   238 			iMemChunks.Compress();
   239 			return;
   240 			}
   241 		}
   242 	}
   243 
   244 EXPORT_C TInt DPcCardSocket::RequestConfig(TInt aCardFunc,DBase *aClientID,TPcCardConfig &anInfo,TUint aFlag)
   245 //
   246 // Configure the card.
   247 //
   248 	{
   249 
   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.
   258 
   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);
   269 
   270 	cf->SetConfigRegMask(anInfo.iRegPresent);
   271 	cf->SetConfigBaseAddr(anInfo.iConfigBaseAddr);
   272 	cf->SetConfigOption(anInfo.iConfigOption,aClientID,aFlag);
   273 	__e32_atomic_add_ord32(&iActiveConfigs, 1);
   274 	return(KErrNone);
   275 	}
   276 
   277 EXPORT_C void DPcCardSocket::ReleaseConfig(TInt aCardFunc,DBase *aClientID)
   278 //
   279 // Return card to memory only config.
   280 //
   281 	{
   282 
   283 	__KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):ReleaseConfig(F:%d)",iSocketNumber,aCardFunc));
   284 	if (IsValidCardFunc(aCardFunc))
   285 		{
   286 		TPcCardFunction *cf=iCardFuncArray[aCardFunc];
   287 		if (cf->IsConfiguredByClient(aClientID))
   288 			{
   289 			if (iState==EPBusOn && Kern::PowerGood())
   290 				WriteConfigReg(aCardFunc,KConfigOptionReg,0); // Restore Config. Option register
   291 
   292 			cf->SetConfigRegMask(0);
   293 			cf->SetConfigBaseAddr(0);	
   294 			cf->SetConfigOption(KInvalidConfOpt,NULL,0);
   295 			__e32_atomic_add_ord32(&iActiveConfigs, TUint32(-1));
   296 			}
   297 		}
   298 	}
   299 
   300 EXPORT_C TInt DPcCardSocket::ReadConfigReg(TInt aCardFunc,TInt aRegOffset,TUint8 &aVal)
   301 //
   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).
   304 //
   305 	{
   306 	TInt offset, err;
   307 	if (!IsValidCardFunc(aCardFunc)|| iState!=EPBusOn || !Kern::PowerGood())
   308 		err=KErrArgument;
   309 	else
   310 		{
   311 		if ((err=iCardFuncArray[aCardFunc]->ConfigRegAddress(aRegOffset,offset))==KErrNone||err==KErrNotSupported)
   312 			{
   313 			TPccdAccessSpeed sp=(VccSetting()==EPccdSocket_3V3)?EAcSpeed600nS:EAcSpeed300nS;
   314 			iAttribWin.SetAccessSpeed(sp);
   315 			iAttribWin.SetupChunkHw();
   316 			iAttribWin.Read(offset,&aVal,1);
   317 			}
   318 		}
   319 	__KTRACE_OPT(KPBUS1,Kern::Printf("<Skt(%d):ReadConfigReg-%d",iSocketNumber,err));
   320 	return(err);
   321 	}
   322 
   323 EXPORT_C TInt DPcCardSocket::WriteConfigReg(TInt aCardFunc,TInt aRegOffset,const TUint8 aVal)
   324 //
   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).
   327 //
   328 	{
   329 	TInt offset, err;
   330 	if (!IsValidCardFunc(aCardFunc)|| iState!=EPBusOn || !Kern::PowerGood())
   331 		err=KErrArgument;
   332 	else
   333 		{
   334 		if ((err=iCardFuncArray[aCardFunc]->ConfigRegAddress(aRegOffset,offset))==KErrNone||err==KErrNotSupported)
   335 			{
   336 			TPccdAccessSpeed sp=(VccSetting()==EPccdSocket_3V3)?EAcSpeed600nS:EAcSpeed300nS;
   337 			iAttribWin.SetAccessSpeed(sp);
   338 			iAttribWin.SetupChunkHw();
   339 			iAttribWin.Write(offset,&aVal,1);
   340 			}
   341 		}
   342 	__KTRACE_OPT(KPBUS1,Kern::Printf("<Skt(%d):WriteConfigReg-%d",iSocketNumber,err));
   343 	return(err);
   344 	}
   345 
   346 const TInt KReadCisBufferSize=0x80;   // 128 Bytes
   347 TInt DPcCardSocket::ReadCis(TPccdMemType aMemType,TInt aPos,TDes8 &aDes,TInt aLen)
   348 //
   349 // Read from CIS 
   350 //
   351 	{
   352 
   353 	__KTRACE_OPT(KPBUS2,Kern::Printf(">Skt(%d):ReadCis(LE:%xH PO:%d TY:%d)",iSocketNumber,aLen,aPos,aMemType));
   354 	RPccdWindow newWin;
   355 	RPccdWindow* win=&newWin;
   356 	TBool needNewChunk=ETrue;
   357 	TInt cisE=(aPos+aLen);
   358 	TInt incrm=1;
   359 	if (aMemType==EPccdAttribMem)
   360 		{
   361 		incrm=2;		// Read every other byte
   362 		cisE<<=1;		
   363 		aPos<<=1;
   364 		if (cisE<=(TInt)KDefaultAttribMemSize)
   365 			{
   366 			needNewChunk=EFalse;
   367 			win=&iAttribWin;
   368 			}
   369 		}
   370 
   371 	if (needNewChunk)
   372 		{
   373 		TPccdChnk chnk(aMemType,aPos,(cisE-aPos));
   374 		TInt r=newWin.Create(this,chnk,EAcSpeed300nS,KPccdChunkShared|KPccdChunkSystemOwned);
   375 		if (r!=KErrNone)
   376 			return(r);
   377 		cisE-=aPos;
   378 		aPos=0;
   379 		}
   380 
   381 	TPccdAccessSpeed sp=(VccSetting()==EPccdSocket_3V3)?EAcSpeed600nS:EAcSpeed300nS;
   382 	win->SetAccessSpeed(sp);
   383 	win->SetupChunkHw();
   384 	aDes.Zero();
   385 	TText8 buf[KReadCisBufferSize];
   386 	TInt s;
   387 	for (;aPos<cisE;aPos+=s)
   388 		{
   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]);   
   393 		} 
   394 
   395 	if (needNewChunk)
   396 		newWin.Close();
   397 	return(KErrNone);
   398 	}
   399 
   400 TInt DPcCardSocket::AddNewFunc(TUint32 anOffset,TPccdMemType aMemType)
   401 //
   402 // Create a new card function and append it to the function array
   403 //
   404 	{
   405 
   406 	__KTRACE_OPT(KPBUS1,Kern::Printf(">Skt(%d):AddNewFunc(T:%d)",iSocketNumber,aMemType));
   407 	TInt r=KErrNoMemory;
   408 	TPcCardFunction* cf=new TPcCardFunction(anOffset,aMemType);
   409 	if (cf)
   410 		{
   411 		r=iCardFuncArray.Append(cf);
   412 		if (r!=KErrNone)
   413 			delete cf;
   414 		}
   415 	return r;
   416 	}
   417 
   418 TPcCardFunction *DPcCardSocket::CardFunc(TInt aCardFunc)
   419 // 
   420 // Get a reference to a specific card function from the function array 
   421 //
   422 	{
   423 												   
   424 	__ASSERT_ALWAYS(IsValidCardFunc(aCardFunc),PcCardPanic(EPcCardBadFunctionNumber));
   425 	return iCardFuncArray[aCardFunc];
   426 	}
   427 
   428 TBool DPcCardSocket::IsConfigLocked()
   429 //
   430 // Returns ETrue if this socket contains a card function which is currently configured.
   431 //
   432 	{
   433 //	TInt i;
   434 //	for (i=CardFuncCount()-1;i>=0;i--)
   435 //		{
   436 //		if (iCardFuncArray[i]->IsConfigured())
   437 //			return(ETrue);
   438 //		}
   439 //	return(EFalse);
   440 	return (iActiveConfigs!=0);
   441 	}
   442 
   443 TBool DPcCardSocket::IsMemoryLocked()
   444 //
   445 // Returns ETrue if any PC Card memory chunks are allocated on this socket.
   446 //
   447 	{
   448 
   449 //	TInt i;
   450 //	for (i=iMemChunks.Count()-1;i>=0;i--)
   451 //		{
   452 //		if ( iMemChunks[i]->IsLocked() )
   453 //			return(ETrue);
   454 //		}
   455 //	return(EFalse);
   456 	return (iClientWindows!=0);
   457 	}
   458 
   459 TPccdSocketVcc DPcCardSocket::VccSetting()
   460 //
   461 // Return voltage setting that this socket is currently set for
   462 //
   463 	{
   464 
   465 	return ((DPcCardVcc*)iVcc)->VoltageSetting();
   466 	}
   467 
   468 EXPORT_C TInt DPcCardSocket::VerifyCard(TPccdType &aType)
   469 //
   470 // Return information about the type of card present 
   471 //
   472 	{
   473 
   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.
   477 	TInt err=KErrNone;
   478     if (CardIsReadyAndVerified()==KErrNone)
   479 		{
   480 		aType.iFuncCount=CardFuncCount();
   481 		for (TInt i=(aType.iFuncCount-1);i>=0;i--)
   482 			aType.iFuncType[i]=CardFunc(i)->FuncType();
   483 		}
   484 	else
   485 		err=KErrNotReady;
   486 
   487 	__KTRACE_OPT(KPBUS1,Kern::Printf("<Cntrl:VerifyCard(S:%d T:%d)-%d",iSocketNumber,(TInt)aType.iFuncType[0],err));
   488 	return(err);
   489 	}
   490 
   491 TInt DPcCardSocket::CardIsReadyAndVerified()
   492 //
   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).
   495 //
   496 	{
   497 
   498 	TInt r=KErrNotReady;
   499 	if (CardIsReady())
   500 		{
   501 		r=KErrNone;
   502 		// Check if card function(s) have been determined (there is always at
   503 		// least a global function record if basic parsing performed).
   504 		if (!IsVerified())
   505 			r=GetCisFormat();
   506 		}
   507 
   508 	__KTRACE_OPT(KPBUS1,Kern::Printf("<Cntrl:CardRdyAndVerif(S:%d)-%xH",iSocketNumber,r));
   509 	return r;
   510 	}
   511 
   512 TBool DPcCardSocket::CardIsReady()
   513 	{
   514 	TBool r=(iState==EPBusOn && Kern::PowerGood());
   515 	__KTRACE_OPT(KPBUS1,Kern::Printf("CardIsReady: %d",r));
   516 	return r;
   517 	}
   518 
   519 TBool DPcCardSocket::CardIsPowered()
   520 	{
   521 	return !iVcc->IsOff();
   522 	}
   523 
   524 TInt DPcCardSocket::GetCisFormat()
   525 //
   526 // Determine the type of card present by parsing the entire CIS. If a 
   527 // Multi-function card is present then parse each CIS.
   528 //
   529 	{
   530 
   531 	__KTRACE_OPT(KPBUS1,Kern::Printf(">GetCisFormat (S:%d)",iSocketNumber));
   532 
   533 	TInt r=AddNewFunc(0,EPccdAttribMem);		// We always have 1st CIS
   534 	if (r!=KErrNone)
   535 		return r;
   536 	if (ValidateCis(0)!=KErrNone)				// Can't use this until func added
   537 		return KErrCorrupt;
   538 	TCisReader cisRd;
   539 	cisRd.iSocket=this;
   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)
   546 		{
   547 		// Multi-Function card 
   548 		firstFuncType=EGlobalCard;
   549 		const TUint8 *tplPtr=tpl.Ptr()+2; // First tuple after link
   550 		TInt funcCount=*tplPtr++;
   551 
   552 		// Add a card function object to the socket for each entry in KCisTplLongLinkMfc tuple
   553 		TPccdMemType memType;
   554 		TUint32 lnkAdr;
   555 		TInt i;
   556 		for (i=0;i<funcCount;i++)
   557 			{
   558 			memType=(*tplPtr++)?EPccdCommon8Mem:EPccdAttribMem;
   559 			TInt j;
   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);
   563 			if (r!=KErrNone)
   564 				return r;
   565 			if (ValidateCis(i+1)!=KErrNone) // Can't use this until func added
   566 				return KErrCorrupt;
   567 			}
   568 		// Parse the CIS of each card function looking for a KCisTplFuncId tuple
   569 		for (i=1;i<=funcCount;i++)
   570 			{
   571 			cisRd.DoSelectCis(i);
   572 			TPccdFuncType ft;
   573 			if (cisRd.DoFindReadTuple(KCisTplFuncId,tpl,0)==KErrNone)
   574 				ft=FuncType(tpl[2]);
   575 			else
   576 				ft=EUnknownCard;
   577 			CardFunc(i)->SetFuncType(ft);
   578 			}
   579 		}
   580 	else
   581 		{
   582 		// Single Function card 
   583 		cisRd.Restart();
   584 		if (cisRd.DoFindReadTuple(KCisTplFuncId,tpl,0)==KErrNone)
   585 			firstFuncType=FuncType(tpl[2]); 
   586 		else
   587 			firstFuncType=EUnknownCard; 
   588 		}
   589 
   590 	CardFunc(0)->SetFuncType(firstFuncType);
   591 	__KTRACE_OPT(KPBUS1,Kern::Printf("<GetCisFormat(T:%d)",firstFuncType));
   592 	return KErrNone;
   593 	}
   594 
   595 TInt DPcCardSocket::ValidateCis(TInt aCardFunc)
   596 //
   597 // Attempt to walk though entire CIS.
   598 //
   599 	{
   600 
   601 	TCisReader cisRd;
   602 	cisRd.iSocket=this;
   603 	TBuf8<KLargeTplBufSize> tpl;
   604 	TInt j=0,err;
   605 	if ((err=cisRd.DoSelectCis(aCardFunc))==KErrNone)
   606 		{
   607 		for (j=0;j<KMaxTuplesPerCis;j++)
   608 			{
   609 			err=cisRd.DoFindReadTuple(KPccdNonSpecificTpl,tpl,(KPccdFindOnly|KPccdReturnLinkTpl|KPccdReportErrors));
   610 			if (err!=KErrNone)
   611 				break;
   612 			}
   613 		if (j>=KMaxTuplesPerCis)
   614 			err=KErrCorrupt;
   615 		if (err==KErrNotFound)
   616 			err=KErrNone;
   617 		}
   618 	__KTRACE_OPT(KPBUS1,Kern::Printf("<Skt:ValidateCis(S:%d F:%d Tuples:%d)-%d",iSocketNumber,aCardFunc,j,err));
   619 	return(err);
   620 	}
   621 
   622 void DPcCardSocket::InitiatePowerUpSequence()
   623 	{
   624 	__KTRACE_OPT(KPBUS1,Kern::Printf("DPcCardSocket(%d)::InitiatePowerUpSequence",iSocketNumber));
   625 	// Check if battery is too low
   626 //	TSupplyStatus ss=(TSupplyStatus)iMachineInfo.iDisableOnLowBattery;
   627 //	if (ss!=EZero)
   628 //		{
   629 //		TSupplyInfoV1 info;
   630 //		Hal::SupplyInfo(info); 
   631 //		if (info.iMainBatteryStatus<ss && !info.iExternalPowerPresent)
   632 //			{
   633 //			iSocket[aSocket]->SetSocketStatus(ESocketBatTooLow);
   634 //			rs=KErrBadPower;
   635 //			break;
   636 //			}
   637 //		}
   638 
   639 	// Check the state of the Voltage sense line
   640 	TSocketIndicators ind;
   641 	Indicators(ind);
   642 	TUint v=(TUint)ind.iVoltSense & ((DPcCardVcc*)iVcc)->VoltageSupported();
   643 	if (v==0)
   644 		{
   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);
   648 		return;
   649 		}
   650 	TPccdSocketVcc sVcc=(v&KPccdVcc_3V3)?EPccdSocket_3V3:EPccdSocket_5V0; // ??? What about xVx / yVy 
   651 	((DPcCardVcc*)iVcc)->SetVoltage(sVcc);
   652 
   653 	// Power up card (current limited).
   654 	__KTRACE_OPT(KPBUS1,Kern::Printf("InitiatePowerUpSequence(S:%d)-Apply Vcc",iSocketNumber));
   655 	if (iVcc->SetState(EPsuOnCurLimit) != KErrNone)
   656 		{
   657 		__KTRACE_OPT(KPBUS1,Kern::Printf("InitiatePowerUpSequence(S:%d)-Vcc problem",iSocketNumber));
   658 		iVcc->SetState(EPsuOff);
   659 		iVcc->SetCurrLimited();
   660 		PowerUpSequenceComplete(KErrGeneral);
   661 		return;
   662 		}
   663 	iCardPowerUpState=EInit;
   664 	iCardPowerUpTickCount=0;
   665 	iCardPowerUpResetLen=KResetOnDefaultLen;
   666 	iCardPowerUpPauseLen=KResetOffDefaultLen;
   667 	iCardPowerUpTimer.Periodic(KPccdPowerUpReqInterval,cardPowerUpTick,this);
   668 	}
   669 
   670 void DPcCardSocket::TerminatePowerUpSequence(TInt aResult)
   671 	{
   672 	__KTRACE_OPT(KPBUS1,Kern::Printf("DPcCardSocket(%d)::TerminatePowerUpSequence result %d",iSocketNumber,aResult));
   673 	ResetPowerUpState();
   674 	if (aResult==KErrNone)
   675 		Restore();
   676 	PowerUpSequenceComplete(aResult);
   677 	}
   678 
   679 void DPcCardSocket::CardPowerUpTick()
   680 	{
   681 	__KTRACE_OPT(KPBUS1,Kern::Printf("CardPowerUpTick S:%d Elapsed %d State %d",iSocketNumber,iCardPowerUpTickCount,iCardPowerUpState));
   682 	if (++iCardPowerUpTickCount>KPwrUpTimeOut)
   683 		{
   684 		iVcc->SetState(EPsuOff);	// should leave this to timeout
   685 		TerminatePowerUpSequence(KErrTimedOut);
   686 		return;
   687 		}
   688 	switch (iCardPowerUpState)
   689 		{
   690 		case EInit:
   691 			HwReset(ETrue);		// Apply reset - Turns on interface
   692 			iCardPowerUpState=EApplyingReset;
   693 			break;
   694 		case EApplyingReset:
   695 			if (iCardPowerUpTickCount>iCardPowerUpResetLen)
   696 				{
   697 				HwReset(EFalse);	// remove reset
   698 				iCardPowerUpState=ECheckVcc;
   699 				}
   700 			break;
   701 		case ECheckVcc:
   702 			{
   703 			iCardPowerUpState=EWaitForVccReading;
   704 			TInt cv=iVcc->CheckVoltage(KPsuChkOnPwrUp);
   705 			if (cv==KErrNotSupported)
   706 				iCardPowerUpState=EWaitForReady;
   707 			else if (cv!=KErrNone)
   708 				TerminatePowerUpSequence(cv);
   709 			break;
   710 			}
   711 		case EWaitForVccReading:
   712 			break;
   713 		case EWaitForReady:
   714 			if (Ready())
   715 				{
   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;
   720 				}
   721 			break;
   722 		case EPauseAfterReady:
   723 			if (iCardPowerUpTickCount>=iCardPowerUpPauseLen)
   724 				{
   725 				// power-up sequence is complete
   726 				TerminatePowerUpSequence(KErrNone);
   727 				}
   728 			break;
   729 		}
   730 	}
   731 
   732 /********************************************
   733  * PC card memory chunk
   734  ********************************************/
   735 DPccdChunkBase::DPccdChunkBase()
   736 //
   737 // Constructor
   738 //
   739 	{
   740 //	iSocket=NULL;
   741 //	iCacheable=EFalse;
   742 	}
   743 
   744 TInt DPccdChunkBase::Create(DPcCardSocket* aSocket, TPccdChnk aChunk, TUint aFlag)
   745 //
   746 // Create a chunk of Pc Card h/w.
   747 //
   748 	{
   749 	iSocket=aSocket;
   750 	iChnk=aChunk;
   751 	iCacheable=(aFlag&KPccdChunkCacheable);
   752 	return DoCreate(aChunk,aFlag);
   753 	}
   754 
   755 DPccdChunkBase::~DPccdChunkBase()
   756 //
   757 // Destructor
   758 //
   759 	{
   760 	__KTRACE_OPT(KPBUS1,Kern::Printf(">DPccdChunkBase destruct %08x",this));
   761 	}
   762 
   763 void DPccdChunkBase::Close()
   764 //
   765 // Destructor
   766 //
   767 	{
   768 	__KTRACE_OPT(KPBUS1,Kern::Printf(">DPccdChunkBase::Close() %08x",this));
   769 
   770 	// Disconnect all the Pc Card windows and then delete chunk
   771 	SDblQueLink* pW=iWindowQ.iA.iNext;
   772 	while (pW!=&iWindowQ.iA)
   773 		{
   774 		RPccdWindow& w=*(RPccdWindow*)pW;
   775 		pW=pW->iNext;
   776 		w.Close();	// closing last window deletes chunk
   777 		}
   778 	__KTRACE_OPT(KPBUS1,Kern::Printf("<DPccdChunkBase::Close() %08x",this));
   779 	}
   780 
   781 TBool DPccdChunkBase::IsRemovable()
   782 //
   783 // Check if this chunk has any permanent windows.
   784 //
   785 	{
   786 	return (iPermanentWindows==0);
   787 	}
   788 
   789 TBool DPccdChunkBase::IsLocked()
   790 //
   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).
   793 //
   794 	{
   795 	return (iWindows>iSystemWindows);
   796 	}
   797 
   798 TInt DPccdChunkBase::AllocateWinCheck(TPccdChnk aWin,TUint aFlag)
   799 //
   800 // Check if it is possible to create the specified window from this chunk.
   801 //
   802 	{
   803 	// Check if they are of compatible type
   804 	if (!IsTypeCompatible(aWin.iMemType))
   805 		return(KErrNotFound);
   806 
   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)
   813 		{
   814 		// Possible success - first check the cache options are compatible
   815 		if (!(aFlag|KPccdChunkCacheable)&&iCacheable)
   816 			return(KErrAccessDenied);
   817 
   818 		// Now check that the requested window isn't already allocated
   819 		SDblQueLink* pW=iWindowQ.iA.iNext;
   820 		while (pW!=&iWindowQ.iA)
   821 			{
   822 			RPccdWindow& w=*(RPccdWindow*)pW;
   823 			pW=pW->iNext;
   824 			if (w.Overlap(aWin.iMemBaseAddr-iChnk.iMemBaseAddr,aWin.iMemLen) )
   825 				return(KErrAccessDenied);
   826 			}
   827 		return(KErrNone);
   828 		}
   829 	if (startIsInChnk||endIsInChnk)
   830 		return(KErrAccessDenied);	// Requested window is partly in this chunk.
   831 	return(KErrNotFound);
   832 	}
   833 
   834 void DPccdChunkBase::AddWindow(RPccdWindow *aWindow)
   835 //
   836 // Add a window to this chunk.
   837 //
   838 	{
   839 	iWindowQ.Add(aWindow);
   840 //	Kern::EnterCS();		Not needed since a single thread is used
   841 	iWindows++;
   842 	if (aWindow->IsPermanent())
   843 		iPermanentWindows++;
   844 	if (aWindow->IsShareable())
   845 		iShareableWindows++;
   846 	if (aWindow->IsSystemOwned())
   847 		iSystemWindows++;
   848 	else
   849 		iSocket->iClientWindows++;
   850 //	Kern::LeaveCS();
   851 	aWindow->iChunk=this;
   852 	}
   853 
   854 void DPccdChunkBase::RemoveWindow(RPccdWindow *aWindow)
   855 //
   856 // Remove a window from this chunk (even if it's permanent). 
   857 //	
   858 	{
   859 
   860 	if (aWindow->iNext && aWindow->iChunk==this)
   861 		{
   862 		aWindow->Deque();
   863 		aWindow->iNext=NULL;
   864 //		Kern::EnterCS();	Not needed since a single thread is used
   865 		iWindows--;
   866 		if (aWindow->IsPermanent())
   867 			iPermanentWindows--;
   868 		if (aWindow->IsShareable())
   869 			iShareableWindows--;
   870 		if (aWindow->IsSystemOwned())
   871 			iSystemWindows--;
   872 		else
   873 			iSocket->iClientWindows--;
   874 //		Kern::LeaveCS();
   875 		if (iWindows==0)
   876 			{
   877 			iSocket->RemoveChunk(this);
   878 			delete this;
   879 			}
   880 		}
   881 	}
   882 
   883 /********************************************
   884  * PC card memory window
   885  ********************************************/
   886 EXPORT_C RPccdWindow::RPccdWindow()
   887 //
   888 // Constructor
   889 //
   890 	: iAccessSpeed(EAcSpeedInValid),iMemType(EPccdAttribMem),iOffset(0),iLen(0),iType(0)
   891 	{
   892 	iNext=NULL;
   893 	iChunk=NULL;
   894 	}
   895 
   896 EXPORT_C TInt RPccdWindow::Create(DPcCardSocket* aSocket, TPccdChnk aChnk, TPccdAccessSpeed aSpeed, TUint aFlag)
   897 //
   898 // Create a block of memory (IO, Common or Attribute memory).
   899 //
   900 	{
   901 
   902 	DPccdChunkBase *chunk=NULL;
   903 	TBool chunkExists=EFalse;
   904 	TInt r;
   905 
   906 	// See if requested window is actually part of a chunk already created
   907 	TInt i;
   908 	for (i=0;i<aSocket->iMemChunks.Count();i++)
   909 		{
   910 		if ((r=aSocket->iMemChunks[i]->AllocateWinCheck(aChnk,aFlag))==KErrNone)
   911 			{
   912 			chunk=aSocket->iMemChunks[i];
   913 			chunkExists=ETrue;
   914 			break;
   915 			}
   916 		if (r==KErrAccessDenied)
   917 			return r;
   918 		}
   919 
   920 	// If necesary, create a chunk
   921 	if (!chunkExists)
   922 		{
   923 		// Create the memory chunk
   924 		chunk=aSocket->NewPccdChunk(aChnk.iMemType);
   925 		if (!chunk)
   926 			return KErrNoMemory;
   927 		TInt r=chunk->Create(aSocket, aChnk, aFlag);
   928 		if (r==KErrNone)
   929 			r=aSocket->iMemChunks.Append(chunk);
   930 		if (r!=KErrNone)
   931 			{
   932 			delete chunk;
   933 			return r;
   934 			}
   935 		}
   936 	__KTRACE_OPT(KPBUS2,Kern::Printf("Skt:CreateMemWindowL-got chunk(existing-%d)",chunkExists));
   937 
   938 	// Create the memory window
   939 	iOffset=aChnk.iMemBaseAddr-chunk->BaseAddr();
   940 	iLen=aChnk.iMemLen;
   941 	iAccessSpeed=aSpeed;
   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"));
   947 	return KErrNone;
   948 	}
   949 
   950 EXPORT_C void RPccdWindow::Close()
   951 	{
   952 	if (iNext && iChunk)
   953 		iChunk->RemoveWindow(this);
   954 	}
   955 
   956 EXPORT_C TInt RPccdWindow::SetupChunkHw(TUint aFlag)
   957 //
   958 // Config h/w in preparation for accessing window. Flag is for platform dependant info.
   959 //
   960 	{
   961 
   962 	if (!iChunk)
   963 		return(KErrNotReady);
   964 	iChunk->SetupChunkHw(iAccessSpeed,iMemType,iWaitSig,aFlag);
   965 //	iVcc->ResetInactivityTimer();
   966 	return(KErrNone);
   967 	}
   968 
   969 EXPORT_C TLinAddr RPccdWindow::LinearAddress()
   970 //
   971 // Return linear address of window
   972 //
   973 	{
   974 	return iChunk->LinearAddress()+iOffset;
   975 	}
   976 
   977 TBool RPccdWindow::Overlap(TUint32 anOffset,TUint aLen)
   978 //
   979 //
   980 //
   981 	{
   982 	// If this window is sharable then it doesn't matter if they overlap or not.
   983 	if (IsShareable())
   984 		return(EFalse);
   985 
   986 	TUint32 winEnd=(anOffset+aLen-1);
   987 	TUint32 thisEnd=(iOffset+iLen-1);
   988 	if ((anOffset>=iOffset && anOffset<=thisEnd) ||
   989 		(winEnd>=iOffset && winEnd<=thisEnd) )
   990 		return(ETrue);
   991 
   992 	return(EFalse);
   993 	}
   994