// Copyright (c) 1999-2010 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// Generic MMC controller types and standard classes for MMC manipulation
// This controller follows MMC spec V4.4+
// 
//

/**
 @file
 @internalComponent
*/

#if !defined(__MMC_H__)
#define __MMC_H__

#include <drivers/pbus.h>
#include <d32locd.h>
#include <drivers/rpmbpacket.h>

// MMC Card maximum system settings

const TInt KMaxMmcSockets = KMaxPBusSockets;

// Forward type declarations

class TMMC;
class TCID;
class TCSD;
class TExtendedCSD;
class TRCA;
class TDSR;
class TMMCStatus;
class TMMCArgument;
class TMMCard;
class TMMCCommandDesc;
class TMMCBusConfig;
class TMMCStackConfig;
class TMMCRCAPool;
class TMMCSessRing;
class TMMCStateMachine;
class DMMCSocket;
class DMMCSession;
class DMMCStack;
class TMMCMachineInfo;
class TMapping;
class TMMCPasswordStore;
class TMMCEraseInfo;
class TMMCMachineInfoV4;
class TMMCMachineInfoV44;
typedef TPckg<TMMCMachineInfo> TMMCardMachineInfoPckg;
typedef TPckg<TMMCMachineInfoV4> TMMCMachineInfoV4Pckg;
typedef TPckg<TMMCMachineInfoV44> TMMCMachineInfoV44Pckg;

enum TMMCAppCommand {EMMCNormalCmd,EMMCApplicationCmd};

// Typedefs

/**
@publishedPartner
@released

Represents the MultiMediaCard error code bit set.

MultiMediaCard error codes are defined as bit masks, mainly for use with
the state machine where the error trap mask may be used. 
The function DMMCSession::EpocErrorCode() converts these error bit values
into standard Symbian OS error values.

@see KMMCErrNone
@see KMMCErrResponseTimeOut
@see KMMCErrDataTimeOut
@see KMMCErrBusyTimeOut
@see KMMCErrBusTimeOut
@see KMMCErrTooManyCards
@see KMMCErrResponseCRC
@see KMMCErrDataCRC
@see KMMCErrCommandCRC
@see KMMCErrStatus
@see KMMCErrNoCard
@see KMMCErrBrokenLock
@see KMMCErrPowerDown
@see KMMCErrAbort
@see KMMCErrStackNotReady
@see KMMCErrNotSupported
@see KMMCErrHardware
@see KMMCErrBusInconsistent
@see KMMCErrBypass
@see KMMCErrInitContext
@see KMMCErrArgument
@see KMMCErrSingleBlock
@see KMMCErrLocked
@see KMMCErrNotFound
@see KMMCErrAlreadyExists
@see KMMCErrGeneral
@see KMMCErrAll
@see KMMCErrBasic
*/
typedef TUint32 TMMCErr;

/**
A structure to define global parameters for the initialisation of an RPMB object.
This is required for devices with emmc4.4+
@internalComponent
*/
struct TRpmbDeviceParms
    {
    DMMCSocket* iSocketPtr;
    TUint iCardNumber;
    };

/*
 Global counter for number or RPMB partitions. Only one partition per device 
 */
GLREF_D TUint NumberOfRpmbs;
/*
 Global holder for RPMB parameters
 */
GLREF_D TRpmbDeviceParms TheRpmbs[KMaxPBusSockets*4];

GLREF_D TBool RpmbParmsPopulated;

/**
Max number of RPMB devices
*/
const TUint MaxIndexRpmb = 0;

/**
MMC Enums and inline functions
*/

/**
@publishedPartner
@released

Defines a set of symbols corresponding to the MultiMediaCard bus commands.

A command is one of the parameter values inserted into a TMMCCommandDesc object.
The commands themselves are defined by the MultiMediaCard specification.

@see TMMCCommandDesc
*/
enum TMMCCommandEnum
	{
	/**
	CMD0; reset all cards to idle state.
	*/
	ECmdGoIdleState			=0,

	
	/**
	CMD1; all cards in the idle state send their operating conditions.
	*/
	ECmdSendOpCond			=1,

	
	/**
	CMD2; all cards send their CID number.
	*/
	ECmdAllSendCID			=2,


	/**
	CMD3; assign relative address to a card.
	*/
	ECmdSetRelativeAddr		=3,


	/**
	CMD4; program the DSR register of all cards.
	*/
	ECmdSetDSR				=4,

	
	/**
	CMD5; toggle device between Sleep and Awake states.
	*/
	ECmd5					=5,
	ECmdSleepAwake			=5,

	
	/**
	CMD6; Switch
	*/
	ECmd6					=6,
	ECmdSwitch				=6,

	
	/**
	CMD7; toggle a card between standby and transfer state, or between
	programming and disconnected state.

    The card is selected by its RCA and deselected by any other address.
	*/
	ECmdSelectCard			=7,

	
	/**
	CMD8; addressed card sends its extended CSD.
	*/
	ECmd8					=8,
	ECmdSendExtendedCSD		=8,

	
	/**
	CMD9; addressed card sends its CSD.
	*/
	ECmdSendCSD				=9,

	
	/**
	CMD10; addressed card sends its CID.
	*/
	ECmdSendCID				=10,

	
	/**
	CMD11; read data stream from the card starting at the given address until
	an ECmdStopTransmission follows.
	
	@see ECmdStopTransmission
	*/
	ECmdReadDatUntilStop	=11,

	
	/**
	CMD12; force the card to stop transmission.
	*/
	ECmdStopTransmission	=12,

	
	/**
	CMD13; addressed card sends its status register.
	*/
	ECmdSendStatus			=13,

	
	/**
	CMD14; BUSTEST_R - Reads the reversed bus testing data pattern from the card.
	
	@see ECmdBustest_W
	*/
	ECmd14					=14,
	ECmdBustest_R			=14,

	
	/**
	CMD15; set the card to the inactive state.
	*/
	ECmdGoInactiveState		=15,

	
	/**
	CMD16; set the block length for all following block commands.
	*/
	ECmdSetBlockLen			=16,

	
	/**
	CMD17; read a single data block from the card.
	*/
	ECmdReadSingleBlock		=17,

	
	/**
	CMD18; continuously transfer data blocks from the card until interrupted
	by ECmdStopTransmission.

	@see ECmdStopTransmission
	*/
	ECmdReadMultipleBlock	=18,

	
	/**
	CMD19; BUSTEST_W - Sends a test data pattern to the card to determine the bus characteristics

	@see ECmdBustest_R
	*/
	ECmd19					=19,
	ECmdBustest_W			=19,

	
	/**
	CMD20; write data stream from the host starting at the given address
	until interrupted by ECmdStopTransmission.

	@see ECmdStopTransmission
	*/
	ECmdWriteDatUntilStop	=20,

	
	/**
	CMD21; reserved for future use.	
	*/
	ECmd21					=21,

	
	/**
	CMD22; reserved for future use.	
	*/
	ECmd22					=22,

	
	/**
	CMD23; define the number of blocks to be transferred in the following
	multiple block read or write command.
	*/
	ECmdSetBlockCount		=23,

	
	/**
	CMD24; write a single block to the card.
	*/
	ECmdWriteBlock			=24,

	
	/**
	CMD25; continuously transfer data blocks to the card until interrupted
	by ECmdStopTransmission.

	@see ECmdStopTransmission
	*/
	ECmdWriteMultipleBlock	=25,
	

	/**
	CMD26; programming of the CID.
	
	This is issued once per card, and is normally reserved for
	the manufacturer.
	*/
	ECmdProgramCID			=26,

	
	/**
	CMD27; programming of the programmable bits of the CSD.
	*/
	ECmdProgramCSD			=27,

	
	/**
	CMD28; set the write protect bit of the addressed group, if the card has
	write protection features.
	*/
	ECmdSetWriteProt		=28,

	
	/**
	CMD29; clear the write protect bit of the addressed group, if the card has
	write protection features.
	*/
	ECmdClearWriteProt		=29,
	

	/**
	CMD30; ask the card to send the status of the write protect bit, if
	the card has write protection features.
	*/
	ECmdSendWriteProt		=30,

	
	/**
	CMD31; reserved for future use.	
	*/
	ECmd31					=31,

	
	/**
	CMD32; set the address of the first sector of the erase group.
	*/
	ECmdTagSectorStart		=32,

	
	/**
	CMD33; set the address of the last sector in a continuous range within
	the selected erase group, or the address of a single sector to be
	selected for erase.
	*/
	ECmdTagSectorEnd		=33,

	
	/**
	CMD34; remove one previously selected sector from the erase selection.
	*/
	ECmdUntagSector			=34,

	
	/**
	CMD35; set the the address of the first erase group within a continuous
	range to be selected for erase.
	*/
	ECmdTagEraseGroupStart	=35,

	
	/**
	CMD36; set the address of the last erase group within a continuous range
	to be selected for erase.
	*/
	ECmdTagEraseGroupEnd	=36,

	
	/**
	CMD37; removes one previously selected erase group from the erase selection.
	*/
	ECmdUntagEraseGroup		=37,

	
	/**
	CMD38; erase all previously selected sectors.
	*/
	ECmdErase				=38,

	
	/**
	CMD39; read and write 8 bit (register) data fields.
	*/
	ECmdFastIO				=39,

	
	/**
	CMD40; set the system into interrupt mode.
	*/
	ECmdGoIRQState			=40,

	
	/**
	CMD41; reserved for future use.	
	*/
	ECmd41					=41,

	
	/**
	CMD42; set/reset the password or lock/unlock the card.
	*/
	ECmdLockUnlock			=42,

	
	/**
	CMD43; reserved for future use.	
	*/
	ECmd43					=43,

	
	/**
	CMD44; reserved for future use.	
	*/
	ECmd44					=44,

	
	/**
	CMD45; reserved for future use.	
	*/
	ECmd45					=45,

	
	/**
	CMD46; reserved for future use.	
	*/
	ECmd46					=46,

	
	/**
	CMD47; reserved for future use.	
	*/
	ECmd47					=47,

	
	/**
	CMD48; reserved for future use.	
	*/
	ECmd48					=48,

	
	/**
	CMD49; reserved for future use.
	*/
	ECmd49					=49,

	
	/**
	CMD50; reserved for future use.	
	*/
	ECmd50					=50,

	
	/**
	CMD51; reserved for future use.	
	*/
	ECmd51					=51,

	
	/**
	CMD52; reserved for future use.	
	*/
	ECmd52					=52,

	
	/**
	CMD53; reserved for future use.	
	*/
	ECmd53					=53,

	
	/**
	CMD54; reserved for future use.	
	*/
	ECmd54					=54,

	
	/**
	CMD55; indicate to the card that the next command is an application
	specific command rather than a standard command.
	*/
	ECmdAppCmd				=55,

	
	/**
	CMD56; transfer a data block to the card, or get a data block from the card,
	for general purpose/application specific commands.
	*/
	ECmdGenCmd				=56,

	
	/**
	CMD57; reserved for future use.	
	*/
	ECmd57					=57,

	
	/**
	CMD58; reserved for future use.	
	*/
	ECmd58					=58,

	
	/**
	CMD59; reserved for future use.
	*/
	ECmd59					=59,

	
	/**
	CMD60; reserved for future use.
	*/
	ECmd60					=60,

	
	/**
	CMD61; reserved for future use.
	*/
	ECmd61					=61,

	
	/**
	CMD62; reserved for future use.
	*/
	ECmd62					=62,

	
	/**
	CMD63; reserved for future use.
	*/
	ECmd63					=63
	};

enum TMMCCommandTypeEnum
	{
	ECmdTypeUK,				// UnKnown command type
	ECmdTypeBC,				// Broadcast Command
	ECmdTypeBCR,			// Broadcast Command with Response
	ECmdTypeAC,				// Addressed Command
	ECmdTypeACS,			// Addressed Command to a Selected card
	ECmdTypeADTCS,			// Addressed Data Transfer Command to a Selected card
	ECmdTypeADC				// Addressed Direct Command to a Selected card
	};

enum TMMCResponseTypeEnum
	{
	ERespTypeNone,
	ERespTypeUnknown,
	ERespTypeR1,			// 32 bits Status
	ERespTypeR1B,			// 32 bits Status with possible busy signal
	ERespTypeR2,			// 128 bits CID or CSD register
	ERespTypeR3,			// 32 bits OCR register
	ERespTypeR4,			// 32 bits Fast I/O
	ERespTypeR5,			// 32 bits IRQ
	ERespTypeR6,
	ERespTypeR7				// not currently defined for MMC
	};


/**
 * Client InterfaceIDs for GetExtInterface
 * @publishedPartner
 * 
 */
enum TMMCExtInterfaceId
    {
    KInterfaceRpmb
    };

class MMCMExtInterface
    {
public:
    virtual TInt Func() = 0;
    };

/**
Interface class to return information for an RPMB capable device.
Used for emmc v4.4+
*/

class MRpmbInfo
    {
public:
    virtual inline TInt RpmbInfo(TUint aDeviceIndex, TRpmbDeviceParms& aParams);
    };

/**
 A generic adapter function for returning an interface of specified type
 The caller should set aInterfacePtr to NULL before calling
 @aInterfaceId Denotes the required interface to be returned
 @aInterfacePtr On completion contains an interface of type specified by aInterfaceId
 @aThis Extends the interface to provide further access to DMMCSession
 */
 
IMPORT_C TInt MMCGetExtInterface(TMMCExtInterfaceId aInterfaceId, MMCMExtInterface*& aInterfacePtr, TAny* aThis = NULL);

/**
@publishedPartner
@released

Defines the set of media types for a MultiMediaCard.
*/
enum TMMCMediaTypeEnum
	{
	/**
	A read only card.
	*/
	EMultiMediaROM,
	
	
	/**
	A writable card.
	*/
	EMultiMediaFlash,
	
	
	/**
	An I/O card.
	*/
	EMultiMediaIO,
	
	
	/**
	A card type that is neither read only, writable nor I/O.
	*/
	EMultiMediaOther,
	
	
	/**
	A card type that is not supported.
	*/
	EMultiMediaNotSupported
	};

enum TMMCSessionTypeEnum
	{
	ECIMNakedSession		 =0,
	ECIMUpdateAcq			 =1,
	ECIMInitStack			 =2,
	ECIMCheckStack			 =3,
	ECIMSetupCard			 =4,
	ECIMReadBlock			 =5,
	ECIMWriteBlock			 =6,
	ECIMReadMBlock			 =7,
	ECIMWriteMBlock			 =8,
	ECIMEraseSector			 =9,
	ECIMEraseGroup			 =10,
	ECIMReadIO				 =11,
	ECIMWriteIO				 =12,
	ECIMLockUnlock			 =13,
	ECIMLockStack			 =14,
	ECIMInitStackAfterUnlock =15,
	ECIMAutoUnlock			 =16,
	ECIMSleep				 =17,
    ECIMRpmbAccess           =18
	};

const TUint KMMCMaxSessionTypeNumber  = 19;
const TUint KMMCMinCustomSession	  = 1024;

const TUint KMMCCmdDirDirBitPosition=	KBit0;			//fixed - dont change it
const TUint KMMCCmdDirIndBitPosition=	(KBit5-KBit0);	//fixed - dont change it
const TUint KMMCCmdDirWBitArgument=		KBit5;
const TUint KMMCCmdDirNegate=			KBit6;
const TUint KMMCCmdDirWBitDirect=		KBit7;

const TUint KMMCCmdReliableWrite	=	KBit31;
const TUint KMMCCmdTrim             =   KBit0;			//Trim command arg

/**
@publishedPartner
@released

An enum whose values specify the data transfer direction.

@see TMMCCommandSpec
*/
enum TMMCCmdDirEnum
	{
	EDirNone = 0,
	EDirRead = KMMCCmdDirWBitDirect,
	EDirWrite = KMMCCmdDirWBitDirect|KMMCCmdDirDirBitPosition,
	EDirWBit0 = KMMCCmdDirWBitArgument + 0,
	EDirRBit0 = (KMMCCmdDirWBitArgument|KMMCCmdDirNegate) + 0
	};




/**
@publishedPartner
@released

An enum whose values specify the width of the data bus

This enum is used by the DMMCStack::SetBusWidth() and TMMCMachineInfo.iMaxBusWidth.
*/
enum TBusWidth
	{
	EBusWidth1 = 0x00,
	EBusWidth4 = 0x02,
	EBusWidth8 = 0x03,
	EBusWidthInvalid = KMaxTUint32
	};

/**
@publishedPartner
@released
*/
const TUint8 KMMCLockUnlockErase =		KBit3;	// In first byte of CMD42 data block

/**
@publishedPartner
@released
*/
const TUint8 KMMCLockUnlockLockUnlock =	KBit2;

/**
@publishedPartner
@released
*/
const TUint8 KMMCLockUnlockClrPwd =		KBit1;

/**
@publishedPartner
@released
*/
const TUint8 KMMCLockUnlockSetPwd =		KBit0;




