kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdcard.cpp
changeset 0 a41df078684a
child 13 46fffbe7b5a7
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1999-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 //
       
    15 
       
    16 #include <drivers/sdcard.h>
       
    17 
       
    18 
       
    19 // ======== TSDCard ========
       
    20 
       
    21 TSDCard::TSDCard()
       
    22 :	iProtectedAreaSize(0), iPARootDirEnd(KPARootDirEndUnknown)
       
    23 	{
       
    24 	// empty
       
    25 	}
       
    26 
       
    27 TInt64 TSDCard::DeviceSize64() const
       
    28 //
       
    29 // returns the SD device size
       
    30 //
       
    31 	{
       
    32 	if(iFlags & KSDCardIsSDCard)
       
    33 		{	
       
    34 		return (IsHighCapacity()) ? 512 * 1024 * (TInt64)(1 + CSD().CSDField(69, 48)) : TMMCard::DeviceSize64();
       
    35 		}
       
    36 		
       
    37 	return(TMMCard::DeviceSize64());
       
    38 	}
       
    39 
       
    40 TUint32 TSDCard::PreferredWriteGroupLength() const
       
    41 //
       
    42 // return SD erase sector size, (SECTOR_SIZE + 1) * 2 ** WRITE_BLK_LEN
       
    43 //
       
    44 	{
       
    45 	if(iFlags & KSDCardIsSDCard)
       
    46 		{	
       
    47 		TSDCSD sdcsd(CSD());
       
    48 		return (sdcsd.SDSectorSize() + 1) * (1 << sdcsd.WriteBlLen());
       
    49 		}
       
    50 		
       
    51 	return(TMMCard::PreferredWriteGroupLength());
       
    52 	}
       
    53 
       
    54 TInt TSDCard::GetFormatInfo(TLDFormatInfo& /*aFormatInfo*/) const
       
    55 	{
       
    56 	return KErrNotSupported;
       
    57 	}
       
    58 
       
    59 TUint32 TSDCard::MinEraseSectorSize() const
       
    60 	{
       
    61 	if(iFlags&KSDCardIsSDCard)
       
    62 		{	
       
    63 		TSDCSD sdcsd(CSD());
       
    64 		if (sdcsd.SDEraseBlkEn())
       
    65 			return sdcsd.WriteBlockLength();		// raised logarithm
       
    66 		else
       
    67 			return (sdcsd.SDSectorSize() + 1) * sdcsd.WriteBlockLength();
       
    68 		}
       
    69 
       
    70 	return TMMCard::MinEraseSectorSize();
       
    71 	}
       
    72 
       
    73 
       
    74 const TUint32 KEraseSectorSizeShift = 8;	// KEraseSectorSizeShift determines the multiple of the sector size 
       
    75 											// that can be erased in one operation
       
    76 TUint32 TSDCard::EraseSectorSize() const
       
    77 	{
       
    78 	if(iFlags&KSDCardIsSDCard)
       
    79 		{	
       
    80 		TSDCSD sdcsd(CSD());
       
    81 		return ((sdcsd.SDSectorSize() + 1) * sdcsd.WriteBlockLength()) << KEraseSectorSizeShift;
       
    82 		}
       
    83 
       
    84 	return TMMCard::EraseSectorSize();
       
    85 	}
       
    86 
       
    87 const TInt KDefaultBlockLen		   = 9;							// 2^9 = 512 bytes
       
    88 const TInt KDefaultBlockLenInBytes = 1 << KDefaultBlockLen;		// 2^9 = 512 bytes
       
    89 const TInt KTwoGbyteSDBlockLen	   = 10;						// 2^10 = 1024 bytes
       
    90 const TInt KFourGbyteSDBlockLen	   = 11;						// 2^11 = 2048 bytes
       
    91 
       
    92 TInt TSDCard::GetEraseInfo(TMMCEraseInfo& aEraseInfo) const
       
    93 //
       
    94 // Return info. on erase services for this card
       
    95 //
       
    96 	{
       
    97 	
       
    98 	// SD Controllers support MMC cards too. Check if we are really dealing with an SD card
       
    99 	if(!(iFlags&KSDCardIsSDCard))
       
   100 		return(TMMCard::GetEraseInfo(aEraseInfo));
       
   101 		
       
   102 	if (CSD().CCC() & KMMCCmdClassErase)
       
   103 		{
       
   104 		// This card supports erase cmds. However, SD cards don't support Erase Group commands (i.e. CMD35, CMD36).
       
   105 		aEraseInfo.iEraseFlags=KMMCEraseClassCmdsSupported; 
       
   106 		
       
   107 		// Return the preferred size to be used as the unit for erase operations.
       
   108 		TSDCSD sdcsd(CSD());
       
   109 		TUint32 prefSize=((sdcsd.SDSectorSize() + 1) * sdcsd.WriteBlockLength());
       
   110 		prefSize<<=KEraseSectorSizeShift;		// Use multiples of the sector size for each erase operation
       
   111 		aEraseInfo.iPreferredEraseUnitSize=prefSize;
       
   112 	
       
   113 		// Return the smallest size that can be used as the unit for erase operations
       
   114 		if (sdcsd.SDEraseBlkEn())
       
   115 			{
       
   116 			aEraseInfo.iMinEraseSectorSize = KDefaultBlockLenInBytes;
       
   117 			}
       
   118 		else
       
   119 			{
       
   120 			aEraseInfo.iMinEraseSectorSize=(sdcsd.SDSectorSize() + 1) * sdcsd.WriteBlockLength();
       
   121 			}
       
   122 		}
       
   123 	else		
       
   124 		aEraseInfo.iEraseFlags=0;
       
   125 		
       
   126 	return(KErrNone);	
       
   127 	}
       
   128 
       
   129 TInt TSDCard::MaxReadBlLen() const
       
   130 /**
       
   131  * Returns the maximum read block length supported by the card encoded as a logarithm
       
   132  * Normally this is the same as the READ_BL_LEN field in the CSD register,
       
   133  * but for high capacity cards (> 2GB) this is set to a maximum of 512 bytes,
       
   134  * if possible, to try to avoid compatibility issues.
       
   135  */
       
   136 	{
       
   137 	if (IsSDCard())
       
   138 		{
       
   139 		TInt blkLenLog2 = CSD().ReadBlLen();
       
   140 		if (blkLenLog2 == KTwoGbyteSDBlockLen || blkLenLog2 == KFourGbyteSDBlockLen)
       
   141 			{
       
   142 			// The SD card spec. makes a special case for 2GByte cards,
       
   143 			// ...and some manufacturers apply the same method to support 4G cards
       
   144 			__KTRACE_OPT(KPBUS1, Kern::Printf("=mmc:mrbl > 2GB SD"));
       
   145 			blkLenLog2 = KDefaultBlockLen;
       
   146 			}
       
   147 		return blkLenLog2;
       
   148 		}
       
   149 	else		// MMC card
       
   150 		{
       
   151 		return (TMMCard::MaxReadBlLen());
       
   152 		}
       
   153 	}
       
   154 
       
   155 TInt TSDCard::MaxWriteBlLen() const
       
   156 /**
       
   157  * Returns the maximum write block length supported by the card encoded as a logarithm
       
   158  * Normally this is the same as the WRITE_BL_LEN field in the CSD register,
       
   159  * but for high capacity cards (> 2GB) this is set to a maximum of 512 bytes,
       
   160  * if possible, to try to avoid compatibility issues.
       
   161  */
       
   162 	{
       
   163 	if (IsSDCard())
       
   164 		{
       
   165 		TInt blkLenLog2 = CSD().WriteBlLen();
       
   166 		if (blkLenLog2 == KTwoGbyteSDBlockLen || blkLenLog2 == KFourGbyteSDBlockLen)
       
   167 			{
       
   168 			// The SD card spec. makes a special case for 2GByte cards,
       
   169 			// ...and some manufacturers apply the same method to support 4G cards
       
   170 			__KTRACE_OPT(KPBUS1, Kern::Printf("=mmc:mwbl > 2GB SD"));
       
   171 			blkLenLog2 = KDefaultBlockLen;
       
   172 			}
       
   173 		return blkLenLog2;
       
   174 		}
       
   175 	else		// MMC card
       
   176 		{
       
   177 		return (TMMCard::MaxWriteBlLen());
       
   178 		}
       
   179 	}
       
   180 	
       
   181 TUint TSDCard::MaxTranSpeedInKilohertz() const
       
   182 /**
       
   183  * Returns the maximum supported clock rate for the card, in Kilohertz.
       
   184  * @return Speed, in Kilohertz
       
   185  */
       
   186 	{
       
   187 	TUint maxClk = TMMCard::MaxTranSpeedInKilohertz();
       
   188 	
       
   189 	if (IsSDCard())
       
   190 		{
       
   191 		__KTRACE_OPT(KPBUS1, Kern::Printf("\t >TSDCard(%d): MaxTranSpeedInKilohertz: %d",(iIndex-1),maxClk));
       
   192 		
       
   193 #ifdef _DEBUG
       
   194 		//MaxClk for SD should only be either 25000KHz or 50000KHz
       
   195 		if ( (maxClk != KSDDTClk25MHz) && (maxClk != KSDDTClk50MHz) )
       
   196 			{
       
   197 			__KTRACE_OPT(KPBUS1, Kern::Printf("\t >DSDStack: Non-Compliant DT Clock"));
       
   198 			}
       
   199 #endif
       
   200 		if (maxClk > KSDDTClk50MHz)
       
   201 			{
       
   202 			//Clock rate exceeds SD possible max clock rate
       
   203 			__KTRACE_OPT(KPBUS1, Kern::Printf("\t >DSDStack: Tuning DT Clock down to 50MHz"));
       
   204 			maxClk = KSDDTClk50MHz;
       
   205 			}
       
   206 		}
       
   207 		
       
   208 	return maxClk;
       
   209 	}
       
   210 
       
   211 // ======== TSDCardArray ========
       
   212 
       
   213 EXPORT_C TInt TSDCardArray::AllocCards()
       
   214 // 
       
   215 // allocate TSDCard objects for iCards and iNewCardsArray.  This function
       
   216 // is called at bootup as part of stack allocation so there is no cleanup
       
   217 // if it fails.
       
   218 //
       
   219 	{
       
   220 	for (TInt i = 0; i < (TInt) KMaxMMCardsPerStack; ++i)
       
   221 		{
       
   222 		// zeroing the card data used to be implicit because embedded in
       
   223 		// CBase-derived DMMCStack.
       
   224 		if ((iCards[i] = new TSDCard) == 0)
       
   225 			return KErrNoMemory;
       
   226 		iCards[i]->iUsingSessionP = 0;
       
   227 		if ((iNewCards[i] = new TSDCard) == 0)
       
   228 			return KErrNoMemory;
       
   229 		}
       
   230 
       
   231 	return KErrNone;
       
   232 	}
       
   233 
       
   234 void TSDCardArray::AddCardSDMode(TUint aCardNumber,const TUint8* aCID,TRCA* aNewRCA)
       
   235 //
       
   236 // Add an MMC card straight to the main card array in slot 'aCardNumber'. Save
       
   237 // the CID value in the slot. Return a RCA for the card.
       
   238 //
       
   239 	{
       
   240 
       
   241 	TRCA rca=0;
       
   242 	
       
   243 	// First, lets check if the same card was here before. If it was, keep the same RCA
       
   244 	if (Card(aCardNumber).IsPresent() && Card(aCardNumber).iCID==aCID)
       
   245 		rca=Card(aCardNumber).iRCA;
       
   246 	else
       
   247 		{
       
   248 		// Allocate and new RCA and store the CID in the slot selected
       
   249 		__ASSERT_ALWAYS( (rca=iOwningStack->iRCAPool.GetFreeRCA())!=0,DMMCSocket::Panic(DMMCSocket::EMMCNoFreeRCA) );
       
   250 		Card(aCardNumber).iCID=aCID;
       
   251 		if ( Card(aCardNumber).iRCA != 0 )
       
   252 			iOwningStack->iRCAPool.UnlockRCA(Card(aCardNumber).iRCA);
       
   253 		Card(aCardNumber).iRCA=rca;
       
   254 		iOwningStack->iRCAPool.LockRCA(Card(aCardNumber).iRCA);
       
   255 		}
       
   256 
       
   257 	Card(aCardNumber).iIndex=(aCardNumber+1); // Mark card as being present
       
   258 	*aNewRCA=rca;
       
   259 	}
       
   260 
       
   261 TInt TSDCardArray::StoreRCAIfUnique(TUint aCardNumber,TRCA& anRCA)
       
   262 //
       
   263 // Check that no other array element has the same RCA value 'anRCA'. If no
       
   264 // no duplication then store in slot 'aCardNumber'.
       
   265 //
       
   266 	{
       
   267 
       
   268 	if (anRCA==0)
       
   269 		return(KErrGeneral);
       
   270 	Card(aCardNumber).iRCA=0;
       
   271 
       
   272 	// Now let's look if we've seen this card before
       
   273 	for ( TUint i=0 ; i<iOwningStack->iMaxCardsInStack ; i++ )
       
   274 		{
       
   275 		if ( Card(i).IsPresent() && Card(i).iRCA==anRCA )
       
   276 			return(KErrInUse);
       
   277 		}
       
   278 	Card(aCardNumber).iRCA=anRCA;
       
   279 	Card(aCardNumber).iIndex=(aCardNumber+1); // Mark card as being present
       
   280 	return(KErrNone);
       
   281 	}
       
   282 
       
   283 EXPORT_C void TSDCardArray::DeclareCardAsGone(TUint aCardNumber)
       
   284 //
       
   285 // reset SD specific fields to initial values and then reset generic MultiMediaCard
       
   286 //
       
   287 	{
       
   288 	Card(aCardNumber).SetBusWidth(1);
       
   289 	TMMCardArray::DeclareCardAsGone(aCardNumber);
       
   290 	}
       
   291 
       
   292 // ======== DSDSession ========
       
   293 
       
   294 void DSDSession::FillAppCommandDesc(TMMCCommandDesc& aDesc, TSDAppCmd aCmd)
       
   295 	{
       
   296 	aDesc.iCommand = (TMMCCommandEnum) aCmd;
       
   297 	aDesc.iArgument = 0;						// set stuff bits to zero
       
   298 	FillAppCommandDesc(aDesc);
       
   299 	}
       
   300 
       
   301 void DSDSession::FillAppCommandDesc(TMMCCommandDesc& aDesc, TSDAppCmd aCmd, TMMCArgument aArg)
       
   302 	{
       
   303 	aDesc.iCommand = (TMMCCommandEnum) aCmd;
       
   304 	aDesc.iArgument = aArg;
       
   305 	FillAppCommandDesc(aDesc);
       
   306 	}
       
   307 
       
   308 const TUint32 CCA = KMMCCmdClassApplication;
       
   309 const TMMCIdxCommandSpec AppCmdSpecTable[] =
       
   310 	{						//	Class	Type		Dir			MBlk	StopT	Rsp Type		Len
       
   311 	{ESDACmdSetBusWidth,		{CCA,ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,	4}}, //ACMD6
       
   312 	{ESDACmdSDStatus,			{CCA,ECmdTypeADTCS,	EDirRead,	EFalse, EFalse, ERespTypeR1,	4}}, //ACMD13
       
   313 	{ESDACmdSendNumWrBlocks,	{CCA,ECmdTypeADTCS,	EDirRead,	EFalse, EFalse, ERespTypeR1,	4}}, //ACMD22
       
   314 	{ESDACmdSetWrBlkEraseCount,	{CCA,ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,	4}}, //ACMD23
       
   315 	{ESDACmdSDAppOpCond,		{CCA,ECmdTypeBCR,	EDirNone,	EFalse, EFalse, ERespTypeR3,	4}}, //ACMD41
       
   316 	{ESDACmdSetClrCardDetect,	{CCA,ECmdTypeAC,	EDirNone,	EFalse, EFalse, ERespTypeR1,	4}}, //ACMD42
       
   317 	{ESDACmdSendSCR,			{CCA,ECmdTypeADTCS,	EDirRead,	EFalse, EFalse, ERespTypeR1,	4}}  //ACMD51
       
   318 };
       
   319 
       
   320 void DSDSession::FillAppCommandDesc(TMMCCommandDesc& aDesc)
       
   321 	{
       
   322 	aDesc.iSpec = FindCommandSpec(AppCmdSpecTable, aDesc.iCommand);
       
   323 	aDesc.iFlags = 0;
       
   324 	aDesc.iBytesDone = 0;
       
   325 	}
       
   326 
       
   327 const TMMCIdxCommandSpec SdSpecificCmdSpecTable[] =
       
   328 /**
       
   329  * SD Specific Command Table
       
   330  *
       
   331  *  - Some commands defined in the SD specification overload those defined in the MMC specification.
       
   332  *    This table contains the SD specific versions of those commands.
       
   333  */
       
   334 	{
       
   335 							//   Class				Type			Dir			MBlk	StopT	Rsp Type		Len
       
   336 	{ESDCmdSendRelativeAddress,	{KMMCCmdClassBasic,	ECmdTypeBCR,	EDirNone,	EFalse,	EFalse,	ERespTypeR6,	4}},	// CMD3 : SEND_RELATIVE_ADDRESS
       
   337 	{ESDCmdSwitchFunction,		{KMMCCmdClassSwitch,ECmdTypeADTCS,	EDirRead,	EFalse,	EFalse,	ERespTypeR1,	4}},	// CMD6 : SWITCH_FUNCTION
       
   338 	{ESDCmdSendIfCond,			{KMMCCmdClassBasic,	ECmdTypeBCR,	EDirNone,	EFalse,	EFalse,	ERespTypeR7,	4}}		// CMD8 : SEND_IF_COND
       
   339 	};
       
   340 
       
   341 void DSDSession::FillSdSpecificCommandDesc(TMMCCommandDesc& aDesc, TSDSpecificCmd aCmd, TMMCArgument aArg)
       
   342 	{
       
   343 	aDesc.iCommand = (TMMCCommandEnum) aCmd;
       
   344 	aDesc.iArgument = aArg;
       
   345 	FillSdSpecificCommandDesc(aDesc);
       
   346 	}
       
   347 
       
   348 void DSDSession::FillSdSpecificCommandDesc(TMMCCommandDesc& aDesc, TSDSpecificCmd aCmd)
       
   349 	{
       
   350 	aDesc.iCommand = (TMMCCommandEnum) aCmd;
       
   351 	aDesc.iArgument = 0;						// set stuff bits to zero
       
   352 	FillSdSpecificCommandDesc(aDesc);
       
   353 	}
       
   354 
       
   355 void DSDSession::FillSdSpecificCommandDesc(TMMCCommandDesc& aDesc)
       
   356 	{
       
   357 	aDesc.iSpec = FindCommandSpec(SdSpecificCmdSpecTable, aDesc.iCommand);
       
   358 	aDesc.iFlags = 0;
       
   359 	aDesc.iBytesDone = 0;
       
   360 	}
       
   361 
       
   362 
       
   363 // ======== DSDStack ========
       
   364 
       
   365 EXPORT_C TInt DSDStack::Init()
       
   366 	{
       
   367 	return DMMCStack::Init();
       
   368 	}
       
   369 
       
   370 
       
   371 const TInt KMaxRCASendLoops=3;
       
   372 const TUint KSDMaxPollAttempts=25;
       
   373 EXPORT_C TMMCErr DSDStack::AcquireStackSM()
       
   374 //
       
   375 // This macro acquires new cards in an SD Card - star topology stack.
       
   376 // This means each card has its own CMD and DAT lines and can be addressed
       
   377 // individually by the Controller in turn. Commands can also be broadcast 
       
   378 // simultaneously to the entire stack. 
       
   379 // It starts with the Controller reading the operating conditions of each 
       
   380 // card in the stack (SEND_OP_COND - ACMD41). Then, the following
       
   381 // initialisation sequence is performed to each card in turn:-
       
   382 // New cards in the stack are identified (ALL_SEND_CID - CMD2) and each one
       
   383 // is requested to publish a relative card address (SEND_RCA - CMD3). Finally,
       
   384 // the card specific data (SEND_CSD - CMD9) is read from each card.
       
   385 // Note that the initialization of MMC cards are supported by this function
       
   386 // if they are encountered. These require a slightly different init. procdure.
       
   387 //
       
   388 	{
       
   389 		enum states
       
   390 			{
       
   391 			EStBegin=0,
       
   392 			EStNextFullRange,
       
   393 			EStSendCIDIssued,
       
   394 			EStIssueSendRCA,
       
   395 			EStSendRCACheck,
       
   396 			EStRCADone,
       
   397 			EStMoreCardsCheck,
       
   398 			EStEnd
       
   399 			};
       
   400 
       
   401 		DMMCSession& s=Session();
       
   402 
       
   403 	SMF_BEGIN
       
   404 
       
   405         __KTRACE_OPT(KPBUS1, Kern::Printf(">DSDStack::AcquireStackSM()"));
       
   406         
       
   407 		iRCAPool.ReleaseUnlocked();
       
   408 		iCxCardCount=0; 		// Reset current card number
       
   409 
       
   410 	SMF_STATE(EStNextFullRange)
       
   411 
       
   412 		iCxCardType = ESDCardTypeUnknown;
       
   413 
       
   414 		AddressCard(iCxCardCount); 	// Address the next card
       
   415 
       
   416 		// Before issueing commands, see if there's actually a card present
       
   417 		if (!CardDetect(iCxCardCount))
       
   418 			SMF_GOTOS(EStMoreCardsCheck)
       
   419 
       
   420 		m.SetTraps(KMMCErrResponseTimeOut);
       
   421 		SMF_INVOKES(InitialiseMemoryCardSMST, EStSendCIDIssued)
       
   422 
       
   423 	SMF_STATE(EStSendCIDIssued)
       
   424 
       
   425 		if( !err )
       
   426 			{
       
   427 			// The card responded with a CID. We need to initialise the
       
   428 			// appropriate entry in the card array with the CID. 
       
   429 			if (iCxCardType==ESDCardTypeIsSD)
       
   430 				{
       
   431 				// Now prepare to recieve an RCA from to the card
       
   432 				CardArray().CardP(iCxCardCount)->iCID=s.ResponseP();
       
   433 				DSDSession::FillSdSpecificCommandDesc(Command(), ESDCmdSendRelativeAddress,0); // SEND_RCA with argument just stuff bits
       
   434 
       
   435 				m.ResetTraps();
       
   436 				iCxPollRetryCount=0; // Init count of send RCA attempts 
       
   437 				SMF_GOTOS(EStIssueSendRCA)
       
   438 				}
       
   439 			else
       
   440 				{
       
   441 				// The card array allocates an RCA, either the old RCA
       
   442 				// if we have seen this card before, or a new one.
       
   443 				TRCA rca;
       
   444 				CardArray().AddCardSDMode(iCxCardCount,s.ResponseP(),&rca);
       
   445 
       
   446 				// Now assign the new RCA to the card
       
   447 				s.FillCommandDesc(ECmdSetRelativeAddr,TMMCArgument(rca));
       
   448 				m.ResetTraps();							
       
   449 				SMF_INVOKES(ExecCommandSMST,EStRCADone)
       
   450 				}
       
   451 			}
       
   452 		else
       
   453 			{
       
   454 			m.ResetTraps();
       
   455 			SMF_GOTOS(EStMoreCardsCheck) // Timed out, try the next card slot
       
   456 			}
       
   457 
       
   458 	SMF_STATE(EStIssueSendRCA)
       
   459 
       
   460 		SMF_INVOKES(ExecCommandSMST,EStSendRCACheck)
       
   461 
       
   462 	SMF_STATE(EStSendRCACheck)
       
   463 
       
   464 		// We need to check that the RCA recieved from the card doesn't clash
       
   465 		// with any others in this stack. RCA is first 2 bytes of response buffer (in big endian)
       
   466 		TRCA rca=(TUint16)((s.ResponseP()[0]<<8) | s.ResponseP()[1]);
       
   467 		if (CardArray().StoreRCAIfUnique(iCxCardCount,rca)!=KErrNone)
       
   468 			SMF_GOTOS( ((++iCxPollRetryCount<KMaxRCASendLoops)?EStIssueSendRCA:EStMoreCardsCheck) )
       
   469 
       
   470 	SMF_STATE(EStRCADone)
       
   471 
       
   472 		SMF_INVOKES(ConfigureMemoryCardSMST, EStMoreCardsCheck)
       
   473 
       
   474 	SMF_STATE(EStMoreCardsCheck)
       
   475 
       
   476 		if (++iCxCardCount < (TInt)iMaxCardsInStack)
       
   477 		    {
       
   478 		    __KTRACE_OPT(KPBUS1, Kern::Printf(">DSDStack::AcquireStackSM(): More Cards to check: %d",iCxCardCount));
       
   479 			SMF_GOTOS(EStNextFullRange)
       
   480 		    }
       
   481 		else
       
   482 		    {		   
       
   483 			AddressCard(KBroadcastToAllCards); // Set back to broadcast mode
       
   484 			__KTRACE_OPT(KPBUS1, Kern::Printf("<DSDStack::AcquireStackSM()"));
       
   485 		    }
       
   486 
       
   487 	SMF_END
       
   488 	}
       
   489 
       
   490 
       
   491 TMMCErr DSDStack::InitialiseMemoryCardSMST(TAny* aStackP)
       
   492 	{ return static_cast<DSDStack*>(aStackP)->InitialiseMemoryCardSM(); }
       
   493 
       
   494 	
       
   495 TMMCErr DSDStack::InitialiseMemoryCardSM()
       
   496 /**
       
   497 */
       
   498 	{
       
   499 		enum states
       
   500 			{
       
   501 			EStBegin=0,
       
   502 			EStSendInterfaceCondition,
       
   503 			EStSentInterfaceCondition,
       
   504 			EStSetFullRangeCmd,
       
   505 			EStCheckForFullRangeCmd41Timeout,
       
   506 			EStSentAppCommandBeforeCheckVoltage,
       
   507 			EStCheckVoltage,
       
   508 			EStFullRangeDone,
       
   509 			EStSetRangeCmd,
       
   510 			EStCheckForRangeCmd41Timeout,
       
   511 			EStSetRangeBusyCheck,
       
   512 			EStCIDCmd,
       
   513 			EStSendCIDIssued,
       
   514 			EStEnd
       
   515 			};
       
   516 
       
   517 		DMMCSession& s=Session();
       
   518 		DMMCPsu* psu=(DMMCPsu*)MMCSocket()->iVcc;
       
   519 			
       
   520 		static const TUint32 KCmd8Param		= 0x0100 | 0x00AA;	// Voltage supplied : 2.7-3.6V, Check Pattern 10101010b
       
   521 		static const TUint32 KCmd8CheckMask = 0x00000FFF;
       
   522 
       
   523 	SMF_BEGIN
       
   524 
       
   525 		iCxCardType = ESDCardTypeUnknown;
       
   526 		s.iCardP = NULL;	// This stops ExecCommandSM() from setting old RCA when sending CMD55
       
   527 
       
   528 		// Send CMD0 to initialise memory
       
   529 		SMF_INVOKES(GoIdleSMST, EStSendInterfaceCondition);
       
   530 
       
   531 	SMF_STATE(EStSendInterfaceCondition)
       
   532 
       
   533 		iCxPollRetryCount=0; 						 // Reset max number of poll attempts on card busy
       
   534 		iConfig.SetPollAttempts(KSDMaxPollAttempts); // Increase card busy timeout to 1 Sec for SD Cards
       
   535 
       
   536 		iConfig.RemoveMode( KMMCModeEnableTimeOutRetry ); // Temporarily disable timeout retries - since we use a timeout event to distinguish between MMC and SD
       
   537 
       
   538 		DSDSession::FillSdSpecificCommandDesc(Command(), ESDCmdSendIfCond, KCmd8Param);
       
   539 
       
   540 		// SD2.0 defines CMD8 as having a new response type - R7
       
   541 		// if the PSL doesn't indicate support for R7, use R1 instead
       
   542 		if (!(MMCSocket()->MachineInfo().iFlags & TMMCMachineInfo::ESupportsR7))
       
   543 			{
       
   544 			__KTRACE_OPT(KPBUS1, Kern::Printf("R7 not supported."));
       
   545 			Command().iSpec.iResponseType = ERespTypeR1;
       
   546 			}
       
   547 
       
   548  
       
   549  		m.SetTraps(KMMCErrAll);
       
   550  		SMF_INVOKES(ExecCommandSMST, EStSentInterfaceCondition)
       
   551  
       
   552  	SMF_STATE(EStSentInterfaceCondition)
       
   553  
       
   554  		if (err == KMMCErrNone)
       
   555  			{
       
   556  			// Check the response for voltage and check pattern
       
   557  			const TUint32 status = TMMC::BigEndian32(s.ResponseP());
       
   558  			if((status & KCmd8CheckMask) == KCmd8Param)
       
   559  				{
       
   560  				__KTRACE_OPT(KPBUS1, Kern::Printf("Found v2 card."));
       
   561 				iCurrentOpRange |= KMMCOCRAccessModeHCS;
       
   562  				}
       
   563  			else
       
   564  				{
       
   565  				// Pattern Mis-match, card does not support the specified voltage range
       
   566  				return( KMMCErrNotSupported );
       
   567  				}
       
   568 
       
   569 			SMF_GOTOS(EStCheckVoltage);
       
   570  			}
       
   571 
       
   572 		// Go idle again after CMD8 failure
       
   573 		SMF_INVOKES(GoIdleSMST, EStCheckVoltage);
       
   574 
       
   575 
       
   576 	SMF_STATE(EStCheckVoltage)
       
   577 
       
   578 
       
   579 		// If platform doesn't support an adjustable voltage PSU then there's no
       
   580 		// point in doing a full range for its supported range. To support range
       
   581 		// checking on a multi-card stack would require a complete scan of all
       
   582 		// cards before actually setting the range. This would over-complicate things
       
   583 		// and make the more normal single card/none adjustable cases less efficient.
       
   584 		if ( !(psu->VoltageSupported()&KMMCAdjustableOpVoltage) || iMaxCardsInStack>1)
       
   585 			{
       
   586 			// if the PSU isn't adjustable then it can't support low voltage mode
       
   587 			iCurrentOpRange&= ~KMMCOCRLowVoltage;
       
   588 
       
   589 			SMF_GOTOS(EStSetRangeCmd)
       
   590 			}
       
   591 
       
   592 	SMF_STATE(EStSetFullRangeCmd)
       
   593 
       
   594 		// Issue ACMD41/CMD1 with omitted voltage range
       
   595 		if (iCxCardType==ESDCardTypeIsMMC)
       
   596 			{
       
   597 			s.FillCommandDesc(ECmdSendOpCond, KMMCOCRAccessModeHCS | KMMCOCRBusy); // Full range + Sector Access + Busy bit (iArgument==KBit31)
       
   598 			SMF_NEXTS(EStFullRangeDone)
       
   599 			}
       
   600 		else
       
   601 			{
       
   602 			DSDSession::FillAppCommandDesc(Command(), ESDACmdSDAppOpCond, TMMCArgument(0));
       
   603 			SMF_NEXTS(EStCheckForFullRangeCmd41Timeout)
       
   604 			}
       
   605 					
       
   606 		m.SetTraps(KMMCErrResponseTimeOut);
       
   607 		SMF_CALL(ExecCommandSMST)
       
   608 
       
   609 	SMF_STATE(EStCheckForFullRangeCmd41Timeout)
       
   610 	
       
   611 		if (err==KMMCErrResponseTimeOut)	
       
   612 			{
       
   613 			__KTRACE_OPT(KPBUS1, Kern::Printf("ACMD 41 not supported - Assuming MMC"));
       
   614 			iCxCardType=ESDCardTypeIsMMC;
       
   615 
       
   616 			// Send CMD0 to re-initialise the card - otherwise we may get 
       
   617 			// KMMCStatErrIllegalCommand returned for the next command
       
   618 			// expecting an R1 response. NB The SD spec recommends ignoring the error
       
   619 			// whereas the SDIO spec recommends this approach (ignoring the error
       
   620 			// would be difficult to code anyway, since by then we're no longer
       
   621 			// in this state machine).
       
   622 			SMF_INVOKES(GoIdleSMST, EStSetFullRangeCmd);	// Repeat - but using CMD1
       
   623 			}
       
   624 		else
       
   625 			{
       
   626 			// No response timeout - so it must be an SD Card
       
   627 			(CardArray().CardP(iCxCardCount)->iFlags)|=KSDCardIsSDCard;
       
   628 			iCxCardType=ESDCardTypeIsSD;
       
   629 			}
       
   630 
       
   631 	SMF_STATE(EStFullRangeDone)
       
   632 
       
   633 		if (!err)												
       
   634 			{
       
   635 			// Card responded with Op range - evaluate the common subset with the current setting.
       
   636 			// Dont worry about the busy bit for now, we'll check that when we repeat the command
       
   637 			const TUint32 range = (iCurrentOpRange & ~KMMCOCRAccessModeHCS) & (TMMC::BigEndian32(s.ResponseP()) & ~KMMCOCRBusy);
       
   638 			if(range == 0)
       
   639 				{
       
   640 				return( KMMCErrNotSupported ); // Card is incompatible with our h/w
       
   641 				}
       
   642 			iCurrentOpRange = range | (iCurrentOpRange & KMMCOCRAccessModeHCS);
       
   643 			}
       
   644 
       
   645 		// Repeat SEND_OP_COND this time setting Current Op Range
       
   646 		if (iCxCardType==ESDCardTypeIsMMC)
       
   647 			{
       
   648 			// If platform and the card both support low voltage mode (1.65 - 1.95v), switch
       
   649 			// NB If this fails then there is no recovery.
       
   650 			if (iCurrentOpRange & KMMCOCRLowVoltage)
       
   651 				{
       
   652 				iCurrentOpRange = KMMCOCRLowVoltage;
       
   653 				SMF_INVOKES( SwitchToLowVoltageSMST, EStSetRangeCmd )
       
   654 				}
       
   655 			}
       
   656 
       
   657 	SMF_STATE(EStSetRangeCmd)
       
   658 
       
   659 		// Issue ACMD41/CMD1 with voltage range
       
   660 		if (iCxCardType==ESDCardTypeIsMMC)
       
   661 			{
       
   662 			s.FillCommandDesc(ECmdSendOpCond,(iCurrentOpRange | KMMCOCRAccessModeHCS | KMMCOCRBusy)); // Range supported + Sector Access Busy bit (iArgument==KBit31)
       
   663 			SMF_NEXTS(EStSetRangeBusyCheck)
       
   664 			}
       
   665 		else
       
   666 			{
       
   667 			TUint arg = (iCurrentOpRange & ~KMMCOCRAccessModeHCS); // Range supported
       
   668 			if((iCurrentOpRange & KMMCOCRAccessModeHCS) != 0)
       
   669 				{
       
   670 				arg |= KMMCOCRAccessModeHCS;
       
   671 				}
       
   672 			DSDSession::FillAppCommandDesc(Command(), ESDACmdSDAppOpCond, arg);
       
   673 			SMF_NEXTS((iCxCardType == ESDCardTypeUnknown)? EStCheckForRangeCmd41Timeout : EStSetRangeBusyCheck)
       
   674 			}
       
   675 
       
   676 		m.SetTraps(KMMCErrResponseTimeOut);
       
   677 		SMF_CALL(ExecCommandSMST)
       
   678 
       
   679 	SMF_STATE(EStCheckForRangeCmd41Timeout)
       
   680 	
       
   681 		__KTRACE_OPT(KPBUS1, Kern::Printf("-mst:ascs:crct:%d", err));
       
   682 		if (err==KMMCErrResponseTimeOut)	
       
   683 			{
       
   684 			iCxCardType=ESDCardTypeIsMMC;
       
   685 			// Send CMD0 to re-initialise the card - otherwise we may get 
       
   686 			// KMMCStatErrIllegalCommand returned for the next command
       
   687 			// expecting an R1 response. NB The SD spec recommends ignoring the error
       
   688 			// whereas the SDIO spec recommends this approach (ignoring the error
       
   689 			// would be difficult to code anyway, since by then we're no longer
       
   690 			// in this state machine).
       
   691 			SMF_INVOKES(GoIdleSMST, EStSetRangeCmd);	// Repeat - but using CMD1
       
   692 			}
       
   693 		else
       
   694 			{
       
   695 			// No response timeout - so it must be an SD Card
       
   696 			__KTRACE_OPT(KPBUS1, Kern::Printf("-mst:ascs:crct2:%x", iCardArray));
       
   697 			__KTRACE_OPT(KPBUS1, Kern::Printf("-mst:ascs:crct3:%x", iCxCardCount));
       
   698 			__KTRACE_OPT(KPBUS1, Kern::Printf("-mst:ascs:crct4:%x", CardArray().CardP(iCxCardCount)));
       
   699 
       
   700 			(CardArray().CardP(iCxCardCount)->iFlags)|=KSDCardIsSDCard;
       
   701 			iCxCardType=ESDCardTypeIsSD;
       
   702 			}
       
   703 			
       
   704 	SMF_STATE(EStSetRangeBusyCheck)
       
   705 
       
   706 		__KTRACE_OPT(KPBUS1, Kern::Printf("-mst:ascs:src:%d",iCxCardType)); // 1:MMC, 2:SD
       
   707 		
       
   708 		if ( !err )
       
   709 			{
       
   710 			const TUint32 ocrResponse = TMMC::BigEndian32(s.ResponseP());
       
   711 
       
   712 			if ((ocrResponse & KMMCOCRBusy) == 0)	
       
   713 				{
       
   714 				__KTRACE_OPT(KPBUS1,Kern::Printf("-sd:upd:bsy"));
       
   715 				// Card is still busy powering up. Check if we should timeout
       
   716 				if ( ++iCxPollRetryCount > iConfig.OpCondBusyTimeout() )
       
   717 					{
       
   718 					__KTRACE_OPT2(KPBUS1, KPANIC, Kern::Printf("-sd:ocr busy timed out"));
       
   719 					return( KMMCErrBusTimeOut );
       
   720 					}
       
   721 					
       
   722 #ifdef _DEBUG
       
   723 				if ( iCxPollRetryCount > KMMCSpecOpCondBusyTimeout )
       
   724 					{
       
   725 					__KTRACE_OPT2(KPBUS1, KPANIC, Kern::Printf("-sd:ocr exceeded spec timeout!! (%d ms)", (iCxPollRetryCount*KMMCRetryGapInMilliseconds)));
       
   726 					}
       
   727 #endif
       
   728 				m.ResetTraps(); 
       
   729 
       
   730 				SMF_INVOKES(RetryGapTimerSMST,EStSetRangeCmd)
       
   731 				}
       
   732 			else
       
   733 				{
       
   734 				if(ocrResponse & KMMCOCRAccessModeHCS)
       
   735 					{
       
   736 					CardArray().CardP(iCxCardCount)->iFlags |= KMMCardIsHighCapacity;
       
   737 #ifdef _DEBUG				
       
   738 					if(iCxCardType == ESDCardTypeIsSD)
       
   739 						{
       
   740 						__KTRACE_OPT(KPBUS1, Kern::Printf("Found large SD card."));
       
   741 						}
       
   742 					else if(iCxCardType == ESDCardTypeIsMMC)
       
   743 						{
       
   744 						__KTRACE_OPT(KPBUS1, Kern::Printf("Found large MMC card."));
       
   745 						}
       
   746 #endif
       
   747 					}
       
   748 				}
       
   749 			}
       
   750 
       
   751 		// Restore original settings
       
   752 		iConfig.SetMode( EffectiveModes(s.iConfig) & KMMCModeEnableTimeOutRetry );
       
   753 		iConfig.SetPollAttempts(KMMCMaxPollAttempts);
       
   754 
       
   755 		// All cards are now ready and notified of the voltage range - ask ASSP to set it up
       
   756 		if (iCxCardType==ESDCardTypeIsMMC)
       
   757 			{
       
   758 			iCurrentOpRange &= ~KMMCOCRAccessModeMask;
       
   759 			}
       
   760 		else
       
   761 			{
       
   762 			iCurrentOpRange &= ~KMMCOCRAccessModeHCS;
       
   763 			}
       
   764 
       
   765 		psu->SetVoltage(iCurrentOpRange);
       
   766 		if (psu->SetState(EPsuOnFull) != KErrNone)
       
   767 			{
       
   768 			return(KMMCErrHardware);
       
   769 			}
       
   770 
       
   771 	SMF_STATE(EStCIDCmd)
       
   772 
       
   773 		s.FillCommandDesc(ECmdAllSendCID,0);
       
   774 		m.ResetTraps();
       
   775 		SMF_INVOKES(ExecCommandSMST,EStSendCIDIssued)
       
   776 
       
   777 	SMF_STATE(EStSendCIDIssued)
       
   778 
       
   779 
       
   780 		// All done - Higher level state machine expects CID in s.ResponseP()
       
   781 
       
   782 	SMF_END
       
   783 	}
       
   784 
       
   785 TMMCErr DSDStack::ConfigureMemoryCardSMST(TAny* aStackP)
       
   786 	{ return static_cast<DSDStack*>(aStackP)->ConfigureMemoryCardSM(); }
       
   787 
       
   788 TMMCErr DSDStack::ConfigureMemoryCardSM()
       
   789 /**
       
   790 */
       
   791 	{
       
   792 		enum states
       
   793 			{
       
   794 			EStBegin=0,
       
   795 			EStSendCSDDone,
       
   796 			EStEnd
       
   797 			};
       
   798 
       
   799 		DMMCSession& s=Session();
       
   800 
       
   801 	//coverity[UNREACHABLE]
       
   802 	//Part of state machine design.
       
   803 	SMF_BEGIN
       
   804 
       
   805 		// Cards is initialised so get its CSD
       
   806 
       
   807 		s.FillCommandDesc(ECmdSendCSD, TUint32(CardArray().CardP(iCxCardCount)->iRCA) << 16);
       
   808 		SMF_INVOKES(ExecCommandSMST, EStSendCSDDone)
       
   809 
       
   810 	SMF_STATE(EStSendCSDDone)
       
   811 
       
   812 		// Store the CSD in the new card entry
       
   813 		TMMCard* cardP = CardArray().CardP(iCxCardCount);
       
   814 		cardP->iCSD = s.ResponseP();
       
   815 
       
   816 		if(CardArray().Card(iCxCardCount).IsSDCard())
       
   817 			{
       
   818 			// Perform SD Specific parsing of the CSD structure
       
   819 			if(cardP->CSD().CCC() & KMMCCmdClassLockCard)
       
   820 				{
       
   821 				cardP->iFlags |= KMMCardIsLockable;
       
   822 				}
       
   823 			}
       
   824 		else
       
   825 			{
       
   826 			// Perform MMC Specific parsing of the CSD structure
       
   827 			TUint specVers = cardP->CSD().SpecVers();	// 1 => 1.4, 2 => 2.0 - 2.2, 3 => 3.1
       
   828 			if ((specVers >= 2) && (cardP->CSD().CCC() & KMMCCmdClassLockCard))
       
   829 				{
       
   830 				cardP->iFlags |= KMMCardIsLockable;
       
   831 				}
       
   832 			}
       
   833 		
       
   834 		// Check the state of the mechanical write protect switch
       
   835 		if (WriteProtected(iCxCardCount))
       
   836 			{
       
   837 			cardP->iFlags |= KMMCardIsWriteProtected;
       
   838 			}
       
   839 
       
   840 	SMF_END
       
   841 	}
       
   842 
       
   843 EXPORT_C TMMCErr DSDStack::InitStackAfterUnlockSM()
       
   844 //
       
   845 // Performs initialisation of the SD card after the card has been unlocked
       
   846 //
       
   847 	{
       
   848 		enum states
       
   849 			{
       
   850 			EStBegin=0,
       
   851 			EStNextCard,
       
   852 			EStSelectCard,
       
   853 			EStSetBusWidth,
       
   854 			EStSetBusWidth1,
       
   855 			EStGetSDStatus,
       
   856 			EStGetSDStatus1,
       
   857 			EStDecodeSDStatus,
       
   858 			EStDeselectCard,
       
   859 			EStCardDeselectedReadCSD,
       
   860 			EStCSDCmdSent,
       
   861 			EStMoreCardsCheck,
       
   862 			EStEnd
       
   863 			};
       
   864 
       
   865 		DMMCSession& s=Session();
       
   866 
       
   867 	SMF_BEGIN
       
   868 
       
   869         __KTRACE_OPT(KPBUS1, Kern::Printf(">DSDStack::InitStackAfterUnlockSM()"));
       
   870 		iRCAPool.ReleaseUnlocked();
       
   871 		iCxCardCount=0; 		// Reset current card number
       
   872 
       
   873 	SMF_STATE(EStNextCard)	    
       
   874 		AddressCard(iCxCardCount); 	// Address the next card
       
   875 
       
   876 		if (!CardDetect(iCxCardCount))
       
   877 			SMF_GOTOS(EStMoreCardsCheck)
       
   878 
       
   879 		s.SetCard(CardArray().CardP(iCxCardCount));
       
   880 
       
   881 		if (!CardArray().Card(iCxCardCount).IsSDCard())
       
   882 			{
       
   883 			SMF_INVOKES( DMMCStack::InitCurrentCardAfterUnlockSMST, EStMoreCardsCheck )
       
   884 			}
       
   885 
       
   886 	SMF_STATE(EStSelectCard)
       
   887 
       
   888 		TRCA targetRCA = CardArray().Card(iCxCardCount).RCA();
       
   889 		if (targetRCA == SelectedCard())
       
   890 			{
       
   891 			SMF_GOTOS(EStSetBusWidth)
       
   892 			}
       
   893 
       
   894 		s.FillCommandDesc(ECmdSelectCard, targetRCA);
       
   895 		SMF_INVOKES(ExecCommandSMST,EStSetBusWidth)
       
   896 
       
   897 	SMF_STATE(EStSetBusWidth)
       
   898 		const TMMCStatus status = s.LastStatus();
       
   899 		if((status & KMMCStatCardIsLocked) != 0)
       
   900 			SMF_GOTOS(EStDeselectCard)
       
   901 
       
   902 		// set bus width with ACMD6
       
   903 		TUint32 arg = TUint32(CardArray().Card(iCxCardCount).RCA()) << 16;
       
   904 		s.FillCommandDesc(ECmdAppCmd, arg);
       
   905 		SMF_INVOKES(IssueCommandCheckResponseSMST,EStSetBusWidth1)
       
   906 
       
   907 	SMF_STATE(EStSetBusWidth1)
       
   908 		CardArray().Card(iCxCardCount).SetBusWidth(4);
       
   909 		DSDSession::FillAppCommandDesc(Command(), ESDACmdSetBusWidth, KSDBusWidth4);
       
   910 		SMF_INVOKES(IssueCommandCheckResponseSMST,EStGetSDStatus)
       
   911 
       
   912 	SMF_STATE(EStGetSDStatus)
       
   913 		// Now we have sent ACMD6, ask the controller to set the bus width to 4
       
   914 		DoSetBusWidth(EBusWidth4);
       
   915 
       
   916 		// get protected area size with ACMD13
       
   917 		TUint32 arg = TUint32(CardArray().Card(iCxCardCount).RCA()) << 16;
       
   918 		s.FillCommandDesc(ECmdAppCmd,arg);
       
   919 		SMF_INVOKES(IssueCommandCheckResponseSMST,EStGetSDStatus1)
       
   920 
       
   921 	SMF_STATE(EStGetSDStatus1)
       
   922 		DSDSession::FillAppCommandDesc(Command(), ESDACmdSDStatus);
       
   923 		s.FillCommandArgs(0, KSDStatusBlockLength, iPSLBuf, KSDStatusBlockLength);
       
   924 		SMF_INVOKES(IssueCommandCheckResponseSMST,EStDecodeSDStatus);
       
   925 
       
   926 	SMF_STATE(EStDecodeSDStatus)
       
   927 #ifdef _DEBUG
       
   928 		for (TUint i = 0; i < KSDStatusBlockLength; ++i)
       
   929 			{
       
   930 			__KTRACE_OPT(KPBUS1, Kern::Printf("SD_STATUS[0x%x] = %x", i, iPSLBuf[i]));
       
   931 			}
       
   932 #endif
       
   933 		// bits 495:480 are SD_CARD_TYPE.  Check this is 00xxh (x = don't care).
       
   934 
       
   935 		if (iPSLBuf[2] != 0)
       
   936 			return KMMCErrNotSupported;
       
   937 
       
   938 		// bits 479:448 contain SIZE_OF_PROTECTED_AREA.  
       
   939 		// (This is bytes 4 to 7 in big-endian format.)
       
   940 
       
   941 		TSDCard& sdc = CardArray().Card(iCxCardCount);
       
   942 		__KTRACE_OPT(KPBUS1, Kern::Printf("\t >DSDStack: Card %d", iCxCardCount));
       
   943 		TUint32 size_of_protected_area = TMMC::BigEndian32(&iPSLBuf[4]);
       
   944 		__KTRACE_OPT(KPBUS1, Kern::Printf("\t >DSDStack: SizeOfProtectedArea: %d", size_of_protected_area));
       
   945 		const TCSD& csd = sdc.CSD();
       
   946 		TUint32 pas = 0;
       
   947 		
       
   948 		if (sdc.IsHighCapacity())
       
   949 			{
       
   950 			// High Capacity Card
       
   951 			// Protected Area = SIZE_OF_PROTECTED_AREA
       
   952 			pas = size_of_protected_area;
       
   953 			__KTRACE_OPT(KPBUS1, Kern::Printf("\t >DSDStack(SDHC): SetProtectedAreaSize: %d", pas));
       
   954 			}
       
   955 		else
       
   956 			{
       
   957 			// Standard Capacity Card
       
   958 			// Protected Area = SIZE_OF_PROTECTED_AREA * C_SIZE_MULT * BLOCK_LEN
       
   959 			pas = size_of_protected_area * (1 << (csd.CSizeMult() + 2 + csd.ReadBlLen()));
       
   960 			__KTRACE_OPT(KPBUS1, Kern::Printf("\t >DSDStack(SDSC): SetProtectedAreaSize: %d", pas));
       
   961 			}		
       
   962 
       
   963 		sdc.SetProtectedAreaSize(pas);
       
   964 
       
   965 		//bits 431:428 contain AU_SIZE
       
   966 		//(This is higher order 4 bits of 10th byte in big endian format)
       
   967 		TUint8 au = TUint8(iPSLBuf[10] >> 4);
       
   968 		if(au == 0)	    //AU_SIZE field in SD status register is undefined.
       
   969 			au = 6;		//Defaulting to value corresponding to 512K	
       
   970 		sdc.SetAUSize(au);
       
   971 
       
   972 		SMF_INVOKES(SwitchToHighSpeedModeSMST, EStDeselectCard)
       
   973 
       
   974 	SMF_STATE(EStDeselectCard)
       
   975 		s.FillCommandDesc(ECmdSelectCard, 0);
       
   976 		SMF_INVOKES(ExecCommandSMST, EStCardDeselectedReadCSD)
       
   977     
       
   978 	SMF_STATE(EStCardDeselectedReadCSD)
       
   979 		//
       
   980       	// Read the card's CSD register (again)
       
   981 		//
       
   982 		//  - We re-read the CSD, as the TRAN_SPEED field may have changed due to a switch to HS Mode
       
   983 		//
       
   984       	TUint32 arg = TUint32(CardArray().Card(iCxCardCount).RCA()) << 16;
       
   985       	s.FillCommandDesc( ECmdSendCSD, arg );
       
   986       	SMF_INVOKES(ExecCommandSMST, EStCSDCmdSent)
       
   987 
       
   988 	SMF_STATE(EStCSDCmdSent)
       
   989 		//
       
   990       	// Store the CSD in the card entry
       
   991 		//
       
   992       	TMMCard* cardP = iCardArray->CardP(iCxCardCount);
       
   993       	cardP->iCSD = s.ResponseP();
       
   994 
       
   995 	SMF_STATE(EStMoreCardsCheck)
       
   996 		if (++iCxCardCount < (TInt)iMaxCardsInStack)
       
   997 		    {
       
   998 		    __KTRACE_OPT(KPBUS1, Kern::Printf("\t >DSDStack: Address Next card: %d",iCxCardCount));
       
   999 			SMF_GOTOS(EStNextCard)
       
  1000 		    }
       
  1001 		else
       
  1002 		    {
       
  1003 			AddressCard(KBroadcastToAllCards);
       
  1004 			__KTRACE_OPT(KPBUS1, Kern::Printf("<DSDStack::InitStackAfterUnlockSM()"));
       
  1005 		    }
       
  1006 
       
  1007 	SMF_END
       
  1008 	
       
  1009 	}
       
  1010 
       
  1011 TMMCErr DSDStack::CIMReadWriteMemoryBlocksSMST(TAny* aStackP)
       
  1012 	{ return( static_cast<DSDStack *>(aStackP)->DMMCStack::CIMReadWriteBlocksSM() ); }
       
  1013 
       
  1014 
       
  1015 EXPORT_C TMMCErr DSDStack::CIMReadWriteBlocksSM()
       
  1016 //
       
  1017 // This macro performs single/multiple block reads and writes
       
  1018 // For normal read/write block operations, this function determines the appropriate
       
  1019 // MMC command to send and fills the command descriptor accordingly based on 
       
  1020 // the value of the session ID set. However, it is necessary to have set the
       
  1021 // command arguments (with DMMCSession::FillCommandArgs()) before this function
       
  1022 // is called.
       
  1023 // For special block read/write operations, e.g. lock/unlock, it is required to
       
  1024 // have already filled the command descriptor (with DMMCSession::FillCommandDesc())
       
  1025 // for the special command required - in addition to have setup the command arguments.
       
  1026 //
       
  1027 	{
       
  1028 		enum states
       
  1029 			{
       
  1030 			EStBegin=0,
       
  1031 			EStRestart,
       
  1032 			EStAttached,
       
  1033 			EStLength1,
       
  1034 			EStLengthSet,
       
  1035 			EStIssued,
       
  1036 			EStWaitFinish,
       
  1037 			EStWaitFinish1,
       
  1038 			EStRWFinish,
       
  1039 			EStDone,
       
  1040 			EStEnd
       
  1041 			};
       
  1042 
       
  1043 		DMMCSession& s = Session();
       
  1044 
       
  1045 		__KTRACE_OPT(KPBUS1,Kern::Printf(">SD:RWBlocksSM %x",TUint(s.iLastStatus)));
       
  1046 
       
  1047 	SMF_BEGIN
       
  1048 
       
  1049 		TSDCard& sdCard = *static_cast<TSDCard*>(s.iCardP);
       
  1050 		AddressCard(sdCard.iIndex-1);
       
  1051 
       
  1052 		if(sdCard.IsSDCard() == EFalse)
       
  1053 			{
       
  1054 			//
       
  1055 			// If this is not an SD card, then use the more appropriate
       
  1056 			// MMC state machine as this is optimised for MMC performance
       
  1057 			//
       
  1058 			SMF_INVOKES(CIMReadWriteMemoryBlocksSMST, EStDone);
       
  1059 			}
       
  1060 
       
  1061 		if(s.iSessionID == ECIMWriteBlock || s.iSessionID == ECIMWriteMBlock)
       
  1062 			{
       
  1063 			// Check that the card supports class 4 (Write) commands
       
  1064 			const TUint ccc = s.iCardP->CSD().CCC();
       
  1065 			if(!(ccc & KMMCCmdClassBlockWrite))
       
  1066 				return( KMMCErrNotSupported );
       
  1067 			}
       
  1068 
       
  1069 		Command().iCustomRetries = 0;			// MBW retries
       
  1070 		s.iState |= KMMCSessStateInProgress;
       
  1071 		m.SetTraps(KMMCErrInitContext);
       
  1072 
       
  1073 	SMF_STATE(EStRestart)		// NB: ErrBypass is not processed here
       
  1074 
       
  1075 		SMF_CALLMEWR(EStRestart) // Create a recursive call entry to recover from the errors trapped
       
  1076 		m.SetTraps(KMMCErrStatus);
       
  1077 		if (s.Command().iSpec.iCommandClass!=KMMCCmdClassApplication || s.Command().iCommand==ECmdAppCmd )
       
  1078 			{
       
  1079 			s.ResetCommandStack();
       
  1080 			SMF_INVOKES( AttachCardSMST, EStAttached )	// attachment is mandatory here
       
  1081 			}
       
  1082 
       
  1083 	SMF_BPOINT(EStAttached)
       
  1084 
       
  1085 		TMMCCommandDesc& cmd = s.Command();
       
  1086 
       
  1087 		const TUint32 blockLength = cmd.BlockLength();
       
  1088 		if((blockLength == 0) || (blockLength > (TUint)KDefaultBlockLenInBytes))
       
  1089 			{
       
  1090 			__KTRACE_OPT(KPBUS1,Kern::Printf(">SD:RWBlocksSM err BlockLen:%d",blockLength));
       
  1091 			return KMMCErrArgument;
       
  1092 			}
       
  1093 
       
  1094 		if(s.iSessionID == ECIMReadBlock	||
       
  1095 		   s.iSessionID == ECIMWriteBlock	||
       
  1096 		   s.iSessionID == ECIMReadMBlock	||
       
  1097 		   s.iSessionID == ECIMWriteMBlock)
       
  1098 			{	
       
  1099 			// read/write operation
       
  1100 			if(!cmd.AdjustForBlockOrByteAccess(s))
       
  1101 				{
       
  1102 				// unable to convert command arguments to suit the underlying block/byte access mode
       
  1103 				return KMMCErrArgument;
       
  1104 				}
       
  1105 			}
       
  1106 
       
  1107 		// Set the block length if it has changed. Always set for ECIMLockUnlock.
       
  1108 		if ((blockLength == s.iCardP->iSetBlockLen) && (s.iSessionID != ECIMLockUnlock))
       
  1109 			{
       
  1110 			SMF_GOTOS( EStLengthSet )
       
  1111 			}
       
  1112 
       
  1113 		s.iCardP->iSetBlockLen = 0;
       
  1114 		s.PushCommandStack();
       
  1115 		s.FillCommandDesc( ECmdSetBlockLen, blockLength );
       
  1116 		SMF_INVOKES( ExecCommandSMST, EStLength1 )
       
  1117 
       
  1118 	SMF_STATE(EStLength1)
       
  1119 
       
  1120 		const TMMCStatus status(s.ResponseP());
       
  1121 		s.PopCommandStack();
       
  1122 		if (status.Error())
       
  1123 			SMF_RETURN(KMMCErrStatus)
       
  1124 		s.iCardP->iSetBlockLen = s.Command().BlockLength();
       
  1125 
       
  1126 	SMF_STATE(EStLengthSet)
       
  1127 
       
  1128 		TMMCCommandDesc& cmd = s.Command();
       
  1129 		TUint opType = 0;
       
  1130 		const TUint kTypeWrite =	KBit0;
       
  1131 		const TUint kTypeMultiple =	KBit1;
       
  1132 		const TUint kTypeSpecial =	KBit2;
       
  1133 		static const TMMCCommandEnum cmdCodes[4] =
       
  1134 			{ECmdReadSingleBlock, ECmdWriteBlock, ECmdReadMultipleBlock, ECmdWriteMultipleBlock};
       
  1135 
       
  1136 		switch( s.iSessionID )
       
  1137 			{
       
  1138 			case ECIMReadBlock:
       
  1139 				break;
       
  1140 			case ECIMWriteBlock:
       
  1141 				opType=kTypeWrite;
       
  1142 				break;
       
  1143 			case ECIMReadMBlock:
       
  1144 				opType=kTypeMultiple;
       
  1145 				break;
       
  1146 			case ECIMWriteMBlock:
       
  1147 				opType=kTypeWrite|kTypeMultiple;
       
  1148 				break;
       
  1149 			case ECIMLockUnlock:
       
  1150 			default:
       
  1151 				opType=kTypeSpecial;
       
  1152 				break;
       
  1153 			}
       
  1154 
       
  1155 		const TUint blocks = cmd.iTotalLength / cmd.BlockLength();
       
  1156 		if ( blocks * cmd.BlockLength() != cmd.iTotalLength )
       
  1157 			return( KMMCErrArgument );
       
  1158 
       
  1159 		if ( !(opType & kTypeSpecial) )	// A special session has already set its command descriptor
       
  1160 			{
       
  1161 			if (blocks==1)
       
  1162 				opType &= ~kTypeMultiple;
       
  1163 
       
  1164 			TUint32 oldFlags = cmd.iFlags;		// Store the existing command flags, as they will be reset by FillCommandDesc()
       
  1165 			cmd.iCommand = cmdCodes[opType];
       
  1166 			s.FillCommandDesc();
       
  1167 			cmd.iFlags = oldFlags;				// ...and restore the old command flags
       
  1168 			}
       
  1169 
       
  1170 		// NB We need to trap KMMCErrStatus errors, because if one occurs, 
       
  1171 		// we still need to wait to exit PRG/RCV/DATA state 
       
  1172 		if (Command().iCommand == ECmdWriteMultipleBlock)
       
  1173 			{
       
  1174 			Command().iExecNotHandle = KMMCErrDataCRC | KMMCErrDataTimeOut;
       
  1175 			m.SetTraps(KMMCErrStatus | KMMCErrDataCRC | KMMCErrDataTimeOut);
       
  1176 			}
       
  1177 		else
       
  1178 			{
       
  1179 			m.SetTraps(KMMCErrStatus);
       
  1180 			}
       
  1181 
       
  1182 		SMF_INVOKES( ExecCommandSMST, EStIssued )
       
  1183 
       
  1184 	SMF_STATE(EStIssued)
       
  1185 
       
  1186 		// check state of card after data transfer with CMD13.
       
  1187 		if (s.Command().Direction() != 0)
       
  1188 			{
       
  1189 			SMF_GOTOS(EStWaitFinish)
       
  1190 			}
       
  1191 
       
  1192 		SMF_GOTOS(EStRWFinish);
       
  1193 
       
  1194 	SMF_STATE(EStWaitFinish)
       
  1195 		// if MBW fail, then recover by rewriting ALL blocks...
       
  1196 		// (used to recover using ACMD22, but this has been changed
       
  1197 		// as is difficult to test for little gain in efficiency)
       
  1198 		if (Command().iCommand == ECmdWriteMultipleBlock && err != 0)
       
  1199 			{
       
  1200 			if (Command().iCustomRetries++ >= (TInt) KSDMaxMBWRetries)
       
  1201 				{
       
  1202 				SMF_RETURN(err)
       
  1203 				}
       
  1204 
       
  1205 			m.Pop();		// remove recursive call to EStRestart
       
  1206 			SMF_GOTOS(EStRestart)			
       
  1207 			}
       
  1208 
       
  1209 		// Save the status and examine it after issuing CMD13...
       
  1210 		// NB We don't know where in the command stack the last response is stored (e.g. there may 
       
  1211 		// have bee a Deselect/Select issued), but we do know last response is stored in iLastStatus
       
  1212 		TMMC::BigEndian4Bytes(s.ResponseP(), s.iLastStatus);
       
  1213 
       
  1214 		// ...else issue CMD13 to poll for the card finishing and check for errors
       
  1215 		s.PushCommandStack();
       
  1216 		s.FillCommandDesc(ECmdSendStatus, 0);
       
  1217 		SMF_INVOKES(ExecCommandSMST, EStWaitFinish1)
       
  1218 
       
  1219 	SMF_STATE(EStWaitFinish1)
       
  1220 
       
  1221 		const TMMCStatus status(s.ResponseP());
       
  1222 		s.PopCommandStack();
       
  1223 
       
  1224 #ifdef __WINS__
       
  1225 		SMF_GOTOS(EStRWFinish);
       
  1226 #else
       
  1227 		const TMMCardStateEnum st1 = status.State();
       
  1228 
       
  1229 		if (st1 == ECardStatePrg || st1 == ECardStateRcv || st1 == ECardStateData)
       
  1230 			{
       
  1231 			SMF_INVOKES(ProgramTimerSMST, EStWaitFinish);
       
  1232 			}
       
  1233 
       
  1234 		if (status.Error())
       
  1235 			SMF_RETURN(KMMCErrStatus)
       
  1236 #endif
       
  1237 		
       
  1238 		// Fall through if CURRENT_STATE is not PGM or DATA
       
  1239 	SMF_STATE(EStRWFinish)
       
  1240 
       
  1241 		if (TMMCStatus(s.ResponseP()).Error() != 0)
       
  1242 			SMF_RETURN(KMMCErrStatus);
       
  1243 
       
  1244 		s.iState &= ~KMMCSessStateInProgress;
       
  1245 
       
  1246 		// skip over recursive entry or throw error and catch in CIMLockUnlockSM()
       
  1247 		return (s.Command().iCommand == ECmdLockUnlock) ? KMMCErrUpdPswd : KMMCErrBypass;
       
  1248 
       
  1249 	SMF_STATE(EStDone)
       
  1250 	    
       
  1251 	    __KTRACE_OPT(KPBUS1,Kern::Printf("<SD:RWBlocksSM()"));
       
  1252 
       
  1253 	SMF_END
       
  1254 	}
       
  1255 
       
  1256 EXPORT_C TMMCErr DSDStack::ModifyCardCapabilitySM()
       
  1257 //
       
  1258 // This function provides a chance to modify the capability of paticular cards.
       
  1259 // Licensee may overide this function to modify certain card's capability as needed.
       
  1260 // A state machine is needed in derived function and function of base class should be
       
  1261 // called in order to act more generic behaviour.
       
  1262 //
       
  1263     {
       
  1264 		enum states
       
  1265 			{
       
  1266 			EStBegin=0,
       
  1267 			EStDone,
       
  1268 			EStEnd
       
  1269 			};
       
  1270 
       
  1271 	//coverity[unreachable]
       
  1272 	//Part of state machine design.
       
  1273 	SMF_BEGIN
       
  1274 
       
  1275     	SMF_INVOKES( DMMCStack::BaseModifyCardCapabilitySMST, EStDone )
       
  1276 
       
  1277     SMF_STATE(EStDone)
       
  1278 
       
  1279     SMF_END
       
  1280 	}
       
  1281 
       
  1282 inline TMMCErr DSDStack::SwitchToHighSpeedModeSMST( TAny* aStackP )
       
  1283 	{ return( static_cast<DSDStack *>(aStackP)->DSDStack::SwitchToHighSpeedModeSM() ); }
       
  1284 
       
  1285 TMMCErr DSDStack::SwitchToHighSpeedModeSM()
       
  1286 	{
       
  1287 		enum states
       
  1288 			{
       
  1289 			EStBegin=0,
       
  1290 			EstCheckController,
       
  1291 			EStSendSCRCmd,
       
  1292 			EStCheckSpecVer,
       
  1293 			EStCheckFunction,
       
  1294 			EStCheckFunctionSent,
       
  1295 			EStSwitchFunctionSent,
       
  1296 			EStDone,
       
  1297 			EStEnd
       
  1298 			};
       
  1299 
       
  1300 		__KTRACE_OPT(KPBUS1,Kern::Printf(">SD:SwitchToHighSpeedModeSM "));
       
  1301 
       
  1302 		DMMCSession& s = Session();
       
  1303 
       
  1304 	SMF_BEGIN
       
  1305 
       
  1306 	SMF_STATE(EstCheckController) 	
       
  1307 	  	// Get the clock speed supported by the controller
       
  1308 		TMMCMachineInfoV4 machineInfo;
       
  1309 		TMMCMachineInfoV4Pckg machineInfoPckg(machineInfo);
       
  1310 		MachineInfo(machineInfoPckg);
       
  1311 		
       
  1312 		if (machineInfo.iVersion >= TMMCMachineInfoV4::EVersion4)
       
  1313 			{
       
  1314 			if (machineInfo.iMaxClockSpeedInMhz < (KSDDTClk50MHz/1000) )
       
  1315 				{
       
  1316 				__KTRACE_OPT(KPBUS1, Kern::Printf("High speed mode not supported by controller"));
       
  1317 				SMF_GOTOS(EStDone);
       
  1318 				}
       
  1319 			}	
       
  1320 
       
  1321 	SMF_STATE(EStSendSCRCmd)
       
  1322 		//
       
  1323       	// ACMD51 Read the SD Configuration Register
       
  1324       	//
       
  1325 		DSDSession::FillAppCommandDesc(Command(), ESDACmdSendSCR);
       
  1326       	s.FillCommandArgs(0, KSDSCRLength, iPSLBuf, KSDSCRLength);
       
  1327       	SMF_INVOKES(ExecCommandSMST, EStCheckSpecVer);
       
  1328 
       
  1329 	SMF_STATE(EStCheckSpecVer)
       
  1330       	//	
       
  1331       	// Check the SD version
       
  1332 		//
       
  1333       	// 0 : version 1.0-1.01	: SDHS Is NOT Supported
       
  1334       	// 1 : version 1.10+	: SDHS Is Supported
       
  1335 		//
       
  1336       	__KTRACE_OPT(KPBUS1,Kern::Printf("   SD Configuration Register received"));
       
  1337       	__KTRACE_OPT(KPBUS1,Kern::Printf("   ...card_status=%x", TUint(s.iLastStatus)));
       
  1338 
       
  1339 #ifdef _DEBUG
       
  1340       	for (TUint32 i = 0; i < KSDSCRLength; ++i)
       
  1341 			{
       
  1342 			__KTRACE_OPT(KPBUS1, Kern::Printf("   ...SCR_STATUS[0x%x] = %x", i, iPSLBuf[i]));
       
  1343 			}
       
  1344 #endif
       
  1345 
       
  1346       	if(iPSLBuf[0]==2)
       
  1347 			{
       
  1348 			__KTRACE_OPT(KPBUS1,Kern::Printf("   ...SD Spec Version 2"));
       
  1349 			SMF_GOTOS(EStCheckFunction);
       
  1350 			}
       
  1351   
       
  1352       	if(iPSLBuf[0]==1)
       
  1353 			{
       
  1354 			__KTRACE_OPT(KPBUS1,Kern::Printf("   ...SD Spec Version 1.10"));
       
  1355 			SMF_GOTOS(EStCheckFunction);
       
  1356 			}
       
  1357   
       
  1358       	if(iPSLBuf[0]==0)
       
  1359 			{
       
  1360 			__KTRACE_OPT(KPBUS1,Kern::Printf("   ...SD Spec Version 1.01"));
       
  1361 			SMF_GOTOS(EStDone);
       
  1362         	}
       
  1363 
       
  1364 	__KTRACE_OPT(KPBUS1,Kern::Printf("   ...SD Spec Version > 2 !"));
       
  1365 
       
  1366 	SMF_STATE(EStCheckFunction)
       
  1367 
       
  1368 		m.SetTraps(KMMCErrResponseTimeOut | KMMCErrNotSupported);
       
  1369 
       
  1370  		//
       
  1371 		// SD1.1 uses CMD6 which is not defined by the MMCA
       
  1372 		//  - fill in command details using the SD Specific command description table
       
  1373 		//
       
  1374 
       
  1375 		DSDSession::FillSdSpecificCommandDesc(Command(), ESDCmdSwitchFunction);
       
  1376 		s.FillCommandArgs(KSDCheckFunctionHighSpeed, KSDSwitchFuncLength, iPSLBuf, KSDSwitchFuncLength);
       
  1377 
       
  1378 		SMF_INVOKES(IssueCommandCheckResponseSMST,EStCheckFunctionSent)
       
  1379 
       
  1380 	SMF_STATE(EStCheckFunctionSent)
       
  1381  
       
  1382        	__KTRACE_OPT(KPBUS1,Kern::Printf("   CheckFunctionSent %x",TUint(s.iLastStatus)));
       
  1383 
       
  1384 		m.ResetTraps();
       
  1385 
       
  1386 		if(err == KMMCErrResponseTimeOut)
       
  1387 			{
       
  1388 	       	__KTRACE_OPT(KPBUS1,Kern::Printf("   ...CMD6 [Read] Response Timeout"));
       
  1389 			SMF_GOTOS(EStDone);
       
  1390 			}
       
  1391 		else if(err == KMMCErrNotSupported)
       
  1392 			{
       
  1393 	       	__KTRACE_OPT(KPBUS1,Kern::Printf("   ...CMD6 [Read] Not Supported"));
       
  1394 			SMF_GOTOS(EStDone);
       
  1395 			}
       
  1396 
       
  1397 #ifdef _DEBUG
       
  1398 		for (TUint32 i = 0; i < KSDSwitchFuncLength; ++i)
       
  1399 			{
       
  1400 	  		__KTRACE_OPT(KPBUS1, Kern::Printf("   ...SD Switch Func Status[0x%x] = %x", i, iPSLBuf[i]));
       
  1401 			}
       
  1402 
       
  1403 		m.SetTraps(KMMCErrResponseTimeOut);
       
  1404 #endif
       
  1405 
       
  1406  		//
       
  1407 		// SD1.1 uses CMD6 which is not defined by the MMCA
       
  1408 		//  - fill in command details using the SD Specific command description table
       
  1409 		//
       
  1410 
       
  1411 		DSDSession::FillSdSpecificCommandDesc(Command(), ESDCmdSwitchFunction);
       
  1412       	s.FillCommandArgs(KSDSwitchFunctionHighSpeed, KSDSwitchFuncLength, iPSLBuf, KSDSwitchFuncLength);
       
  1413 
       
  1414       	SMF_INVOKES(IssueCommandCheckResponseSMST,EStSwitchFunctionSent)
       
  1415 	
       
  1416 	SMF_STATE(EStSwitchFunctionSent)
       
  1417 
       
  1418 #ifdef _DEBUG
       
  1419 		m.ResetTraps();
       
  1420 
       
  1421 		if(err == KMMCErrResponseTimeOut)
       
  1422 			{
       
  1423 	       	__KTRACE_OPT(KPBUS1,Kern::Printf("   ...CMD6 [Write] Response Timeout"));
       
  1424 			}
       
  1425 
       
  1426 		for (TUint32 i = 0; i < KSDSwitchFuncLength; ++i)
       
  1427 			{
       
  1428 	  		__KTRACE_OPT(KPBUS1, Kern::Printf("   ...SD Switch[0x%x] = %x", i, iPSLBuf[i]));
       
  1429 			}
       
  1430 #endif
       
  1431 
       
  1432 	SMF_STATE(EStDone)
       
  1433       
       
  1434 	SMF_END
       
  1435 	}
       
  1436 
       
  1437 
       
  1438 EXPORT_C DMMCSession* DSDStack::AllocSession(const TMMCCallBack& aCallBack) const
       
  1439 /**
       
  1440 * Factory function to create DMMCSession derived object.  Non-generic MMC
       
  1441 * controllers can override this to generate more specific objects.
       
  1442 * @param aCallBack Callback function to notify the client that a session has completed
       
  1443 * @return A pointer to the new session
       
  1444 */
       
  1445 	{
       
  1446 	return new DSDSession(aCallBack);
       
  1447 	}
       
  1448 
       
  1449 EXPORT_C void DSDStack::Dummy1() {}
       
  1450 EXPORT_C void DSDStack::Dummy2() {}
       
  1451 EXPORT_C void DSDStack::Dummy3() {}
       
  1452 EXPORT_C void DSDStack::Dummy4() {}