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