/**
@publishedPartner
@released
	
A utility class that contains convenience functions to handle conversion
to and from big-endian format.
*/
class TMMC
	{
public:
	static inline TUint32 BigEndian32(const TUint8*);
	static inline void BigEndian4Bytes(TUint8* aPtr, TUint32 aVal);
	};


//		Generic MMC layer constants

const TInt  KMaxMMCStacks=1;					// Number of separate MMC buses
const TUint KMaxMMCardsPerStack=4;				// Limits the number of cards in each stack

const TUint KBroadcastToAllCards=0xFFFFFFFF;

//		MMC Spec related constants

const TUint KMMCMaxResponseLength=16;			// in bytes
const TUint KMMCCIDLength=16;
const TUint KMMCCSDLength=16;
const TUint KMMCExtendedCSDLength=512;
const TUint KMMCBusClockFOD=400;				// Identification clock in kiloherz
const TUint KMMCCommandMask = 63;				// Size of TMMCCommandEnum enumerator

// Command Classes Bit Set

/**
@publishedPartner
@released
*/
const TUint32 KMMCCmdClassNone=			  0;

/**
@publishedPartner
@released
*/
const TUint32 KMMCCmdClassBasic=		  KBit0;

/**
@publishedPartner
@released
*/
const TUint32 KMMCCmdClassStreamRead=	  KBit1;

/**
@publishedPartner
@released
*/
const TUint32 KMMCCmdClassBlockRead=	  KBit2;

/**
@publishedPartner
@released
*/
const TUint32 KMMCCmdClassStreamWrite=	  KBit3;

/**
@publishedPartner
@released
*/
const TUint32 KMMCCmdClassBlockWrite=	  KBit4;

/**
@publishedPartner
@released
*/
const TUint32 KMMCCmdClassErase=		  KBit5;

/**
@publishedPartner
@released
*/
const TUint32 KMMCCmdClassWriteProtection=KBit6;

/**
@publishedPartner
@released
*/
const TUint32 KMMCCmdClassLockCard=		  KBit7;

/**
@publishedPartner
@released
*/
const TUint32 KMMCCmdClassApplication=	  KBit8;

/**
@publishedPartner
@released
*/
const TUint32 KMMCCmdClassIOMode=		  KBit9;

/**
@publishedPartner
@released
*/
const TUint32 KMMCCmdClassReserved10=	  KBit10;
const TUint32 KMMCCmdClassSwitch=		  KBit10;

/**
@publishedPartner
@released
*/
const TUint32 KMMCCmdClassReserved11=	  KBit11;

//		Specific MMC implementation constants

const TUint KMaxMMCMachineStackDepth=20;		// TMMCStateMachine stack depth
const TUint KMaxMMCCommandStackDepth=9;			// Session TMMCCommandDesc stack depth
const TUint KMMCIdleCommandsAtRestart=2;		// Number of CMD0s to be issued at initialisation
const TUint KMMCMaxJobsInStackWorkSet=8;		// Number of sessions simultaneously served
const TUint KMMCPollGapInMilliseconds=40;
const TUint KMMCMaxPollAttempts=5;				// 40*5 = 200ms
const TUint KMMCRetryGapInMilliseconds=10;
const TUint KMMCMaxTimeOutRetries=1;
const TUint KMMCMaxCRCRetries=1;
const TUint16 KMMCMaxUnlockRetries=4;
const TUint16 KMMCMaxAutoUnlockRetries=25;
const TUint KMMCMaxGlobalRetries=1;
const TUint16 KMMCSpecOpCondBusyTimeout=100 ;     //MMC/SD Standard OCR timeout 1 second
const TUint16 KMMCMaxOpCondBusyTimeout=150;		// 10*150 = 1500ms
const TUint KMMCLowVoltagePowerUpTimeoutInMilliseconds=2;	// 1ms + 74 400KHz clock cycles
const TUint KMMCUnlockRetryGapInMilliseconds = 200;			// Unlock retry gap

// DMMCStack Modes Bit Set
const TUint32 KMMCModeEnableClientConfig =	KBit0;	// Merge with session iConfig
const TUint32 KMMCModeEnableTimeOutRetry =	KBit1;	// Auto retry on response time-outs
const TUint32 KMMCModeTimeOutRetryGap =		KBit2;	// Force timer delay between retries
const TUint32 KMMCModeEnableCRCRetry =		KBit3;	// Command or response CRC errors
const TUint32 KMMCModeCRCRetryGap =			KBit4;
const TUint32 KMMCModeDataCRCRetry =		KBit5;	// Repeat data transaction from the last valid position
const TUint32 KMMCModeEnableUnlockRetry =	KBit6;	// Resend CMD42 for unreliable cards
const TUint32 KMMCModeEnablePreemption =	KBit7;	// Allow sessions to share the MMC bus
const TUint32 KMMCModePreemptOnBusy =		KBit8;	// Release bus control if busy
const TUint32 KMMCModePreemptOnRetry =		KBit9;	// Release bus control before timeout/crc retries
const TUint32 KMMCModePreemptInGaps =		KBit10;	// Preempt whenever gap timer is invoked
const TUint32 KMMCModeEnqueIfLocked =		KBit11;	// Enque session if DMMCStack is locked
const TUint32 KMMCModeCardControlled =		KBit12;	// Use Session CardP to get RCAs etc.
const TUint32 KMMCModeCompleteInStackDFC =	KBit13;	// Run DMMCStack in DFC when completing
const TUint32 KMMCModeEnableBusyPoll =		KBit14;	// Enables mechanism recovering from busy timeouts
const TUint32 KMMCModeBusyPollGap =			KBit15;
const TUint32 KMMCModeEnableRetries =		KBit16;	// This mode removed disables all retries/polls
const TUint32 KMMCModeMask =				KBit17 - KBit0;

// The following modes are effective for MasterConfig only
const TUint32 KMMCModeClientPollAttempts =		KBit20;
const TUint32 KMMCModeClientTimeOutRetries =	KBit21;
const TUint32 KMMCModeClientCRCRetries =		KBit22;
const TUint32 KMMCModeClientUnlockRetries =		KBit23;
const TUint32 KMMCModeClientBusClock =			KBit24;
const TUint32 KMMCModeClientClockIn =			KBit25;
const TUint32 KMMCModeClientClockOut =			KBit26;
const TUint32 KMMCModeClientResponseTimeOut =	KBit27;
const TUint32 KMMCModeClientDataTimeOut =		KBit28;
const TUint32 KMMCModeClientBusyTimeOut =		KBit29;
const TUint32 KMMCModeClientiOpCondBusyTimeout = KBit30;
const TUint32 KMMCModeClientMask =	KBit31 - KBit20;

// The following modes cannot be enabled by a client if disabled in MasterConfig
const TUint32 KMMCModeMasterOverrides=
								KMMCModeEnableClientConfig	|
								KMMCModeEnablePreemption	|
								KMMCModeEnqueIfLocked		|
								KMMCModeClientMask;

// The following modes are always effective, even if the ClientConfig is disabled
const TUint32 KMMCModeClientOverrides=
								KMMCModeEnableClientConfig	|
								KMMCModeCardControlled;


// The default MasterConfig modes
const TUint32 KMMCModeDefault=	KMMCModeEnableClientConfig	|
								KMMCModeEnableRetries		|
								KMMCModeEnableTimeOutRetry	|
								KMMCModeTimeOutRetryGap		|
								KMMCModeEnableCRCRetry		|
								KMMCModeCRCRetryGap			|
								KMMCModeDataCRCRetry		|
								KMMCModeEnableUnlockRetry	|
								KMMCModeEnablePreemption	|
								KMMCModePreemptInGaps		|
								KMMCModeEnqueIfLocked		|
								KMMCModeCardControlled		|
								KMMCModeClientMask;


// MMC Error Code Bit Set

/**
@publishedPartner
@released

A MultiMediaCard error code.

Indicates no error.

@see TMMCErr
*/
const TUint32 KMMCErrNone=0;


/**
@publishedPartner
@released

A MultiMediaCard error code.

Timed out waiting for a response from the card after issuing a command.

@see TMMCErr
*/
const TUint32 KMMCErrResponseTimeOut=KBit0;


/**
@publishedPartner
@released

A MultiMediaCard error code.

Timed out waiting for a data block to be received during a data read command.

@see TMMCErr
*/
const TUint32 KMMCErrDataTimeOut=	 KBit1;


/**
@publishedPartner
@released

A MultiMediaCard error code.

Timed out waiting for a data block to be requested during a data write command.

@see TMMCErr
*/
const TUint32 KMMCErrBusyTimeOut=	 KBit2;


/**
@publishedPartner
@released

A MultiMediaCard error code.

Timed out during the CIM_UPDATE_ACQ macro waiting for a card to power up.
Cards that are still powering up return busy in response to a SEND_OP_COND command. 

@see TMMCErr
*/
const TUint32 KMMCErrBusTimeOut=	 KBit3;


/**
@publishedPartner
@released

A MultiMediaCard error code.

The host has detected more cards in a stack that it can handle, or it has
detected more cards than it was expecting, for example, more cards than physical slots.

@see TMMCErr
*/
const TUint32 KMMCErrTooManyCards=	 KBit4;


/**
@publishedPartner
@released

A MultiMediaCard error code.

The host has detected a CRC error in a response received from a card.

@see TMMCErr
*/
const TUint32 KMMCErrResponseCRC=	 KBit5;


/**
@publishedPartner
@released

A MultiMediaCard error code.

The host has detected a CRC error in a data block received from a card.

@see TMMCErr
*/
const TUint32 KMMCErrDataCRC=		 KBit6;


/**
@publishedPartner
@released

A MultiMediaCard error code.

The card has detected a CRC error in a command received from the host.

@see TMMCErr
*/
const TUint32 KMMCErrCommandCRC=	 KBit7;


/**
@publishedPartner
@released

A MultiMediaCard error code.

An R1 response was received from the card with one or more of the error flags
set in the card status field.

@see TMMCErr
*/
const TUint32 KMMCErrStatus=		 KBit8;


/**
@publishedPartner
@released

A MultiMediaCard error code.

A session was submitted without first being set-up with a card object,
or was set-up with a card object that is no longer present.

@see TMMCErr
*/
const TUint32 KMMCErrNoCard=		 KBit9;


/**
@publishedPartner
@released

A MultiMediaCard error code.

The session had the stack locked but the MultiMediaCard controller had
to override the lock to perform some other bus activity. 

@see TMMCErr
*/
const TUint32 KMMCErrBrokenLock=	 KBit10;


/**
@publishedPartner
@released

A MultiMediaCard error code.

The card was powered down.

@see TMMCErr
*/
const TUint32 KMMCErrPowerDown=		 KBit11;


/**
@publishedPartner
@released

A MultiMediaCard error code.

The session was stopped.

@see TMMCErr
*/
const TUint32 KMMCErrAbort=			 KBit12;


/**
@publishedPartner
@released

A MultiMediaCard error code.

The stack has not yet been initialised.

@see TMMCErr
*/
const TUint32 KMMCErrStackNotReady=	 KBit13;


/**
@publishedPartner
@released

A MultiMediaCard error code.

The session requested a service or feature that is not supported.

@see TMMCErr
*/
const TUint32 KMMCErrNotSupported=	 KBit14;


/**
@publishedPartner
@released

A MultiMediaCard error code.

Indicates a general hardware related error.

@see TMMCErr
*/
const TUint32 KMMCErrHardware=		 KBit15;


/**
@publishedPartner
@released

A MultiMediaCard error code.

An unexpected or inconsistent bus state has been detected.

@see TMMCErr
*/
const TUint32 KMMCErrBusInconsistent=KBit16;




// SM control error codes

/**
@publishedPartner
@released

A MultiMediaCard error code.

This is used interally by the MultiMediaCard controller.

@see TMMCErr
*/
const TUint32 KMMCErrBypass=		 KBit17;


/**
@publishedPartner
@released

A MultiMediaCard error code.

This is used internally by the MultiMediaCard controller in the process
of re-initialising a card to recover from an inconsistent bus state.

@see TMMCErr
*/
const TUint32 KMMCErrInitContext=	 KBit18;


/**
@publishedPartner
@released

A MultiMediaCard error code.

Indicates a bad argument.

@see TMMCErr
*/
const TUint32 KMMCErrArgument=		 KBit19;


/**
@publishedPartner
@released

A MultiMediaCard error code.

A multiple block operation was requested, but the length specified was
less than that of a block.

@see TMMCErr
*/
const TUint32 KMMCErrSingleBlock=	 KBit20;



/**
@internalComponent
*/
const TUint32 KMMCErrUpdPswd=		 KBit21;




// General error codes

/**
@publishedPartner
@released

A MultiMediaCard error code.

The card is locked.

@see TMMCErr
*/
const TUint32 KMMCErrLocked=			KBit22;


/**
@publishedPartner
@released

A MultiMediaCard error code.

Indicates a general 'not found' type  error.

@see TMMCErr
*/
const TUint32 KMMCErrNotFound=			KBit23;


/**
@publishedPartner
@released

An MultiMediaCard error code:

Indicates a general already 'exists type' error.

@see TMMCErr
*/
const TUint32 KMMCErrAlreadyExists=		KBit24;


/**
@publishedPartner
@released

An MultiMediaCard error code:

Indicates an unspecified error.

@see TMMCErr
*/
const TUint32 KMMCErrGeneral=			KBit25;


/**
@publishedPartner
@released

A bitmask of all MultiMediaCard error codes.
*/
const TUint32 KMMCErrAll = (KBit26 - KBit0);

/**
@publishedPartner
@released

A subset of MultiMediaCard error codes.
*/
const TUint32 KMMCErrBasic = (KMMCErrAll & ~(
								KMMCErrBypass		|
								KMMCErrUpdPswd		|
								KMMCErrInitContext	|
								KMMCErrArgument		|
								KMMCErrSingleBlock	|
								KMMCErrLocked		|
								KMMCErrNotFound		|
								KMMCErrAlreadyExists|
								KMMCErrGeneral));

// DMMC Stack and Session control bits

// Stack State bits
const TUint32 KMMCStackStateRunning=		KBit0;	// Stack scheduler active
const TUint32 KMMCStackStateWaitingToLock=	KBit1;	//
const TUint32 KMMCStackStateLocked=			KBit2;	//
const TUint32 KMMCStackStateWaitingDFC=		KBit3;
const TUint32 KMMCStackStateInitInProgress=	KBit4;
const TUint32 KMMCStackStateReScheduled=	KBit5;
const TUint32 KMMCStackStateJobChooser=		KBit6;
const TUint32 KMMCStackStateDoDeselect=		KBit7;
const TUint32 KMMCStackStateBusInconsistent=KBit8;
const TUint32 KMMCStackStateInitPending=	KBit9;
const TUint32 KMMCStackStateCardRemoved=    KBit10;
const TUint32 KMMCStackStateSleepinProgress=KBit11;
const TUint32 KMMCStackStateSleep=    		KBit12;
const TUint32 KMMCStackStateYielding=		KBit13;

// Session Blocking bits definition

/**
@publishedPartner
@released

A bit, which when set in a call to DMMCStack::BlockCurrentSession(), indicates
that the current session is to be blocked, awaiting an event that is to
be handled at the platform specific level.

For example, the session may be waiting for:

- a response following a command
- an interrupt indicating that data transfer is required
- a platform specific layer specific timer.

@see DMMCStack::BlockCurrentSession()
*/
const TUint32 KMMCBlockOnASSPFunction=	KBit0;

const TUint32 KMMCBlockOnPollTimer     = KBit1;
const TUint32 KMMCBlockOnRetryTimer    = KBit2;
const TUint32 KMMCBlockOnNoRun         = KBit3;
const TUint32 KMMCBlockOnDoor          = KBit4;
const TUint32 KMMCBlockOnWaitToLock    = KBit5;
const TUint32 KMMCBlockOnCardInUse     = KBit6;
const TUint32 KMMCBlockOnPgmTimer      = KBit7;
const TUint32 KMMCBlockOnInterrupt     = KBit8;
const TUint32 KMMCBlockOnDataTransfer  = KBit9;
const TUint32 KMMCBlockOnMoreData      = KBit10;
const TUint32 KMMCBlockOnYielding      = KBit11;  // Yielding to other commands

const TUint32 KMMCBlockOnAsynchMask    = KMMCBlockOnASSPFunction |
										 KMMCBlockOnPollTimer    |
										 KMMCBlockOnRetryTimer   |
										 KMMCBlockOnPgmTimer     |
										 KMMCBlockOnInterrupt    |
										 KMMCBlockOnDataTransfer |
										 KMMCBlockOnMoreData;

const TUint32 KMMCBlockOnGapTimersMask = KMMCBlockOnPollTimer  |
										 KMMCBlockOnRetryTimer |
										 KMMCBlockOnPgmTimer;

// Session State bits definition
const TUint32 KMMCSessStateEngaged     = KBit0;	// Processed by DMMCStack
const TUint32 KMMCSessStateInProgress  = KBit1;	// No longer safe to restart
const TUint32 KMMCSessStateCritical    = KBit2;	// Re-initialise the stack if aborted
const TUint32 KMMCSessStateSafeInGaps  = KBit3;
const TUint32 KMMCSessStateDoReSchedule= KBit4;

