kernel/eka/drivers/pbus/mmc/session.cpp
changeset 0 a41df078684a
child 13 46fffbe7b5a7
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <drivers/mmc.h>
       
    17 
       
    18 
       
    19 //	--------  class DMMCSession  --------
       
    20 
       
    21 EXPORT_C DMMCSession::DMMCSession(const TMMCCallBack& aCallBack)
       
    22 /**
       
    23  * Constructor - initializes callbacks and timers.
       
    24  * Once the session has been engaged, the completion of the request is signalled by calling 
       
    25  * the function provided in aCallback. A session will be completed in this way if it has completed
       
    26  * normally, an error has occurred or the session has been stopped by this or another client.
       
    27  * @param aCallBack reference to a TMMCCallback object to be called upon completion.
       
    28  */
       
    29 	: iCallBack(aCallBack),
       
    30 #ifdef __EPOC32__
       
    31 	iPollTimer(DMMCSession::PollTimerCallBack, this),
       
    32 	iRetryTimer(DMMCSession::RetryTimerCallBack, this),
       
    33 	iProgramTimer(DMMCSession::ProgramTimerCallBack, this),
       
    34 #endif	// #ifdef __EPOC32__
       
    35 	iConfig()
       
    36 	{
       
    37 	}
       
    38 
       
    39 EXPORT_C DMMCSession::~DMMCSession()
       
    40 /**
       
    41  * Destructor.
       
    42  */
       
    43 	{
       
    44 	// Ensure that the stack isn't currently running in another thread's context, otherwise this session won't be 
       
    45 	// removed from the stack's workset until some time later - by which time the session will have been deleted
       
    46 	__ASSERT_ALWAYS(!iStackP->StackRunning(), DMMCSocket::Panic(DMMCSocket::EMMCNotInDfcContext));
       
    47 	Abort();
       
    48 	UnlockStack();
       
    49 	}
       
    50 
       
    51 EXPORT_C void DMMCSession::SetCard(TMMCard* aCardP)
       
    52 /**
       
    53  * Assigns a card to the session. The card pointer would normally be obtained via a call of DMMCStack::CardP(). 
       
    54  * Assigning a card to the session is the means by which a particular card in the stack is targeted for a 
       
    55  * particular request. Some requests involve broadcasting to the entire stack. However, the majority involve 
       
    56  * an individual card at some stage of the process and so an attempt to engage the session before a card has 
       
    57  * been assigned to it will generally fail straight away. It is possible to change the card assigned to the 
       
    58  * session as long as this is not attempted while the session is engaged.
       
    59  * @param aCardP A pointer to the card to be assigned to the session.
       
    60  */
       
    61 	{
       
    62 	iCardP = aCardP;
       
    63 	iCID = iCardP->CID();
       
    64 	}
       
    65 
       
    66 EXPORT_C void DMMCSession::SetupCIMReadBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP)
       
    67 /**
       
    68  * Sets the session up to perform the CIM_READ_BLOCK macro as outlined by the MMCA. 
       
    69  * Having set-up the session for this operation, the client must then engage the session before the operation can commence. 
       
    70  * The CIM_READ_BLOCK macro reads a single block from the card. It starts by setting the block length (CMD16) as specified 
       
    71  * in 'aLength'. It then reads a single block of data (CMD17) from the card at offset 'aDevAddr' on the card into system 
       
    72  * memory starting at address 'aMemoryP'.
       
    73  * @param aDevAddr Contains offset to the block to be read from the card
       
    74  * @param aLength Block length
       
    75  * @param aMemoryP host destination address
       
    76  */
       
    77 	{
       
    78 	ResetCommandStack();
       
    79 	FillCommandArgs(aDevAddr, aLength, aMemoryP, aLength);
       
    80 	iSessionID = ECIMReadBlock;
       
    81 	}
       
    82 
       
    83 EXPORT_C void DMMCSession::SetupCIMWriteBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP)
       
    84 /**
       
    85  * Set up the session to perform the CIM_WRITE_BLOCK macro as outlined by the MMCA.
       
    86  * Having set-up the session for this operation, the client must then engage the session before the operation can commence. 
       
    87  * The CIM_WRITE_BLOCK macro writes a single block to the card. It starts by setting the block length (CMD16) as specified 
       
    88  * in 'aLength'. It then writes a single block of data (CMD24) to the card at offset 'aDevAddr' on the card reading from system 
       
    89  * memory starting at address 'aMemoryP'.
       
    90  * @param aDevAddr Contains offset to the block to be written on the card
       
    91  * @param aLength Block length
       
    92  * @param aMemoryP Host source address
       
    93  */
       
    94 	{
       
    95 	ResetCommandStack();
       
    96 	FillCommandArgs(aDevAddr, aLength, aMemoryP, aLength);
       
    97 	iSessionID = ECIMWriteBlock;
       
    98 	}
       
    99 
       
   100 EXPORT_C void DMMCSession::SetupCIMReadMBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP, TUint32 aBlkLen)
       
   101 /**
       
   102  * Set up the session to perform the CIM_READ_MBLOCK macro as outlined by the MMCA.
       
   103  * Having set-up the session for this operation, the client must then engage the session before the operation can commence. 
       
   104  * The CIM_READ_MBLOCK macro reads a series of blocks from the card. It starts by setting the block length (CMD16) as specified 
       
   105  * in 'aBlkLen'. It then issues the read multiple block command (CMD18) to continually transfer blocks from the card to host 
       
   106  * starting at offset 'aDevAddr' on the card into system memory starting at address 'aMemoryP'. This continues until 'aLength'
       
   107  * bytes have been read at which point the Controller issues the stop command (CMD12) to halt the transfer.
       
   108  * @param aDevAddr Contains offset to the block to be read from the card
       
   109  * @param aLength Total number of bytes to read.
       
   110  * @param aMemoryP Host destination address
       
   111  * @param aBlkLen Block length
       
   112  */
       
   113 	{
       
   114 	ResetCommandStack();
       
   115 	FillCommandArgs(aDevAddr, aLength, aMemoryP, aBlkLen);
       
   116 	iSessionID = ECIMReadMBlock;
       
   117 	}
       
   118 
       
   119 EXPORT_C void DMMCSession::SetupCIMWriteMBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP, TUint32 aBlkLen)
       
   120 /**
       
   121  * Set up the session to perform the CIM_WRITE_MBLOCK macro as outlined by the MMCA.
       
   122  * Having set-up the session for this operation, the client must then engage the session before the operation can commence. 
       
   123  * The CIM_WRITE_MBLOCK macro writes a series of blocks to the card. It starts by setting the block length (CMD16) as specified 
       
   124  * in 'aBlkLen'. It then issues the write multiple block command (CMD25) to continually transfer blocks from host to the card 
       
   125  * starting at address 'aMemoryP' in system memory and offset 'aDevAddr' on the card.. This continues until 'aLength' bytes have 
       
   126  * been written at which point the Controller issues the stop command (CMD12) to halt the transfer
       
   127  * @param aDevAddr Contains offset to the block to be written on the card
       
   128  * @param aLength Total number of bytes to write.
       
   129  * @param aMemoryP Host source address
       
   130  * @param aBlkLen Block length
       
   131  */
       
   132 	{
       
   133 	ResetCommandStack();
       
   134 	FillCommandArgs(aDevAddr, aLength, aMemoryP, aBlkLen);
       
   135 	iSessionID = ECIMWriteMBlock;
       
   136 	}
       
   137 
       
   138 EXPORT_C void DMMCSession::SetupCIMEraseSector(TMMCArgument aDevAddr, TUint32 aLength)
       
   139 /**
       
   140  * Set up the session to perform the CIM_ERASE_SECTOR macro broadly as outlined by the MMCA. 
       
   141  * However, the macro only performs a sector erase of a contiguous area and doesn't support the un-tagging of particular sectors 
       
   142  * within the initial tagged area. Having set-up the session for this operation, the client must then engage the session before 
       
   143  * the operation can commence. 
       
   144  * The CIM_ERASE_SECTOR macro erases a range of sectors on the card starting at offset 'aDevAddr' on the card and ending at offset 
       
   145  * 'aDevAdd'+'aLength'. The entire area specified must lie within a single erase group. (The erase group size can be read from the CSD).
       
   146  * The specified start offset and end offset need not coincide exactly with a sector boundary since the card will ignore LSBs below 
       
   147  * the sector size. The tag sector start command (CMD32) is first issued setting the address of the first sector to be erased. 
       
   148  * This is followed by the tag sector end command (CMD33) setting the address of the last sector to be erased. Now that the erase 
       
   149  * sectors are tagged, the erase command (CMD38) is sent followed by a send status command (CMD13) to read any additional status 
       
   150  * information from the card.
       
   151  * @param aDevAddr Contains offset to the first block to be erased
       
   152  * @param aLength Total number of bytes to erase
       
   153  */
       
   154 	{
       
   155 	ResetCommandStack();
       
   156 	FillCommandArgs(aDevAddr, aLength, NULL, 0);
       
   157 	iSessionID = ECIMEraseSector;
       
   158 	}
       
   159 
       
   160 EXPORT_C void DMMCSession::SetupCIMEraseGroup(TMMCArgument aDevAddr, TUint32 aLength)
       
   161 /**
       
   162  * Set up the session to perform the CIM_ERASE_GROUP macro broadly as outlined by the MMCA. 
       
   163  * However, the macro only performs an erase group erase of a contiguous area and doesn't support the un-tagging of particular 
       
   164  * erase groups within the initial tagged area. Having set-up the session for this operation, the client must then engage the 
       
   165  * session before the operation can commence. 
       
   166  * The CIM_ERASE_GROUP macro erases a range of erase groups on the card starting at offset 'aDevAddr' on the card and ending at 
       
   167  * offset 'aDevAdd'+'aLength'. The specified start offset and end offset need not coincide exactly with an erase group boundary 
       
   168  * since the card will ignore LSBs below the erase group size. The tag ease group start command (CMD35) is first issued setting 
       
   169  * the address of the first erase group to be erased. This is followed by the tag erase group end command (CMD36) setting the 
       
   170  * address of the last erase group to be erased. Now that the erase groups are tagged, the erase command (CMD38) is sent followed 
       
   171  * by a send status command (CMD13) to read any additional status information from the card.
       
   172  * @param aDevAddr Contains offset to the first block to be erased
       
   173  * @param aLength Total number of bytes to erase
       
   174  */
       
   175 	{
       
   176 	ResetCommandStack();
       
   177 	FillCommandArgs(aDevAddr, aLength, NULL, 0);
       
   178 	iSessionID = ECIMEraseGroup;
       
   179 	}
       
   180 
       
   181 EXPORT_C void DMMCSession::SetupCIMReadIO(TUint8 aRegAddr, TUint32 aLength, TUint8* aMemoryP)
       
   182 /** 
       
   183  * Set up the session to perform the read i/o macro (CMD39).
       
   184  * This macro reads a stream of bytes from an I/O register on a MultiMediaCard. This makes use of the fast i/o (CMD39) command, 
       
   185  * reading 'aLength' bytes of data from I/O register 'aRegAddr' on the card into system memory starting at address 'aMemoryP'. 
       
   186  * Having set-up the session for this operation, the client must then engage the session before the operation can commence. 
       
   187  * @param aRegAddr Address of IO register
       
   188  * @param aLength Total number of bytes to read
       
   189  * @param aMemoryP Host destination address
       
   190  */
       
   191 	{
       
   192 	ResetCommandStack();
       
   193 	FillCommandArgs(aRegAddr, aLength, aMemoryP, 0);
       
   194 	iSessionID = ECIMReadIO;
       
   195 	}
       
   196 
       
   197 EXPORT_C void DMMCSession::SetupCIMWriteIO(TUint8 aRegAddr, TUint32 aLength, TUint8* aMemoryP)
       
   198 /** 
       
   199  * Set up the session to perform the write i/o macro (CMD39). 
       
   200  * This macro writes a stream of bytes to an I/O register on a MultiMediaCard. This makes use of the fast i/o (CMD39) command,
       
   201  * writing 'aLength' bytes of data to I/O register 'aRegAddr' on the card from system memory starting at address 'aMemoryP'. 
       
   202  * Having set-up the session for this operation, the client must then engage the session before the operation can commence. 
       
   203  * @param aRegAddr Address of IO register
       
   204  * @param aLength Total number of bytes to write
       
   205  * @param aMemoryP Host source address
       
   206  */
       
   207 	{
       
   208 	ResetCommandStack();
       
   209 	FillCommandArgs(aRegAddr, aLength, aMemoryP, 0);
       
   210 	iSessionID = ECIMWriteIO;
       
   211 	}
       
   212 
       
   213 EXPORT_C void DMMCSession::SetupCIMLockUnlock(TUint32 aLength, TUint8* aMemoryP)
       
   214 /**
       
   215  * Set up the session to perform the lock-unlock macro (CMD42). 
       
   216  * This macro is used to manage the password protection feature (if supported) on a MultiMediaCard. 
       
   217  * This same macro is used to lock or unlock a card, set or clear a password or force erase a card.  
       
   218  * Having set-up the session for the required operation, the client must then engage the session before 
       
   219  * the operation can commence. 
       
   220  * The block length (CMD16) as specified in 'aLength' is first set. The lock unlock command (CMD42) is 
       
   221  * then issued. This command has the same structure as a regular single block write command. 
       
   222  * A data block is written to the card from system memory starting at address 'aMemoryP'. The transferred 
       
   223  * data block should contain the password setting mode, the password length and the password data if appropriate.
       
   224  * @param aLength Block length
       
   225  * @param aMemoryP Host source address containing password data
       
   226  */
       
   227 	{
       
   228 	__KTRACE_OPT(KPBUS1, Kern::Printf("ms:slu%08x", aLength));
       
   229 
       
   230 	ResetCommandStack();
       
   231 	FillCommandDesc(ECmdLockUnlock);
       
   232 	FillCommandArgs(0, aLength, aMemoryP, aLength);
       
   233 	iSessionID = ECIMLockUnlock;
       
   234 	}
       
   235 
       
   236 EXPORT_C void DMMCSession::SetupCommand(TMMCCommandEnum aCommand, TMMCArgument anArgument)
       
   237 /** 
       
   238  * Set up the session to issue a raw command to the card. 
       
   239  * This raw command function should be used when issuing a known command with or without an argument. 
       
   240  * Having set-up the session for this operation, the client must then engage this session before 
       
   241  * the operation can commence.
       
   242  * @param aCommand Command to be sent
       
   243  * @param anArgument Associated argument
       
   244  */
       
   245 	{
       
   246 	ResetCommandStack();
       
   247 	FillCommandDesc(aCommand, anArgument);
       
   248 	iSessionID = ECIMNakedSession;
       
   249 	}
       
   250 
       
   251 EXPORT_C void DMMCSession::SetupRSCommand(TMMCCommandEnum aCommand, TMMCArgument anArgument,
       
   252 							TUint32 aResponseLength, TMMCCommandTypeEnum aCommandType,
       
   253 							TMMCResponseTypeEnum aResponseType,
       
   254 							TUint32 aCommandClass)
       
   255 /**
       
   256  * Set up the session to issue a raw command to the card. 
       
   257  * This raw command function should be used when issuing an unknown command, an argument and an unknown response type.
       
   258  * Having set-up the session for this operation, the client must then engage this session before the operation can commence.
       
   259  * @param aCommand
       
   260  * @param anArgument
       
   261  * @param aResponseLength
       
   262  * @param aCommandType
       
   263  * @param aResponseType
       
   264  * @param aCommandClass
       
   265  * @todo Complete the parameter descriptions
       
   266  */
       
   267 	{
       
   268 	ResetCommandStack();
       
   269 	FillCommandDesc(aCommand, anArgument);
       
   270 	TMMCCommandSpec& cmdSpec = Command().iSpec;
       
   271 	cmdSpec.iDirection = EDirNone;
       
   272 
       
   273 	if( aResponseLength <= KMMCMaxResponseLength )
       
   274 		cmdSpec.iResponseLength = aResponseLength;
       
   275 
       
   276 	if( aCommandType != ECmdTypeUK )
       
   277 		cmdSpec.iCommandType = aCommandType;
       
   278 
       
   279 	if( aResponseType != ERespTypeUnknown )
       
   280 		cmdSpec.iResponseType = aResponseType;
       
   281 
       
   282 	if( aCommandClass != KMMCCmdClassNone )
       
   283 		cmdSpec.iCommandClass = aCommandClass;
       
   284 
       
   285 	iSessionID = ECIMNakedSession;
       
   286 	}
       
   287 
       
   288 EXPORT_C void DMMCSession::SetupDTCommand(TMMCCommandEnum aCommand, TMMCArgument anArgument,
       
   289 							TUint32 aTotalLength, TUint8* aMemoryAddress, TUint32 aBlockLength,
       
   290 							TBool aStopTransmission, TMMCCmdDirEnum aDir,
       
   291 							TUint32 aCommandClass)
       
   292 /**
       
   293  * Set up the session to issue a raw command to the card. 
       
   294  * This raw command function should be used when issuing a generic transfer command and argument.
       
   295  * Having set-up the session for this operation, the client must then engage this session before
       
   296  * the operation can commence.
       
   297  * @param aCommand
       
   298  * @param anArgument
       
   299  * @param aTotalLength
       
   300  * @param aMemoryAddress
       
   301  * @param aBlockLength
       
   302  * @param aStopTransmission
       
   303  * @param aDir
       
   304  * @param aCommandClass
       
   305  * @todo Complete the parameter descriptions
       
   306  */
       
   307 	{
       
   308 	ResetCommandStack();
       
   309 	FillCommandDesc(aCommand);
       
   310 	FillCommandArgs(anArgument, aTotalLength, aMemoryAddress, aBlockLength);
       
   311 	TMMCCommandDesc& cmd = Command();
       
   312 
       
   313 	if( aBlockLength == 0 )
       
   314 		cmd.iBlockLength = aTotalLength;
       
   315 
       
   316 	cmd.iSpec.iMultipleBlocks = (cmd.iBlockLength != aTotalLength);
       
   317 
       
   318 	if( aStopTransmission )
       
   319 		cmd.iSpec.iUseStopTransmission = ETrue;
       
   320 
       
   321 	if( aDir != EDirNone )
       
   322 		{
       
   323 		cmd.iSpec.iUseStopTransmission = aStopTransmission;
       
   324 		cmd.iSpec.iDirection = aDir;
       
   325 		}
       
   326 
       
   327 	if( aCommandClass != KMMCCmdClassNone )
       
   328 		cmd.iSpec.iCommandClass = aCommandClass;
       
   329 
       
   330 	iSessionID = ECIMNakedSession;
       
   331 	}
       
   332 
       
   333 void DMMCSession::SetupCIMControl(TInt aSessID)
       
   334 //
       
   335 // find matching macro function for supplied session
       
   336 //
       
   337 	{
       
   338 	TMMCSMSTFunc f = GetMacro(aSessID);
       
   339 
       
   340 	if (f == 0)
       
   341 		f = DMMCStack::NoSessionSMST;
       
   342 
       
   343 	iSessionID = (TMMCSessionTypeEnum) aSessID;
       
   344 	iBytesTransferred = 0;
       
   345 	iMMCExitCode = KMMCErrNone;
       
   346 	iState = 0;
       
   347 	iInitContext = 0;
       
   348 	iGlobalRetries = 0;
       
   349 	iDoAbort = iDoStop = iDoComplete = EFalse;
       
   350 	iBlockOn = 0;
       
   351 
       
   352 	ResetCommandStack();
       
   353 
       
   354 	iMachine.Setup(f, iStackP);
       
   355 	}
       
   356 
       
   357 EXPORT_C TMMCSMSTFunc DMMCSession::GetMacro(TInt aSessNum) const
       
   358 	{
       
   359 	TMMCSMSTFunc f = 0;
       
   360 
       
   361 	static const TMMCSMSTFunc macros[KMMCMaxSessionTypeNumber] =
       
   362 		{
       
   363 		DMMCStack::NakedSessionSMST,
       
   364 		DMMCStack::CIMUpdateAcqSMST,
       
   365 		DMMCStack::CIMInitStackSMST,
       
   366 		DMMCStack::CIMCheckStackSMST,
       
   367 		DMMCStack::CIMSetupCardSMST,
       
   368 		DMMCStack::CIMReadWriteBlocksSMST,			// CIMReadBlock
       
   369 		DMMCStack::CIMReadWriteBlocksSMST,			// CIMWriteBlock
       
   370 		DMMCStack::CIMReadWriteBlocksSMST,			// CIMReadMBlock
       
   371 		DMMCStack::CIMReadWriteBlocksSMST,			// CIMWriteMBlock
       
   372 		DMMCStack::CIMEraseSMST,
       
   373 		DMMCStack::CIMEraseSMST,
       
   374 		DMMCStack::CIMReadWriteIOSMST,
       
   375 		DMMCStack::CIMReadWriteIOSMST,
       
   376 		DMMCStack::CIMLockUnlockSMST,				// CIMLockUnlock
       
   377 		DMMCStack::NoSessionSMST,					// CIMLockStack is never really executed as a session
       
   378 		DMMCStack::InitStackAfterUnlockSMST,
       
   379 		DMMCStack::CIMAutoUnlockSMST,
       
   380 		DMMCStack::ExecSleepCommandSMST				// CIMSleep
       
   381 		};
       
   382 
       
   383 	if (aSessNum >= 0 && aSessNum < (TInt) KMMCMaxSessionTypeNumber)
       
   384 		f = macros[aSessNum];
       
   385 
       
   386 	return f;
       
   387 	}
       
   388 
       
   389 EXPORT_C TInt DMMCSession::Engage()
       
   390 /**
       
   391  * Enque this session for execution on the DMMCStack object which is serving it.
       
   392  * @return KErrBadDriver if no stack is associated with the session
       
   393  * @return KErrServerBusy if the stack is currently locked (and KMMCModeEnqueIfLocked flag is cleared)
       
   394  * @return KErrNotReady if the media is not present
       
   395  * @return KErrNone if successful
       
   396  */
       
   397 	{
       
   398 	__KTRACE_OPT(KPBUS1,Kern::Printf(">ms:eng"));
       
   399 
       
   400 	if( iStackP == NULL )
       
   401 		return( KErrBadDriver );
       
   402 
       
   403 	if( iStackP->iLockingSessionP != NULL && iStackP->iLockingSessionP != this &&
       
   404 		(iStackP->EffectiveModes(iConfig) & KMMCModeEnqueIfLocked) == 0 )
       
   405 		return( KErrServerBusy );
       
   406 
       
   407 	const TMediaState doorState=iStackP->MMCSocket()->iMediaChange->MediaState();
       
   408 
       
   409 	__KTRACE_OPT(KPBUS1,Kern::Printf(">MMC:Eng ds = %x", doorState));
       
   410 
       
   411 	if (doorState == EDoorOpen)
       
   412 		return KErrNotReady;
       
   413 
       
   414 	SetupCIMControl(iSessionID);
       
   415 
       
   416 	iStackP->Add(this);
       
   417 
       
   418 	__KTRACE_OPT(KPBUS1,Kern::Printf("<ms:eng"));
       
   419 	return(KErrNone);
       
   420 	}
       
   421 
       
   422 // Command specification table for standard MMC commands (CMD0 - CMD63)
       
   423 extern const TMMCCommandSpec CommandTable[KMMCCommandMask+1] =
       
   424 	{//  Class				  Type			Dir			MBlk	StopT	Rsp Type		  Len	Cmd No
       
   425 	{KMMCCmdClassBasic,		ECmdTypeBC,		EDirNone,	EFalse, EFalse, ERespTypeNone,		0}, //CMD0
       
   426 	{KMMCCmdClassBasic,		ECmdTypeBCR,	EDirNone,	EFalse, EFalse, ERespTypeR3,		4}, //CMD1
       
   427 	{KMMCCmdClassBasic,		ECmdTypeBCR,	EDirNone,	EFalse, EFalse, ERespTypeR2,		16},//CMD2
       
   428 	{KMMCCmdClassBasic,		ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD3
       
   429 	{KMMCCmdClassBasic,		ECmdTypeBC,		EDirNone,	EFalse, EFalse, ERespTypeNone,		0}, //CMD4
       
   430 	{KMMCCmdClassBasic,		ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeR1B,		0}, //CMD5 - SLEEP/AWAKE
       
   431 	{KMMCCmdClassBasic,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1B,		0}, //CMD6
       
   432 	{KMMCCmdClassBasic,		ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeR1B,		4}, //CMD7
       
   433 	{KMMCCmdClassBasic,		ECmdTypeADTCS,	EDirRead,	EFalse, EFalse, ERespTypeR1,		512}, //CMD8
       
   434 	{KMMCCmdClassBasic,		ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeR2,		16},//CMD9
       
   435 	{KMMCCmdClassBasic,		ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeR2,		16},//CMD10
       
   436 	{KMMCCmdClassStreamRead,ECmdTypeADTCS,	EDirRead,	EFalse, ETrue,	ERespTypeR1,		4}, //CMD11
       
   437 	{KMMCCmdClassBasic,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1B,		4}, //CMD12
       
   438 	{KMMCCmdClassBasic,		ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD13
       
   439 	{KMMCCmdClassBlockRead,	ECmdTypeADTCS,	EDirRead,	EFalse, EFalse, ERespTypeR1,		4}, //CMD14 - BUSTEST_R
       
   440 	{KMMCCmdClassBasic,		ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeNone,		0}, //CMD15
       
   441 	{KMMCCmdClassBlockRead,	ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD16
       
   442 	{KMMCCmdClassBlockRead,	ECmdTypeADTCS,	EDirRead,	EFalse, EFalse, ERespTypeR1,		4}, //CMD17
       
   443 	{KMMCCmdClassBlockRead,	ECmdTypeADTCS,	EDirRead,	ETrue,	ETrue,	ERespTypeR1,		4}, //CMD18
       
   444 	{KMMCCmdClassBlockWrite,ECmdTypeADTCS,	EDirWrite,	EFalse, EFalse, ERespTypeR1,		4}, //CMD19 - BUSTEST_W
       
   445 	{KMMCCmdClassStreamWrite,ECmdTypeADTCS, EDirWrite,	EFalse, ETrue,	ERespTypeR1,		4}, //CMD20
       
   446 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD21
       
   447 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD22
       
   448 	{KMMCCmdClassBlockRead | 
       
   449 	 KMMCCmdClassBlockWrite,ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,	4}, //CMD23
       
   450 	{KMMCCmdClassBlockWrite,ECmdTypeADTCS,	EDirWrite,	EFalse, EFalse, ERespTypeR1,		4}, //CMD24
       
   451 	{KMMCCmdClassBlockWrite,ECmdTypeADTCS,	EDirWrite,	ETrue,	ETrue,	ERespTypeR1,		4}, //CMD25
       
   452 	{KMMCCmdClassBlockWrite,ECmdTypeADTCS,	EDirWrite,	EFalse, EFalse, ERespTypeR1,		4}, //CMD26
       
   453 	{KMMCCmdClassBlockWrite,ECmdTypeADTCS,	EDirWrite,	EFalse, EFalse, ERespTypeR1,		4}, //CMD27
       
   454 	{KMMCCmdClassWriteProtection,ECmdTypeACS,EDirNone,	EFalse, EFalse, ERespTypeR1B,		4}, //CMD28
       
   455 	{KMMCCmdClassWriteProtection,ECmdTypeACS,EDirNone,	EFalse, EFalse, ERespTypeR1B,		4}, //CMD29
       
   456 	{KMMCCmdClassWriteProtection,ECmdTypeADTCS,EDirRead,EFalse, EFalse, ERespTypeR1,		4}, //CMD30
       
   457 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD31
       
   458 	{KMMCCmdClassErase,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD32
       
   459 	{KMMCCmdClassErase,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD33
       
   460 	{KMMCCmdClassErase,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD34
       
   461 	{KMMCCmdClassErase,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD35
       
   462 	{KMMCCmdClassErase,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD36
       
   463 	{KMMCCmdClassErase,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD37
       
   464 	{KMMCCmdClassErase,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1B,		4}, //CMD38
       
   465 	{KMMCCmdClassIOMode,	ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeR4,		4}, //CMD39
       
   466 	{KMMCCmdClassIOMode,	ECmdTypeBCR,	EDirNone,	EFalse, EFalse, ERespTypeR5,		4}, //CMD40
       
   467 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD41
       
   468 	{KMMCCmdClassLockCard,	ECmdTypeADTCS,	EDirWrite,	EFalse, EFalse, ERespTypeR1B,		4}, //CMD42
       
   469 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD43
       
   470 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD44
       
   471 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD45
       
   472 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD46
       
   473 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD47
       
   474 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD48
       
   475 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD49
       
   476 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD50
       
   477 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD51
       
   478 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD52
       
   479 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD53
       
   480 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD54
       
   481 	{KMMCCmdClassApplication,ECmdTypeAC,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD55
       
   482 	{KMMCCmdClassApplication,ECmdTypeADTCS,	EDirRBit0,	EFalse, EFalse, ERespTypeR1B,		4}, //CMD56
       
   483 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD57
       
   484 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD58
       
   485 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD59
       
   486 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD60
       
   487 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD61
       
   488 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD62
       
   489 	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}	//CMD63
       
   490 	};
       
   491 
       
   492 
       
   493 EXPORT_C void DMMCSession::FillCommandDesc()
       
   494 /**
       
   495  * Fills the current command descriptor with the default data according to MMC spec V2.1
       
   496  */
       
   497 	{
       
   498 	TMMCCommandDesc& cmd = Command();
       
   499 	cmd.iSpec = CommandTable[cmd.iCommand & KMMCCommandMask];
       
   500 
       
   501 	cmd.iFlags = 0;
       
   502 	cmd.iBytesDone = 0;
       
   503 	}
       
   504 
       
   505 EXPORT_C void DMMCSession::FillCommandDesc(TMMCCommandEnum aCommand)
       
   506 /**
       
   507  * Initialises the current command according to whether it is a normal
       
   508  * or an application command.
       
   509  * @param aCommand Contains the command.
       
   510  */
       
   511 	{
       
   512 	Command().iCommand = aCommand;
       
   513 	Command().iArgument = 0;					// set stuff bits to zero
       
   514 	FillCommandDesc();
       
   515 	}
       
   516 
       
   517 EXPORT_C void DMMCSession::FillCommandDesc(TMMCCommandEnum aCommand, TMMCArgument anArgument)
       
   518 /**
       
   519  * Initialises the current command with an argument according to whether
       
   520  * it is a normal or an application command.
       
   521  * @param aCommand Contains the command.
       
   522  * @param anArgument Specifies the argument.
       
   523  */
       
   524 	{
       
   525 	TMMCCommandDesc& cmd = Command();
       
   526 	cmd.iCommand = aCommand;
       
   527 	FillCommandDesc();
       
   528 	cmd.iArgument = anArgument;
       
   529 	}
       
   530 
       
   531 EXPORT_C void DMMCSession::FillCommandArgs(TMMCArgument anArgument, TUint32 aLength, TUint8* aMemoryP,
       
   532 								  TUint32 aBlkLen)
       
   533 /**
       
   534  * Initialises the current commands arguments with the specified parameters
       
   535  * It is necessary to have set the command arguments with this command prior
       
   536  * to engaging a read/write macro or command.
       
   537  * @param anArgument Command specific argument.
       
   538  * @param aLength aLength Total number of bytes to read/write.
       
   539  * @param aMemoryP Host source/destination address
       
   540  * @param aBlkLen Block length
       
   541  */
       
   542 	{
       
   543 	TMMCCommandDesc& cmd = Command();
       
   544 
       
   545 	cmd.iArgument = anArgument;
       
   546 	cmd.iTotalLength = aLength;
       
   547 	cmd.iDataMemoryP = aMemoryP;
       
   548 	cmd.iBlockLength = aBlkLen;
       
   549 	cmd.iFlags = 0;
       
   550 	}
       
   551 
       
   552 const TMMCCommandSpec& DMMCSession::FindCommandSpec(const TMMCIdxCommandSpec aSpecs[], TInt aIdx)
       
   553 /**
       
   554  * Searches the supplied command specification list for the specification corresponding to the
       
   555  * supplied command.
       
   556  * @param aSpecs The command specification list to be searched.
       
   557  * @param aIdx The requested command.
       
   558  */
       
   559 	{
       
   560 	TInt i = 0;
       
   561 	while (aSpecs[i].iIdx != aIdx)
       
   562 		++i;
       
   563 	return aSpecs[i].iSpec;
       
   564 	}
       
   565 
       
   566 void DMMCSession::SynchBlock(TUint32 aFlag)
       
   567 //
       
   568 // Blocks a session synchronously (within scheduler context)
       
   569 //
       
   570 	{
       
   571 	(void)__e32_atomic_ior_ord32(&iBlockOn, aFlag);
       
   572 	}
       
   573 
       
   574 void DMMCSession::SynchUnBlock(TUint32 aFlag)
       
   575 //
       
   576 // Unblocks a session synchronously (within scheduler context)
       
   577 //
       
   578 	{
       
   579 	if( (iBlockOn & aFlag) == 0 )
       
   580 		return;
       
   581 
       
   582 	(void)__e32_atomic_and_ord32(&iBlockOn, ~aFlag);
       
   583 	}
       
   584 
       
   585 EXPORT_C TRCA DMMCSession::CardRCA()
       
   586 /**
       
   587  * Checks that the card is still the same and ready
       
   588  * @return A TRCA object containing the card's RCA (or 0 if the card is not ready)
       
   589  */
       
   590 	{
       
   591 
       
   592 	// Rely on 'CardIsGone' bit rather than a CID comparison	
       
   593 	if ( iCardP != NULL && iCardP->IsPresent() && !(iState & KMMCSessStateCardIsGone) ) 
       
   594 		return( iCardP->RCA() );
       
   595 	return(0);
       
   596 	}
       
   597 
       
   598 #ifdef __EPOC32__
       
   599 void DMMCSession::ProgramTimerCallBack(TAny* aSessP)
       
   600 	{
       
   601 	__KTRACE_OPT(KPBUS1,Kern::Printf("=mss:pgtcb"));
       
   602 	
       
   603     static_cast<DMMCSession *>(aSessP)->iState |= KMMCSessStateDoDFC;
       
   604 	static_cast<DMMCSession *>(aSessP)->UnBlock(KMMCBlockOnPgmTimer, KMMCErrNone);
       
   605 	}
       
   606 
       
   607 void DMMCSession::PollTimerCallBack(TAny* aSessP)
       
   608 	{
       
   609 	__KTRACE_OPT(KPBUS1,Kern::Printf("=mss:ptcb"));
       
   610 
       
   611     static_cast<DMMCSession *>(aSessP)->iState |= KMMCSessStateDoDFC;
       
   612 	static_cast<DMMCSession *>(aSessP)->UnBlock(KMMCBlockOnPollTimer, KMMCErrNone);
       
   613 	}
       
   614 
       
   615 void DMMCSession::RetryTimerCallBack(TAny* aSessP)
       
   616 	{
       
   617 	__KTRACE_OPT(KPBUS1,Kern::Printf("=mss:rtcb"));
       
   618 
       
   619     static_cast<DMMCSession *>(aSessP)->iState |= KMMCSessStateDoDFC;
       
   620 	static_cast<DMMCSession *>(aSessP)->UnBlock(KMMCBlockOnRetryTimer, KMMCErrNone);
       
   621 	}
       
   622 
       
   623 #endif	// #ifdef __EPOC32__
       
   624 
       
   625 EXPORT_C TInt DMMCSession::EpocErrorCode() const
       
   626 /**
       
   627  * Returns the last Symbian OS style error code returned in this session. 
       
   628  * The Symbian OS error code is derived from both the last MMC specific exit code MMCExitCode()
       
   629  * and the last status information from the card (iLastStatus).
       
   630  * @return Standard Symbian OS error code
       
   631  */
       
   632 	{
       
   633 	__KTRACE_OPT(KPBUS1,Kern::Printf("=mss:eee:%08x,%08x", MMCExitCode(), LastStatus().State() ));
       
   634 
       
   635 	struct errorTableEntry
       
   636 		{
       
   637 		TUint32 iMask;
       
   638 		TInt iErrorCode;
       
   639 		};
       
   640 
       
   641 	static const errorTableEntry mmcTable[] = 
       
   642 		{
       
   643 		{KMMCErrNotSupported,									KErrNotSupported},
       
   644 		{KMMCErrStackNotReady,									KErrBadPower},
       
   645 		{KMMCErrArgument,										KErrArgument},
       
   646 		{KMMCErrBrokenLock | KMMCErrPowerDown | KMMCErrAbort,	KErrAbort},
       
   647 		{KMMCErrNoCard | KMMCErrResponseTimeOut | KMMCErrDataTimeOut |
       
   648 			KMMCErrBusyTimeOut | KMMCErrBusTimeOut,				KErrNotReady},
       
   649 		{KMMCErrResponseCRC|KMMCErrDataCRC|KMMCErrCommandCRC,	KErrCorrupt},
       
   650 		{KMMCErrLocked,											KErrLocked},
       
   651 		{KMMCErrNotFound,										KErrNotFound},
       
   652 		{KMMCErrAlreadyExists,									KErrAlreadyExists},
       
   653 		{KMMCErrGeneral,										KErrGeneral},
       
   654 		{~0UL,													KErrUnknown}
       
   655 		};
       
   656 
       
   657 	static const errorTableEntry statusTable[] = 
       
   658 		{
       
   659 		{KMMCStatErrOverrun|KMMCStatErrUnderrun|
       
   660 			KMMCStatErrCardECCFailed|KMMCStatErrComCRCError,	KErrGeneral},
       
   661 		{KMMCStatErrCSDOverwrite|KMMCStatErrWPViolation,		KErrWrite},
       
   662 		{KMMCStatErrLockUnlock,									KErrLocked},
       
   663 		{KMMCStatErrIllegalCommand,								KErrNotSupported},
       
   664 		{KMMCStatErrEraseParam|KMMCStatErrEraseSeqError|
       
   665 			KMMCStatErrBlockLenError|KMMCStatErrAddressError|
       
   666 			KMMCStatErrOutOfRange,								KErrArgument},
       
   667 		{~0UL,													KErrUnknown}
       
   668 		};
       
   669 
       
   670 	TUint32 errCode = MMCExitCode();
       
   671 
       
   672 	if( errCode == 0 )
       
   673 		return KErrNone;
       
   674 
       
   675 	const errorTableEntry* ptr = &mmcTable[0];
       
   676 
       
   677 	if( errCode == KMMCErrStatus )
       
   678 		{
       
   679 		ptr = &statusTable[0];
       
   680 
       
   681 		if( (errCode = LastStatus()) == 0 )
       
   682 			return( KErrUnknown );
       
   683 		}
       
   684 
       
   685 	for( ;; )
       
   686 		if( (errCode & ptr->iMask) != 0 )
       
   687 			return( ptr->iErrorCode );
       
   688 		else
       
   689 			ptr++;
       
   690 	}