os/kernelhwsrv/kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdcard.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdcard.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1629 @@
     1.4 +// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include <drivers/sdcard.h>
    1.20 +#include "OstTraceDefinitions.h"
    1.21 +#ifdef OST_TRACE_COMPILER_IN_USE
    1.22 +#include "locmedia_ost.h"
    1.23 +#ifdef __VC32__
    1.24 +#pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
    1.25 +#endif
    1.26 +#include "sdcardTraces.h"
    1.27 +#endif
    1.28 +
    1.29 +
    1.30 +// ======== TSDCard ========
    1.31 +
    1.32 +TSDCard::TSDCard()
    1.33 +:	iProtectedAreaSize(0), iPARootDirEnd(KPARootDirEndUnknown)
    1.34 +	{
    1.35 +	// empty
    1.36 +	}
    1.37 +
    1.38 +TInt64 TSDCard::DeviceSize64() const
    1.39 +//
    1.40 +// returns the SD device size
    1.41 +//
    1.42 +	{
    1.43 +	OstTraceFunctionEntry1( TSDCARD_DEVICESIZE64_ENTRY, this );
    1.44 +	if(iFlags & KSDCardIsSDCard)
    1.45 +		{	
    1.46 +		return (IsHighCapacity()) ? 512 * 1024 * (TInt64)(1 + CSD().CSDField(69, 48)) : TMMCard::DeviceSize64();
    1.47 +		}
    1.48 +		
    1.49 +	return(TMMCard::DeviceSize64());
    1.50 +	}
    1.51 +
    1.52 +TUint32 TSDCard::PreferredWriteGroupLength() const
    1.53 +//
    1.54 +// return SD erase sector size, (SECTOR_SIZE + 1) * 2 ** WRITE_BLK_LEN
    1.55 +//
    1.56 +	{
    1.57 +	OstTraceFunctionEntry1( TSDCARD_PREFERREDWRITEGROUPLENGTH_ENTRY, this );
    1.58 +	if(iFlags & KSDCardIsSDCard)
    1.59 +		{	
    1.60 +		TSDCSD sdcsd(CSD());
    1.61 +		return (sdcsd.SDSectorSize() + 1) * (1 << sdcsd.WriteBlLen());
    1.62 +		}
    1.63 +		
    1.64 +	return(TMMCard::PreferredWriteGroupLength());
    1.65 +	}
    1.66 +
    1.67 +TInt TSDCard::GetFormatInfo(TLDFormatInfo& /*aFormatInfo*/) const
    1.68 +	{
    1.69 +	return KErrNotSupported;
    1.70 +	}
    1.71 +
    1.72 +TUint32 TSDCard::MinEraseSectorSize() const
    1.73 +	{
    1.74 +	if(iFlags&KSDCardIsSDCard)
    1.75 +		{	
    1.76 +		TSDCSD sdcsd(CSD());
    1.77 +		if (sdcsd.SDEraseBlkEn())
    1.78 +			return sdcsd.WriteBlockLength();		// raised logarithm
    1.79 +		else
    1.80 +			return (sdcsd.SDSectorSize() + 1) * sdcsd.WriteBlockLength();
    1.81 +		}
    1.82 +
    1.83 +	return TMMCard::MinEraseSectorSize();
    1.84 +	}
    1.85 +
    1.86 +
    1.87 +const TUint32 KEraseSectorSizeShift = 8;	// KEraseSectorSizeShift determines the multiple of the sector size 
    1.88 +											// that can be erased in one operation
    1.89 +TUint32 TSDCard::EraseSectorSize() const
    1.90 +	{
    1.91 +	if(iFlags&KSDCardIsSDCard)
    1.92 +		{	
    1.93 +		TSDCSD sdcsd(CSD());
    1.94 +		return ((sdcsd.SDSectorSize() + 1) * sdcsd.WriteBlockLength()) << KEraseSectorSizeShift;
    1.95 +		}
    1.96 +
    1.97 +	return TMMCard::EraseSectorSize();
    1.98 +	}
    1.99 +
   1.100 +const TInt KDefaultBlockLen		   = 9;							// 2^9 = 512 bytes
   1.101 +const TInt KDefaultBlockLenInBytes = 1 << KDefaultBlockLen;		// 2^9 = 512 bytes
   1.102 +const TInt KTwoGbyteSDBlockLen	   = 10;						// 2^10 = 1024 bytes
   1.103 +const TInt KFourGbyteSDBlockLen	   = 11;						// 2^11 = 2048 bytes
   1.104 +
   1.105 +TInt TSDCard::GetEraseInfo(TMMCEraseInfo& aEraseInfo) const
   1.106 +//
   1.107 +// Return info. on erase services for this card
   1.108 +//
   1.109 +	{
   1.110 +	OstTraceFunctionEntry1( TSDCARD_GETERASEINFO_ENTRY, this );
   1.111 +	
   1.112 +	// SD Controllers support MMC cards too. Check if we are really dealing with an SD card
   1.113 +	if(!(iFlags&KSDCardIsSDCard))
   1.114 +		return(TMMCard::GetEraseInfo(aEraseInfo));
   1.115 +		
   1.116 +	if (CSD().CCC() & KMMCCmdClassErase)
   1.117 +		{
   1.118 +		// This card supports erase cmds. However, SD cards don't support Erase Group commands (i.e. CMD35, CMD36).
   1.119 +		OstTrace0( TRACE_INTERNALS, TSDCARD_GETERASEINFO, "Card supports erase class commands" );		
   1.120 +		aEraseInfo.iEraseFlags=KMMCEraseClassCmdsSupported; 
   1.121 +		
   1.122 +		// Return the preferred size to be used as the unit for erase operations.
   1.123 +		TSDCSD sdcsd(CSD());
   1.124 +		TUint32 prefSize=((sdcsd.SDSectorSize() + 1) * sdcsd.WriteBlockLength());
   1.125 +		prefSize<<=KEraseSectorSizeShift;		// Use multiples of the sector size for each erase operation
   1.126 +		aEraseInfo.iPreferredEraseUnitSize=prefSize;
   1.127 +	
   1.128 +		// Return the smallest size that can be used as the unit for erase operations
   1.129 +		if (sdcsd.SDEraseBlkEn())
   1.130 +			{
   1.131 +			aEraseInfo.iMinEraseSectorSize = KDefaultBlockLenInBytes;
   1.132 +			}
   1.133 +		else
   1.134 +			{
   1.135 +			aEraseInfo.iMinEraseSectorSize=(sdcsd.SDSectorSize() + 1) * sdcsd.WriteBlockLength();
   1.136 +			}
   1.137 +		}
   1.138 +	else		
   1.139 +		aEraseInfo.iEraseFlags=0;
   1.140 +		
   1.141 +	OstTraceFunctionExitExt( TSDCARD_GETERASEINFO_EXIT, this, KErrNone );
   1.142 +	return KErrNone;	
   1.143 +	}
   1.144 +
   1.145 +TInt TSDCard::MaxReadBlLen() const
   1.146 +/**
   1.147 + * Returns the maximum read block length supported by the card encoded as a logarithm
   1.148 + * Normally this is the same as the READ_BL_LEN field in the CSD register,
   1.149 + * but for high capacity cards (> 2GB) this is set to a maximum of 512 bytes,
   1.150 + * if possible, to try to avoid compatibility issues.
   1.151 + */
   1.152 +	{
   1.153 +	OstTraceFunctionEntry1( TSDCARD_MAXREADBLLEN_ENTRY, this );
   1.154 +	if (IsSDCard())
   1.155 +		{
   1.156 +		TInt blkLenLog2 = CSD().ReadBlLen();
   1.157 +		if (blkLenLog2 == KTwoGbyteSDBlockLen || blkLenLog2 == KFourGbyteSDBlockLen)
   1.158 +			{
   1.159 +			// The SD card spec. makes a special case for 2GByte cards,
   1.160 +			// ...and some manufacturers apply the same method to support 4G cards
   1.161 +			__KTRACE_OPT(KPBUS1, Kern::Printf("=mmc:mrbl > 2GB SD"));
   1.162 +			OstTrace0( TRACE_INTERNALS, TSDCARD_MAXREADBLLEN, "SD Card > 2GB" );
   1.163 +			blkLenLog2 = KDefaultBlockLen;
   1.164 +			}
   1.165 +		OstTraceFunctionExitExt( TSDCARD_MAXREADBLLEN_EXIT, this, blkLenLog2 );
   1.166 +		return blkLenLog2;
   1.167 +		}
   1.168 +	else		// MMC card
   1.169 +		{
   1.170 +		TInt ret = TMMCard::MaxReadBlLen();
   1.171 +		OstTraceFunctionExitExt( DUP1_TSDCARD_MAXREADBLLEN_EXIT, this, ret );
   1.172 +		return ret;
   1.173 +		}
   1.174 +	}
   1.175 +
   1.176 +TInt TSDCard::MaxWriteBlLen() const
   1.177 +/**
   1.178 + * Returns the maximum write block length supported by the card encoded as a logarithm
   1.179 + * Normally this is the same as the WRITE_BL_LEN field in the CSD register,
   1.180 + * but for high capacity cards (> 2GB) this is set to a maximum of 512 bytes,
   1.181 + * if possible, to try to avoid compatibility issues.
   1.182 + */
   1.183 +	{
   1.184 +	OstTraceFunctionEntry1( TSDCARD_MAXWRITEBLLEN_ENTRY, this );
   1.185 +	if (IsSDCard())
   1.186 +		{
   1.187 +		TInt blkLenLog2 = CSD().WriteBlLen();
   1.188 +		if (blkLenLog2 == KTwoGbyteSDBlockLen || blkLenLog2 == KFourGbyteSDBlockLen)
   1.189 +			{
   1.190 +			// The SD card spec. makes a special case for 2GByte cards,
   1.191 +			// ...and some manufacturers apply the same method to support 4G cards
   1.192 +			__KTRACE_OPT(KPBUS1, Kern::Printf("=mmc:mwbl > 2GB SD"));
   1.193 +			OstTrace0( TRACE_INTERNALS, TSDCARD_MAXWRITEBLLEN, "SD Card > 2GB" );
   1.194 +			blkLenLog2 = KDefaultBlockLen;
   1.195 +			}
   1.196 +		OstTraceFunctionExitExt( TSDCARD_MAXWRITEBLLEN_EXIT, this, blkLenLog2 );
   1.197 +		return blkLenLog2;
   1.198 +		}
   1.199 +	else		// MMC card
   1.200 +		{
   1.201 +		TInt ret = TMMCard::MaxWriteBlLen();
   1.202 +		OstTraceFunctionExitExt( DUP1_TSDCARD_MAXWRITEBLLEN_EXIT, this, ret );
   1.203 +		return ret;
   1.204 +		}
   1.205 +	}
   1.206 +	
   1.207 +TUint TSDCard::MaxTranSpeedInKilohertz() const
   1.208 +/**
   1.209 + * Returns the maximum supported clock rate for the card, in Kilohertz.
   1.210 + * @return Speed, in Kilohertz
   1.211 + */
   1.212 +	{
   1.213 +	OstTraceFunctionEntry1( TSDCARD_MAXTRANSPEEDINKILOHERTZ_ENTRY, this );
   1.214 +	TUint maxClk = TMMCard::MaxTranSpeedInKilohertz();
   1.215 +	
   1.216 +	if (IsSDCard())
   1.217 +		{
   1.218 +		__KTRACE_OPT(KPBUS1, Kern::Printf("\t >TSDCard(%d): MaxTranSpeedInKilohertz: %d",(iIndex-1),maxClk));
   1.219 +		
   1.220 +#ifdef _DEBUG
   1.221 +		//MaxClk for SD should only be either 25000KHz or 50000KHz
   1.222 +		if ( (maxClk != KSDDTClk25MHz) && (maxClk != KSDDTClk50MHz) )
   1.223 +			{
   1.224 +			__KTRACE_OPT(KPBUS1, Kern::Printf("\t >DSDStack: Non-Compliant DT Clock"));
   1.225 +			OstTrace0( TRACE_INTERNALS, TSDCARD_MAXTRANSPEEDINKILOHERTZ, "Non-Compliant DT Clock" );			
   1.226 +			}
   1.227 +#endif
   1.228 +		if (maxClk > KSDDTClk50MHz)
   1.229 +			{
   1.230 +			//Clock rate exceeds SD possible max clock rate
   1.231 +			__KTRACE_OPT(KPBUS1, Kern::Printf("\t >DSDStack: Tuning DT Clock down to 50MHz"));
   1.232 +			OstTrace0( TRACE_INTERNALS, TSDCARD_MAXTRANSPEEDINKILOHERTZ1, "Tuning DT Clock down to 50MHz" );			
   1.233 +			maxClk = KSDDTClk50MHz;
   1.234 +			}
   1.235 +		}
   1.236 +		
   1.237 +	OstTraceFunctionExitExt( TSDCARD_MAXTRANSPEEDINKILOHERTZ_EXIT, this, maxClk );
   1.238 +	return maxClk;
   1.239 +	}
   1.240 +
   1.241 +// ======== TSDCardArray ========
   1.242 +
   1.243 +EXPORT_C TInt TSDCardArray::AllocCards()
   1.244 +// 
   1.245 +// allocate TSDCard objects for iCards and iNewCardsArray.  This function
   1.246 +// is called at bootup as part of stack allocation so there is no cleanup
   1.247 +// if it fails.
   1.248 +//
   1.249 +	{
   1.250 +	OstTraceFunctionEntry1( TSDCARDARRAY_ALLOCCARDS_ENTRY, this );
   1.251 +	for (TInt i = 0; i < (TInt) KMaxMMCardsPerStack; ++i)
   1.252 +		{
   1.253 +		// zeroing the card data used to be implicit because embedded in
   1.254 +		// CBase-derived DMMCStack.
   1.255 +		if ((iCards[i] = new TSDCard) == 0)
   1.256 +		    {
   1.257 +			OstTraceFunctionExitExt( TSDCARDARRAY_ALLOCCARDS_EXIT, this, KErrNoMemory );
   1.258 +			return KErrNoMemory;
   1.259 +		    }
   1.260 +		iCards[i]->iUsingSessionP = 0;
   1.261 +		if ((iNewCards[i] = new TSDCard) == 0)
   1.262 +		    {
   1.263 +			OstTraceFunctionExitExt( DUP1_TSDCARDARRAY_ALLOCCARDS_EXIT, this, KErrNoMemory );
   1.264 +			return KErrNoMemory;
   1.265 +			}
   1.266 +		}
   1.267 +
   1.268 +	OstTraceFunctionExitExt( DUP2_TSDCARDARRAY_ALLOCCARDS_EXIT, this, KErrNone );
   1.269 +	return KErrNone;
   1.270 +	}
   1.271 +
   1.272 +void TSDCardArray::AddCardSDMode(TUint aCardNumber,const TUint8* aCID,TRCA* aNewRCA)
   1.273 +//
   1.274 +// Add an MMC card straight to the main card array in slot 'aCardNumber'. Save
   1.275 +// the CID value in the slot. Return a RCA for the card.
   1.276 +//
   1.277 +	{
   1.278 +	OstTraceFunctionEntryExt( TSDCARDARRAY_ADDCARDSDMODE_ENTRY, this );
   1.279 +
   1.280 +	TRCA rca=0;
   1.281 +	
   1.282 +	// First, lets check if the same card was here before. If it was, keep the same RCA
   1.283 +	if (Card(aCardNumber).IsPresent() && Card(aCardNumber).iCID==aCID)
   1.284 +		rca=Card(aCardNumber).iRCA;
   1.285 +	else
   1.286 +		{
   1.287 +		// Allocate and new RCA and store the CID in the slot selected
   1.288 +		__ASSERT_ALWAYS( (rca=iOwningStack->iRCAPool.GetFreeRCA())!=0,DMMCSocket::Panic(DMMCSocket::EMMCNoFreeRCA) );
   1.289 +		Card(aCardNumber).iCID=aCID;
   1.290 +		if ( Card(aCardNumber).iRCA != 0 )
   1.291 +			iOwningStack->iRCAPool.UnlockRCA(Card(aCardNumber).iRCA);
   1.292 +		Card(aCardNumber).iRCA=rca;
   1.293 +		iOwningStack->iRCAPool.LockRCA(Card(aCardNumber).iRCA);
   1.294 +		}
   1.295 +
   1.296 +	Card(aCardNumber).iIndex=(aCardNumber+1); // Mark card as being present
   1.297 +	*aNewRCA=rca;
   1.298 +	OstTraceFunctionExit1( TSDCARDARRAY_ADDCARDSDMODE_EXIT, this );
   1.299 +	}
   1.300 +
   1.301 +TInt TSDCardArray::StoreRCAIfUnique(TUint aCardNumber,TRCA& anRCA)
   1.302 +//
   1.303 +// Check that no other array element has the same RCA value 'anRCA'. If no
   1.304 +// no duplication then store in slot 'aCardNumber'.
   1.305 +//
   1.306 +	{
   1.307 +	OstTraceExt3(TRACE_FLOW, TSDCARDARRAY_STORERCAIFUNIQUE_ENTRY ,"TSDCardArray::StoreRCAIfUnique;aCardNumber=%x;anRCA=%x;this=%x", aCardNumber, (TUint) anRCA, (TUint) this);
   1.308 +
   1.309 +	if (anRCA==0)
   1.310 +		{
   1.311 +		OstTraceFunctionExitExt( TSDCARDARRAY_STORERCAIFUNIQUE_EXIT, this, KErrGeneral );
   1.312 +		return KErrGeneral;
   1.313 +		}
   1.314 +	Card(aCardNumber).iRCA=0;
   1.315 +
   1.316 +	// Now let's look if we've seen this card before
   1.317 +	for ( TUint i=0 ; i<iOwningStack->iMaxCardsInStack ; i++ )
   1.318 +		{
   1.319 +		if ( Card(i).IsPresent() && Card(i).iRCA==anRCA )
   1.320 +			{
   1.321 +			OstTraceFunctionExitExt( DUP1_TSDCARDARRAY_STORERCAIFUNIQUE_EXIT, this, KErrInUse );
   1.322 +			return KErrInUse;
   1.323 +			}
   1.324 +		}
   1.325 +	Card(aCardNumber).iRCA=anRCA;
   1.326 +	Card(aCardNumber).iIndex=(aCardNumber+1); // Mark card as being present
   1.327 +	OstTraceFunctionExitExt( DUP2_TSDCARDARRAY_STORERCAIFUNIQUE_EXIT, this, KErrNone );
   1.328 +	return KErrNone;
   1.329 +	}
   1.330 +
   1.331 +EXPORT_C void TSDCardArray::DeclareCardAsGone(TUint aCardNumber)
   1.332 +//
   1.333 +// reset SD specific fields to initial values and then reset generic MultiMediaCard
   1.334 +//
   1.335 +	{
   1.336 +	OstTraceFunctionEntryExt( TSDCARDARRAY_DECLARECARDASGONE_ENTRY, this );
   1.337 +	Card(aCardNumber).SetBusWidth(1);
   1.338 +	TMMCardArray::DeclareCardAsGone(aCardNumber);
   1.339 +	OstTraceFunctionExit1( TSDCARDARRAY_DECLARECARDASGONE_EXIT, this );
   1.340 +	}
   1.341 +
   1.342 +// ======== DSDSession ========
   1.343 +
   1.344 +void DSDSession::FillAppCommandDesc(TMMCCommandDesc& aDesc, TSDAppCmd aCmd)
   1.345 +	{
   1.346 +	OstTraceFunctionEntry0( DSDSESSION_FILLAPPCOMMANDDESC_ENTRY );
   1.347 +	aDesc.iCommand = (TMMCCommandEnum) aCmd;
   1.348 +	aDesc.iArgument = 0;						// set stuff bits to zero
   1.349 +	FillAppCommandDesc(aDesc);
   1.350 +	OstTraceFunctionExit0( DSDSESSION_FILLAPPCOMMANDDESC_EXIT );
   1.351 +	}
   1.352 +
   1.353 +void DSDSession::FillAppCommandDesc(TMMCCommandDesc& aDesc, TSDAppCmd aCmd, TMMCArgument aArg)
   1.354 +	{
   1.355 +	OstTraceFunctionEntry0( DUP1_DSDSESSION_FILLAPPCOMMANDDESC_ENTRY );
   1.356 +	aDesc.iCommand = (TMMCCommandEnum) aCmd;
   1.357 +	aDesc.iArgument = aArg;
   1.358 +	FillAppCommandDesc(aDesc);
   1.359 +	OstTraceFunctionExit0( DUP1_DSDSESSION_FILLAPPCOMMANDDESC_EXIT );
   1.360 +	}
   1.361 +
   1.362 +const TUint32 CCA = KMMCCmdClassApplication;
   1.363 +const TMMCIdxCommandSpec AppCmdSpecTable[] =
   1.364 +	{						//	Class	Type		Dir			MBlk	StopT	Rsp Type		Len
   1.365 +	{ESDACmdSetBusWidth,		{CCA,ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,	4}}, //ACMD6
   1.366 +	{ESDACmdSDStatus,			{CCA,ECmdTypeADTCS,	EDirRead,	EFalse, EFalse, ERespTypeR1,	4}}, //ACMD13
   1.367 +	{ESDACmdSendNumWrBlocks,	{CCA,ECmdTypeADTCS,	EDirRead,	EFalse, EFalse, ERespTypeR1,	4}}, //ACMD22
   1.368 +	{ESDACmdSetWrBlkEraseCount,	{CCA,ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,	4}}, //ACMD23
   1.369 +	{ESDACmdSDAppOpCond,		{CCA,ECmdTypeBCR,	EDirNone,	EFalse, EFalse, ERespTypeR3,	4}}, //ACMD41
   1.370 +	{ESDACmdSetClrCardDetect,	{CCA,ECmdTypeAC,	EDirNone,	EFalse, EFalse, ERespTypeR1,	4}}, //ACMD42
   1.371 +	{ESDACmdSendSCR,			{CCA,ECmdTypeADTCS,	EDirRead,	EFalse, EFalse, ERespTypeR1,	4}}  //ACMD51
   1.372 +};
   1.373 +
   1.374 +void DSDSession::FillAppCommandDesc(TMMCCommandDesc& aDesc)
   1.375 +	{
   1.376 +	OstTraceFunctionEntry0( DUP2_DSDSESSION_FILLAPPCOMMANDDESC_ENTRY );
   1.377 +	aDesc.iSpec = FindCommandSpec(AppCmdSpecTable, aDesc.iCommand);
   1.378 +	aDesc.iFlags = 0;
   1.379 +	aDesc.iBytesDone = 0;
   1.380 +	OstTraceFunctionExit0( DUP2_DSDSESSION_FILLAPPCOMMANDDESC_EXIT );
   1.381 +	}
   1.382 +
   1.383 +const TMMCIdxCommandSpec SdSpecificCmdSpecTable[] =
   1.384 +/**
   1.385 + * SD Specific Command Table
   1.386 + *
   1.387 + *  - Some commands defined in the SD specification overload those defined in the MMC specification.
   1.388 + *    This table contains the SD specific versions of those commands.
   1.389 + */
   1.390 +	{
   1.391 +							//   Class				Type			Dir			MBlk	StopT	Rsp Type		Len
   1.392 +	{ESDCmdSendRelativeAddress,	{KMMCCmdClassBasic,	ECmdTypeBCR,	EDirNone,	EFalse,	EFalse,	ERespTypeR6,	4}},	// CMD3 : SEND_RELATIVE_ADDRESS
   1.393 +	{ESDCmdSwitchFunction,		{KMMCCmdClassSwitch,ECmdTypeADTCS,	EDirRead,	EFalse,	EFalse,	ERespTypeR1,	4}},	// CMD6 : SWITCH_FUNCTION
   1.394 +	{ESDCmdSendIfCond,			{KMMCCmdClassBasic,	ECmdTypeBCR,	EDirNone,	EFalse,	EFalse,	ERespTypeR7,	4}}		// CMD8 : SEND_IF_COND
   1.395 +	};
   1.396 +
   1.397 +void DSDSession::FillSdSpecificCommandDesc(TMMCCommandDesc& aDesc, TSDSpecificCmd aCmd, TMMCArgument aArg)
   1.398 +	{
   1.399 +	OstTraceFunctionEntry0( DSDSESSION_FILLSDSPECIFICCOMMANDDESC_ENTRY );
   1.400 +	aDesc.iCommand = (TMMCCommandEnum) aCmd;
   1.401 +	aDesc.iArgument = aArg;
   1.402 +	FillSdSpecificCommandDesc(aDesc);
   1.403 +	OstTraceFunctionExit0( DSDSESSION_FILLSDSPECIFICCOMMANDDESC_EXIT );
   1.404 +	}
   1.405 +
   1.406 +void DSDSession::FillSdSpecificCommandDesc(TMMCCommandDesc& aDesc, TSDSpecificCmd aCmd)
   1.407 +	{
   1.408 +	OstTraceFunctionEntry0( DUP1_DSDSESSION_FILLSDSPECIFICCOMMANDDESC_ENTRY );
   1.409 +	aDesc.iCommand = (TMMCCommandEnum) aCmd;
   1.410 +	aDesc.iArgument = 0;						// set stuff bits to zero
   1.411 +	FillSdSpecificCommandDesc(aDesc);
   1.412 +	OstTraceFunctionExit0( DUP1_DSDSESSION_FILLSDSPECIFICCOMMANDDESC_EXIT );
   1.413 +	}
   1.414 +
   1.415 +void DSDSession::FillSdSpecificCommandDesc(TMMCCommandDesc& aDesc)
   1.416 +	{
   1.417 +	OstTraceFunctionEntry0( DUP2_DSDSESSION_FILLSDSPECIFICCOMMANDDESC_ENTRY );
   1.418 +	aDesc.iSpec = FindCommandSpec(SdSpecificCmdSpecTable, aDesc.iCommand);
   1.419 +	aDesc.iFlags = 0;
   1.420 +	aDesc.iBytesDone = 0;
   1.421 +	OstTraceFunctionExit0( DUP2_DSDSESSION_FILLSDSPECIFICCOMMANDDESC_EXIT );
   1.422 +	}
   1.423 +
   1.424 +
   1.425 +// ======== DSDStack ========
   1.426 +
   1.427 +EXPORT_C TInt DSDStack::Init()
   1.428 +	{
   1.429 +	OstTraceFunctionEntry1( DSDSTACK_INIT_ENTRY, this );
   1.430 +	TInt ret = DMMCStack::Init();
   1.431 +	OstTraceFunctionExitExt( DSDSTACK_INIT_EXIT, this, ret );
   1.432 +	return ret;
   1.433 +	}
   1.434 +
   1.435 +
   1.436 +const TInt KMaxRCASendLoops=3;
   1.437 +const TUint KSDMaxPollAttempts=25;
   1.438 +EXPORT_C TMMCErr DSDStack::AcquireStackSM()
   1.439 +//
   1.440 +// This macro acquires new cards in an SD Card - star topology stack.
   1.441 +// This means each card has its own CMD and DAT lines and can be addressed
   1.442 +// individually by the Controller in turn. Commands can also be broadcast 
   1.443 +// simultaneously to the entire stack. 
   1.444 +// It starts with the Controller reading the operating conditions of each 
   1.445 +// card in the stack (SEND_OP_COND - ACMD41). Then, the following
   1.446 +// initialisation sequence is performed to each card in turn:-
   1.447 +// New cards in the stack are identified (ALL_SEND_CID - CMD2) and each one
   1.448 +// is requested to publish a relative card address (SEND_RCA - CMD3). Finally,
   1.449 +// the card specific data (SEND_CSD - CMD9) is read from each card.
   1.450 +// Note that the initialization of MMC cards are supported by this function
   1.451 +// if they are encountered. These require a slightly different init. procdure.
   1.452 +//
   1.453 +	{
   1.454 +		enum states
   1.455 +			{
   1.456 +			EStBegin=0,
   1.457 +			EStNextFullRange,
   1.458 +			EStSendCIDIssued,
   1.459 +			EStIssueSendRCA,
   1.460 +			EStSendRCACheck,
   1.461 +			EStRCADone,
   1.462 +			EStMoreCardsCheck,
   1.463 +			EStEnd
   1.464 +			};
   1.465 +
   1.466 +		DMMCSession& s=Session();
   1.467 +		OstTrace1( TRACE_INTERNALS, DSDSTACK_ATTACHCARDSM, "Current session = 0x%x", &s );
   1.468 +
   1.469 +	SMF_BEGIN
   1.470 +
   1.471 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_ATTACHCARDSM1, "EStBegin" );
   1.472 +        __KTRACE_OPT(KPBUS1, Kern::Printf(">DSDStack::AcquireStackSM()"));
   1.473 +        
   1.474 +		iRCAPool.ReleaseUnlocked();
   1.475 +		iCxCardCount=0; 		// Reset current card number
   1.476 +
   1.477 +	SMF_STATE(EStNextFullRange)
   1.478 +
   1.479 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_ATTACHCARDSM2, "EStNextFullRange" );
   1.480 +		iCxCardType = ESDCardTypeUnknown;
   1.481 +
   1.482 +		AddressCard(iCxCardCount); 	// Address the next card
   1.483 +
   1.484 +		// Before issueing commands, see if there's actually a card present
   1.485 +		if (!CardDetect(iCxCardCount))
   1.486 +			SMF_GOTOS(EStMoreCardsCheck)
   1.487 +
   1.488 +		m.SetTraps(KMMCErrResponseTimeOut);
   1.489 +		SMF_INVOKES(InitialiseMemoryCardSMST, EStSendCIDIssued)
   1.490 +
   1.491 +	SMF_STATE(EStSendCIDIssued)
   1.492 +
   1.493 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_ATTACHCARDSM3, "EStSendCIDIssued" );
   1.494 +		if( !err )
   1.495 +			{
   1.496 +			// The card responded with a CID. We need to initialise the
   1.497 +			// appropriate entry in the card array with the CID. 
   1.498 +			if (iCxCardType==ESDCardTypeIsSD)
   1.499 +				{
   1.500 +				// Now prepare to recieve an RCA from to the card
   1.501 +				CardArray().CardP(iCxCardCount)->iCID=s.ResponseP();
   1.502 +				DSDSession::FillSdSpecificCommandDesc(Command(), ESDCmdSendRelativeAddress,0); // SEND_RCA with argument just stuff bits
   1.503 +
   1.504 +				m.ResetTraps();
   1.505 +				iCxPollRetryCount=0; // Init count of send RCA attempts 
   1.506 +				SMF_GOTOS(EStIssueSendRCA)
   1.507 +				}
   1.508 +			else
   1.509 +				{
   1.510 +				// The card array allocates an RCA, either the old RCA
   1.511 +				// if we have seen this card before, or a new one.
   1.512 +				TRCA rca;
   1.513 +				CardArray().AddCardSDMode(iCxCardCount,s.ResponseP(),&rca);
   1.514 +
   1.515 +				// Now assign the new RCA to the card
   1.516 +				s.FillCommandDesc(ECmdSetRelativeAddr,TMMCArgument(rca));
   1.517 +				m.ResetTraps();							
   1.518 +				SMF_INVOKES(ExecCommandSMST,EStRCADone)
   1.519 +				}
   1.520 +			}
   1.521 +		else
   1.522 +			{
   1.523 +			m.ResetTraps();
   1.524 +			SMF_GOTOS(EStMoreCardsCheck) // Timed out, try the next card slot
   1.525 +			}
   1.526 +
   1.527 +	SMF_STATE(EStIssueSendRCA)
   1.528 +
   1.529 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_ATTACHCARDSM4, "EStIssueSendRCA" );
   1.530 +		SMF_INVOKES(ExecCommandSMST,EStSendRCACheck)
   1.531 +
   1.532 +	SMF_STATE(EStSendRCACheck)
   1.533 +
   1.534 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_ATTACHCARDSM5, "EStSendRCACheck" );
   1.535 +		// We need to check that the RCA recieved from the card doesn't clash
   1.536 +		// with any others in this stack. RCA is first 2 bytes of response buffer (in big endian)
   1.537 +		TRCA rca=(TUint16)((s.ResponseP()[0]<<8) | s.ResponseP()[1]);
   1.538 +		if (CardArray().StoreRCAIfUnique(iCxCardCount,rca)!=KErrNone)
   1.539 +			SMF_GOTOS( ((++iCxPollRetryCount<KMaxRCASendLoops)?EStIssueSendRCA:EStMoreCardsCheck) )
   1.540 +
   1.541 +	SMF_STATE(EStRCADone)
   1.542 +
   1.543 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_ATTACHCARDSM6, "EStRCADone" );
   1.544 +		SMF_INVOKES(ConfigureMemoryCardSMST, EStMoreCardsCheck)
   1.545 +
   1.546 +	SMF_STATE(EStMoreCardsCheck)
   1.547 +
   1.548 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_ATTACHCARDSM7, "EStMoreCardsCheck" );
   1.549 +		if (++iCxCardCount < (TInt)iMaxCardsInStack)
   1.550 +		    {
   1.551 +		    __KTRACE_OPT(KPBUS1, Kern::Printf(">DSDStack::AcquireStackSM(): More Cards to check: %d",iCxCardCount));
   1.552 +			OstTrace1( TRACE_INTERNALS, DSDSTACK_ACQUIRESTACKSM8, "More Cards to check: iCxCardCount=%d", iCxCardCount );		    
   1.553 +			SMF_GOTOS(EStNextFullRange)
   1.554 +		    }
   1.555 +		else
   1.556 +		    {		   
   1.557 +			AddressCard(KBroadcastToAllCards); // Set back to broadcast mode
   1.558 +			__KTRACE_OPT(KPBUS1, Kern::Printf("<DSDStack::AcquireStackSM()"));
   1.559 +		    }
   1.560 +
   1.561 +	SMF_END
   1.562 +	}
   1.563 +
   1.564 +
   1.565 +TMMCErr DSDStack::InitialiseMemoryCardSMST(TAny* aStackP)
   1.566 +	{ return static_cast<DSDStack*>(aStackP)->InitialiseMemoryCardSM(); }
   1.567 +
   1.568 +	
   1.569 +TMMCErr DSDStack::InitialiseMemoryCardSM()
   1.570 +/**
   1.571 +*/
   1.572 +	{
   1.573 +		enum states
   1.574 +			{
   1.575 +			EStBegin=0,
   1.576 +			EStSendInterfaceCondition,
   1.577 +			EStSentInterfaceCondition,
   1.578 +			EStSetFullRangeCmd,
   1.579 +			EStCheckForFullRangeCmd41Timeout,
   1.580 +			EStSentAppCommandBeforeCheckVoltage,
   1.581 +			EStCheckVoltage,
   1.582 +			EStFullRangeDone,
   1.583 +			EStSetRangeCmd,
   1.584 +			EStCheckForRangeCmd41Timeout,
   1.585 +			EStSetRangeBusyCheck,
   1.586 +			EStCIDCmd,
   1.587 +			EStSendCIDIssued,
   1.588 +			EStEnd
   1.589 +			};
   1.590 +
   1.591 +		DMMCSession& s=Session();
   1.592 +		DMMCPsu* psu=(DMMCPsu*)MMCSocket()->iVcc;
   1.593 +		OstTrace1( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM, "Current session = 0x%x", &s );
   1.594 +			
   1.595 +		static const TUint32 KCmd8Param		= 0x0100 | 0x00AA;	// Voltage supplied : 2.7-3.6V, Check Pattern 10101010b
   1.596 +		static const TUint32 KCmd8CheckMask = 0x00000FFF;
   1.597 +
   1.598 +	SMF_BEGIN
   1.599 +
   1.600 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM1, "EStBegin" );
   1.601 +		iCxCardType = ESDCardTypeUnknown;
   1.602 +		s.iCardP = NULL;	// This stops ExecCommandSM() from setting old RCA when sending CMD55
   1.603 +
   1.604 +		// Send CMD0 to initialise memory
   1.605 +		SMF_INVOKES(GoIdleSMST, EStSendInterfaceCondition);
   1.606 +
   1.607 +	SMF_STATE(EStSendInterfaceCondition)
   1.608 +
   1.609 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM2, "EStSendInterfaceCondition" );
   1.610 +		iCxPollRetryCount=0; 						 // Reset max number of poll attempts on card busy
   1.611 +		iConfig.SetPollAttempts(KSDMaxPollAttempts); // Increase card busy timeout to 1 Sec for SD Cards
   1.612 +
   1.613 +		iConfig.RemoveMode( KMMCModeEnableTimeOutRetry ); // Temporarily disable timeout retries - since we use a timeout event to distinguish between MMC and SD
   1.614 +
   1.615 +		DSDSession::FillSdSpecificCommandDesc(Command(), ESDCmdSendIfCond, KCmd8Param);
   1.616 +
   1.617 +		// SD2.0 defines CMD8 as having a new response type - R7
   1.618 +		// if the PSL doesn't indicate support for R7, use R1 instead
   1.619 +		if (!(MMCSocket()->MachineInfo().iFlags & TMMCMachineInfo::ESupportsR7))
   1.620 +			{
   1.621 +			__KTRACE_OPT(KPBUS1, Kern::Printf("R7 not supported."));
   1.622 +			OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM3, "R7 not supported" );
   1.623 +			Command().iSpec.iResponseType = ERespTypeR1;
   1.624 +			}
   1.625 +
   1.626 + 
   1.627 + 		m.SetTraps(KMMCErrAll);
   1.628 + 		SMF_INVOKES(ExecCommandSMST, EStSentInterfaceCondition)
   1.629 + 
   1.630 + 	SMF_STATE(EStSentInterfaceCondition)
   1.631 + 
   1.632 + 		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM4, "EStSentInterfaceCondition" );
   1.633 + 		if (err == KMMCErrNone)
   1.634 + 			{
   1.635 + 			// Check the response for voltage and check pattern
   1.636 + 			const TUint32 status = TMMC::BigEndian32(s.ResponseP());
   1.637 + 			if((status & KCmd8CheckMask) == KCmd8Param)
   1.638 + 				{
   1.639 + 				__KTRACE_OPT(KPBUS1, Kern::Printf("Found v2 card."));
   1.640 + 				OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM5, "Found v2 card" );
   1.641 +				iCurrentOpRange |= KMMCOCRAccessModeHCS;
   1.642 + 				}
   1.643 + 			else
   1.644 + 				{
   1.645 + 				// Pattern Mis-match, card does not support the specified voltage range
   1.646 + 				OstTraceFunctionExitExt( DSDSTACK_INITIALISEMEMORYCARDSM_EXIT, this, (TInt) KMMCErrNotSupported );
   1.647 + 				return KMMCErrNotSupported;
   1.648 + 				}
   1.649 +
   1.650 +			SMF_GOTOS(EStCheckVoltage);
   1.651 + 			}
   1.652 +
   1.653 +		// Go idle again after CMD8 failure
   1.654 +		SMF_INVOKES(GoIdleSMST, EStCheckVoltage);
   1.655 +
   1.656 +
   1.657 +	SMF_STATE(EStCheckVoltage)
   1.658 +
   1.659 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM6, "EStCheckVoltage" );
   1.660 +		// If platform doesn't support an adjustable voltage PSU then there's no
   1.661 +		// point in doing a full range for its supported range. To support range
   1.662 +		// checking on a multi-card stack would require a complete scan of all
   1.663 +		// cards before actually setting the range. This would over-complicate things
   1.664 +		// and make the more normal single card/none adjustable cases less efficient.
   1.665 +		if ( !(psu->VoltageSupported()&KMMCAdjustableOpVoltage) || iMaxCardsInStack>1)
   1.666 +			{
   1.667 +			// if the PSU isn't adjustable then it can't support low voltage mode
   1.668 +			iCurrentOpRange&= ~KMMCOCRLowVoltage;
   1.669 +
   1.670 +			SMF_GOTOS(EStSetRangeCmd)
   1.671 +			}
   1.672 +
   1.673 +	SMF_STATE(EStSetFullRangeCmd)
   1.674 +
   1.675 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM7, "EStSetFullRangeCmd" );
   1.676 +		// Issue ACMD41/CMD1 with omitted voltage range
   1.677 +		if (iCxCardType==ESDCardTypeIsMMC)
   1.678 +			{
   1.679 +			s.FillCommandDesc(ECmdSendOpCond, KMMCOCRAccessModeHCS | KMMCOCRBusy); // Full range + Sector Access + Busy bit (iArgument==KBit31)
   1.680 +			SMF_NEXTS(EStFullRangeDone)
   1.681 +			}
   1.682 +		else
   1.683 +			{
   1.684 +			DSDSession::FillAppCommandDesc(Command(), ESDACmdSDAppOpCond, TMMCArgument(0));
   1.685 +			SMF_NEXTS(EStCheckForFullRangeCmd41Timeout)
   1.686 +			}
   1.687 +					
   1.688 +		m.SetTraps(KMMCErrResponseTimeOut);
   1.689 +		SMF_CALL(ExecCommandSMST)
   1.690 +
   1.691 +	SMF_STATE(EStCheckForFullRangeCmd41Timeout)
   1.692 +	
   1.693 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM8, "EStCheckForFullRangeCmd41Timeout" );
   1.694 +		if (err==KMMCErrResponseTimeOut)	
   1.695 +			{
   1.696 +			__KTRACE_OPT(KPBUS1, Kern::Printf("ACMD 41 not supported - Assuming MMC"));
   1.697 +			OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM9, "ACMD 41 not supported - Assuming MMC" );
   1.698 +			iCxCardType=ESDCardTypeIsMMC;
   1.699 +
   1.700 +			// Send CMD0 to re-initialise the card - otherwise we may get 
   1.701 +			// KMMCStatErrIllegalCommand returned for the next command
   1.702 +			// expecting an R1 response. NB The SD spec recommends ignoring the error
   1.703 +			// whereas the SDIO spec recommends this approach (ignoring the error
   1.704 +			// would be difficult to code anyway, since by then we're no longer
   1.705 +			// in this state machine).
   1.706 +			SMF_INVOKES(GoIdleSMST, EStSetFullRangeCmd);	// Repeat - but using CMD1
   1.707 +			}
   1.708 +		else
   1.709 +			{
   1.710 +			// No response timeout - so it must be an SD Card
   1.711 +			(CardArray().CardP(iCxCardCount)->iFlags)|=KSDCardIsSDCard;
   1.712 +			iCxCardType=ESDCardTypeIsSD;
   1.713 +			}
   1.714 +
   1.715 +	SMF_STATE(EStFullRangeDone)
   1.716 +
   1.717 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM10, "EStFullRangeDone" );
   1.718 +		if (!err)												
   1.719 +			{
   1.720 +			// Card responded with Op range - evaluate the common subset with the current setting.
   1.721 +			// Dont worry about the busy bit for now, we'll check that when we repeat the command
   1.722 +			const TUint32 range = (iCurrentOpRange & ~KMMCOCRAccessModeHCS) & (TMMC::BigEndian32(s.ResponseP()) & ~KMMCOCRBusy);
   1.723 +			if(range == 0)
   1.724 +				{
   1.725 +				OstTraceFunctionExitExt( DSDSTACK_INITIALISEMEMORYCARDSM_EXIT1, this, (TInt) KMMCErrNotSupported );
   1.726 +				return KMMCErrNotSupported; // Card is incompatible with our h/w
   1.727 +				}
   1.728 +			iCurrentOpRange = range | (iCurrentOpRange & KMMCOCRAccessModeHCS);
   1.729 +			}
   1.730 +
   1.731 +		// Repeat SEND_OP_COND this time setting Current Op Range
   1.732 +		if (iCxCardType==ESDCardTypeIsMMC)
   1.733 +			{
   1.734 +			// If platform and the card both support low voltage mode (1.65 - 1.95v), switch
   1.735 +			// NB If this fails then there is no recovery.
   1.736 +			if (iCurrentOpRange & KMMCOCRLowVoltage)
   1.737 +				{
   1.738 +				iCurrentOpRange = KMMCOCRLowVoltage;
   1.739 +				SMF_INVOKES( SwitchToLowVoltageSMST, EStSetRangeCmd )
   1.740 +				}
   1.741 +			}
   1.742 +
   1.743 +	SMF_STATE(EStSetRangeCmd)
   1.744 +
   1.745 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM11, "EStSetRangeCmd" );
   1.746 +		// Issue ACMD41/CMD1 with voltage range
   1.747 +		if (iCxCardType==ESDCardTypeIsMMC)
   1.748 +			{
   1.749 +			s.FillCommandDesc(ECmdSendOpCond,(iCurrentOpRange | KMMCOCRAccessModeHCS | KMMCOCRBusy)); // Range supported + Sector Access Busy bit (iArgument==KBit31)
   1.750 +			SMF_NEXTS(EStSetRangeBusyCheck)
   1.751 +			}
   1.752 +		else
   1.753 +			{
   1.754 +			TUint arg = (iCurrentOpRange & ~KMMCOCRAccessModeHCS); // Range supported
   1.755 +			if((iCurrentOpRange & KMMCOCRAccessModeHCS) != 0)
   1.756 +				{
   1.757 +				arg |= KMMCOCRAccessModeHCS;
   1.758 +				}
   1.759 +			DSDSession::FillAppCommandDesc(Command(), ESDACmdSDAppOpCond, arg);
   1.760 +			SMF_NEXTS((iCxCardType == ESDCardTypeUnknown)? EStCheckForRangeCmd41Timeout : EStSetRangeBusyCheck)
   1.761 +			}
   1.762 +
   1.763 +		m.SetTraps(KMMCErrResponseTimeOut);
   1.764 +		SMF_CALL(ExecCommandSMST)
   1.765 +
   1.766 +	SMF_STATE(EStCheckForRangeCmd41Timeout)
   1.767 +	
   1.768 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM12, "EStCheckForRangeCmd41Timeout" );
   1.769 +		__KTRACE_OPT(KPBUS1, Kern::Printf("-mst:ascs:crct:%d", err));
   1.770 +		OstTrace1( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM13, "err=%d", (TInt) err);
   1.771 +		if (err==KMMCErrResponseTimeOut)	
   1.772 +			{
   1.773 +			iCxCardType=ESDCardTypeIsMMC;
   1.774 +			// Send CMD0 to re-initialise the card - otherwise we may get 
   1.775 +			// KMMCStatErrIllegalCommand returned for the next command
   1.776 +			// expecting an R1 response. NB The SD spec recommends ignoring the error
   1.777 +			// whereas the SDIO spec recommends this approach (ignoring the error
   1.778 +			// would be difficult to code anyway, since by then we're no longer
   1.779 +			// in this state machine).
   1.780 +			SMF_INVOKES(GoIdleSMST, EStSetRangeCmd);	// Repeat - but using CMD1
   1.781 +			}
   1.782 +		else
   1.783 +			{
   1.784 +			// No response timeout - so it must be an SD Card
   1.785 +			__KTRACE_OPT(KPBUS1, Kern::Printf("-mst:ascs:crct2:%x", iCardArray));
   1.786 +			__KTRACE_OPT(KPBUS1, Kern::Printf("-mst:ascs:crct3:%x", iCxCardCount));
   1.787 +			__KTRACE_OPT(KPBUS1, Kern::Printf("-mst:ascs:crct4:%x", CardArray().CardP(iCxCardCount)));
   1.788 +			OstTraceExt3(TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM14, "iCardArray=0x%x;iCxCardCount=%d;CardArray().CardP(iCxCardCount)=%d", (TUint) iCardArray, (TInt) iCxCardCount, (TInt) CardArray().CardP(iCxCardCount));
   1.789 +
   1.790 +			(CardArray().CardP(iCxCardCount)->iFlags)|=KSDCardIsSDCard;
   1.791 +			iCxCardType=ESDCardTypeIsSD;
   1.792 +			}
   1.793 +			
   1.794 +	SMF_STATE(EStSetRangeBusyCheck)
   1.795 +
   1.796 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM15, "EStSetRangeBusyCheck" );
   1.797 +		__KTRACE_OPT(KPBUS1, Kern::Printf("-mst:ascs:src:%d",iCxCardType)); // 1:MMC, 2:SD
   1.798 +		OstTrace1( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM16, "iCxCardType=%d", iCxCardType);
   1.799 +		
   1.800 +		if ( !err )
   1.801 +			{
   1.802 +			const TUint32 ocrResponse = TMMC::BigEndian32(s.ResponseP());
   1.803 +
   1.804 +			if ((ocrResponse & KMMCOCRBusy) == 0)	
   1.805 +				{
   1.806 +				__KTRACE_OPT(KPBUS1,Kern::Printf("-sd:upd:bsy"));
   1.807 +				// Card is still busy powering up. Check if we should timeout
   1.808 +				if ( ++iCxPollRetryCount > iConfig.OpCondBusyTimeout() )
   1.809 +					{
   1.810 +					__KTRACE_OPT2(KPBUS1, KPANIC, Kern::Printf("-sd:ocr busy timed out"));
   1.811 +					OstTraceFunctionExitExt( DSDSTACK_INITIALISEMEMORYCARDSM_EXIT2, this, (TInt) KMMCErrBusTimeOut );
   1.812 +					return KMMCErrBusTimeOut;
   1.813 +					}
   1.814 +					
   1.815 +#ifdef _DEBUG
   1.816 +				if ( iCxPollRetryCount > KMMCSpecOpCondBusyTimeout )
   1.817 +					{
   1.818 +					__KTRACE_OPT2(KPBUS1, KPANIC, Kern::Printf("-sd:ocr exceeded spec timeout!! (%d ms)", (iCxPollRetryCount*KMMCRetryGapInMilliseconds)));
   1.819 +					OstTrace1( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM17, "Exceeded spec timeout (%d ms)", (iCxPollRetryCount*KMMCRetryGapInMilliseconds));
   1.820 +					}
   1.821 +#endif
   1.822 +				m.ResetTraps(); 
   1.823 +
   1.824 +				SMF_INVOKES(RetryGapTimerSMST,EStSetRangeCmd)
   1.825 +				}
   1.826 +			else
   1.827 +				{
   1.828 +				if(ocrResponse & KMMCOCRAccessModeHCS)
   1.829 +					{
   1.830 +					CardArray().CardP(iCxCardCount)->iFlags |= KMMCardIsHighCapacity;
   1.831 +#ifdef _DEBUG				
   1.832 +					if(iCxCardType == ESDCardTypeIsSD)
   1.833 +						{
   1.834 +						__KTRACE_OPT(KPBUS1, Kern::Printf("Found large SD card."));
   1.835 +						OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM18, "Found large SD card" );
   1.836 +						}
   1.837 +					else if(iCxCardType == ESDCardTypeIsMMC)
   1.838 +						{
   1.839 +						__KTRACE_OPT(KPBUS1, Kern::Printf("Found large MMC card."));
   1.840 +						OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM19, "Found large MMC card" );
   1.841 +						}
   1.842 +#endif
   1.843 +					}
   1.844 +				}
   1.845 +			}
   1.846 +
   1.847 +		// Restore original settings
   1.848 +		iConfig.SetMode( EffectiveModes(s.iConfig) & KMMCModeEnableTimeOutRetry );
   1.849 +		iConfig.SetPollAttempts(KMMCMaxPollAttempts);
   1.850 +
   1.851 +		// All cards are now ready and notified of the voltage range - ask ASSP to set it up
   1.852 +		if (iCxCardType==ESDCardTypeIsMMC)
   1.853 +			{
   1.854 +			iCurrentOpRange &= ~KMMCOCRAccessModeMask;
   1.855 +			}
   1.856 +		else
   1.857 +			{
   1.858 +			iCurrentOpRange &= ~KMMCOCRAccessModeHCS;
   1.859 +			}
   1.860 +
   1.861 +		psu->SetVoltage(iCurrentOpRange);
   1.862 +		if (psu->SetState(EPsuOnFull) != KErrNone)
   1.863 +			{
   1.864 +			OstTraceFunctionExitExt( DSDSTACK_INITIALISEMEMORYCARDSM_EXIT3, this, (TInt) KMMCErrHardware );
   1.865 +			return KMMCErrHardware;
   1.866 +			}
   1.867 +
   1.868 +	SMF_STATE(EStCIDCmd)
   1.869 +
   1.870 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM20, "EStCIDCmd" );
   1.871 +		s.FillCommandDesc(ECmdAllSendCID,0);
   1.872 +		m.ResetTraps();
   1.873 +		SMF_INVOKES(ExecCommandSMST,EStSendCIDIssued)
   1.874 +
   1.875 +	SMF_STATE(EStSendCIDIssued)
   1.876 +
   1.877 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM21, "EStSendCIDIssued" );
   1.878 +		// All done - Higher level state machine expects CID in s.ResponseP()
   1.879 +
   1.880 +	SMF_END
   1.881 +	}
   1.882 +
   1.883 +TMMCErr DSDStack::ConfigureMemoryCardSMST(TAny* aStackP)
   1.884 +	{ return static_cast<DSDStack*>(aStackP)->ConfigureMemoryCardSM(); }
   1.885 +
   1.886 +TMMCErr DSDStack::ConfigureMemoryCardSM()
   1.887 +/**
   1.888 +*/
   1.889 +	{
   1.890 +		enum states
   1.891 +			{
   1.892 +			EStBegin=0,
   1.893 +			EStSendCSDDone,
   1.894 +			EStEnd
   1.895 +			};
   1.896 +
   1.897 +		DMMCSession& s=Session();
   1.898 +		OstTrace1( TRACE_INTERNALS, DSDSTACK_CONFIGUREMEMORYCARDSM, "Current session = 0x%x", &s );
   1.899 +
   1.900 +	//coverity[UNREACHABLE]
   1.901 +	//Part of state machine design.
   1.902 +	SMF_BEGIN
   1.903 +
   1.904 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_CONFIGUREMEMORYCARDSM1, "EStBegin" );
   1.905 +		// Cards is initialised so get its CSD
   1.906 +
   1.907 +		s.FillCommandDesc(ECmdSendCSD, TUint32(CardArray().CardP(iCxCardCount)->iRCA) << 16);
   1.908 +		SMF_INVOKES(ExecCommandSMST, EStSendCSDDone)
   1.909 +
   1.910 +	SMF_STATE(EStSendCSDDone)
   1.911 +
   1.912 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_CONFIGUREMEMORYCARDSM2, "EStSendCSDDone" );
   1.913 +		// Store the CSD in the new card entry
   1.914 +		TMMCard* cardP = CardArray().CardP(iCxCardCount);
   1.915 +		cardP->iCSD = s.ResponseP();
   1.916 +
   1.917 +		if(CardArray().Card(iCxCardCount).IsSDCard())
   1.918 +			{
   1.919 +			// Perform SD Specific parsing of the CSD structure
   1.920 +			if(cardP->CSD().CCC() & KMMCCmdClassLockCard)
   1.921 +				{
   1.922 +				cardP->iFlags |= KMMCardIsLockable;
   1.923 +				}
   1.924 +			}
   1.925 +		else
   1.926 +			{
   1.927 +			// Perform MMC Specific parsing of the CSD structure
   1.928 +			TUint specVers = cardP->CSD().SpecVers();	// 1 => 1.4, 2 => 2.0 - 2.2, 3 => 3.1
   1.929 +			if ((specVers >= 2) && (cardP->CSD().CCC() & KMMCCmdClassLockCard))
   1.930 +				{
   1.931 +				cardP->iFlags |= KMMCardIsLockable;
   1.932 +				}
   1.933 +			}
   1.934 +		
   1.935 +		// Check the state of the mechanical write protect switch
   1.936 +		if (WriteProtected(iCxCardCount))
   1.937 +			{
   1.938 +			cardP->iFlags |= KMMCardIsWriteProtected;
   1.939 +			}
   1.940 +
   1.941 +	SMF_END
   1.942 +	}
   1.943 +
   1.944 +EXPORT_C TMMCErr DSDStack::InitStackAfterUnlockSM()
   1.945 +//
   1.946 +// Performs initialisation of the SD card after the card has been unlocked
   1.947 +//
   1.948 +	{
   1.949 +		enum states
   1.950 +			{
   1.951 +			EStBegin=0,
   1.952 +			EStNextCard,
   1.953 +			EStSelectCard,
   1.954 +			EStSetBusWidth,
   1.955 +			EStSetBusWidth1,
   1.956 +			EStGetSDStatus,
   1.957 +			EStGetSDStatus1,
   1.958 +			EStDecodeSDStatus,
   1.959 +			EStDeselectCard,
   1.960 +			EStCardDeselectedReadCSD,
   1.961 +			EStCSDCmdSent,
   1.962 +			EStMoreCardsCheck,
   1.963 +			EStEnd
   1.964 +			};
   1.965 +
   1.966 +		DMMCSession& s=Session();
   1.967 +		OstTrace1( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM, "Current session = 0x%x", &s );
   1.968 +
   1.969 +	SMF_BEGIN
   1.970 +
   1.971 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM1, "EStBegin" );
   1.972 +        __KTRACE_OPT(KPBUS1, Kern::Printf(">DSDStack::InitStackAfterUnlockSM()"));
   1.973 +		iRCAPool.ReleaseUnlocked();
   1.974 +		iCxCardCount=0; 		// Reset current card number
   1.975 +
   1.976 +	SMF_STATE(EStNextCard)	    
   1.977 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM2, "EStNextCard" );
   1.978 +		AddressCard(iCxCardCount); 	// Address the next card
   1.979 +
   1.980 +		if (!CardDetect(iCxCardCount))
   1.981 +			SMF_GOTOS(EStMoreCardsCheck)
   1.982 +
   1.983 +		s.SetCard(CardArray().CardP(iCxCardCount));
   1.984 +
   1.985 +		if (!CardArray().Card(iCxCardCount).IsSDCard())
   1.986 +			{
   1.987 +			SMF_INVOKES( DMMCStack::InitCurrentCardAfterUnlockSMST, EStMoreCardsCheck )
   1.988 +			}
   1.989 +
   1.990 +	SMF_STATE(EStSelectCard)
   1.991 +
   1.992 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM3, "EStSelectCard" );
   1.993 +		TRCA targetRCA = CardArray().Card(iCxCardCount).RCA();
   1.994 +		if (targetRCA == SelectedCard())
   1.995 +			{
   1.996 +			SMF_GOTOS(EStSetBusWidth)
   1.997 +			}
   1.998 +
   1.999 +		s.FillCommandDesc(ECmdSelectCard, targetRCA);
  1.1000 +		SMF_INVOKES(ExecCommandSMST,EStSetBusWidth)
  1.1001 +
  1.1002 +	SMF_STATE(EStSetBusWidth)
  1.1003 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM4, "EStSetBusWidth" );
  1.1004 +		const TMMCStatus status = s.LastStatus();
  1.1005 +		if((status & KMMCStatCardIsLocked) != 0)
  1.1006 +			SMF_GOTOS(EStDeselectCard)
  1.1007 +
  1.1008 +		// set bus width with ACMD6
  1.1009 +		TUint32 arg = TUint32(CardArray().Card(iCxCardCount).RCA()) << 16;
  1.1010 +		s.FillCommandDesc(ECmdAppCmd, arg);
  1.1011 +		SMF_INVOKES(IssueCommandCheckResponseSMST,EStSetBusWidth1)
  1.1012 +
  1.1013 +	SMF_STATE(EStSetBusWidth1)
  1.1014 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM5, "EStSetBusWidth1" );
  1.1015 +		CardArray().Card(iCxCardCount).SetBusWidth(4);
  1.1016 +		DSDSession::FillAppCommandDesc(Command(), ESDACmdSetBusWidth, KSDBusWidth4);
  1.1017 +		SMF_INVOKES(IssueCommandCheckResponseSMST,EStGetSDStatus)
  1.1018 +
  1.1019 +	SMF_STATE(EStGetSDStatus)
  1.1020 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM6, "EStGetSDStatus" );
  1.1021 +		// Now we have sent ACMD6, ask the controller to set the bus width to 4
  1.1022 +		DoSetBusWidth(EBusWidth4);
  1.1023 +
  1.1024 +		// get protected area size with ACMD13
  1.1025 +		TUint32 arg = TUint32(CardArray().Card(iCxCardCount).RCA()) << 16;
  1.1026 +		s.FillCommandDesc(ECmdAppCmd,arg);
  1.1027 +		SMF_INVOKES(IssueCommandCheckResponseSMST,EStGetSDStatus1)
  1.1028 +
  1.1029 +	SMF_STATE(EStGetSDStatus1)
  1.1030 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM7, "EStGetSDStatus1" );
  1.1031 +		DSDSession::FillAppCommandDesc(Command(), ESDACmdSDStatus);
  1.1032 +		s.FillCommandArgs(0, KSDStatusBlockLength, iPSLBuf, KSDStatusBlockLength);
  1.1033 +		SMF_INVOKES(IssueCommandCheckResponseSMST,EStDecodeSDStatus);
  1.1034 +
  1.1035 +	SMF_STATE(EStDecodeSDStatus)
  1.1036 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM8, "EStDecodeSDStatus" );
  1.1037 +#ifdef _DEBUG
  1.1038 +		for (TUint i = 0; i < KSDStatusBlockLength; ++i)
  1.1039 +			{
  1.1040 +			__KTRACE_OPT(KPBUS1, Kern::Printf("SD_STATUS[0x%x] = %x", i, iPSLBuf[i]));
  1.1041 +			OstTraceExt2( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM9, "SD_STATUS[0x%x]=0x%x", i, (TUint) iPSLBuf[i]);
  1.1042 +			}
  1.1043 +#endif
  1.1044 +		// bits 495:480 are SD_CARD_TYPE.  Check this is 00xxh (x = don't care).
  1.1045 +
  1.1046 +		if (iPSLBuf[2] != 0)
  1.1047 +		    {
  1.1048 +			OstTraceFunctionExitExt( DSDSTACK_INITSTACKAFTERUNLOCKSM_EXIT, this, (TInt) KMMCErrNotSupported );
  1.1049 +			return KMMCErrNotSupported;
  1.1050 +		    }
  1.1051 +
  1.1052 +		// bits 479:448 contain SIZE_OF_PROTECTED_AREA.  
  1.1053 +		// (This is bytes 4 to 7 in big-endian format.)
  1.1054 +
  1.1055 +		TSDCard& sdc = CardArray().Card(iCxCardCount);
  1.1056 +		__KTRACE_OPT(KPBUS1, Kern::Printf("\t >DSDStack: Card %d", iCxCardCount));
  1.1057 +		TUint32 size_of_protected_area = TMMC::BigEndian32(&iPSLBuf[4]);
  1.1058 +		__KTRACE_OPT(KPBUS1, Kern::Printf("\t >DSDStack: SizeOfProtectedArea: %d", size_of_protected_area));
  1.1059 +		OstTraceExt2( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM10, "iCxCardCount=%d;SizeOfProtectedArea=%d", iCxCardCount, (TInt) size_of_protected_area);
  1.1060 +		const TCSD& csd = sdc.CSD();
  1.1061 +		TUint32 pas = 0;
  1.1062 +		
  1.1063 +		if (sdc.IsHighCapacity())
  1.1064 +			{
  1.1065 +			// High Capacity Card
  1.1066 +			// Protected Area = SIZE_OF_PROTECTED_AREA
  1.1067 +			pas = size_of_protected_area;
  1.1068 +			__KTRACE_OPT(KPBUS1, Kern::Printf("\t >DSDStack(SDHC): SetProtectedAreaSize: %d", pas));
  1.1069 +			OstTrace1( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM11, "SDHC: SetProtectedAreaSize=%d", pas);
  1.1070 +			}
  1.1071 +		else
  1.1072 +			{
  1.1073 +			// Standard Capacity Card
  1.1074 +			// Protected Area = SIZE_OF_PROTECTED_AREA * C_SIZE_MULT * BLOCK_LEN
  1.1075 +			pas = size_of_protected_area * (1 << (csd.CSizeMult() + 2 + csd.ReadBlLen()));
  1.1076 +			__KTRACE_OPT(KPBUS1, Kern::Printf("\t >DSDStack(SDSC): SetProtectedAreaSize: %d", pas));
  1.1077 +			OstTrace1( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM12, "SDSC: SetProtectedAreaSize=%d", pas);
  1.1078 +			}		
  1.1079 +
  1.1080 +		sdc.SetProtectedAreaSize(pas);
  1.1081 +
  1.1082 +		//bits 431:428 contain AU_SIZE
  1.1083 +		//(This is higher order 4 bits of 10th byte in big endian format)
  1.1084 +		TUint8 au = TUint8(iPSLBuf[10] >> 4);
  1.1085 +		if(au == 0)	    //AU_SIZE field in SD status register is undefined.
  1.1086 +			au = 6;		//Defaulting to value corresponding to 512K	
  1.1087 +		sdc.SetAUSize(au);
  1.1088 +
  1.1089 +		SMF_INVOKES(SwitchToHighSpeedModeSMST, EStDeselectCard)
  1.1090 +
  1.1091 +	SMF_STATE(EStDeselectCard)
  1.1092 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM13, "EStDeselectCard" );
  1.1093 +		s.FillCommandDesc(ECmdSelectCard, 0);
  1.1094 +		SMF_INVOKES(ExecCommandSMST, EStCardDeselectedReadCSD)
  1.1095 +    
  1.1096 +	SMF_STATE(EStCardDeselectedReadCSD)
  1.1097 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM14, "EStCardDeselectedReadCSD" );
  1.1098 +		//
  1.1099 +      	// Read the card's CSD register (again)
  1.1100 +		//
  1.1101 +		//  - We re-read the CSD, as the TRAN_SPEED field may have changed due to a switch to HS Mode
  1.1102 +		//
  1.1103 +      	TUint32 arg = TUint32(CardArray().Card(iCxCardCount).RCA()) << 16;
  1.1104 +      	s.FillCommandDesc( ECmdSendCSD, arg );
  1.1105 +      	SMF_INVOKES(ExecCommandSMST, EStCSDCmdSent)
  1.1106 +
  1.1107 +	SMF_STATE(EStCSDCmdSent)
  1.1108 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM15, "EStCSDCmdSent" );
  1.1109 +		//
  1.1110 +      	// Store the CSD in the card entry
  1.1111 +		//
  1.1112 +      	TMMCard* cardP = iCardArray->CardP(iCxCardCount);
  1.1113 +      	cardP->iCSD = s.ResponseP();
  1.1114 +
  1.1115 +	SMF_STATE(EStMoreCardsCheck)
  1.1116 +		OstTrace0( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM16, "EStMoreCardsCheck" );
  1.1117 +		if (++iCxCardCount < (TInt)iMaxCardsInStack)
  1.1118 +		    {
  1.1119 +		    __KTRACE_OPT(KPBUS1, Kern::Printf("\t >DSDStack: Address Next card: %d",iCxCardCount));
  1.1120 +		    OstTrace1( TRACE_INTERNALS, DSDSTACK_INITSTACKAFTERUNLOCKSM17, "Address Next card=%d", iCxCardCount);
  1.1121 +			SMF_GOTOS(EStNextCard)
  1.1122 +		    }
  1.1123 +		else
  1.1124 +		    {
  1.1125 +			AddressCard(KBroadcastToAllCards);
  1.1126 +			__KTRACE_OPT(KPBUS1, Kern::Printf("<DSDStack::InitStackAfterUnlockSM()"));
  1.1127 +		    }
  1.1128 +
  1.1129 +	SMF_END
  1.1130 +	
  1.1131 +	}
  1.1132 +
  1.1133 +TMMCErr DSDStack::CIMReadWriteMemoryBlocksSMST(TAny* aStackP)
  1.1134 +	{ return( static_cast<DSDStack *>(aStackP)->DMMCStack::CIMReadWriteBlocksSM() ); }
  1.1135 +
  1.1136 +
  1.1137 +EXPORT_C TMMCErr DSDStack::CIMReadWriteBlocksSM()
  1.1138 +//
  1.1139 +// This macro performs single/multiple block reads and writes
  1.1140 +// For normal read/write block operations, this function determines the appropriate
  1.1141 +// MMC command to send and fills the command descriptor accordingly based on 
  1.1142 +// the value of the session ID set. However, it is necessary to have set the
  1.1143 +// command arguments (with DMMCSession::FillCommandArgs()) before this function
  1.1144 +// is called.
  1.1145 +// For special block read/write operations, e.g. lock/unlock, it is required to
  1.1146 +// have already filled the command descriptor (with DMMCSession::FillCommandDesc())
  1.1147 +// for the special command required - in addition to have setup the command arguments.
  1.1148 +//
  1.1149 +	{
  1.1150 +		enum states
  1.1151 +			{
  1.1152 +			EStBegin=0,
  1.1153 +			EStRestart,
  1.1154 +			EStAttached,
  1.1155 +			EStLength1,
  1.1156 +			EStLengthSet,
  1.1157 +			EStIssued,
  1.1158 +			EStWaitFinish,
  1.1159 +			EStWaitFinish1,
  1.1160 +			EStRWFinish,
  1.1161 +			EStDone,
  1.1162 +			EStEnd
  1.1163 +			};
  1.1164 +
  1.1165 +		DMMCSession& s = Session();
  1.1166 +		OstTrace1( TRACE_INTERNALS, DSDSTACK_CIMREADWRITEBLOCKSSM, "Current session = 0x%x", &s );
  1.1167 +
  1.1168 +		__KTRACE_OPT(KPBUS1,Kern::Printf(">SD:RWBlocksSM %x",TUint(s.iLastStatus)));
  1.1169 +
  1.1170 +	SMF_BEGIN
  1.1171 +
  1.1172 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_CIMREADWRITEBLOCKSSM1, "EStBegin" );
  1.1173 +		TSDCard& sdCard = *static_cast<TSDCard*>(s.iCardP);
  1.1174 +		AddressCard(sdCard.iIndex-1);
  1.1175 +
  1.1176 +		if(sdCard.IsSDCard() == EFalse)
  1.1177 +			{
  1.1178 +			//
  1.1179 +			// If this is not an SD card, then use the more appropriate
  1.1180 +			// MMC state machine as this is optimised for MMC performance
  1.1181 +			//
  1.1182 +			SMF_INVOKES(CIMReadWriteMemoryBlocksSMST, EStDone);
  1.1183 +			}
  1.1184 +
  1.1185 +		if(s.iSessionID == ECIMWriteBlock || s.iSessionID == ECIMWriteMBlock)
  1.1186 +			{
  1.1187 +			// Check that the card supports class 4 (Write) commands
  1.1188 +			const TUint ccc = s.iCardP->CSD().CCC();
  1.1189 +			if(!(ccc & KMMCCmdClassBlockWrite))
  1.1190 +			    {
  1.1191 +				OstTraceFunctionExitExt( DSDSTACK_CIMREADWRITEBLOCKSSM_EXIT, this, (TInt) KMMCErrNotSupported );
  1.1192 +				return KMMCErrNotSupported;
  1.1193 +			    }
  1.1194 +			}
  1.1195 +
  1.1196 +		Command().iCustomRetries = 0;			// MBW retries
  1.1197 +		s.iState |= KMMCSessStateInProgress;
  1.1198 +		m.SetTraps(KMMCErrInitContext);
  1.1199 +
  1.1200 +	SMF_STATE(EStRestart)		// NB: ErrBypass is not processed here
  1.1201 +
  1.1202 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_CIMREADWRITEBLOCKSSM2, "EStRestart" );
  1.1203 +		SMF_CALLMEWR(EStRestart) // Create a recursive call entry to recover from the errors trapped
  1.1204 +		m.SetTraps(KMMCErrStatus);
  1.1205 +		if (s.Command().iSpec.iCommandClass!=KMMCCmdClassApplication || s.Command().iCommand==ECmdAppCmd )
  1.1206 +			{
  1.1207 +			s.ResetCommandStack();
  1.1208 +			SMF_INVOKES( AttachCardSMST, EStAttached )	// attachment is mandatory here
  1.1209 +			}
  1.1210 +
  1.1211 +	SMF_BPOINT(EStAttached)
  1.1212 +
  1.1213 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_CIMREADWRITEBLOCKSSM3, "EStAttached" );
  1.1214 +		TMMCCommandDesc& cmd = s.Command();
  1.1215 +
  1.1216 +		const TUint32 blockLength = cmd.BlockLength();
  1.1217 +		if((blockLength == 0) || (blockLength > (TUint)KDefaultBlockLenInBytes))
  1.1218 +			{
  1.1219 +			__KTRACE_OPT(KPBUS1,Kern::Printf(">SD:RWBlocksSM err BlockLen:%d",blockLength));
  1.1220 +			OstTrace1( TRACE_INTERNALS, DSDSTACK_CIMREADWRITEBLOCKSSM4, "blockLength=%d", blockLength );
  1.1221 +			OstTraceFunctionExitExt( DSDSTACK_CIMREADWRITEBLOCKSSM_EXIT1, this, (TInt) KMMCErrArgument );
  1.1222 +			return KMMCErrArgument;
  1.1223 +			}
  1.1224 +
  1.1225 +		if(s.iSessionID == ECIMReadBlock	||
  1.1226 +		   s.iSessionID == ECIMWriteBlock	||
  1.1227 +		   s.iSessionID == ECIMReadMBlock	||
  1.1228 +		   s.iSessionID == ECIMWriteMBlock)
  1.1229 +			{	
  1.1230 +			// read/write operation
  1.1231 +			if(!cmd.AdjustForBlockOrByteAccess(s))
  1.1232 +				{
  1.1233 +				// unable to convert command arguments to suit the underlying block/byte access mode
  1.1234 +				OstTraceFunctionExitExt( DSDSTACK_CIMREADWRITEBLOCKSSM_EXIT2, this, (TInt) KMMCErrArgument );
  1.1235 +				return KMMCErrArgument;
  1.1236 +				}
  1.1237 +			}
  1.1238 +
  1.1239 +		// Set the block length if it has changed. Always set for ECIMLockUnlock.
  1.1240 +		if ((blockLength == s.iCardP->iSetBlockLen) && (s.iSessionID != ECIMLockUnlock))
  1.1241 +			{
  1.1242 +			SMF_GOTOS( EStLengthSet )
  1.1243 +			}
  1.1244 +
  1.1245 +		s.iCardP->iSetBlockLen = 0;
  1.1246 +		s.PushCommandStack();
  1.1247 +		s.FillCommandDesc( ECmdSetBlockLen, blockLength );
  1.1248 +		SMF_INVOKES( ExecCommandSMST, EStLength1 )
  1.1249 +
  1.1250 +	SMF_STATE(EStLength1)
  1.1251 +
  1.1252 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_CIMREADWRITEBLOCKSSM5, "EStLength1" );
  1.1253 +		const TMMCStatus status(s.ResponseP());
  1.1254 +		s.PopCommandStack();
  1.1255 +		if (status.Error())
  1.1256 +		    {
  1.1257 +		    OstTraceFunctionExitExt( DSDSTACK_CIMREADWRITEBLOCKSSM_EXIT3, this, (TInt) KMMCErrStatus );
  1.1258 +			SMF_RETURN(KMMCErrStatus)
  1.1259 +		    }
  1.1260 +		s.iCardP->iSetBlockLen = s.Command().BlockLength();
  1.1261 +
  1.1262 +	SMF_STATE(EStLengthSet)
  1.1263 +
  1.1264 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_CIMREADWRITEBLOCKSSM6, "EStLengthSet" );
  1.1265 +		TMMCCommandDesc& cmd = s.Command();
  1.1266 +		TUint opType = 0;
  1.1267 +		const TUint kTypeWrite =	KBit0;
  1.1268 +		const TUint kTypeMultiple =	KBit1;
  1.1269 +		const TUint kTypeSpecial =	KBit2;
  1.1270 +		static const TMMCCommandEnum cmdCodes[4] =
  1.1271 +			{ECmdReadSingleBlock, ECmdWriteBlock, ECmdReadMultipleBlock, ECmdWriteMultipleBlock};
  1.1272 +
  1.1273 +		switch( s.iSessionID )
  1.1274 +			{
  1.1275 +			case ECIMReadBlock:
  1.1276 +				break;
  1.1277 +			case ECIMWriteBlock:
  1.1278 +				opType=kTypeWrite;
  1.1279 +				break;
  1.1280 +			case ECIMReadMBlock:
  1.1281 +				opType=kTypeMultiple;
  1.1282 +				break;
  1.1283 +			case ECIMWriteMBlock:
  1.1284 +				opType=kTypeWrite|kTypeMultiple;
  1.1285 +				break;
  1.1286 +			case ECIMLockUnlock:
  1.1287 +			default:
  1.1288 +				opType=kTypeSpecial;
  1.1289 +				break;
  1.1290 +			}
  1.1291 +
  1.1292 +		const TUint blocks = cmd.iTotalLength / cmd.BlockLength();
  1.1293 +		if ( blocks * cmd.BlockLength() != cmd.iTotalLength )
  1.1294 +		    {
  1.1295 +			OstTraceFunctionExitExt( DSDSTACK_CIMREADWRITEBLOCKSSM_EXIT4, this, (TInt) KMMCErrArgument );
  1.1296 +			return KMMCErrArgument;
  1.1297 +		    }
  1.1298 +
  1.1299 +		if ( !(opType & kTypeSpecial) )	// A special session has already set its command descriptor
  1.1300 +			{
  1.1301 +			if (blocks==1)
  1.1302 +				opType &= ~kTypeMultiple;
  1.1303 +
  1.1304 +			TUint32 oldFlags = cmd.iFlags;		// Store the existing command flags, as they will be reset by FillCommandDesc()
  1.1305 +			cmd.iCommand = cmdCodes[opType];
  1.1306 +			s.FillCommandDesc();
  1.1307 +			cmd.iFlags = oldFlags;				// ...and restore the old command flags
  1.1308 +			}
  1.1309 +
  1.1310 +		// NB We need to trap KMMCErrStatus errors, because if one occurs, 
  1.1311 +		// we still need to wait to exit PRG/RCV/DATA state 
  1.1312 +		if (Command().iCommand == ECmdWriteMultipleBlock)
  1.1313 +			{
  1.1314 +			Command().iExecNotHandle = KMMCErrDataCRC | KMMCErrDataTimeOut;
  1.1315 +			m.SetTraps(KMMCErrStatus | KMMCErrDataCRC | KMMCErrDataTimeOut);
  1.1316 +			}
  1.1317 +		else
  1.1318 +			{
  1.1319 +			m.SetTraps(KMMCErrStatus);
  1.1320 +			}
  1.1321 +
  1.1322 +		SMF_INVOKES( ExecCommandSMST, EStIssued )
  1.1323 +
  1.1324 +	SMF_STATE(EStIssued)
  1.1325 +
  1.1326 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_CIMREADWRITEBLOCKSSM7, "EStIssued" );
  1.1327 +		// check state of card after data transfer with CMD13.
  1.1328 +		if (s.Command().Direction() != 0)
  1.1329 +			{
  1.1330 +			SMF_GOTOS(EStWaitFinish)
  1.1331 +			}
  1.1332 +
  1.1333 +		SMF_GOTOS(EStRWFinish);
  1.1334 +
  1.1335 +	SMF_STATE(EStWaitFinish)
  1.1336 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_CIMREADWRITEBLOCKSSM8, "EStWaitFinish" );
  1.1337 +		// if MBW fail, then recover by rewriting ALL blocks...
  1.1338 +		// (used to recover using ACMD22, but this has been changed
  1.1339 +		// as is difficult to test for little gain in efficiency)
  1.1340 +		if (Command().iCommand == ECmdWriteMultipleBlock && err != 0)
  1.1341 +			{
  1.1342 +			if (Command().iCustomRetries++ >= (TInt) KSDMaxMBWRetries)
  1.1343 +				{
  1.1344 +				OstTraceFunctionExitExt( DSDSTACK_CIMREADWRITEBLOCKSSM_EXIT5, this, (TInt) err );
  1.1345 +				SMF_RETURN(err)
  1.1346 +				}
  1.1347 +
  1.1348 +			m.Pop();		// remove recursive call to EStRestart
  1.1349 +			SMF_GOTOS(EStRestart)			
  1.1350 +			}
  1.1351 +
  1.1352 +		// Save the status and examine it after issuing CMD13...
  1.1353 +		// NB We don't know where in the command stack the last response is stored (e.g. there may 
  1.1354 +		// have bee a Deselect/Select issued), but we do know last response is stored in iLastStatus
  1.1355 +		TMMC::BigEndian4Bytes(s.ResponseP(), s.iLastStatus);
  1.1356 +
  1.1357 +		// ...else issue CMD13 to poll for the card finishing and check for errors
  1.1358 +		s.PushCommandStack();
  1.1359 +		s.FillCommandDesc(ECmdSendStatus, 0);
  1.1360 +		SMF_INVOKES(ExecCommandSMST, EStWaitFinish1)
  1.1361 +
  1.1362 +	SMF_STATE(EStWaitFinish1)
  1.1363 +
  1.1364 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_CIMREADWRITEBLOCKSSM9, "EStWaitFinish1" );
  1.1365 +		const TMMCStatus status(s.ResponseP());
  1.1366 +		s.PopCommandStack();
  1.1367 +
  1.1368 +#ifdef __WINS__
  1.1369 +		SMF_GOTOS(EStRWFinish);
  1.1370 +#else
  1.1371 +		const TMMCardStateEnum st1 = status.State();
  1.1372 +
  1.1373 +		if (st1 == ECardStatePrg || st1 == ECardStateRcv || st1 == ECardStateData)
  1.1374 +			{
  1.1375 +			SMF_INVOKES(ProgramTimerSMST, EStWaitFinish);
  1.1376 +			}
  1.1377 +
  1.1378 +		if (status.Error())
  1.1379 +		    {
  1.1380 +			OstTraceFunctionExitExt( DUP7_DSDSTACK_CIMREADWRITEBLOCKSSM_EXIT, this, (TInt) KMMCErrStatus );
  1.1381 +			SMF_RETURN(KMMCErrStatus)
  1.1382 +		    }
  1.1383 +#endif
  1.1384 +		
  1.1385 +		// Fall through if CURRENT_STATE is not PGM or DATA
  1.1386 +	SMF_STATE(EStRWFinish)
  1.1387 +
  1.1388 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_CIMREADWRITEBLOCKSSM10, "EStRWFinish" );
  1.1389 +		if (TMMCStatus(s.ResponseP()).Error() != 0)
  1.1390 +		    {
  1.1391 +		    OstTraceFunctionExitExt( DSDSTACK_CIMREADWRITEBLOCKSSM_EXIT6, this, (TInt) KMMCErrStatus );
  1.1392 +			SMF_RETURN(KMMCErrStatus);
  1.1393 +		    }
  1.1394 +
  1.1395 +		s.iState &= ~KMMCSessStateInProgress;
  1.1396 +
  1.1397 +		// skip over recursive entry or throw error and catch in CIMLockUnlockSM()
  1.1398 +		TMMCErr ret = (s.Command().iCommand == ECmdLockUnlock) ? KMMCErrUpdPswd : KMMCErrBypass; 
  1.1399 +		OstTraceFunctionExitExt( DSDSTACK_CIMREADWRITEBLOCKSSM_EXIT7, this, (TInt) ret );
  1.1400 +		return ret;
  1.1401 +
  1.1402 +	SMF_STATE(EStDone)
  1.1403 +	    
  1.1404 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_CIMREADWRITEBLOCKSSM11, "EStDone" );
  1.1405 +	    __KTRACE_OPT(KPBUS1,Kern::Printf("<SD:RWBlocksSM()"));
  1.1406 +
  1.1407 +	SMF_END
  1.1408 +	}
  1.1409 +
  1.1410 +EXPORT_C TMMCErr DSDStack::ModifyCardCapabilitySM()
  1.1411 +//
  1.1412 +// This function provides a chance to modify the capability of paticular cards.
  1.1413 +// Licensee may overide this function to modify certain card's capability as needed.
  1.1414 +// A state machine is needed in derived function and function of base class should be
  1.1415 +// called in order to act more generic behaviour.
  1.1416 +//
  1.1417 +    {
  1.1418 +		enum states
  1.1419 +			{
  1.1420 +			EStBegin=0,
  1.1421 +			EStDone,
  1.1422 +			EStEnd
  1.1423 +			};
  1.1424 +
  1.1425 +	//coverity[unreachable]
  1.1426 +	//Part of state machine design.
  1.1427 +	SMF_BEGIN
  1.1428 +
  1.1429 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_MODIFYCARDCAPABILITYSM, "EStBegin" );
  1.1430 +    	SMF_INVOKES( DMMCStack::BaseModifyCardCapabilitySMST, EStDone )
  1.1431 +
  1.1432 +    SMF_STATE(EStDone)
  1.1433 +    
  1.1434 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_MODIFYCARDCAPABILITYSM1, "EStDone" );
  1.1435 +
  1.1436 +    SMF_END
  1.1437 +	}
  1.1438 +
  1.1439 +inline TMMCErr DSDStack::SwitchToHighSpeedModeSMST( TAny* aStackP )
  1.1440 +	{ return( static_cast<DSDStack *>(aStackP)->DSDStack::SwitchToHighSpeedModeSM() ); }
  1.1441 +
  1.1442 +TMMCErr DSDStack::SwitchToHighSpeedModeSM()
  1.1443 +	{
  1.1444 +		enum states
  1.1445 +			{
  1.1446 +			EStBegin=0,
  1.1447 +			EstCheckController,
  1.1448 +			EStSendSCRCmd,
  1.1449 +			EStCheckSpecVer,
  1.1450 +			EStCheckFunction,
  1.1451 +			EStCheckFunctionSent,
  1.1452 +			EStSwitchFunctionSent,
  1.1453 +			EStDone,
  1.1454 +			EStEnd
  1.1455 +			};
  1.1456 +
  1.1457 +		__KTRACE_OPT(KPBUS1,Kern::Printf(">SD:SwitchToHighSpeedModeSM "));
  1.1458 +
  1.1459 +		DMMCSession& s = Session();
  1.1460 +		OstTrace1( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM, "Current session = 0x%x", &s );
  1.1461 +
  1.1462 +	SMF_BEGIN
  1.1463 +
  1.1464 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM1, "EStBegin");
  1.1465 +	
  1.1466 +	SMF_STATE(EstCheckController) 	
  1.1467 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM2, "EstCheckController");
  1.1468 +	  	// Get the clock speed supported by the controller
  1.1469 +		TMMCMachineInfoV4 machineInfo;
  1.1470 +		TMMCMachineInfoV4Pckg machineInfoPckg(machineInfo);
  1.1471 +		MachineInfo(machineInfoPckg);
  1.1472 +		
  1.1473 +		if (machineInfo.iVersion >= TMMCMachineInfoV4::EVersion4)
  1.1474 +			{
  1.1475 +			if (machineInfo.iMaxClockSpeedInMhz < (KSDDTClk50MHz/1000) )
  1.1476 +				{
  1.1477 +				__KTRACE_OPT(KPBUS1, Kern::Printf("High speed mode not supported by controller"));
  1.1478 +				OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM3, "High speed mode not supported by controller");
  1.1479 +				SMF_GOTOS(EStDone);
  1.1480 +				}
  1.1481 +			}	
  1.1482 +
  1.1483 +	SMF_STATE(EStSendSCRCmd)
  1.1484 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM4, "EStSendSCRCmd");
  1.1485 +		//
  1.1486 +      	// ACMD51 Read the SD Configuration Register
  1.1487 +      	//
  1.1488 +		DSDSession::FillAppCommandDesc(Command(), ESDACmdSendSCR);
  1.1489 +      	s.FillCommandArgs(0, KSDSCRLength, iPSLBuf, KSDSCRLength);
  1.1490 +      	SMF_INVOKES(ExecCommandSMST, EStCheckSpecVer);
  1.1491 +
  1.1492 +	SMF_STATE(EStCheckSpecVer)
  1.1493 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM5, "EStCheckSpecVer");
  1.1494 +      	//	
  1.1495 +      	// Check the SD version
  1.1496 +		//
  1.1497 +      	// 0 : version 1.0-1.01	: SDHS Is NOT Supported
  1.1498 +      	// 1 : version 1.10+	: SDHS Is Supported
  1.1499 +		//
  1.1500 +      	__KTRACE_OPT(KPBUS1,Kern::Printf("   SD Configuration Register received"));
  1.1501 +      	__KTRACE_OPT(KPBUS1,Kern::Printf("   ...card_status=%x", TUint(s.iLastStatus)));
  1.1502 +      	OstTrace1( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM6, "SD Configuration Register received: card_status=0x%x", (TUint) s.iLastStatus);
  1.1503 +
  1.1504 +#ifdef _DEBUG
  1.1505 +      	for (TUint32 i = 0; i < KSDSCRLength; ++i)
  1.1506 +			{
  1.1507 +			__KTRACE_OPT(KPBUS1, Kern::Printf("   ...SCR_STATUS[0x%x] = %x", i, iPSLBuf[i]));
  1.1508 +			}
  1.1509 +#endif
  1.1510 +
  1.1511 +      	if(iPSLBuf[0]==2)
  1.1512 +			{
  1.1513 +			__KTRACE_OPT(KPBUS1,Kern::Printf("   ...SD Spec Version 2"));
  1.1514 +			OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM7, "SD Spec Version 2");
  1.1515 +			SMF_GOTOS(EStCheckFunction);
  1.1516 +			}
  1.1517 +  
  1.1518 +      	if(iPSLBuf[0]==1)
  1.1519 +			{
  1.1520 +			__KTRACE_OPT(KPBUS1,Kern::Printf("   ...SD Spec Version 1.10"));
  1.1521 +			OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM8, "SD Spec Version 1.10");
  1.1522 +			SMF_GOTOS(EStCheckFunction);
  1.1523 +			}
  1.1524 +  
  1.1525 +      	if(iPSLBuf[0]==0)
  1.1526 +			{
  1.1527 +			__KTRACE_OPT(KPBUS1,Kern::Printf("   ...SD Spec Version 1.01"));
  1.1528 +			OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM9, "SD Spec Version 1.01");
  1.1529 +			SMF_GOTOS(EStDone);
  1.1530 +        	}
  1.1531 +
  1.1532 +	__KTRACE_OPT(KPBUS1,Kern::Printf("   ...SD Spec Version > 2 !"));
  1.1533 +	OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM10, "SD Spec Version > 2");
  1.1534 +
  1.1535 +	SMF_STATE(EStCheckFunction)
  1.1536 +
  1.1537 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM11, "EStCheckFunction");
  1.1538 +		m.SetTraps(KMMCErrResponseTimeOut | KMMCErrNotSupported);
  1.1539 +
  1.1540 + 		//
  1.1541 +		// SD1.1 uses CMD6 which is not defined by the MMCA
  1.1542 +		//  - fill in command details using the SD Specific command description table
  1.1543 +		//
  1.1544 +
  1.1545 +		DSDSession::FillSdSpecificCommandDesc(Command(), ESDCmdSwitchFunction);
  1.1546 +		s.FillCommandArgs(KSDCheckFunctionHighSpeed, KSDSwitchFuncLength, iPSLBuf, KSDSwitchFuncLength);
  1.1547 +
  1.1548 +		SMF_INVOKES(IssueCommandCheckResponseSMST,EStCheckFunctionSent)
  1.1549 +
  1.1550 +	SMF_STATE(EStCheckFunctionSent)
  1.1551 + 
  1.1552 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM12, "EStCheckFunctionSent");
  1.1553 +       	__KTRACE_OPT(KPBUS1,Kern::Printf("   CheckFunctionSent %x",TUint(s.iLastStatus)));
  1.1554 +       	OstTrace1( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM13, "CheckFunctionSent=0x%x", (TUint) s.iLastStatus);
  1.1555 +
  1.1556 +		m.ResetTraps();
  1.1557 +
  1.1558 +		if(err == KMMCErrResponseTimeOut)
  1.1559 +			{
  1.1560 +	       	__KTRACE_OPT(KPBUS1,Kern::Printf("   ...CMD6 [Read] Response Timeout"));
  1.1561 +	       	OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM14, "CMD6 [Read] Response Timeout");
  1.1562 +			SMF_GOTOS(EStDone);
  1.1563 +			}
  1.1564 +		else if(err == KMMCErrNotSupported)
  1.1565 +			{
  1.1566 +	       	__KTRACE_OPT(KPBUS1,Kern::Printf("   ...CMD6 [Read] Not Supported"));
  1.1567 +	       	OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM15, "CMD6 [Read] Not Supported");
  1.1568 +			SMF_GOTOS(EStDone);
  1.1569 +			}
  1.1570 +
  1.1571 +#ifdef _DEBUG
  1.1572 +		for (TUint32 i = 0; i < KSDSwitchFuncLength; ++i)
  1.1573 +			{
  1.1574 +	  		__KTRACE_OPT(KPBUS1, Kern::Printf("   ...SD Switch Func Status[0x%x] = %x", i, iPSLBuf[i]));
  1.1575 +			}
  1.1576 +
  1.1577 +		m.SetTraps(KMMCErrResponseTimeOut);
  1.1578 +#endif
  1.1579 +
  1.1580 + 		//
  1.1581 +		// SD1.1 uses CMD6 which is not defined by the MMCA
  1.1582 +		//  - fill in command details using the SD Specific command description table
  1.1583 +		//
  1.1584 +
  1.1585 +		DSDSession::FillSdSpecificCommandDesc(Command(), ESDCmdSwitchFunction);
  1.1586 +      	s.FillCommandArgs(KSDSwitchFunctionHighSpeed, KSDSwitchFuncLength, iPSLBuf, KSDSwitchFuncLength);
  1.1587 +
  1.1588 +      	SMF_INVOKES(IssueCommandCheckResponseSMST,EStSwitchFunctionSent)
  1.1589 +	
  1.1590 +	SMF_STATE(EStSwitchFunctionSent)
  1.1591 +
  1.1592 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM16, "EStSwitchFunctionSent");
  1.1593 +#ifdef _DEBUG
  1.1594 +		m.ResetTraps();
  1.1595 +
  1.1596 +		if(err == KMMCErrResponseTimeOut)
  1.1597 +			{
  1.1598 +	       	__KTRACE_OPT(KPBUS1,Kern::Printf("   ...CMD6 [Write] Response Timeout"));
  1.1599 +	       	OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM17, "CMD6 [Write] Response Timeout");
  1.1600 +			}
  1.1601 +
  1.1602 +		for (TUint32 i = 0; i < KSDSwitchFuncLength; ++i)
  1.1603 +			{
  1.1604 +	  		__KTRACE_OPT(KPBUS1, Kern::Printf("   ...SD Switch[0x%x] = %x", i, iPSLBuf[i]));
  1.1605 +	  		OstTraceExt2( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM18, "SD Switch[0x%x]=0x%x", (TUint) i, (TUint) iPSLBuf[i]);
  1.1606 +			}
  1.1607 +#endif
  1.1608 +
  1.1609 +	SMF_STATE(EStDone)
  1.1610 +	
  1.1611 +        OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM19, "EStSwitchFunctionSent");
  1.1612 +      
  1.1613 +	SMF_END
  1.1614 +	}
  1.1615 +
  1.1616 +
  1.1617 +EXPORT_C DMMCSession* DSDStack::AllocSession(const TMMCCallBack& aCallBack) const
  1.1618 +/**
  1.1619 +* Factory function to create DMMCSession derived object.  Non-generic MMC
  1.1620 +* controllers can override this to generate more specific objects.
  1.1621 +* @param aCallBack Callback function to notify the client that a session has completed
  1.1622 +* @return A pointer to the new session
  1.1623 +*/
  1.1624 +	{
  1.1625 +	OstTraceFunctionEntry1( DSDSTACK_ALLOCSESSION_ENTRY, this );
  1.1626 +	return new DSDSession(aCallBack);
  1.1627 +	}
  1.1628 +
  1.1629 +EXPORT_C void DSDStack::Dummy1() {}
  1.1630 +EXPORT_C void DSDStack::Dummy2() {}
  1.1631 +EXPORT_C void DSDStack::Dummy3() {}
  1.1632 +EXPORT_C void DSDStack::Dummy4() {}