/**
@publishedPartner
@released

A bit that when set into DMMCSession::iState before calling 
DMMCStack::UnBlockCurrentSession(), causes a DFC to be queued in order
to resume the state machine at some later stage.
*/
const TUint32 KMMCSessStateDoDFC				  = KBit5;
const TUint32 KMMCSessStateBlockOnDoor			  = KBit6;
const TUint32 KMMCSessStateCardIsGone			  = KBit7;
const TUint32 KMMCSessStateASSPEngaged			  = KBit8;
const TUint32 KMMCSessStateAllowDirectCommands    = KBit9;  // Allow Direct Commands (Using CMD) during Data Transfer

class TCID
/**
	CID class

	@publishedPartner
	@released
*/
	{
public:
	inline TCID() {}					// Default constructor
	inline TCID(const TUint8*);
	inline TCID& operator=(const TCID&);
	inline TCID& operator=(const TUint8*);
	inline TBool operator==(const TCID&) const;
	inline TBool operator==(const TUint8*) const;
	inline void Copy(TUint8*) const;		// Copies big endian 16 bytes CID
	inline TUint8 At(TUint anIndex) const;	// Byte from CID at anIndex
private:
	TUint8 iData[KMMCCIDLength];		// Big endian 128 bit bitfield representing CID
	};


class TCSD
/**
	CSD class

	@publishedPartner
	@released
*/
	{
public:
	inline TCSD() {memclr(this, sizeof(*this));}	// Default constructor
	inline TCSD(const TUint8*);
	inline TCSD& operator=(const TCSD&);
	inline TCSD& operator=(const TUint8*);
	inline void Copy(TUint8*) const;		// Copies big endian 16 bytes CSD
	inline TUint8 At(TUint anIndex) const;	// Byte from CSD at anIndex
public:
	inline TUint CSDStructure() const;
	inline TUint SpecVers() const;
	inline TUint Reserved120() const;
	inline TUint TAAC() const;
	inline TUint NSAC() const;
	inline TUint TranSpeed() const;
	inline TUint CCC() const;
	inline TUint ReadBlLen() const;
	inline TBool ReadBlPartial() const;
	inline TBool WriteBlkMisalign() const;
	inline TBool ReadBlkMisalign() const;
	inline TBool DSRImp() const;
	inline TUint Reserved74() const;
	inline TUint CSize() const;
	inline TUint VDDRCurrMin() const;
	inline TUint VDDRCurrMax() const;
	inline TUint VDDWCurrMin() const;
	inline TUint VDDWCurrMax() const;
	inline TUint CSizeMult() const;
	inline TUint EraseGrpSize() const;
	inline TUint EraseGrpMult() const;
	inline TUint WPGrpSize() const;
	inline TBool WPGrpEnable() const;
	inline TUint DefaultECC() const;
	inline TUint R2WFactor() const;
	inline TUint WriteBlLen() const;
	inline TBool WriteBlPartial() const;
	inline TUint Reserved16() const;
	inline TBool FileFormatGrp() const;
	inline TBool Copy() const;
	inline TBool PermWriteProtect() const;
	inline TBool TmpWriteProtect() const;
	inline TUint FileFormat() const;
	inline TUint ECC() const;
	inline TUint CRC() const;
public:
	IMPORT_C TUint DeviceSize() const;		// Uses functions above to calculate device capacity
	IMPORT_C TMMCMediaTypeEnum MediaType() const;
	IMPORT_C TUint ReadBlockLength() const;	// Read Block Length in bytes
	IMPORT_C TUint WriteBlockLength() const;// Write Block Length in bytes
	IMPORT_C TUint EraseSectorSize() const;	// Erase sector size (default 512 bytes)
	IMPORT_C TUint EraseGroupSize() const;	// Erase group size (default 16*<sector size> bytes)
	IMPORT_C TUint MinReadCurrentInMilliamps() const;
	IMPORT_C TUint MinWriteCurrentInMilliamps() const;
	IMPORT_C TUint MaxReadCurrentInMilliamps() const;
	IMPORT_C TUint MaxWriteCurrentInMilliamps() const;
	IMPORT_C TUint MaxTranSpeedInKilohertz() const;
public:
	IMPORT_C TUint CSDField(const TUint& aTopBit, const TUint& aBottomBit) const;	/**< @internalComponent */
	TUint8 iData[KMMCCSDLength];												/**< @internalComponent */ // Big endian 128 bit bitfield representing CSD	
	};


class TExtendedCSD
/**
	Extended CSD register class.
	For more information about this register, see the MultimediaCard System 
	Specification, Version 4.4

	@publishedPartner
	@released
*/
	{
public:
	/** 
	An enum used by TExtendedCSD::GetWriteArg() to construct a TMMCArgument object.
	The value chosen defines how the register or command set is to be modified.
	*/
	enum TExtCSDAccessBits 
		{
		/** Change the card's command set */
		ECmdSet, 
		/** Set the specified bits */
		ESetBits, 
		/** Clear the specified bits */
		EClearBits, 
		/** Write the specified byte */
		EWriteByte
		};
	/** 
	This enum defines various field offsets into the Modes Segment (i.e.
	the writable part) of the Extended CSD register.
	*/
	enum TExtCSDModesFieldIndex 
		{
		/** Offset of the CMD_SET field */
		ECmdSetIndex = 191, 
		/** Offset of the CMD_SET_REV field */
		ECmdSetRevIndex = 189, 
		/** Offset of the POWER_CLASS field */
		EPowerClassIndex = 187,
		/** Offset of the HS_TIMING field */
		EHighSpeedInterfaceTimingIndex = 185,
		/** Offset of the BUS_WIDTH field */
		EBusWidthModeIndex = 183,
		/** Offset of the BOOT_CONFIG field */
		EBootConfigIndex = 179,
        /** Offset of the BOOT_CONFIG_PROT field */
        EBootConfigProtectionIndex = 178,
		/** Offset of the BOOT_BUS_WIDTH field */
		EBootBusWidthIndex = 177,
		/** Offset of the ERASE_GROUP_DEF field */
		EEraseGroupDefIndex = 175,
        /** Offset of the BOOT_WP field */
        EBootAreaWriteProtectionIndex = 173,
        /** Offset of the USER_WP field */
        EUserAreaWriteProtectionIndex = 171,
        /** Offset of the FW_CONFIG field */
        EFwConfigIndex = 169,
        /** Offset of the RST_n_FUNCTION field */
        EHardwareResetFunctionIndex = 162,
        /** Offset of the PARTITIONS_ATTRIBUTE field */
        EPartitionsAttributeIndex = 156,
        /** Offset of the PARTITION_SETTING_COMPLETED field */
        EPartitionSettingIndex = 155,
        /** Offset of the GP_SIZE_MULT field */



		};

	/** 
	This enum defines various field offsets into the Properties Segment (i.e.
	the read-only part) of the Extended CSD register.
	*/
	enum TExtCSDPropertiesFieldIndex
		{
		/** Offset of the EXT_CSD_REV field */
		EExtendedCSDRevIndex = 192,
		/** Offset of the CARD_TYPE field */
		ECardTypeIndex = 196,
		/** Offset of the ACC_SIZE field */
		EAccessSizeIndex = 225,
		/** Offset of the HC_ERASE_GRP_SIZE field */
		EHighCapacityEraseGroupSizeIndex = 224
		};
		
	/**	This enum defines the values for the Extended CSD Revision register	*/
	enum TExtendedCSDRev
		{
		EExtendedCSDRev1_0 = 0,
		EExtendedCSDRev1_1 = 1,
		EExtendedCSDRev1_2 = 2,
		EExtendedCSDRev1_3 = 3,
		EExtendedCSDRev1_4 = 4,
		EExtendedCSDRev1_5 = 5
		};

	/** This enum defines the bus width encoding used by the BUS_WIDTH field */
	enum TExtCSDBusWidths
		{
		EExtCsdBusWidth1 = 0x00,
		EExtCsdBusWidth4 = 0x01,
		EExtCsdBusWidth8 = 0x02
		};

	/** 
	This enum defines the different MMCV4.x card types available as defined 
	in the CARD_TYPE field 
	*/
	enum TCardTypes
		{
		EHighSpeedCard26Mhz = 0x01,
		EHighSpeedCard52Mhz = 0x02,
		ECardTypeMsk        = 0x03 
		};
	
	/**
	This enum defines the boot config encoding used by the BOOT_CONFIG field
	*/
	enum TExtCSDBootConfig // in v4.4 this is now called PARTITION_CONFIG
		{
		ESelectUserArea	 				= 0x00,
		ESelectBootPartition1 			= 0x01,
		ESelectBootPartition2 			= 0x02,
		ESelectRPMB						= 0x03, // R/W Replay Protected Memory Block (RPMB)
		ESelectGPAPartition1			= 0x04, // Access to General Purpose Area partition 1
		ESelectGPAPartition2			= 0x05, // Access to General Purpose Area partition 2
		ESelectGPAPartition3 			= 0x06, // Access to General Purpose Area partition 3
		ESelectGPAPartition4 			= 0x07, // Access to General Purpose Area partition 4		
		EEnableBootPartition1forBoot 	= 0x08,
		EEnableBootPartition2forBoot 	= 0x10,
		EEnableUserAreaforBoot			= 0x38,
		EEnableBootAck  				= 0x40,
		EPartitionTestMode              = 0x100 // Indicates test mode for eMMC partitions
		};

	/**
	This enum defines the Boot Bus Width encoding used by the BOOT_BUS_WIDTH field
	*/
	enum TExtCSDBootBusWidth
		{
		EBootBusWidth1Bit			= 0x00,
		EBootBusWidth4Bit			= 0x01,
		EBootBusWidth8Bit			= 0x02,
		EResetBusWidthafterBoot		= 0x08
		};

	/**
	This enum defines the Erase Group Definition encoding 
	used by the ERASE_GROUP_DEF field
	*/
	enum TExtCSDEraseGroupDef
		{
		
		EEraseGrpDefEnableOldSizes		= 0x00,
		EEraseGrpDefEnableHighCapSizes	= 0x01
		};
	
public:
	/** Default constructor */
	inline TExtendedCSD();				
	/** 
	Constructor
	@param aPtr a byte buffer containing the contents of the register
	*/
	inline TExtendedCSD(const TUint8* aPtr);
	/** 
	Copy constructor
	@param aCSD a reference to another instance of the same class
	*/
	inline TExtendedCSD& operator=(const TExtendedCSD& aCSD);
	/** 
	Copy constructor
	@param aPtr a byte buffer containing the contents of the register
	*/
	inline TExtendedCSD& operator=(const TUint8* aPtr);

	/** Returns the byte at a particular offset into the register
	@param anIndex the offset into the register
	*/
	inline TUint8 At(TUint anIndex) const;
	
	/** returns a pointer to the raw data */
	inline TUint8* Ptr();
	
	/** 
	Constructs and then returns a TMMCArgument which can be used to 
	write to the register using the SWITCH command (CMD6)
	@param aAccess specifies how the register or command set is to be modified.
	@param aIndex the offset into the register
	@param aValue the value to write to the field in the register
	@param aCmdSet The command set to write. Valid if aAccess = ECmdSet
	*/
	inline static TMMCArgument GetWriteArg(TExtCSDAccessBits aAccess, TExtCSDModesFieldIndex aIndex, TUint aValue, TUint aCmdSet);
	
	/** returns the contents of the CMD_SET field */
	inline TUint SupportedCmdSet() const;
	
	/** returns the contents of the SEC_COUNT field */
	inline TUint SectorCount() const;
	
	/** returns the contents of the MIN_PERF_W_8_52 field */
	inline TUint MinPerfWrite8Bit52Mhz() const;
	
	/** returns the contents of the MIN_PERF_R_8_52 field */
	inline TUint MinPerfRead8Bit52Mhz() const;
	
	/** returns the contents of the MIN_PERF_W_8_26_4_52 field */
	inline TUint MinPerfWrite8Bit26Mhz_4Bit52Mhz() const;
	
	/** returns the contents of the MIN_PERF_R_8_26_4_52 field */
	inline TUint MinPerfRead8Bit26Mhz_4Bit52Mhz() const;
	
	/** returns the contents of the MIN_PERF_W_4_26 field */
	inline TUint MinPerfWrite4Bit26Mhz() const;
	
	/** returns the contents of the MIN_PERF_R_4_26 field */
	inline TUint MinPerfRead4Bit26Mhz() const;
	
	/** returns the contents of the PWR_CL_26_360 field */
	inline TUint PowerClass26Mhz360V() const;
	
	/** returns the contents of the PWR_CL_52_360 field */
	inline TUint PowerClass52Mhz360V() const;
	
	/** returns the contents of the PWR_CL_26_195 field */
	inline TUint PowerClass26Mhz195V() const;
	
	/** returns the contents of the PWR_CL_52_195 field */
	inline TUint PowerClass52Mhz195V() const;
	
	/** returns the contents of the CARD_TYPE field */
	inline TUint CardType() const;
	
	/** returns the contents of the CSD_STRUCTURE field */
	inline TUint CSDStructureVer() const;
	
	/** returns the contents of the EXT_CSD_REV field */
	inline TUint ExtendedCSDRev() const;
	
	/** returns the contents of the CMD_SET field */
	inline TUint CmdSet() const;
	
	/** returns the contents of the CMD_SET_REV field */
	inline TUint CmdSetRev() const;
	
	/** returns the contents of the POWER_CLASS field */
	inline TUint PowerClass() const;
	
	/** returns the contents of the HS_TIMING field */
	inline TUint HighSpeedTiming() const;
	
	/** returns the contents of the BUS_WIDTH field */
	inline TUint BusWidthMode() const;
	
	/** returns the contents of the BOOT_CONFIG field */
	inline TUint BootConfig() const;

	/** returns the contents of the BOOT_BUS_WIDTH field */
	inline TUint BootBusWidth() const;

	/** returns the contents of the ERASE_GROUP_DEF field */
	inline TUint EraseGroupDef() const;

	/** returns the contents of the ACC_SIZE field */
	inline TUint AccessSize() const;

	/** returns the contents of the HC_ERASE_GRP_SIZE field */
	inline TUint HighCapacityEraseGroupSize() const;
	
	/** returns the contents of the BOOT_INFO field */
	inline TUint BootInfo() const;
	
	/** returns the contents of the BOOT_SIZE_MUTLI field */
	inline TUint BootSizeMultiple() const;
	
	/** returns the size of the boot partitions in sectors */
	inline TUint32 BootSizeInSectors() const;
	
	/** returns the contents of the ERASE_TIMEOUT_MULT field */
	inline TUint EraseTimeoutMultiple() const;
	
	/** returns the contents of the REL_WR_SEC_C field */
	inline TUint ReliableWriteSector() const;
	
	/** returns the contents of the HC_WP_GRP_SIZE field */
	inline TUint HighCapacityWriteProtectGroupSize() const;
	
	/** returns the contents of the S_C_VCC field */
	inline TUint SleepCurrentVcc() const;
	
	/** returns the contents of the S_C_VCCQ field */
	inline TUint SleepCurrentVccQ() const;
	
	/** returns the contents of the S_A_TIMEOUT field */
	inline TUint SleepAwakeTimeout() const;
	
	/** returns True if the CARD_TYPE field conatains a valid value **/
	inline TBool IsSupportedCardType() const;

    /** returns the contents of the ERASED_MEM_CONT field */
    inline TUint ErasedMemoryContent() const;

    /** returns the contents of the BOOT_CONFIG_PROT field */
    inline TUint BootConfigProt() const;

    /** returns the contents of the BOOT_WP field */
    inline TUint BootAreaWriteProtectionReg() const;

    /** returns the contents of the USER_WP field */
    inline TUint UserAreaWriteProtectionReg() const;

    /** returns the contents of the FW_CONFIG field */
    inline TUint FwConfiguration() const;

    /** returns the RPMB size based on contents of the RPMB_SIZE_MULT field */
    inline TUint32 RpmbSize() const;
    
    /** returns the RPMB size in sectors */
    inline TUint32 RpmbSizeInSectors() const;

    /** returns the contents of the RST_n_FUNCTION field */
    inline TUint HwResetFunction() const;

    /** returns the contents of the PARTITIONING_SUPPORT field */
    inline TUint PartitioningSupport() const;

    /** returns the Max Enhanced Area Size base on the contents of the
        MAX_ENH_SIZE_MULT field */
    inline TUint32 MaxEnhancedAreaSize() const;

    /** returns the contents of the PARTITIONS_ATTRIBUTE field */
    inline TUint PartitionsAttribute() const;

    /** returns the contents of the PARTITION_SETTING_COMPLETED field */
    inline TUint PartitioningSetting() const;

    /** returns the General purpose partition sizes based on contents of the
        GP_SIZE_MULT fields */
    inline TUint64 GeneralPurposePartition1Size() const;
    inline TUint64 GeneralPurposePartition2Size() const;
    inline TUint64 GeneralPurposePartition3Size() const;
    inline TUint64 GeneralPurposePartition4Size() const;
    
    /** returns the General Purpose Partition sizes in sectors */
    inline TUint32 GeneralPurposePartition1SizeInSectors() const;
    inline TUint32 GeneralPurposePartition2SizeInSectors() const;
    inline TUint32 GeneralPurposePartition3SizeInSectors() const;
    inline TUint32 GeneralPurposePartition4SizeInSectors() const;

    /** returns the Enhanced User Data Area Size based on thec contents of the
        ENH_SIZE_MULT fields */
    inline TUint64 EnhancedUserDataAreaSize() const;

    /** returns the Enhanced User Data Start Address based on the contents of
        the ENH_START_ADDR fields */
    inline TUint32 EnhancedUserDataStartAddress() const;

    /** returns the contents of the SEC_BAD_BLK_MGMNT field */
    inline TUint BadBlockManagementMode() const;

private:
    inline TUint64 PartitionSize(TUint8 aMult0, TUint8 aMult1, TUint8 aMult2, TUint32 aMultiplier) const;

	/** 
	@internalComponent little endian 512 byte field representing extended CSD	
	*/
	TUint8 iData[KMMCExtendedCSDLength];
	};

