kernel/eka/drivers/pbus/pccard/socket.cpp
changeset 9 96e5fb8b040d
child 43 c1f20ce4abcf
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     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