const TInt KMMCSelectPartitionMask		= KBit0 | KBit1 | KBit2;

//	32 bit MMC card status field (response R1)

const TUint32 KMMCStatAppCmd=			KBit5;
const TUint32 KMMCStatSwitchError=		KBit7;
const TUint32 KMMCStatReadyForData=		KBit8;
const TUint32 KMMCStatCurrentStateMask=	(KBit13-KBit9);
const TUint32 KMMCStatEraseReset=		KBit13;
const TUint32 KMMCStatCardECCDisabled=	KBit14;
const TUint32 KMMCStatWPEraseSkip=		KBit15;
const TUint32 KMMCStatErrCSDOverwrite=	KBit16;
const TUint32 KMMCStatErrOverrun=		KBit17;
const TUint32 KMMCStatErrUnderrun=		KBit18;
const TUint32 KMMCStatErrUnknown=		KBit19;
const TUint32 KMMCStatErrCCError=		KBit20;
const TUint32 KMMCStatErrCardECCFailed=	KBit21;
const TUint32 KMMCStatErrIllegalCommand=KBit22;
const TUint32 KMMCStatErrComCRCError=	KBit23;
const TUint32 KMMCStatErrLockUnlock=	KBit24;
const TUint32 KMMCStatCardIsLocked=		KBit25;
const TUint32 KMMCStatErrWPViolation=	KBit26;
const TUint32 KMMCStatErrEraseParam=	KBit27;
const TUint32 KMMCStatErrEraseSeqError=	KBit28;
const TUint32 KMMCStatErrBlockLenError=	KBit29;
const TUint32 KMMCStatErrAddressError=	KBit30;
const TUint32 KMMCStatErrOutOfRange=	KBit31;

const TUint32 KMMCStatErrorMask=		KMMCStatErrOutOfRange	|
										KMMCStatSwitchError		|
										KMMCStatErrAddressError	|
										KMMCStatErrBlockLenError|
										KMMCStatErrEraseSeqError|
										KMMCStatErrEraseParam	|
										KMMCStatErrWPViolation	|
										KMMCStatErrLockUnlock	|
										KMMCStatErrCardECCFailed|
										KMMCStatErrCCError		|
										KMMCStatErrUnknown		|
										KMMCStatErrUnderrun		|
										KMMCStatErrOverrun		|
										KMMCStatErrCSDOverwrite;


const TUint32 KMMCStatClearByReadMask=	KMMCStatErrOutOfRange	|
										KMMCStatErrAddressError	|
										KMMCStatErrBlockLenError|
										KMMCStatErrEraseSeqError|
										KMMCStatErrEraseParam	|
										KMMCStatErrWPViolation	|
										KMMCStatErrLockUnlock	|
										KMMCStatErrCardECCFailed|
										KMMCStatErrCCError		|
										KMMCStatErrUnknown		|
										KMMCStatErrUnderrun		|
										KMMCStatErrOverrun		|
										KMMCStatErrCSDOverwrite	|
										KMMCStatWPEraseSkip		|
										KMMCStatEraseReset		|
										KMMCStatAppCmd;

enum TMMCardStateEnum
	{
	ECardStateIdle = 0,
	ECardStateReady =	(1 << 9),
	ECardStateIdent =	(2 << 9),
	ECardStateStby =	(3 << 9),
	ECardStateTran =	(4 << 9),
	ECardStateData =	(5 << 9),
	ECardStateRcv =		(6 << 9),
	ECardStatePrg =		(7 << 9),
	ECardStateDis =		(8 << 9),
	ECardStateBtst = 	(9 << 9),
	ECardStateSlp = 	(10 << 9)
	};

class TMMCStatus
/**
	MMC Status class. 
	This class can be used to get the MMC card state machine and response status.
	For the details of MMC card state machine and command response refer to MMC card specification.
    
	@see DMMCStack
	@publishedPartner
	@released
*/
	{
public:
	/**
    * Default constructor.
    */
	inline TMMCStatus() {}
	inline TMMCStatus(const TUint8*);
	inline TMMCStatus(const TUint32&);
	inline operator TUint32() const;
	inline TUint32 Error() const;
	inline TMMCardStateEnum State() const;
	inline void UpdateState(TMMCardStateEnum aState);
private:
	TUint32 iData;				//	32 bit bitfield representing status register
	};



const TUint32 KMMCOCRBusy           = KBit31;			// OCR Busy Bit (Response R3)
const TUint32 KMMCOCRAccessModeHCS	= KBit30;			// OCR Access Mode + SD HCS Bit  (Response R3)
const TUint32 KMMCOCRLowVoltage     = KBit7;			// 1.65 - 1.95 volt support
const TUint32 KMMCOCRAccessModeMask	= KBit30 | KBit29;	// OCR Access Mode : [00 : Byte], [10 : Block]



/**
	Defines the bit value that can be used in TPBusPsuInfo::iVoltageSupported
	to indicate that the MultiMediaCard PSU supports voltage adjustment.

	@publishedPartner
	@released
*/
#define KMMCAdjustableOpVoltage KMMCOCRBusy // Use same bit to flag ASSP PSU supports voltage adjustment.


class TMMCArgument
/**
	MMC Argument class

	@publishedPartner
	@released
*/
	{
public:
	inline TMMCArgument();
	inline TMMCArgument(const TUint32&);
	inline TMMCArgument(TRCA);
	inline TMMCArgument(TDSR);
	inline operator TUint32() const;
	inline void SetRCA(TRCA);
private:
	TUint32 iData;				//	32 bit bitfield representing the argument
	};


class TRCA
/**
	MMC RCA (Relative Card Address) class
*/
	{
public:
	inline TRCA() {}
	inline TRCA(TUint16);
	inline TRCA(TInt);
	inline TRCA(TMMCArgument);
	inline operator TUint16() const;
private:
	TUint16	iData;	// 16 bit bitfield representing MultiMedia Card's RCA
	};


class TDSR
/**
	MMC DSR (Driver Stage Register) class
*/
	{
public:
	inline TDSR();
	inline TDSR(TUint16);
	inline operator TUint16() const;
private:
	TUint16	iData;	// 16 bit bitfield representing MultiMedia Card's DSR
	};


// Card specific information and context

/**
@publishedPartner
@released
*/
const TUint32 KMMCardHasPassword=			KBit0;

/**
@publishedPartner
@released
*/
const TUint32 KMMCardIsWriteProtected=		KBit1;

/**
@publishedPartner
@released
*/
const TUint32 KMMCardIsLockable=			KBit2;
const TUint32 KMMCardIsHighCapacity=		KBit3;
const TUint32 KMMCardIsHighSpeed=			KBit4;

const TUint32 KMMCardMMCFlagMask=			0x0000ffff;

const TUint32 KMMCardFirstCustomFlag=		KBit16;
const TUint32 KMMCardCustomFlagMask=		0xffff0000;

const TUint32 KMMCardHighCapBlockSize=		512;
const TUint32 KMMCardHighCapBlockSizeLog2=	9;

NONSHARABLE_CLASS(TMMCard)
/**
	MMC card class
*/
	{
public:
	inline TBool IsHighCapacity() const;

	/**	@publishedPartner
		@released */
	TMMCard();

	/**	@publishedPartner
		@released */
	inline TBool IsPresent() const;

	/**	@publishedPartner
		@released */
	IMPORT_C TBool IsReady() const;

	/**	@publishedPartner
		@released */
	IMPORT_C TBool IsLocked() const;

	/**	@publishedPartner
		@released */
	inline TMMCMediaTypeEnum MediaType() const;

	/**	@publishedPartner
		@released */
	inline TUint DeviceSize() const;

	/**	@publishedPartner
		@released */
	inline const TCID& CID() const;

	/**	@publishedPartner
		@released */
	inline const TCSD& CSD() const;

	/**	@publishedPartner
		@released */
	inline const TExtendedCSD& ExtendedCSD() const;

	/**	@publishedPartner
		@released */
	inline TRCA RCA() const;

	/**	@publishedPartner
		@released */
	inline TBool HasPassword() const;

	/**	@publishedPartner
		@released */
	inline TBool IsWriteProtected() const;	// Always EFalse in MMC build

	/**	@publishedPartner
		@released */
	inline TInt BusWidth() const;

	/**	@publishedPartner
		@released */
	inline void SetBusWidth(TInt aBusWidth);

    /** @internalTechnology */
	inline void SetHighSpeedClock(TUint32 aHighSpeedClock);

    /** @internalTechnology */
	inline TUint32 HighSpeedClock() const;

	/**	@publishedPartner
		@released */
	virtual TUint32 PreferredWriteGroupLength() const;

	/**	@publishedPartner
		@released */
	virtual TInt GetFormatInfo(TLDFormatInfo& aFormatInfo) const;

	/**	@publishedPartner
		@released */
	virtual TUint32 MinEraseSectorSize() const;

	/**	@publishedPartner
		@released */
	virtual TUint32 EraseSectorSize() const;

	virtual TUint MaxTranSpeedInKilohertz() const;

	virtual TInt GetEraseInfo(TMMCEraseInfo& anEraseInfo) const;

	/**	@publishedPartner
		@released 

		Returns the maximum block length supported by the card encoded as a logarithm.
		This may be less than the READ_BL_LEN field in the CSD 
		register depending on the type of card and it's capacity.
	*/
	virtual TInt MaxReadBlLen() const;

	/**	@publishedPartner
		@released 

		Returns the maximum write block length supported by the card encoded as a logarithm.
		This may be less than the WRITE_BL_LEN field in the CSD 
		register depending on the type of card and it's capacity.
	*/
	virtual TInt MaxWriteBlLen() const;

	/**	@publishedPartner
		@released */
	virtual TInt64 DeviceSize64() const;

private:
	inline TInt Number() const;
public:
	TInt iIndex;
	TMMCStatus iStatus;				// last card's status
	TUint32 iSetBlockLen;			// current block length set for the card
	TMMCCommandEnum iLastCommand;	// Last Command code issued for the card
	TCID iCID;
	TCSD iCSD;
	TRCA iRCA;
	DMMCSession* iUsingSessionP;	// session which has this card attached
	TUint32 iFlags;					
	TExtendedCSD iExtendedCSD;
private:
	TUint32 iHighSpeedClock;
	TInt iSpare[4];
	TInt iBusWidth;
	friend class DMMCStack;
	friend class TMMCardArray;
	};

class TMMCardArray
/**
	MMC card array class
*/
	{
public:
	inline TMMCardArray(DMMCStack* anOwningStack);
	
	/**	@publishedPartner
		@released */
	IMPORT_C virtual TInt AllocCards();

	void InitNewCardScan();

	/**	@publishedPartner
		@released */
	IMPORT_C void AddNewCard(const TUint8* aCID,TRCA* aNewRCA);

	inline TUint NewCardCount();
	inline TInt CardsPresent();
	inline TMMCard* NewCardP(TUint aNewCardNumber);
	inline TMMCard* CardP(TUint aCardNumber);
	inline TMMCard& Card(TUint aCardNumber);
	inline TMMCard& NewCard(TUint aCardNumber);
	TInt MergeCards(TBool aFirstPass);
	void UpdateAcquisitions(TUint* aMaxClock);

    /** @internalTechnology */
	TInt CardIndex(const TMMCard* aCard);
	
	/**	@publishedPartner
		@released */
	IMPORT_C virtual void DeclareCardAsGone(TUint aCardNumber);

protected:										// initialized by AllocCards()
	void MoveCardAndLockRCA(TMMCard& aSrc,TMMCard& aDest,TInt aDestIndex);
	DMMCStack* iOwningStack;
	TInt iCardsPresent;
	TUint iNewCardsCount;
	TMMCard* iCards[KMaxMMCardsPerStack];
	TMMCard* iNewCards[KMaxMMCardsPerStack];
	};

// MMC Command descriptor

const TUint32 KMMCCmdFlagBytesValid=	KBit0;	// iBytesDone has a valid data
const TUint32 KMMCCmdFlagTransStopped=	KBit1;	// CMD12 has been successfully issued
const TUint32 KMMCCmdFlagStatusReceived=KBit2;	// Raised by ASSP layer, cleared by ExecCommandSM()
const TUint32 KMMCCmdFlagExecTopBusy=	KBit3;	// ExecCommandSM() flag
const TUint32 KMMCCmdFlagExecSelBusy=	KBit4;	// ExecCommandSM() flag
const TUint32 KMMCCmdFlagBlockAddress=	KBit5;	// Block addressing mode
const TUint32 KMMCCmdFlagDMARamValid=   KBit6;  // Memory is DMA'able flag
const TUint32 KMMCCmdFlagDoubleBuffer=  KBit7;  // The current DT command is double-buffered
const TUint32 KMMCCmdFlagPhysAddr=		KBit8;  // Address is a physical address
const TUint32 KMMCCmdFlagReliableWrite=	KBit9;  // Current command is Reliable Write
const TUint32 KMMCCmdFlagDeleteNotify=  KBit10; // Current command is Delete Notify
const TUint32 KMMCCmdFlagRpmbIO=        KBit11; // Current command is of RPMB type

const TUint32 KMMCCmdFlagASSPFlags=	KMMCCmdFlagBytesValid	|
									KMMCCmdFlagTransStopped	|
									KMMCCmdFlagStatusReceived;




/**
The MultiMediaCard command specification.

@publishedPartner
@released
*/
class TMMCCommandSpec
	{
public:
    /**
    The command class as defined by the MultiMediaCard System Specification.
    */
	TUint32 iCommandClass;
	
	/**
	The command type as defined by the MultiMediaCard System Specification.
	*/
	TMMCCommandTypeEnum iCommandType;
	
	/**
	The data transfer direction.
	*/
	TMMCCmdDirEnum iDirection;
	
	/**
	ETrue indicates more than one data block is to be tranferred.
	*/
	TBool iMultipleBlocks;
	
	/**
	ETrue indicates use standard stop transmission mode.
	*/
	TBool iUseStopTransmission;		// CMD12 has to be used in the end
	
	/**
	The expected response type.
	
	Note:
	
	- if this is EResponseTypeNone, then no response is expected.
	- if this is ERespTypeR2, then a long (128-bit) response is expected.
	- for all other types, a standard (32-bit) response is expected.
	*/
	TMMCResponseTypeEnum iResponseType;
	
	/**
	Expected response length (currently 4 or 16 bytes).
	*/
	TUint iResponseLength;
	};

class TMMCIdxCommandSpec
/**
	MMC Index command spec class
*/
	{
public:
	TInt iIdx;
	TMMCCommandSpec iSpec;
	};




/**
	MMC command description.
	
	When issuing an individual command over the bus, the MultiMediaCard
	controller uses an object of this type to specify the parameters
	for the command, and to receive back any response.
	
	Commands are issued by passing an object of this type to
	the DMMCStack::IssueMMCCommandSM() function, which is implemented by
	the platform specific layer.

	@publishedPartner
	@released
*/
class TMMCCommandDesc
	{
public:
	IMPORT_C TInt Direction() const;			// returns -1/0/+1 for read/none/write
 
	inline TBool IsBlockCmd() const;
	inline TUint32 NumBlocks() const;
	inline TInt64 Arg64() const;	
	inline TBool IsDoubleBuffered() const;
	inline TUint32 BufferLength() const;
	inline TUint32 BlockLength() const;
	inline TBool IsPhysicalAddress() const;
	TBool AdjustForBlockOrByteAccess(const DMMCSession& aSession);

	void Dump(TUint8* aResponseP, TMMCErr aErr);

public:
    /**
    @internalComponent
    */
	TUint32 iFlags;
	
	/**
	The command code.
	
	This can be written directly to the MMC controller hardware.
	*/
	TMMCCommandEnum iCommand;
	
	/**
    The argument to be supplied with the command.
    
   	This can be written directly to the MMC controller hardware.
	*/
	TMMCArgument iArgument;
	
	/**
	The total length of the data to be tranferred.
	*/
	TUint32 iTotalLength;
	
	/**
	A pointer to the location from where the data is to be read, or written. 
	*/
	TUint8* iDataMemoryP;
	
	/**
	The block length to be used in a data transaction.
	*/
	TUint32 iBlockLength;
	
	/**
	The MultiMediaCard command specification.
	*/
	TMMCCommandSpec iSpec;
	
	/**
	The number of bytes transferred since the last time the card was selected.
	*/
	TUint32 iBytesDone;
	
    /**
    @internalComponent
    */
	TUint iPollAttempts;			// Retry counters
	
    /**
    @internalComponent
    */
	TUint iTimeOutRetries;
	
    /**
    @internalComponent
    */
	TUint iCRCRetries;
	
    /**
    @internalComponent
    */
	TUint16 iUnlockRetries;
	
    /**
    @internalComponent
    */
	TUint16 iOpCondBusyTimeout;		// Units of 10mS
	
    /**
    @internalComponent
    */
	TUint iCustomRetries;
	
    /**
    @internalComponent
    */
	TUint32 iExecNotHandle;			// error codes to not handle in ExecCommandSM()
	
	/**
	The area into which the command response is put.
	
	This is in big-endian format.
	*/
	TUint8 iResponse[KMMCMaxResponseLength];
	};




/**
	MMC bus configuration.

    An object of this type is passed to the Variant implementation
	of DMMCStack::SetBusConfigDefaults(), which should fill the public data
	members with appropriate information and values.

	@publishedPartner
	@released
*/
class TMMCBusConfig
	{
public:
    /**
    The hardware interface clock, in KHz.
    */
	TUint iBusClock;
	
	
	/**
	The bus clock when clocking in data, in KHz.
	*/
	TUint iClockIn;
	
	
	/**
	The bus clock when clocking out data, in KHz.
	*/
	TUint iClockOut;
	
	
	/**
	The response timeout value, in uS.
	*/
	TUint iResponseTimeOut;
	
	
	/**
	The data timeout value, in uS.
	*/
	TUint iDataTimeOut;
	
	
	/**
	The busy timeout value, in uS.
	*/
	TUint iBusyTimeOut;
	};


class TMMCStackConfig
/**
   	@publishedPartner
	@released

	Holds the stack configuration settings on behalf of a session.

	Each DMMCSession object contains the public member DMMCSession::iConfig - an instance of the TMMCStackConfig class.
	By changing these settings, the client can override the master (i.e. default) stack configuration settings. 

	However, these changes only remain in effect for the period that the session remains the current session.
	In this way, the client is able to change the settings employed by the Controller (e.g. bus clock, enable retries, 
	change time-out values, restore defaults etc) while it performs that client's request. 

	The client would generally set-up the stack configuration it requires prior to submitting the session.
*/
	{
public:
	inline TMMCStackConfig();
	inline void SetMode(TUint32 aMask);
	inline void RemoveMode(TUint32 aMask);
	inline void UseDefault(TUint32 aMask);
	inline void SetPollAttempts(TUint aData);
	inline void SetTimeOutRetries(TUint aData);
	inline void SetCRCRetries(TUint aData);
	inline void SetBusClockInKhz(TUint aParam);			// In kilohertz
	inline void SetTicksClockIn(TUint aParam);			// Number of clock ticks in ClockIn phase
	inline void SetTicksClockOut(TUint aParam);			// Number of clock ticks in ClockOut phase
	inline void SetResponseTimeOutInTicks(TUint aParam);	// Timeout in bus clock ticks
	inline void SetDataTimeOutInMcs(TUint aParam);		// in microseconds
	inline void SetBusyTimeOutInMcs(TUint aParam);		// in microseconds
	inline void SetOpCondBusyTimeout(TUint16 aData);	// Units of 10mS
	inline TInt OpCondBusyTimeout();
	TUint iPollAttempts;
private:
	TUint32 iModes;
	TUint32 iUpdateMask;
	TUint32 iClientMask;
	TUint iTimeOutRetries;
	TUint iCRCRetries;
	TUint16 iUnlockRetries;
	TUint16 iOpCondBusyTimeout;							// Units of 10mS
	TMMCBusConfig iBusConfig;
	friend class DMMCStack;
	};


class TMMCRCAPool
/**
	MMC RCA Pool
*/
	{
public:
	inline TMMCRCAPool();
	TRCA GetFreeRCA();
	inline void LockRCA(TRCA);
	inline void UnlockRCA(TRCA);
	inline void ReleaseUnlocked();
private:
	TUint32 iPool;
	TUint32 iLocked;
	};


class TMMCSessRing
/**
	MMC session ring
*/
	{
public:
	TMMCSessRing();
	inline TBool IsEmpty() const;
	void Erase();
	inline void SetMarker();				// Sets Marker into Point position
	inline void AdvanceMarker();			// Moves Marker one position forward
	inline void Point();					// Sets Point into Marker position
	TBool Point(DMMCSession* aSessP);		// Finds aSessP and sets Point to it
	void Add(DMMCSession* aSessP);			// Inserts aSessP before the Marker; Point moves to Marker
	void Add(TMMCSessRing& aRing);
	DMMCSession* Remove();					// Removes at Point; Point moves forward
	void Remove(DMMCSession* aSessP);		// Points aSessP first, then remove()
	inline TUint Size() const;
	inline operator DMMCSession*() const;
	DMMCSession* operator++(TInt);			// returns Point and moves it forward; stops at Marker
private:
	DMMCSession* iPMark;
	DMMCSession* iPoint;
	DMMCSession* iPrevP;
	TUint iSize;
	};


//
// DMMCStack State Machine Functions are supported by TMMCStateMachine class
//
// The structure of state machine functions is assumed to be as follows
//
// TMMCErr DMMCStack::FunctionNameSMST( TAny* aPtr )
//	{ return( STATIC_CAST(DMMCStack*,aPtr)->FunctionNameSM() ); }
//
// TMMCErr DMMCStack::FunctionNameSM()
//	{
//		enum states {EStBegin=0, ..., EStEnd };
//		DMMCSession& s = Session();
//		TMMCStateMachine& m = Machine();
//		const TMMCErr err = m.SetExitCode( 0 );
//
//		for(;;)
//		{
//			switch(m.State())
//			{
//			case EStBegin:
//				{
//					....
//				}
//			case EStNext:
//				{
//					.....
//				}
//			case EStEnd: break;
//			default: Panic(...);
//			}
//			break;
//		}
//		return(m.Pop());
//	}
//
// State Machine remembers the next state number and function name and goes there as soon
// as the control is returned to the session. To release the control and wait for the next
// re-entrance (which will happen immediately if the session is not blocked or, as soon as
// an asynchronous event removes the blocking condition), a state machine function has to
// return( 0 ); Returning non-zero exit code will result in the session being completed with
// that error code unless a caller state machine function has explicitly intercepted such
// an error with m.SetTraps( TMMCErr aMask ).
//
// To make a state machine function code more readable, the following macros are provided:
//
// SMF_NEXTS(nexts)				- set the next state to "nexts"
// SMF_CALL(func)				- invoke SM function "func", then go to the next state
// SMF_CALLWAIT(func)			- the same as above, but sleep at the entry point
// SMF_CALLMYS(nexts,retst)		- invoke current SM function at "nexts" entry point
// SMF_CALLMEWR(retst)			- invoke me right here with return state retst
// SMF_INVOKES(func,nexts)		- invoke SM function "func", then go to the state "nexts"
// SMF_INVOKEWAITS(func,nexts)	- the same as above, but sleep at the entry point
// SMF_WAIT						- sleep at the next state
// SMF_WAITS(nexts)				- set next state to "nexts", then sleep
// SMF_RETURN(value)			- return an error to the caller SM function
// SMF_EXIT						- return to the caller SM function
// SMF_EXITWAIT					- the same as above, but sleep at the exit point
// SMF_JUMP(func)				- transfer the control to SM function "func"
// SMF_JUMPWAIT(func)			- the same as above, but sleep at the entry point
// SMF_GOTONEXTS				- goto the next state
// SMF_GOTOS(nexts)				- set the next state to "nexts", then go to it
// SMF_STATE(sname)				- declare the state name "sname"
// SMF_BPOINT(sname)			- declare the state "sname" and sleep here if blocked statically
//

/**
@publishedPartner
@released

Declares the start of a state machine case switch statement.

The macro assumes that the first state defined by the state machine
function is EStBegin.

NOTES:

- the code generates an opening curly brace that must be matched by
a closing curly brace. Typically, this is provided by the SMF_STATE or
the SMF_END macros.

@see SMF_STATE
@see SMF_END
*/
#define SMF_BEGIN TMMCStateMachine& m=Machine();const TMMCErr err=m.SetExitCode(0);\
				for(;;){switch(m.State()){case EStBegin:{if(err) (void)0;

/**
@publishedPartner
@released

Declares the end of a state machine case switch statement.

The macro assumes that the last state defined by the state machine
function is EStEnd.

NOTES:

- the code generated assumes that there are earlier calls to SMF_BEGIN, 
and zero or more calls to SMF_STATE.

@see SMF_BEGIN
@see SMF_STATE
*/
#define SMF_END }case EStEnd:break;default:DMMCSocket::Panic(DMMCSocket::EMMCMachineState);}break;}\
				return(m.Pop());


/**
@publishedPartner
@released

Sets the next state when the current state machine
function is re-entered.

@param nexts The next state to be entered in the current state machine.
*/
#define SMF_NEXTS(nexts) m.SetState(nexts);


/**
@publishedPartner
@released

Pushes a state machine entry onto the stack, specifying the child state machine
function to be invoked.

The child function will be entered at state 0 (EStBegin), when the state machine
is next dispatched.

Control returns from this state machine function after completion of
all functions coded by this macro.

@param func The child state machine function to be invoked.
*/
#define SMF_CALL(func) return(m.Push(func));


/**
@publishedPartner
@released

Pushes a state machine entry onto the stack, specifying the child state machine
function to be invoked.

The state machine is blocked before entry to the child function, but when
it becomes unblocked, the child function will be entered at state 0 (EStBegin)
when the state machine is next dispatched.

Control returns from this state machine function after completion of
all functions coded by this macro.

@param func The child state machine function to be invoked.
*/
#define SMF_CALLWAIT(func) return(m.Push(func,ETrue));


/**
@publishedPartner
@released

Sets the next state for the current state machine function - control will
flow to this state on completion of all functions coded by this macro.

The macro also pushes a state machine entry onto the stack, specifying
the CURRENT state machine function as the child state machine function to be
invoked, and sets the state in which this child state machine function will
be entered, when it gains control.

NOTES:

- the child function is the same as the parent function.
- the state machine is blocked on return from the current state machine function.

@param nexts The state in which the child state machine function will
             gain control.
@param retst The next state for the current state machine function.
*/
#define SMF_CALLMYS(nexts,retst) {m.SetState(retst);m.PushMe();m.SetState(nexts);continue;}


/**
@publishedPartner
@released

Sets the next state for the current state machine function - control flows to
the next instruction on completion of all functions coded by this macro.

The macro also pushes a state machine entry onto the stack, specifying
the CURRENT state machine function as the child state machine function to be
invoked. The child function will be entered at state 0 (EStBegin), when the state machine
is next dispatched.

NOTES:

- the child function is the same as the parent function.
- the state machine is blocked on return from the current state machine function.

@param retst The next state for the current state machine function.
*/
#define SMF_CALLMEWR(retst) {m.SetState(retst);m.PushMe();}


/**
@publishedPartner
@released

Sets the next state for the current state machine function.

The macro also pushes a state machine entry onto the stack, specifying
the child state machine function to be
invoked. The child function will be entered at state 0 (EStBegin), when the state machine
is next dispatched.

Control returns from the current state machine function after completion of
all functions coded by this macro.

@param func  The child state machine function to be invoked.
@param nexts The next state for the current state machine function.
*/
#define SMF_INVOKES(func,nexts) {m.SetState(nexts);return(m.Push(func));}


/**
@publishedPartner
@released

Sets the next state for the current state machine function.

The macro also pushes a state machine entry onto the stack, specifying
the child state machine function to be
invoked. The child function will be entered at state 0 (EStBegin), when the state machine
is next dispatched.

Control returns from the current state machine function after completion of
all functions coded by this macro.

NOTES:

- the state machine is blocked on return from the current state machine function.

@param func  The child state machine function to be invoked.
@param nexts The next state for the current state machine function. 
*/
#define SMF_INVOKEWAITS(func,nexts) {m.SetState(nexts);return(m.Push(func,ETrue));}


/**
@publishedPartner
@released

Returns from the current state machine function, and the state machine then blocks (waits).
*/
#define SMF_WAIT return(0);


/**
@publishedPartner
@released

Sets the next state for the current state machine function; control then returns
from the current state machine function, and the state machine blocks (waits).

@param nexts The next state for the current state machine function. 
*/
#define SMF_WAITS(nexts) return(m.SetState(nexts));


/**
@publishedPartner
@released

Returns the specified error value to the calling (parent) state machine function.

@param value The error value to be returned.
*/
#define SMF_RETURN(value) {m.Pop();return(value);}


/**
@publishedPartner
@released

Returns to the calling state machine function.
*/
#define SMF_EXIT break;


/**
@publishedPartner
@released

Returns to the calling state machine function, and the state machine blocks (waits).
*/
#define SMF_EXITWAIT return(m.Pop(ETrue));


/**
@publishedPartner
@released

Transfers control to the specified state machine function.

NOTES:

- this function is executed at the same stack entry level as the current state machine function.

@param func The state machine function to which control is to be transferred.
*/
#define SMF_JUMP(func) return(m.Jump(func));


/**
@publishedPartner
@released

Transfers control to the specified state machine function, and waits
at its entry point.

@param func The state machine function to which control is to be transferred.
*/
#define SMF_JUMPWAIT(func) return(m.Jump(func,ETrue));


/**
@publishedPartner
@released

Goes to the next state.
*/
#define SMF_GOTONEXTS continue;


/**
@publishedPartner
@released

Sets the next state and then goes to that state.

@param nexts The next state.
*/
#define SMF_GOTOS(nexts) {m.SetState(nexts);continue;}


/**
@publishedPartner
@released

Declares the name of a state.

This is used to generate a case statement based on the state name.

@param sname The state name.
*/
#define SMF_STATE(sname) }case sname:{


/**
@publishedPartner
@released

Declares the name of a state, and sleeps here
if blocked statically.

@param sname The state name.
*/
#define SMF_BPOINT(sname) }case sname: if(StaticBlocks()) return(m.SetState(sname));{




class TMMCStateMachine
/**
	The MultiMediaCard state machine.

	@publishedPartner
	@released
*/
	{
public:
	inline void Setup(TMMCErr (*anEntry)(TAny*), TAny* aContextP);
	IMPORT_C void Reset();
	IMPORT_C TMMCErr Dispatch();
	inline TMMCErr ExitCode();
	inline TMMCErr SetExitCode(TMMCErr aCode);
	inline TUint State();
	inline TMMCErr SetState(TUint aState);
	inline void SuppressSuspension();
	inline void SetTraps(TMMCErr aMask);
	inline void ResetTraps();
	inline void Abort();
	inline TMMCErr Pop(TBool aSuspend=EFalse);
	inline TMMCErr PushMe();
	IMPORT_C TMMCErr Push(TMMCErr (*anEntry)(TAny*), TBool aSuspend=EFalse);
	IMPORT_C TMMCErr Jump(TMMCErr (*anEntry)(TAny*), TBool aSuspend=EFalse);
private:
	class TMMCMachineStackEntry
		{
	public:
		TMMCErr (*iFunction)(TAny*);
		TUint iState;
		TMMCErr iTrapMask;
		};
	TBool iAbort;
	TBool iSuspend;
	TAny* iContextP;
	TMMCErr iExitCode;
	TInt iSP;
	TMMCMachineStackEntry iStack[KMaxMMCMachineStackDepth];
	};

class TMMCCallBack
/**
	This class is used to notify the request completion as a callback function for the clients of DMMCSession.
    The callback function will be called on session completion.
	Callback function is used to indicate Asynchronous Completion.

	@see DMMCSession
	@publishedPartner
	@released
*/
	{
public:
	inline TMMCCallBack();
	inline TMMCCallBack(void (*aFunction)(TAny* aPtr));
	inline TMMCCallBack(void (*aFunction)(TAny* aPtr), TAny* aPtr);
	inline void CallBack() const;
public:
	/**
	A pointer to the callback function.
	*/
	void (*iFunction)(TAny* aPtr);

	/**
	A pointer that is passed to the callback function when
	the callback function is called.
	*/
	TAny* iPtr;
	};

// DMMCStack serves an incoming queue of session requests.
// Each queue element is represented by an instance of the following class

typedef TMMCErr (*TMMCSMSTFunc)(TAny*);

class DMMCSession : public DBase
/**
	Provides the main interface between the client and the MMC Socket, allowing commands and responses
	to be processed asynchronously on the stack.

	Each client creates it own instance of this class.  It is then able to make MultiMediaCard requests 
	on the selected stack by configuring the DMMCSession object with relevant information for the request 
	and then submitting (or engaging) this session object.

	The session is used to pass commands either to the entire stack (a broadcast command), or to individual
	cards in the stack. The class contains functions for initiating  macro functions as laid down by the
	MultiMediaCard Association (MMCA) as well as lower level functions allowing a client to control the
	stack in a more explicit manner.

	All requests on the MultiMediaCard stack which involve bus activity are inherently asynchronous.  When
	creating a DMMCSession object, a client supplies a call-back function as part of the constructor.
	Once a client has engaged a session on the stack, it is informed of the completion of the request by
	the Controller calling this call-back function.

	@publishedPartner
	@released
*/
	{
public:
	IMPORT_C virtual ~DMMCSession();
	IMPORT_C DMMCSession(const TMMCCallBack& aCallBack);

	// Object initialisation
	inline void SetStack(DMMCStack* aStackP);
	IMPORT_C void SetCard(TMMCard* aCardP);

	// Control macros setup
	inline void SetupCIMUpdateAcq();
	inline void SetupCIMInitStack();
	inline void SetupCIMCheckStack();
	inline void SetupCIMSetupCard();
	inline void SetupCIMLockStack();
	inline void SetupCIMInitStackAfterUnlock();
	inline void SetupCIMAutoUnlock();

	// Data transfer macros setup
	IMPORT_C void SetupCIMReadBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP);
	IMPORT_C void SetupCIMWriteBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP);
	IMPORT_C void SetupCIMReadMBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP, TUint32 aBlkLen);
	IMPORT_C void SetupCIMWriteMBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP, TUint32 aBlkLen);
	IMPORT_C void SetupCIMEraseSector(TMMCArgument aDevAddr, TUint32 aLength);
	IMPORT_C void SetupCIMEraseGroup(TMMCArgument aDevAddr, TUint32 aLength);
	IMPORT_C void SetupCIMReadIO(TUint8 aRegAddr, TUint32 aLength, TUint8* aMemoryP);
	IMPORT_C void SetupCIMWriteIO(TUint8 aRegAddr, TUint32 aLength, TUint8* aMemoryP);
	IMPORT_C void SetupCIMLockUnlock(TUint32 aLength, TUint8* aMemoryP);

	// Data transfer macros setup (block mode)
	inline void SetupCIMReadBlock(TMMCArgument aBlockAddr, TUint8* aMemoryP, TUint32 aBlocks = 1);
	inline void SetupCIMWriteBlock(TMMCArgument aBlockAddr, TUint8* aMemoryP, TUint32 aBlocks = 1);
	inline void SetupCIMEraseMSector(TMMCArgument aBlockAddr, TUint32 aBlocks = 1);
	inline void SetupCIMEraseMGroup(TMMCArgument aBlockAddr, TUint32 aBlocks = 1);
	
	// RPMB access macros setup
	inline void SetupRpmbSendRequest(TBool aSetReliableWrite);
    inline void SetupRpmbReceiveResponse();
    inline void SetupRpmbSendReadResultRegisterRequest();
		
	// Raw commands (must be used in the locked bus state only)
	// Known commands with or without (with a default) argument
	IMPORT_C void SetupCommand(TMMCCommandEnum aCommand, TMMCArgument anArgument=0);

	// Generic unknown command with unknown response type
	IMPORT_C void SetupRSCommand(TMMCCommandEnum aCommand, TMMCArgument anArgument,
								TUint32 aResponseLength, TMMCCommandTypeEnum aCommandType=ECmdTypeUK,
								TMMCResponseTypeEnum aResponseType=ERespTypeUnknown,
								TUint32 aCommandClass=KMMCCmdClassNone);

	// Generic data transfer command
	IMPORT_C void SetupDTCommand(TMMCCommandEnum aCommand, TMMCArgument anArgument,
								TUint32 aTotalLength, TUint8* aMemoryAddress, TUint32 aBlockLength=0,
								TBool aStopTransmission=EFalse, TMMCCmdDirEnum aDir=EDirNone,
								TUint32 aCommandClass=KMMCCmdClassNone);
	// Actions
	IMPORT_C TInt Engage();					// Enque session for execution
	inline void UnlockStack();				// Unlock the bus
	inline void Stop();						// Signal session to complete (stop and complete)
	inline void Abort();					// Abort only (no completion)

	// Info retrieval
	IMPORT_C TInt EpocErrorCode() const;	// Derived from MMCExitCode and LastStatus
	inline TMMCSessionTypeEnum SessionID() const;
	inline DMMCStack* StackP() const;		// DMMCStack serving this session
	inline TMMCard* CardP() const;			// The current card pointer
	inline TBool IsEngaged() const;			// Session is being served by DMMCStack
	inline TMMCErr MMCExitCode() const;		// MMC specific error code returned by DMMCStack
	inline TMMCStatus LastStatus() const;	// Last R1 response received from the card
	inline TUint32 BytesTransferred() const;// The actual amount of data transferred in this session
	inline TUint8* ResponseP();				// Current command response (&iCommand[iCmdSP].iResponse)
	inline TUint32 EffectiveModes() const;	// Modes which DMMCStack will consider as effective
	//
	inline void ResetCommandStack();
private:
	void SetupCIMControl(TInt aSessNum);
protected:
	IMPORT_C virtual TMMCSMSTFunc GetMacro(TInt aSessNum) const;
	inline void Block(TUint32 aFlag);
	inline void UnBlock(TUint32 aFlag, TMMCErr anExitCode);
private:
#ifdef __EPOC32__
	static void PollTimerCallBack(TAny* aSessP);
	static void RetryTimerCallBack(TAny* aSessP);
	static void ProgramTimerCallBack(TAny* aSessP);
#endif
	inline void SwapMe();
	void SynchBlock(TUint32 aFlag);
	void SynchUnBlock(TUint32 aFlag);
public:
	static const TMMCCommandSpec& FindCommandSpec(const TMMCIdxCommandSpec aSpecs[], TInt aIdx);
	IMPORT_C void FillCommandDesc();
	IMPORT_C void FillCommandDesc(TMMCCommandEnum aCommand);
	IMPORT_C void FillCommandDesc(TMMCCommandEnum aCommand, TMMCArgument anArgument);
	IMPORT_C void FillCommandArgs(TMMCArgument anArgument, TUint32 aLength, TUint8* aMemoryP, TUint32 aBlkLen);
	inline TMMCCommandDesc& Command();	// The current command descriptor
	
	inline void PushCommandStack();
	inline void PopCommandStack();
	
	inline void SetPartition(TInt aPartition);
	inline TInt Partition() const;

	// Methods for double-buffered data transfer:
	inline TBool RequestMoreData();
	inline void EnableDoubleBuffering(TUint32 aNumBlocks);							  /**< @internalTechnology */
	inline void SetDataTransferCallback(TMMCCallBack& aCallback);					  /**< @internalTechnology */
	inline void MoreDataAvailable(TUint32 aNumBlocks, TUint8* aMemoryP, TInt aError); /**< @internalTechnology */

	inline void SaveCard();			/**< @internalTechnology */
	inline void RestoreCard();		/**< @internalTechnology */

public:
	/**
    The last R1 response.
	*/
	TMMCStatus iLastStatus;

	/**
	A pointer to the card object.
	*/
	TMMCard* iCardP;				// Pointer to Card Info object
	IMPORT_C TRCA CardRCA();		// Checks that card is still ready - otherwise returns 0
	TMMCSessionTypeEnum iSessionID;
private:
	DMMCSession* iLinkP;			//
protected:
	TMMCCallBack iCallBack;			// Where to report the completion
private:
	DMMCStack* iStackP;				// Pointer to Stack Controller
	TCID iCID;						// Card ID to ensure we are still talking to the same card
	TUint32 iBytesTransferred;		// The actual amount of data transferred in this session
	TMMCErr iMMCExitCode;			// State Machine exit code (MMC specific)
public:
    /**
    Session state flags (synchronous).
    */
	TUint32 iState;
private:
	TUint iInitContext;				// Stack Initialiser pass number
	TUint iGlobalRetries;			// Global retry counter

	// Asynchronous flags analysed by scheduler
	TBool volatile iDoAbort;		// Marks the session for abort
	TBool volatile iDoStop;			// Stop the session as soon as it's safe
	TBool volatile iDoComplete;		// Completion callback is now to be invoked
	TBool iBrokenLock;				// Stack lock is broken by force major
	//
	TUint32 iBlockOn;				// blocking reasons
	TInt iCmdSP;					// Current Command stack index
	
	TMMCCommandDesc iCommand[KMaxMMCCommandStackDepth];	// Command stack
	
	TMMCCallBack iDataTransferCallback;	// A callback function, used to request more data when performing double-buffering

	TUint32 iSpare[20];					// Spare data (stolen from iCommand)
	
	TUint32 iPartition;					// The targetted partition
	
	TMMCard* iSavedCardP;			// Saved copy of iCardP

	TMMCStateMachine iMachine;		// State Machine context
#ifdef __EPOC32__
	NTimer iPollTimer;
	NTimer iRetryTimer;
	NTimer iProgramTimer;
#endif
public:
	TMMCStackConfig iConfig;		// Client configuration parameters
	friend class DMMCStack;
	friend class TMMCSessRing;
	friend class TMMCardArray;
	};


class DMMCStack : public DBase
/**
	This object controls access to the MultiMediaCard stack.
	The DMMCSocket owns an instance of this class for the MultiMediaCard stack that it manages.

	@publishedPartner
	@released
*/
	{
public:
	/** extension interfaces Ids */
	enum TInterfaceId
		{
		KInterfaceMachineInfo,
		KInterfaceSwitchToLowVoltageSM,
		KInterfaceSetBusWidth,
		KInterfaceDemandPagingInfo,
		KInterfaceCancelSession,
		KInterfaceDoWakeUpSM,
		KInterfaceAddressCard,
		};

	/** generic interface */
	class MInterface
		{
	public:
		virtual TInt Function() = 0;
		};

	/** 
	Demand paging support 
	@see KInterfaceDemandPagingInfo
	*/
	class TDemandPagingInfo
		{
	public:
		const TInt* iPagingDriveList;
		TInt iDriveCount;
		TUint iPagingType;
		TInt iReadShift;
		TUint iNumPages;
		TBool iWriteProtected;
		TInt iSlotNumber;
		TUint iSpare[2];
		} ;
	/**
	 * An optional interface implemented by the PSL for returning demand-paging information.
	 * @see KInterfaceDemandPagingInfo
	 */
	class MDemandPagingInfo
		{
	public:
		virtual TInt DemandPagingInfo(TDemandPagingInfo& aInfo) = 0;
		};
	
	/**
	 * An optional interface State machine implemented by the PSL for handling asynchronous VccCore powerup
	 * @see KInterfaceDoWakeUpSM
	 */
	class MDoWakeUp
		{
	public:
		virtual TMMCErr DoWakeUpSM()=0;
		};

	/**
	 * An optional interface implemented by the derived class. Used when the stack supports more than one 
	 * card and the cards are individually selectable, i.e. iMultiplexedBus is true
	 * @see KInterfaceAddressCard
	 */
	class MAddressCard
		{
	public:
		virtual void AddressCard(TInt aCardNumber)=0;
		};


public:
	IMPORT_C DMMCStack(TInt aBus, DMMCSocket* aSocket);
	IMPORT_C virtual TInt Init();
	//
	// Actions
	inline void ReportPowerUp();
	inline void ReportPowerDown();
	inline void Reset();					// Discard all requests and clear up
	inline void CompleteAll(TMMCErr aCode);	// Complete all operations with an error
	inline void CancelSession(DMMCSession* aSession);

	IMPORT_C void PowerUpStack();
	IMPORT_C void PowerDownStack();
	void QSleepStack();
	IMPORT_C TInt Stop(TMMCard* aCardP);
	//
	// Inquiries
	inline TUint MaxCardsInStack() const;
	inline TMMCard* CardP(TUint aCardNumber);
	inline DMMCSocket* MMCSocket() const;
	inline TMMCPasswordStore* PasswordStore() const;
	inline TBool InitStackInProgress() const;
	inline TBool HasSessionsQueued() const;
	inline TBool HasCardsPresent();
	inline void BufferInfo(TUint8*& aBuf, TInt& aBufLen, TInt& aMinorBufLen);
	inline TInt DemandPagingInfo(TDemandPagingInfo& aInfo);
	inline TBool StackRunning() const;


#ifdef __EPOC32__

    /**
    Defines the period for the poll timer.
    
    The poll timer is used by the generic layer for platforms 
    that do not provide an interrupt to indicate
    when programming mode is finished.
    
    @return The poll timer period, in milliseconds.
    */
	virtual TInt ProgramPeriodInMilliSeconds()	const =0;
#endif

	/**
	 * Calculates the minimum range that must be read off a card, an optimisation that takes advantage
	 * of the partial read feature found on some cards.  It takes the logical range that the media driver
	 * wants to read from the card, and increases it to take into account factors such as FIFO width and
	 * minimum DMA transfer size.
	 * @param aCard A pointer to the MMC Card
	 * @param aStart The required start position
	 * @param aEnd The required end position
	 * @param aPhysStart The adjusted start position
	 * @param aPhysEnd The adjusted end position
	 */
	virtual void AdjustPartialRead(const TMMCard* aCard, TUint32 aStart, TUint32 aEnd, TUint32* aPhysStart, TUint32* aPhysEnd) const =0;

	/**
	 * Returns the details of the buffer allocated by the socket for data transfer operations.  The buffer
	 * is allocated and configured at the variant layer to allow , for example, contiguous pages to be
	 * allocated for DMA transfers.
	 * @param aMDBuf A pointer to the allocated buffer
	 * @param aMDBufLen The length of the allocated buffer
	 */
	virtual void GetBufferInfo(TUint8** aMDBuf, TInt* aMDBufLen) =0;

	/**
	 * Gets the platform specific configuration information.
	 * @see TMMCMachineInfo
	 */
	virtual void MachineInfo(TMMCMachineInfo& aMachineInfo) =0;

	/**
	 * Creates the session object
	 */
	IMPORT_C virtual DMMCSession* AllocSession(const TMMCCallBack& aCallBack) const;

protected:
	// Platform layer service
	inline TMMCBusConfig& BusConfig();
	inline TMMCBusConfig& MasterBusConfig();
	inline DMMCSession& Session();				// Current session
	inline TMMCCommandDesc& Command();			// Current command descriptor of current session
	inline TMMCStateMachine& Machine();			// State machine of current session
	inline void BlockCurrentSession(TUint32 aFlag);
	inline void UnBlockCurrentSession(TUint32 aFlag, TMMCErr anExitCode);
	inline void ReportInconsistentBusState();
	inline void ReportASSPEngaged();
	inline void ReportASSPDisengaged();
	inline TRCA CurrentSessCardRCA();			// Checks that card is still ready - otherwise returns 0
	inline void CurrentSessPushCmdStack();
	inline void CurrentSessPopCmdStack();
	inline void CurrentSessFillCmdDesc(TMMCCommandEnum aCommand);
	inline void CurrentSessFillCmdDesc(TMMCCommandEnum aCommand,TMMCArgument anArgument);
	inline void CurrentSessFillCmdArgs(TMMCArgument anArgument,TUint32 aLength,TUint8* aMemoryP,TUint32 aBlkLen);
	inline TRCA SelectedCard() const;
	inline void YieldStack(TMMCCommandTypeEnum aCommand);

	void DoSetClock(TUint32 aClock);
	void DoSetBusWidth(TUint32 aBusWidth);
	TBusWidth BusWidthEncoding(TInt aBusWidth) const;
	TUint MaxTranSpeedInKilohertz(const TMMCard& aCard) const;

	// Stack service provided by platform/variant layer.

	/** 
	 * Returns the default master settings for the platform.
	 * @param aConfig A TMMCBusConfig reference to be filled in with the default settings.
	 * @param aClock The requested clock frequency (may be ignored if the hardware cannot support it).
	 */
	virtual void SetBusConfigDefaults(TMMCBusConfig& aConfig, TUint aClock)=0;

	/** 
	 * Switches from identification mode of operation to data transfer mode operation. 
	 *
	 * Note that at this point the clock information in iBusConfig will not have been updated 
	 * to the new data transfer rate. This function should generally just switch from open drain 
	 * to push-pull bus mode - with the clock rate being changed at the start of IssueMMCCommandSM, 
	 * where iBusConfig will be valid.
	 */
	virtual void InitClockOff()=0;

	/** 
	 * Stop all activities on the host stack. 
	 *
	 * This will generally perform the same operations as for ASSPDisengage() but this will additionally 
	 * turn off the clock to the hardware interface and release any requested power requirements made on 
	 * the power model. (That is release any power requirements made as part of the InitClockOnSM() function).
	 *
	 * Called from the platform independent layer when it is required to immediately cancel any PSL asynchronous 
	 * activity because the current session has been aborted.
	 *
	 * This function should normally include a call to ReportAsspDisengaged() at the end, to report to the PIL 
	 * that the PSL level resources have been disengaged. 
	 */
	virtual void ASSPReset()=0;

	/**
	 * Called each time a session which has engaged PSL resources has completed or has been aborted. 
	 *
	 * This should disable any activities which were required to perform the session just completed/aborted.
	 * It shouldn't however turn off the clock to the hardware interface (which will be turned off instead 
	 * by the inactivity timer). This typically disables DMA and interface interrupts and forces the hardware 
	 * interface into idle.
	 *
	 * This function should normally include a call to ReportAsspDisengaged() at the end, to report to the PIL 
	 * that the PSL level resources have been disengaged. 
	 */
	virtual void ASSPDisengage()=0;

	/**
	 * Called as part of the bus power down sequence. It stops all activities on the host stack, turns off the clock 
	 * to the hardware interface and releases any requested power requirements made on the power model 
	 * (i.e. very often a straight call of ASSPReset()). 
	 *
	 * This shouldn't turn off the MMC PSU as this will be performed immediately afterwards by the PSU class.
	 */
	virtual void DoPowerDown()=0;

	IMPORT_C virtual TBool CardDetect(TUint aCardNumber);
	IMPORT_C virtual TBool WriteProtected(TUint aCardNumber);
	//
	// State Machine functions implemented in platform layer.

	/**
	 * Called as a child function at the start of the CIM_UPDATE_ACQ macro state machine. 
	 *
	 * It should perform the necessary PSL level actions associated with powering up the bus. This includes 
	 * turning on the MMC PSU. However, the hardware interface clock should not be turned on as part of this function.
	 *
	 * If the Controller has to request power resources from the power model (e.g a fast system clock required all the 
	 * time the bus is powered) then this state machine function can be used to asynchronously wait for this resource 
	 * to become available.
	 *
	 * Upon completion, DMMCStack::ReportPowerUp() should be called.
	 *
	 * @return KMMCErrNone if completed successfully or standard TMMCErr code otherwise
	 */
	virtual TMMCErr DoPowerUpSM()=0;
	
	/**
	 * Turns on the clock to the hardware interface. 
	 *
	 * This state machine function is called as a child function as part of the CIM_UPDATE_ACQ macro state machine. 
	 *
	 * It is implemented as a state machine function since it may be necessary to include a short delay after the 
	 * clock has been turned on to allow it to stabilise, or in some cases it may be necessary to wait for a power 
	 * resource to become available.
	 *
	 * This function should normally include a call to ReportAsspEngaged() at the start, to report to the PIL that the PSL 
	 * level resources have been engaged.
	 *
	 * @return KMMCErrNone if completed successfully or standard TMMCErr code otherwise
	 */
	virtual TMMCErr InitClockOnSM()=0;
	
	/**
	 * Executes a single command over the bus.
	 *
	 * The input parameters are passed via the current command descriptor on the session's command stack 
	 * (TMMCCommandDesc class), which specifies the type of command, response type, arguments etc..
	 *
	 * @return KMMCErrNone if completed successfully or standard TMMCErr code otherwise
	 */
	IMPORT_C virtual TMMCErr IssueMMCCommandSM()=0;

	TBool StaticBlocks();

	/**
	 * Indicates that the PSL should change the bus width.
	 * Must be implemented by the Platform Specific Layer if MMCV4 4/8-bit bus mode is required
	 */
	IMPORT_C virtual void SetBusWidth(TUint32 aBusWidth);

	/**
	 * Retrieves a TMMCMachineInfoV4 from the PSL
	 * Must be implemented by the Platform Specific Layer if MMCV4 support is required
	 */
public:
	IMPORT_C virtual void MachineInfo(TDes8& aMachineInfo);

protected:
	/**
	 * Switches the MMC bus to low voltage mode
	 */
	TMMCErr SwitchToLowVoltageSM();

	
private:
	//
	// Session service
	void Add(DMMCSession* aSessP);
	void Abort(DMMCSession* aSessP);
	void Stop(DMMCSession* aSessP);
	void UnlockStack(DMMCSession* aSessP);
	void MarkComplete(DMMCSession* aSessP, TMMCErr anExitCode);
	//
	//	Stack control and operations support
	// Scheduler and its supplementary functions
	enum TMMCStackSchedStateEnum
		{
		ESchedContinue=0,
		ESchedLoop=1,
		ESchedExit,
		ESchedChooseJob
		};
	void Scheduler(volatile TBool& aFlag);
	void DoSchedule();
	TMMCStackSchedStateEnum SchedGetOnDFC();
	void SchedSetContext(DMMCSession* aSessP);
	void SchedDoAbort(DMMCSession* aSessP);
	TMMCStackSchedStateEnum SchedResolveStatBlocks(DMMCSession* aSessP);
	TMMCStackSchedStateEnum SchedGroundDown(DMMCSession* aSessP, TMMCErr aReason);
	TMMCStackSchedStateEnum SchedEnqueStackSession(TMMCSessionTypeEnum aSessID);
	void SchedGrabEntries();
	void SchedDisengage();
	TBool SchedAllowDirectCommands(DMMCSession* aSessP);
	TBool SchedYielding(DMMCSession* aSessP);
	inline TMMCStackSchedStateEnum SchedAbortPass();
	inline TMMCStackSchedStateEnum SchedCompletionPass();
	inline TMMCStackSchedStateEnum SchedInitStack();
	inline TMMCStackSchedStateEnum SchedSleepStack();
	inline TBool SchedPreemptable();
	inline TMMCStackSchedStateEnum SchedSession();
	inline TMMCStackSchedStateEnum SchedChooseJob();
	//
	// Miscellaneous SM function service
protected:	
	void MergeConfig(DMMCSession* aSessP);
private:
	inline void DeselectsToIssue(TUint aNumber);

	// Static Completion routines.
	static void StackDFC(TAny* aStackP);
	static void StackSessionCBST(TAny* aStackP);
	TInt StackSessionCB();
	static void AutoUnlockCBST(TAny *aStackP);
	TInt AutoUnlockCB();
	
protected:
	IMPORT_C void Block(DMMCSession* aSessP, TUint32 aFlag);
	IMPORT_C void UnBlock(DMMCSession* aSessP, TUint32 aFlag, TMMCErr anExitCode);

protected:
	// State machines.  The adapter functions just call the non-static versions.
	// Top-level state machines.
	static   TMMCErr NakedSessionSMST(TAny* aStackP);				// ECIMNakedSession
	inline   TMMCErr NakedSessionSM();
	static   TMMCErr CIMUpdateAcqSMST(TAny* aStackP);				// ECIMUpdateAcq
	         TMMCErr CIMUpdateAcqSM();
	static   TMMCErr CIMInitStackSMST(TAny* aStackP);				// ECIMInitStack
	inline   TMMCErr CIMInitStackSM();
	static   TMMCErr CIMCheckStackSMST(TAny* aStackP);			// ECIMCheckStack
	inline   TMMCErr CIMCheckStackSM();
	static   TMMCErr CIMSetupCardSMST(TAny* aStackP);				// ECIMSetupCard
	inline   TMMCErr CIMSetupCardSM();
	IMPORT_C static  TMMCErr CIMReadWriteBlocksSMST(TAny* aStackP);		// ECIMReadBlock, ECIMWriteBlock, ECIMReadMBlock, ECIMWriteMBlock
	IMPORT_C virtual TMMCErr CIMReadWriteBlocksSM();
	static   TMMCErr CIMEraseSMST(TAny* aStackP);					// ECIMEraseSector, ECIMEraseGroup
	inline   TMMCErr CIMEraseSM();
	static   TMMCErr CIMReadWriteIOSMST(TAny* aStackP);			// ECIMReadIO, ECIMWriteIO
	inline   TMMCErr CIMReadWriteIOSM();
	static   TMMCErr CIMLockUnlockSMST(TAny *aStackP);			// ECIMLockUnlock
	inline   TMMCErr CIMLockUnlockSM();
	static   TMMCErr NoSessionSMST(TAny* aStackP);				// ECIMLockStack
	inline   TMMCErr NoSessionSM();
	static   TMMCErr AcquireStackSMST(TAny* aStackP);
	IMPORT_C virtual TMMCErr AcquireStackSM();
	static   TMMCErr CheckStackSMST(TAny* aStackP);			// ECIMCheckStack
	inline   TMMCErr CheckStackSM();
	static   TMMCErr CheckLockStatusSMST(TAny* aStackP);
	inline   TMMCErr CheckLockStatusSM();
    static	 TMMCErr ModifyCardCapabilitySMST(TAny* aStackP);
    IMPORT_C virtual TMMCErr ModifyCardCapabilitySM();
    static	 TMMCErr BaseModifyCardCapabilitySMST(TAny* aStackP);
	static   TMMCErr DoPowerUpSMST(TAny* aStackP);
	static   TMMCErr InitClockOnSMST(TAny* aStackP);
	IMPORT_C static  TMMCErr IssueMMCCommandSMST(TAny* aStackP);

	static   TMMCErr CIMAutoUnlockSMST(TAny* aStackP);
	inline   TMMCErr CIMAutoUnlockSM();

	static   TMMCErr InitStackAfterUnlockSMST(TAny* aStackP);				// ECIMInitStackAfterUnlock
	IMPORT_C virtual TMMCErr InitStackAfterUnlockSM();
	
	static	 TMMCErr InitCurrentCardAfterUnlockSMST(TAny* aStackP);

	static   TMMCErr AttachCardSMST(TAny* aStackP);
	inline   TMMCErr AttachCardSM();
	static   TMMCErr ExecCommandSMST(TAny* aStackP);
	inline   TMMCErr ExecCommandSM();
	static   TMMCErr IssueCommandCheckResponseSMST(TAny* aStackP);
	inline   TMMCErr IssueCommandCheckResponseSM();
	static   TMMCErr PollGapTimerSMST(TAny* aStackP);
	inline   TMMCErr PollGapTimerSM();
	static   TMMCErr RetryGapTimerSMST(TAny* aStackP);
	inline   TMMCErr RetryGapTimerSM();
	static   TMMCErr ProgramTimerSMST(TAny *aStackP);
	inline   TMMCErr ProgramTimerSM();
	static   TMMCErr GoIdleSMST(TAny* aStackP);
	inline	 TMMCErr GoIdleSM();
	static   TMMCErr SwitchPartitionSMST(TAny* aStackP);
	inline	 TMMCErr SwitchPartitionSM();

	static   TMMCErr SwitchToLowVoltageSMST(TAny* aStackP);
	
	static   TMMCErr DoWakeUpSMST(TAny* aStackP);
	

private:
	static   TMMCErr ConfigureHighSpeedSMST(TAny* aStackP);
	inline	 TMMCErr ConfigureHighSpeedSM();

	static   TMMCErr DetermineBusWidthAndClockSMST(TAny* aStackP);
	inline	 TMMCErr DetermineBusWidthAndClockSM();

	static   TMMCErr ExecSwitchCommandST(TAny* aStackP);
	inline	 TMMCErr ExecSwitchCommand();
	
	static   TMMCErr ExecSleepCommandSMST(TAny* aStackP);
	inline	 TMMCErr ExecSleepCommandSM();
	
	static   TMMCErr ExecAwakeCommandSMST(TAny* aStackP);
	inline	 TMMCErr ExecAwakeCommandSM();

	static   TMMCErr LowVoltagePowerupTimerSMST(TAny *aStackP);
	TMMCErr LowVoltagePowerupTimerSM();

	static   TMMCErr ExecBusTestSMST(TAny* aStackP);
	inline	 TMMCErr ExecBusTestSM();

	static TMMCErr CIMRpmbAccessSMST(TAny* aStackP);
    TMMCErr CIMRpmbAccessSM();

	static TMMCErr  CIMRpmbWriteAuthenticationKeySMST(TAny* aStackP);
    TMMCErr CIMRpmbWriteAuthenticationKeySM();

	static TMMCErr CIMRpmbReadWrCounterSMST(TAny* aStackP);
    TMMCErr CIMRpmbReadWrCounterSM();

	static TMMCErr CIMRpmbWriteSMST(TAny* aStackP);
    TMMCErr CIMRpmbWriteSM();

	static TMMCErr CIMRpmbReadSMST(TAny* aStackP);
    TMMCErr CIMRpmbReadSM();

	enum TBusWidthAndClock
		{
		E1Bit20Mhz  = 0x0000,

		E4Bits26Mhz = 0x0001,
		E4Bits52Mhz = 0x0002,

		E8Bits26Mhz = 0x0004,
		E8Bits52Mhz = 0x0008,
		};
	enum TBusWidthAndClockMasks
		{
		E4BitMask = E4Bits26Mhz | E4Bits52Mhz,
		E8BitMask = E8Bits26Mhz | E8Bits52Mhz,
		E26MhzMask = E4Bits26Mhz | E8Bits26Mhz,
		E52MhzMask = E4Bits52Mhz | E8Bits52Mhz
		};

	void DetermineBusWidthAndClock(const TMMCard& aCard, TBool aLowVoltage, TUint& aPowerClass, TBusWidthAndClock& aBusWidthAndClock);
	TUint GetPowerClass(const TMMCard& aCard, TBusWidthAndClock aWidthAndClock, TBool aLowVoltage);
	
	void DoAddressCard(TInt aCardNumber);


    //	----------- Data Members -------------
private:
	//
	// Synchronous status, data structures and control info.
	TUint32 iStackState;
	TUint iInitContext;				// Stack Initialiser pass number
	DMMCSession* iLockingSessionP;
	TMMCSessRing iWorkSet;
	TMMCSessRing iReadyQueue;
	TMMCSessRing iEntryQueue;
	TDfc iStackDFC;
	TRCA iSelectedCard;
	DMMCSocket* iSocket;
	DMMCSession* iStackSession;
	DMMCSession iAutoUnlockSession;
	TInt iAutoUnlockIndex;			// index into iCards
protected:
	TUint8* iPSLBuf;
private:
	TInt iPSLBufLen;
	TInt iMinorBufLen;
	TUint8 iSpare[2];
	TBool volatile iSleep;
	DThread* iNotifierThread;
	TRequestStatus* iNotifierReqStat;
	enum TInitState {EISPending, EISDone};
	TInitState iInitState;
	//
	//	Stack and Scheduler control
	// Asynchronous sheduler attention flags
	TBool volatile iAttention;	// There are ready sessions
	TBool volatile iAbortReq;	// There are sessions marked for abort
	TBool volatile iCompReq;	// There are sessions to complete
	TBool volatile iInitialise;	// Enforce InitStack (after enforced PowerDown)
	TBool volatile iUpdate;		// Enque InitStack into iWorkSet
	// Other asynchronous flags
	TBool volatile iPoweredUp;
	TBool volatile iDFCRunning;
	TBool volatile iAbortAll;
	TMMCErr volatile iCompleteAllExitCode;
	//
	// Session context
protected:
	DMMCSession* iSessionP;
private:
	//
	// Bus control
	TDSR iCurrentDSR;
	//
	// Stack data structures and Session/StateMachine miscellaneous
	TUint iDeselectsToIssue;
	TInt iCxDeselectCount;
	TUint8 iCMD42CmdByte;
	TMediaPassword iMPTgt;
public:
	IMPORT_C TUint32 EffectiveModes(const TMMCStackConfig& aClientConfig);
	TUint32 iCurrentOpRange;
	TInt iCxCardCount;
	TInt iCxPollRetryCount;
	TMMCStackConfig iConfig;
	TUint iMaxCardsInStack;
	TMMCRCAPool iRCAPool;
	TMMCardArray* iCardArray;
	TMMCStackConfig iMasterConfig;
	friend class DMMCSocket;
	friend class DMMCSession;
	friend class TMMCardArray;

protected:
	/** 
	Gets an interface from a derived class
	N.B the derived class should call the base class's default implementation of this function
	if it does not support the specified interface
	replaces reserved virtual Dummy4()
	*/
	IMPORT_C virtual void GetInterface(TInterfaceId aInterfaceId, MInterface*& aInterfacePtr);

private:
	TBusWidthAndClock iBusWidthAndClock;
	TInt iSelectedCardIndex;
    //
    // Reserved members to maintain binary compatibility
protected:
	TBool   iMultiplexedBus;			// ETrue if cards are individually selectable.  EFalse if stacked on a common bus.
private:
	TMMCCommandTypeEnum iYieldCommandType;
	TInt    iReserved;

protected:	
	// Pointer to protected utility class which allows class to grow while maintining BC
	// replaces fourth element of iReserved[]
	class DBody;
	friend class DBody;
	DBody* iBody;
	};



class TMMCMachineInfo

/**
	Platform-specific configuration information for the 
	MultiMediaCard stack.
	
	An object of this type is passed to the Variant implementation
	of DMMCStack::MachineInfo(), which should fill the public data
	members with appropriate information and values.

	@publishedPartner
	@released
*/
	{

public:
	enum THardwareConfig
		{
		/**
		Set this bit in iFlags if hardware supports SPI mode (not currently supported - set this bit to zero)
		*/
		ESupportsSPIMode		 = 0x01,

		/**
		Set this bit in iFlags if the PSL is enabled for double-buffered data transfers
		*/
		ESupportsDoubleBuffering = 0x02,

		/**
		Set this bit in iFlags if the PSL supports response type R7
		*/
		ESupportsR7				 = 0x04,

		/**
		Set this bit in iFlags if the hardware DMA controller utilises 8-Bit Addressing
		*/
		EDma8BitAddressing		 = 0x08,

		/**
		Set this bit in iFlags if the hardware DMA controller utilises 16-Bit Addressing
		*/
		EDma16BitAddressing		 = 0x10,

		/**
		Set this bit in iFlags if the hardware DMA controller utilises 32-Bit Addressing
		*/
		EDma32BitAddressing		 = 0x20,

		/**
		Set this bit in iFlags if the hardware DMA controller utilises 64-Bit Addressing
		*/
		EDma64BitAddressing		 = 0x40,
		
		/**
		Set this in iFlags if the hardware supports DMA and can cope with being given a physical address.
		This also sets the ESupportsDoubleBuffering flag, physical addressing is dependent on
		doublebuffering functionality.
		@see ESupportsDoubleBuffering
		@see KMMCCmdFlagPhysAddr flag 
		*/
		ESupportsDMA			 = 0x082,

		/**
		Set this in iFlags if the hardware is unable to perform data transfers of more than 256K
			- Transfers greater than 256K will be split into multiple transactions.
		*/
		EMaxTransferLength_256K	 = 0x100,

		/**
		Set this in iFlags if the hardware is unable to perform data transfers of more than 512K
			- Transfers greater than 512K will be split into multiple transactions.
		*/
		EMaxTransferLength_512K	 = 0x200,

		/**
		Set this in iFlags if the hardware is unable to perform data transfers of more than 1M
			- Transfers greater than 1M will be split into multiple transactions.
		*/
		EMaxTransferLength_1M	 = 0x300,

		/**
		Set this in iFlags if the hardware is unable to perform data transfers of more than 2M
			- Transfers greater than 2M will be split into multiple transactions.
		*/
		EMaxTransferLength_2M	 = 0x400,

		/**
		Set this in iFlags if the hardware is unable to perform data transfers of more than 4M
			- Transfers greater than 4M will be split into multiple transactions.
		*/
		EMaxTransferLength_4M	 = 0x500,

		/**
		Set this in iFlags if the hardware is unable to perform data transfers of more than 8M
			- Transfers greater than 8M will be split into multiple transactions.
		*/
		EMaxTransferLength_8M	 = 0x600,

		/**
		Set this in iFlags if the hardware is unable to perform data transfers of more than 16M
			- Transfers greater than 16M will be split into multiple transactions.
		*/
		EMaxTransferLength_16M	 = 0x700,

		/**
		The card in slot 1 is internal, i.e. not removable
		*/
		ESlot1Internal			 = 0x0800,

		/**
		The card in slot 2 is internal, i.e. not removable
		*/
		ESlot2Internal			 = 0x1000,
		};

public:
    /**
    The total number of MultiMediaCard slots for this stack.
    
    Be aware that this refers to the stack, and NOT to the platform;
    a platform can have multiple stacks.
    */
	TInt iTotalSockets;
	
	/**
	Not currently used.
	
	Set this value to zero.
	*/
	TInt iTotalMediaChanges;
	
	/**
	Not currently used.
	
	Set this value to zero.
	*/
	TInt iTotalPrimarySupplies;
	
	union
		{
		/**
		Indicates whether the SPI protocol is being used or not.
		
		SPI not currently supported; set this to EFalse.
		*/
		TBool iSPIMode;						// SPI mode not yet supported
		/**
		Hardware configuration flags
		*/
		TUint32 iFlags;
		};

    /**
    The number of the first peripheral bus slot claimed by the
    MultiMediaCard controller.
    
    Symbian OS supports 4, so set this to a value in the range 0-3.
    */
    TInt iBaseBusNumber;
	};



/**
	Platform-specific configuration information for the 
	MultiMediaCard stack. Contains information pertinent to 
	MMC specification version 4.0/4.1
	
	An object of this type is passed to the Variant implementation
	of DMMCStack::MachineInfo(), which should fill the public data
	members with appropriate information and values.

@internalComponent
*/
class TMMCMachineInfoV4 : public TMMCMachineInfo
	{
public:
	inline TMMCMachineInfoV4() {memclr(this, sizeof(*this));}

	/**
	The version of the structure returned by the PSL in a call to DMMStack::MachineInfo()
	The fields defined in TMMCMachineInfoV4 are only valid if the version is EVersion4 or higher
	*/
	enum TVersion {EVersion3, EVersion4};
	TVersion iVersion;

    /**
    The maximum bus width supported.
    */
	TBusWidth iMaxBusWidth;

	/** 
	Maximum clock frequency supported,
	N.B. if the controller's maximum clock rate is only slightly less than one of the 
	"high-speed" clock frequencies defined in MMC spec 4.0 (i.e 26 Mhz and 52 Mhz), then 
	it can still report that it is supported and then run at the slightly lower clock rate.
	*/
	enum THighSpeedClocks {EClockSpeed26Mhz = 26, EClockSpeed52Mhz = 52};
	TUint iMaxClockSpeedInMhz;

    /**
    The power class supported for 3.6V (high voltage).
	This is a 4-bit value encoded in the same way as the POWER_CLASS field in the EXT_CSD 
	register. i.e. 0=100mA, 1=120mA, ... 10=450mA.
	See MMC sepcification version 4.1, EXT_CSD register.
    */
	enum THiVoltagePowerClasses {EHi100mA, EHi120mA, EHi150mA, EHi180mA, EHi200mA, EHi220mA, EHi250mA, EHi300mA, EHi350mA, EHi400mA, EHi450mA };
	TUint iHighVoltagePowerClass;

    /**
    The power class supported for 1.95V (low voltage).
	This is a 4-bit value encoded in the same way as the POWER_CLASS field in the EXT_CSD 
	register. i.e. 0=65mA, 1=70mA, ... 10=250mA.
	See MMC sepcification version 4.1, EXT_CSD register.
    */
	enum TLoVoltagePowerClasses {ELo065mA, ELo070mA, ELo080mA, ELo090mA, ELo100mA, ELo120mA, ELo140mA, ELo160mA, ELo180mA, ELo200mA, ELo250mA };
	TUint iLowVoltagePowerClass;
	};



/**
	Platform-specific configuration information for the 
	MultiMediaCard stack. Contains information pertinent to 
	MMC specification version 4.4
	
	An object of this type is passed to the Variant implementation
	of DMMCStack::MachineInfo(), which should fill the public data
	members with appropriate information and values.

@internalComponent
*/
class TMMCMachineInfoV44 : public TMMCMachineInfoV4
	{
public:
	inline TMMCMachineInfoV44() {memclr(this, sizeof(*this));}

	/**
	The version of the structure returned by the PSL in a call to 
	DMMStack::MachineInfo()
	The fields defined in TMMCMachineInfoV44 are only valid if the 
	version is EVersion44 or higher
	*/
	enum TVersion {EVersion3, EVersion4, EVersion44};

    /**
    Use iRpmbSlotCount and iRpmbSlotList to define a list of up to
	four slots for devices containing an RPMB partitions to be 
	exposed
    */
	TUint iRpmbSlotCount;
	TUint * iRpmbSlotList;
	
	TUint8 iSpare[14];
	};


class DMMCPsu : public DPBusPsuBase 
/**
	DPBusPsuBase derived abstract class to control the MMC socket's power supply.

	This class is intended for derivation at the variant layer, which handles the
	variant specific functionality of the power supply.

	@publishedPartner
	@released
*/
    {
public:
	IMPORT_C DMMCPsu(TInt aPsuNum, TInt aMediaChangedNum);

	// Re-declaring virtual and pure-virtual interface defined in DPBusPsuBase for clarity...
    
	IMPORT_C virtual TInt DoCreate();

	/**
	 * Controls the power supply.
	 * Implemented by the variant, directly controls the power to the MMC stack.
	 * @param aState A TPBusPsuState enumeration specifying the required state
	 *				 (EPsuOnFull, EPsuOff, EPsuOnCurLimit)
	 */
	virtual void DoSetState(TPBusPsuState aState)=0;

	/**
	 * Checks the PSU's voltage.
	 * Implemented by the variant, uses a mechanism such as a comparator to check
	 * the PSU's voltage level.  Upon reciept of the voltage level (the process may
	 * be asynchronous), the variant calls ReceiveVoltageCheckResult() with KErrNone
	 * if the voltage is OK, KErrGeneral if there is a problem, or KErrNotReady if the
	 * hardware has not yet powered up.
	 */
	virtual void DoCheckVoltage()=0;

	/**
	 * Fills in the supplied TPBusPsuInfo object with the characteristics of the platform.
	 * Provided at the variant layer.
	 * @param anInfo A reference to a TPBusPsuInfo to be filled in with the PSU characteristics.
	 */
    virtual void PsuInfo(TPBusPsuInfo &anInfo)=0;

	inline void SetVoltage(TUint32 aVoltage);
	
	static void SleepCheck(TAny* aPtr);

protected:		  
    /**
	 * The current voltage setting, in OCR register format
	 */
	TUint32 iVoltageSetting; 
    };

class DMMCMediaChange : public DMediaChangeBase
/**
	DMediaChangeBase derived abstract class to handle the isertion and removal of removable media.

	This class is intended for derivation at the variant layer, which handles the variant specific
	functionality such as interrupt detection, and calls functions of the DMediaChangeBase class 
	to pass notifications of media change to the socket layers.

	@publishedPartner
	@released
*/
	{
public:
	IMPORT_C DMMCMediaChange(TInt aMediaChangeNum);	
	
	// Re-declaring virtual and pure-virtual interface defined in DMediaChangeBase for clarity...
	
	IMPORT_C virtual TInt Create();

	/**
	 * Forces a media change, executing the same actions as if a door open has occurred.
	 * @see DoDoorOpen
	 */
	virtual void ForceMediaChange()=0;

	/**
	 * Called by DMediaChangeBase when the door is opened.
	 * Implemented at the variant layer, DoDoorOpen is invoked in response to the variant
	 * calling ::DoDoorOpenService upon detection of a door open event. 
	 * DoDoorOpen may queue a debounce timer which masks further events until it expires.
	 * @see DoDoorClosed
	 */
	virtual void DoDoorOpen()=0;
	
	/**
	 * Called by DMediaChangeBase when the door is closed.
	 * Implemented at the variant layer, DoDoorClosed is invoked in response to the variant
	 * calling ::DoorOpenService upon detection of a door closed event.
	 * Systems without a door should perform this sequence when the debounce timer has 
	 * expired after a door open event has been detected.
	 * @see DoDoorOpen
	 */
	virtual void DoDoorClosed()=0;
	
	/**
	 * Returns the current state of the door.
	 * Implemented at the variant layer to provide information as to the state of the door.
	 * @return TMediaState enumeration descibing the state of door (EDoorOpen, EDoorClosed).
	 */	
	virtual TMediaState MediaState() = 0;
	};


/*===========================================================================*/
/* CLASS : DMMCEmbeddedMediaChange                                               */
/*===========================================================================*/
NONSHARABLE_CLASS(DMMCEmbeddedMediaChange) : public DMMCMediaChange
/**
 * This class looks after the processing to be carried out when the media door
 * is opened or closed.  It may be queried without the interrupt being enabled.
 *
 */
    {
public:
	DMMCEmbeddedMediaChange(TInt aMediaChangeNum) : DMMCMediaChange(aMediaChangeNum){};
	
    /// Directly calls the media change event
    virtual void        ForceMediaChange() {return;};

    /// Handle media door open (called on media door open interrupt).
    virtual void        DoDoorOpen() {return;};

    /// Handle media door closing (called on media door open interrupt).
    virtual void        DoDoorClosed() {return;};

    /// Return status of media changed signal.
    virtual TMediaState MediaState() {return EDoorClosed;};
    };



class TMapping
/**
	MMC Mapping
*/
	{
public:
	TBuf8<KMMCCIDLength> iCID;
	TMediaPassword iPWD;
	enum TState {EStPending, EStValid, EStInvalid};
	TState iState;
	};

NONSHARABLE_CLASS(TMMCPasswordStore) : public TPasswordStore
/**
	MMC Password Store
*/
	{
public:
	TMMCPasswordStore();

	// Pure virtual...
	TInt Init();
	TInt ReadPasswordData(TDes8 &aBuf);
	TInt WritePasswordData(TDesC8 &aBuf);
	TInt PasswordStoreLengthInBytes();

public:
	TMapping *FindMappingInStore(const TCID &aCID);
	TInt InsertMapping(const TCID &aCID, const TMediaPassword &aPWD, TMapping::TState aState);
	IMPORT_C TBool IsMappingIncorrect(const TCID& aCID, const TMediaPassword& aPWD);

	static TInt CompareCID(const TMapping& aLeft, const TMapping& aRight);
	TIdentityRelation<TMapping> iIdentityRelation;

private:
	RArray<TMapping> *iStore;

	friend class DMMCSocket;
	};

class DMMCSocket : public DPBusSocket
/**
	This DPBusSocket derived object oversees the power supplies
	and media change functionality of DMMCStack Objects.  A socket 
	directly corresponds to a single stack, which may support multiple cards.

	@publishedPartner
	@released
*/
	{
public:
	IMPORT_C DMMCSocket(TInt aSocketNumber, TMMCPasswordStore* aPasswordStore);
	
	// Functions inherited from DPBusSocket
	virtual TInt Init();
	virtual void InitiatePowerUpSequence();
	virtual TBool CardIsPresent();
	virtual void Reset1();
	virtual void Reset2();
	
	TInt TotalSupportedCards();

	// MMC specific functions
	inline DMMCStack* Stack(TInt aBus);
    inline void ResetInactivity(TInt aBus);
	inline const TMMCMachineInfo& MachineInfo() const;
	
	virtual void AdjustPartialRead(const TMMCard* aCard, TUint32 aStart, TUint32 aEnd, TUint32* aPhysStart, TUint32* aPhysEnd) const;
	virtual void GetBufferInfo(TUint8** aMDBuf, TInt* aMDBufLen);
	virtual TInt PrepareStore(TInt aBus, TInt aFunc, TLocalDrivePasswordData &aData);

	inline TBool SupportsDoubleBuffering();
	inline TUint32 MaxDataTransferLength();
	inline TUint32 DmaAlignment();

protected:
	// MMC specific functions
	virtual void GetMachineInfo();

private:
	// Password Store Control Functions
	TInt PasswordControlStart(const TCID &aCID, const TMediaPassword *aPWD);
	void PasswordControlEnd(DMMCSession *aSessP, TInt aResult);
	TBool RefreshStore();

protected:
    TMMCMachineInfo iMachineInfo;
	TMMCPasswordStore* iPasswordStore;

public:
	DMMCStack* iStack;
	DMMCPsu* iVccCore;

private:
	TUint32 iReserved[4];
	
public:	
	enum TMMCPanic
		{
		EMMCMachineStack				=0,
		EMMCMachineState				=1,
		EMMCSessRingNoSession			=2,
		EMMCStackSessionEngaged			=3,
		EMMCInitStackBlocked			=4,
		EMMCNoFreeRCA					=5,
		EMMCCommandStack				=6,
		EMMCRWSessionID					=7,
		EMMCEraseSessionID				=8,
		EMMCIOSessionID					=9,
		EMMCSessionNoPswdCard			=10,
		EMMCSessionPswdCmd				=11,
		EMMCSessionBadSessionID			=12,
		EMMCSetBusWidthNotImplemented	=13,
		EMMCInvalidNumberOfCardSlots	=14,
		EMMCBadBusWidth					=15,
		EMMCInvalidDBCommand			=16,
		EMMCInvalidDBBlockLength		=17,
		EMMCUnblockingInWrongContext	=18,
		EMMCInvalidCardNumber			=19,
		EMMCNotInDfcContext				=20,
		EMMCAddressCardNotSupported		=21,
		EMMCInvalidPartitionNumber      =22
		};
    IMPORT_C static void Panic(TMMCPanic aPanic);
	friend class DMMCStack;
	friend class DMMCSession;
	friend class DMMCMediaChange;
	};

const TUint32 KMMCEraseClassCmdsSupported=	KBit0;
const TUint32 KMMCEraseGroupCmdsSupported=	KBit1;
NONSHARABLE_CLASS(TMMCEraseInfo)
	{
public:
	inline TBool EraseClassCmdsSupported() const;	
	inline TBool EraseGroupCmdsSupported() const;	
public:
	TUint32 iEraseFlags;
	TUint32 iPreferredEraseUnitSize;
	TUint32 iMinEraseSectorSize;
	};
	
#include <drivers/mmc.inl>

#endif	// __MMC_H__

