os/kernelhwsrv/kernel/eka/drivers/pbus/mmc/session.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/drivers/pbus/mmc/session.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,779 @@
     1.4 +// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include <drivers/mmc.h>
    1.20 +#include "OstTraceDefinitions.h"
    1.21 +#ifdef OST_TRACE_COMPILER_IN_USE
    1.22 +#include "locmedia_ost.h"
    1.23 +#ifdef __VC32__
    1.24 +#pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
    1.25 +#endif
    1.26 +#include "sessionTraces.h"
    1.27 +#endif
    1.28 +
    1.29 +
    1.30 +
    1.31 +//	--------  class DMMCSession  --------
    1.32 +
    1.33 +EXPORT_C DMMCSession::DMMCSession(const TMMCCallBack& aCallBack)
    1.34 +/**
    1.35 + * Constructor - initializes callbacks and timers.
    1.36 + * Once the session has been engaged, the completion of the request is signalled by calling 
    1.37 + * the function provided in aCallback. A session will be completed in this way if it has completed
    1.38 + * normally, an error has occurred or the session has been stopped by this or another client.
    1.39 + * @param aCallBack reference to a TMMCCallback object to be called upon completion.
    1.40 + */
    1.41 +	: iCallBack(aCallBack),
    1.42 +#ifdef __EPOC32__
    1.43 +	iPollTimer(DMMCSession::PollTimerCallBack, this),
    1.44 +	iRetryTimer(DMMCSession::RetryTimerCallBack, this),
    1.45 +	iProgramTimer(DMMCSession::ProgramTimerCallBack, this),
    1.46 +#endif	// #ifdef __EPOC32__
    1.47 +	iConfig()
    1.48 +	{
    1.49 +	OstTraceFunctionEntry1( DMMCSESSION_DMMCSESSION_ENTRY, this );
    1.50 +	}
    1.51 +
    1.52 +EXPORT_C DMMCSession::~DMMCSession()
    1.53 +/**
    1.54 + * Destructor.
    1.55 + */
    1.56 +	{
    1.57 +	OstTraceFunctionEntry1( DUP1_DMMCSESSION_DMMCSESSION_ENTRY, this );
    1.58 +	// Ensure that the stack isn't currently running in another thread's context, otherwise this session won't be 
    1.59 +	// removed from the stack's workset until some time later - by which time the session will have been deleted
    1.60 +	__ASSERT_ALWAYS(!iStackP->StackRunning(), DMMCSocket::Panic(DMMCSocket::EMMCNotInDfcContext));
    1.61 +	Abort();
    1.62 +	UnlockStack();
    1.63 +	OstTraceFunctionExit1( DUP1_DMMCSESSION_DMMCSESSION_EXIT, this );
    1.64 +	}
    1.65 +
    1.66 +EXPORT_C void DMMCSession::SetCard(TMMCard* aCardP)
    1.67 +/**
    1.68 + * Assigns a card to the session. The card pointer would normally be obtained via a call of DMMCStack::CardP(). 
    1.69 + * Assigning a card to the session is the means by which a particular card in the stack is targeted for a 
    1.70 + * particular request. Some requests involve broadcasting to the entire stack. However, the majority involve 
    1.71 + * an individual card at some stage of the process and so an attempt to engage the session before a card has 
    1.72 + * been assigned to it will generally fail straight away. It is possible to change the card assigned to the 
    1.73 + * session as long as this is not attempted while the session is engaged.
    1.74 + * @param aCardP A pointer to the card to be assigned to the session.
    1.75 + */
    1.76 +	{
    1.77 +	OstTraceFunctionEntryExt( DMMCSESSION_SETCARD_ENTRY, this );
    1.78 +	iCardP = aCardP;
    1.79 +	iCID = iCardP->CID();
    1.80 +	OstTraceFunctionExit1( DMMCSESSION_SETCARD_EXIT, this );
    1.81 +	}
    1.82 +
    1.83 +EXPORT_C void DMMCSession::SetupCIMReadBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP)
    1.84 +/**
    1.85 + * Sets the session up to perform the CIM_READ_BLOCK macro as outlined by the MMCA. 
    1.86 + * Having set-up the session for this operation, the client must then engage the session before the operation can commence. 
    1.87 + * The CIM_READ_BLOCK macro reads a single block from the card. It starts by setting the block length (CMD16) as specified 
    1.88 + * in 'aLength'. It then reads a single block of data (CMD17) from the card at offset 'aDevAddr' on the card into system 
    1.89 + * memory starting at address 'aMemoryP'.
    1.90 + * @param aDevAddr Contains offset to the block to be read from the card
    1.91 + * @param aLength Block length
    1.92 + * @param aMemoryP host destination address
    1.93 + */
    1.94 +	{
    1.95 +	OstTraceExt4(TRACE_FLOW, DMMCSESSION_SETUPCIMREADBLOCK_ENTRY, "DMMCSession::SetupCIMReadBlock;aDevAddr=%x;aLength=%x;aMemoryP=%x;this=%x", (TUint) aDevAddr, (TUint) aLength, (TUint) aMemoryP, (TUint) this);
    1.96 +	ResetCommandStack();
    1.97 +	FillCommandArgs(aDevAddr, aLength, aMemoryP, aLength);
    1.98 +	iSessionID = ECIMReadBlock;
    1.99 +	OstTraceFunctionExit1( DMMCSESSION_SETUPCIMREADBLOCK_EXIT, this );
   1.100 +	}
   1.101 +
   1.102 +EXPORT_C void DMMCSession::SetupCIMWriteBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP)
   1.103 +/**
   1.104 + * Set up the session to perform the CIM_WRITE_BLOCK macro as outlined by the MMCA.
   1.105 + * Having set-up the session for this operation, the client must then engage the session before the operation can commence. 
   1.106 + * The CIM_WRITE_BLOCK macro writes a single block to the card. It starts by setting the block length (CMD16) as specified 
   1.107 + * in 'aLength'. It then writes a single block of data (CMD24) to the card at offset 'aDevAddr' on the card reading from system 
   1.108 + * memory starting at address 'aMemoryP'.
   1.109 + * @param aDevAddr Contains offset to the block to be written on the card
   1.110 + * @param aLength Block length
   1.111 + * @param aMemoryP Host source address
   1.112 + */
   1.113 +	{
   1.114 +	OstTraceExt4(TRACE_FLOW, DMMCSESSION_SETUPCIMWRITEBLOCK_ENTRY, "DMMCSession::SetupCIMWriteBlock;aDevAddr=%x;aLength=%x;aMemoryP=%x;this=%x", (TUint) aDevAddr, (TUint) aLength, (TUint) aMemoryP, (TUint) this);
   1.115 +	ResetCommandStack();
   1.116 +	FillCommandArgs(aDevAddr, aLength, aMemoryP, aLength);
   1.117 +	iSessionID = ECIMWriteBlock;
   1.118 +	OstTraceFunctionExit1( DMMCSESSION_SETUPCIMWRITEBLOCK_EXIT, this );
   1.119 +	}
   1.120 +
   1.121 +EXPORT_C void DMMCSession::SetupCIMReadMBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP, TUint32 aBlkLen)
   1.122 +/**
   1.123 + * Set up the session to perform the CIM_READ_MBLOCK macro as outlined by the MMCA.
   1.124 + * Having set-up the session for this operation, the client must then engage the session before the operation can commence. 
   1.125 + * The CIM_READ_MBLOCK macro reads a series of blocks from the card. It starts by setting the block length (CMD16) as specified 
   1.126 + * in 'aBlkLen'. It then issues the read multiple block command (CMD18) to continually transfer blocks from the card to host 
   1.127 + * starting at offset 'aDevAddr' on the card into system memory starting at address 'aMemoryP'. This continues until 'aLength'
   1.128 + * bytes have been read at which point the Controller issues the stop command (CMD12) to halt the transfer.
   1.129 + * @param aDevAddr Contains offset to the block to be read from the card
   1.130 + * @param aLength Total number of bytes to read.
   1.131 + * @param aMemoryP Host destination address
   1.132 + * @param aBlkLen Block length
   1.133 + */
   1.134 +	{
   1.135 +	OstTraceExt5(TRACE_FLOW, DMMCSESSION_SETUPCIMREADMBLOCK_ENTRY, "DMMCSession::SetupCIMReadMBlock;aDevAddr=%x;aLength=%x;aMemoryP=%x;aBlkLen=%x;this=%x", (TUint) aDevAddr, (TUint) aLength, (TUint) aMemoryP, (TUint) aBlkLen,(TUint) this);
   1.136 +	ResetCommandStack();
   1.137 +	FillCommandArgs(aDevAddr, aLength, aMemoryP, aBlkLen);
   1.138 +	iSessionID = ECIMReadMBlock;
   1.139 +	OstTraceFunctionExit1( DMMCSESSION_SETUPCIMREADMBLOCK_EXIT, this );
   1.140 +	}
   1.141 +
   1.142 +EXPORT_C void DMMCSession::SetupCIMWriteMBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP, TUint32 aBlkLen)
   1.143 +/**
   1.144 + * Set up the session to perform the CIM_WRITE_MBLOCK macro as outlined by the MMCA.
   1.145 + * Having set-up the session for this operation, the client must then engage the session before the operation can commence. 
   1.146 + * The CIM_WRITE_MBLOCK macro writes a series of blocks to the card. It starts by setting the block length (CMD16) as specified 
   1.147 + * in 'aBlkLen'. It then issues the write multiple block command (CMD25) to continually transfer blocks from host to the card 
   1.148 + * starting at address 'aMemoryP' in system memory and offset 'aDevAddr' on the card.. This continues until 'aLength' bytes have 
   1.149 + * been written at which point the Controller issues the stop command (CMD12) to halt the transfer
   1.150 + * @param aDevAddr Contains offset to the block to be written on the card
   1.151 + * @param aLength Total number of bytes to write.
   1.152 + * @param aMemoryP Host source address
   1.153 + * @param aBlkLen Block length
   1.154 + */
   1.155 +	{
   1.156 +	OstTraceExt5(TRACE_FLOW, DMMCSESSION_SETUPCIMWRITEMBLOCK_ENTRY, "DMMCSession::SetupCIMWriteMBlock;aDevAddr=%x;aLength=%x;aMemoryP=%x;aBlkLen=%x;this=%x", (TUint) aDevAddr, (TUint) aLength, (TUint) aMemoryP, (TUint) aBlkLen,(TUint) this);
   1.157 +	ResetCommandStack();
   1.158 +	FillCommandArgs(aDevAddr, aLength, aMemoryP, aBlkLen);
   1.159 +	iSessionID = ECIMWriteMBlock;
   1.160 +	OstTraceFunctionExit1( DMMCSESSION_SETUPCIMWRITEMBLOCK_EXIT, this );
   1.161 +	}
   1.162 +
   1.163 +EXPORT_C void DMMCSession::SetupCIMEraseSector(TMMCArgument aDevAddr, TUint32 aLength)
   1.164 +/**
   1.165 + * Set up the session to perform the CIM_ERASE_SECTOR macro broadly as outlined by the MMCA. 
   1.166 + * However, the macro only performs a sector erase of a contiguous area and doesn't support the un-tagging of particular sectors 
   1.167 + * within the initial tagged area. Having set-up the session for this operation, the client must then engage the session before 
   1.168 + * the operation can commence. 
   1.169 + * The CIM_ERASE_SECTOR macro erases a range of sectors on the card starting at offset 'aDevAddr' on the card and ending at offset 
   1.170 + * 'aDevAdd'+'aLength'. The entire area specified must lie within a single erase group. (The erase group size can be read from the CSD).
   1.171 + * The specified start offset and end offset need not coincide exactly with a sector boundary since the card will ignore LSBs below 
   1.172 + * the sector size. The tag sector start command (CMD32) is first issued setting the address of the first sector to be erased. 
   1.173 + * This is followed by the tag sector end command (CMD33) setting the address of the last sector to be erased. Now that the erase 
   1.174 + * sectors are tagged, the erase command (CMD38) is sent followed by a send status command (CMD13) to read any additional status 
   1.175 + * information from the card.
   1.176 + * @param aDevAddr Contains offset to the first block to be erased
   1.177 + * @param aLength Total number of bytes to erase
   1.178 + */
   1.179 +	{
   1.180 +	OstTraceExt3(TRACE_FLOW, DMMCSESSION_SETUPCIMERASESECTOR_ENTRY, "DMMCSession::SetupCIMEraseSector;aDevAddr=%x;aLength=%x;this=%x", (TUint) aDevAddr, (TUint) aLength, (TUint) this);
   1.181 +	ResetCommandStack();
   1.182 +	FillCommandArgs(aDevAddr, aLength, NULL, 0);
   1.183 +	iSessionID = ECIMEraseSector;
   1.184 +	OstTraceFunctionExit1( DMMCSESSION_SETUPCIMERASESECTOR_EXIT, this );
   1.185 +	}
   1.186 +
   1.187 +EXPORT_C void DMMCSession::SetupCIMEraseGroup(TMMCArgument aDevAddr, TUint32 aLength)
   1.188 +/**
   1.189 + * Set up the session to perform the CIM_ERASE_GROUP macro broadly as outlined by the MMCA. 
   1.190 + * However, the macro only performs an erase group erase of a contiguous area and doesn't support the un-tagging of particular 
   1.191 + * erase groups within the initial tagged area. Having set-up the session for this operation, the client must then engage the 
   1.192 + * session before the operation can commence. 
   1.193 + * The CIM_ERASE_GROUP macro erases a range of erase groups on the card starting at offset 'aDevAddr' on the card and ending at 
   1.194 + * offset 'aDevAdd'+'aLength'. The specified start offset and end offset need not coincide exactly with an erase group boundary 
   1.195 + * since the card will ignore LSBs below the erase group size. The tag ease group start command (CMD35) is first issued setting 
   1.196 + * the address of the first erase group to be erased. This is followed by the tag erase group end command (CMD36) setting the 
   1.197 + * address of the last erase group to be erased. Now that the erase groups are tagged, the erase command (CMD38) is sent followed 
   1.198 + * by a send status command (CMD13) to read any additional status information from the card.
   1.199 + * @param aDevAddr Contains offset to the first block to be erased
   1.200 + * @param aLength Total number of bytes to erase
   1.201 + */
   1.202 +	{
   1.203 +	OstTraceExt3(TRACE_FLOW, DMMCSESSION_SETUPCIMERASEGROUP_ENTRY, "DMMCSession::SetupCIMEraseGroup;aDevAddr=%x;aLength=%x;this=%x", (TUint) aDevAddr, (TUint) aLength, (TUint) this);
   1.204 +	ResetCommandStack();
   1.205 +	FillCommandArgs(aDevAddr, aLength, NULL, 0);
   1.206 +	iSessionID = ECIMEraseGroup;
   1.207 +	OstTraceFunctionExit1( DMMCSESSION_SETUPCIMERASEGROUP_EXIT, this );
   1.208 +	}
   1.209 +
   1.210 +EXPORT_C void DMMCSession::SetupCIMReadIO(TUint8 aRegAddr, TUint32 aLength, TUint8* aMemoryP)
   1.211 +/** 
   1.212 + * Set up the session to perform the read i/o macro (CMD39).
   1.213 + * 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, 
   1.214 + * reading 'aLength' bytes of data from I/O register 'aRegAddr' on the card into system memory starting at address 'aMemoryP'. 
   1.215 + * Having set-up the session for this operation, the client must then engage the session before the operation can commence. 
   1.216 + * @param aRegAddr Address of IO register
   1.217 + * @param aLength Total number of bytes to read
   1.218 + * @param aMemoryP Host destination address
   1.219 + */
   1.220 +	{
   1.221 +	OstTraceFunctionEntryExt( DMMCSESSION_SETUPCIMREADIO_ENTRY, this );
   1.222 +	ResetCommandStack();
   1.223 +	FillCommandArgs(aRegAddr, aLength, aMemoryP, 0);
   1.224 +	iSessionID = ECIMReadIO;
   1.225 +	OstTraceFunctionExit1( DMMCSESSION_SETUPCIMREADIO_EXIT, this );
   1.226 +	}
   1.227 +
   1.228 +EXPORT_C void DMMCSession::SetupCIMWriteIO(TUint8 aRegAddr, TUint32 aLength, TUint8* aMemoryP)
   1.229 +/** 
   1.230 + * Set up the session to perform the write i/o macro (CMD39). 
   1.231 + * 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,
   1.232 + * writing 'aLength' bytes of data to I/O register 'aRegAddr' on the card from system memory starting at address 'aMemoryP'. 
   1.233 + * Having set-up the session for this operation, the client must then engage the session before the operation can commence. 
   1.234 + * @param aRegAddr Address of IO register
   1.235 + * @param aLength Total number of bytes to write
   1.236 + * @param aMemoryP Host source address
   1.237 + */
   1.238 +	{
   1.239 +	OstTraceFunctionEntryExt( DMMCSESSION_SETUPCIMWRITEIO_ENTRY, this );
   1.240 +	ResetCommandStack();
   1.241 +	FillCommandArgs(aRegAddr, aLength, aMemoryP, 0);
   1.242 +	iSessionID = ECIMWriteIO;
   1.243 +	OstTraceFunctionExit1( DMMCSESSION_SETUPCIMWRITEIO_EXIT, this );
   1.244 +	}
   1.245 +
   1.246 +EXPORT_C void DMMCSession::SetupCIMLockUnlock(TUint32 aLength, TUint8* aMemoryP)
   1.247 +/**
   1.248 + * Set up the session to perform the lock-unlock macro (CMD42). 
   1.249 + * This macro is used to manage the password protection feature (if supported) on a MultiMediaCard. 
   1.250 + * This same macro is used to lock or unlock a card, set or clear a password or force erase a card.  
   1.251 + * Having set-up the session for the required operation, the client must then engage the session before 
   1.252 + * the operation can commence. 
   1.253 + * The block length (CMD16) as specified in 'aLength' is first set. The lock unlock command (CMD42) is 
   1.254 + * then issued. This command has the same structure as a regular single block write command. 
   1.255 + * A data block is written to the card from system memory starting at address 'aMemoryP'. The transferred 
   1.256 + * data block should contain the password setting mode, the password length and the password data if appropriate.
   1.257 + * @param aLength Block length
   1.258 + * @param aMemoryP Host source address containing password data
   1.259 + */
   1.260 +	{
   1.261 +	OstTraceFunctionEntryExt( DMMCSESSION_SETUPCIMLOCKUNLOCK_ENTRY, this );
   1.262 +	__KTRACE_OPT(KPBUS1, Kern::Printf("ms:slu%08x", aLength));
   1.263 +
   1.264 +	ResetCommandStack();
   1.265 +	FillCommandDesc(ECmdLockUnlock);
   1.266 +	FillCommandArgs(0, aLength, aMemoryP, aLength);
   1.267 +	iSessionID = ECIMLockUnlock;
   1.268 +	OstTraceFunctionExit1( DMMCSESSION_SETUPCIMLOCKUNLOCK_EXIT, this );
   1.269 +	}
   1.270 +
   1.271 +EXPORT_C void DMMCSession::SetupCommand(TMMCCommandEnum aCommand, TMMCArgument anArgument)
   1.272 +/** 
   1.273 + * Set up the session to issue a raw command to the card. 
   1.274 + * This raw command function should be used when issuing a known command with or without an argument. 
   1.275 + * Having set-up the session for this operation, the client must then engage this session before 
   1.276 + * the operation can commence.
   1.277 + * @param aCommand Command to be sent
   1.278 + * @param anArgument Associated argument
   1.279 + */
   1.280 +	{
   1.281 +	OstTraceExt3(TRACE_FLOW, DMMCSESSION_SETUPCOMMAND_ENTRY, "DMMCSession::SetupCommand;aCommand=%d;anArgument=%x;this=%x", (TInt) aCommand, (TUint) anArgument, (TUint) this);
   1.282 +	ResetCommandStack();
   1.283 +	FillCommandDesc(aCommand, anArgument);
   1.284 +	iSessionID = ECIMNakedSession;
   1.285 +	OstTraceFunctionExit1( DMMCSESSION_SETUPCOMMAND_EXIT, this );
   1.286 +	}
   1.287 +
   1.288 +EXPORT_C void DMMCSession::SetupRSCommand(TMMCCommandEnum aCommand, TMMCArgument anArgument,
   1.289 +							TUint32 aResponseLength, TMMCCommandTypeEnum aCommandType,
   1.290 +							TMMCResponseTypeEnum aResponseType,
   1.291 +							TUint32 aCommandClass)
   1.292 +/**
   1.293 + * Set up the session to issue a raw command to the card. 
   1.294 + * This raw command function should be used when issuing an unknown command, an argument and an unknown response type.
   1.295 + * Having set-up the session for this operation, the client must then engage this session before the operation can commence.
   1.296 + * @param aCommand
   1.297 + * @param anArgument
   1.298 + * @param aResponseLength
   1.299 + * @param aCommandType
   1.300 + * @param aResponseType
   1.301 + * @param aCommandClass
   1.302 + * @todo Complete the parameter descriptions
   1.303 + */
   1.304 +	{
   1.305 +	OstTraceExt4( TRACE_FLOW, DMMCSESSION_SETUPRSCOMMAND_ENTRY1, "DMMCSession::SetupRSCommand;aCommand=%d;anArgument=%x;aResponseLength=%x;this=%x", (TInt) aCommand, (TUint) anArgument, (TUint) aResponseLength, (TUint) this );
   1.306 +	OstTraceExt4( TRACE_FLOW, DMMCSESSION_SETUPRSCOMMAND_ENTRY2, "DMMCSession::SetupRSCommand;aCommandType=%d;aResponseType=%d;aCommandClass=%x;this=%x", (TInt) aCommandType, (TInt) aResponseType, (TUint) aCommandClass, (TUint) this );
   1.307 +	ResetCommandStack();
   1.308 +	FillCommandDesc(aCommand, anArgument);
   1.309 +	TMMCCommandSpec& cmdSpec = Command().iSpec;
   1.310 +	cmdSpec.iDirection = EDirNone;
   1.311 +
   1.312 +	if( aResponseLength <= KMMCMaxResponseLength )
   1.313 +		cmdSpec.iResponseLength = aResponseLength;
   1.314 +
   1.315 +	if( aCommandType != ECmdTypeUK )
   1.316 +		cmdSpec.iCommandType = aCommandType;
   1.317 +
   1.318 +	if( aResponseType != ERespTypeUnknown )
   1.319 +		cmdSpec.iResponseType = aResponseType;
   1.320 +
   1.321 +	if( aCommandClass != KMMCCmdClassNone )
   1.322 +		cmdSpec.iCommandClass = aCommandClass;
   1.323 +
   1.324 +	iSessionID = ECIMNakedSession;
   1.325 +	OstTraceFunctionExit1( DMMCSESSION_SETUPRSCOMMAND_EXIT, this );
   1.326 +	}
   1.327 +
   1.328 +EXPORT_C void DMMCSession::SetupDTCommand(TMMCCommandEnum aCommand, TMMCArgument anArgument,
   1.329 +							TUint32 aTotalLength, TUint8* aMemoryAddress, TUint32 aBlockLength,
   1.330 +							TBool aStopTransmission, TMMCCmdDirEnum aDir,
   1.331 +							TUint32 aCommandClass)
   1.332 +/**
   1.333 + * Set up the session to issue a raw command to the card. 
   1.334 + * This raw command function should be used when issuing a generic transfer command and argument.
   1.335 + * Having set-up the session for this operation, the client must then engage this session before
   1.336 + * the operation can commence.
   1.337 + * @param aCommand
   1.338 + * @param anArgument
   1.339 + * @param aTotalLength
   1.340 + * @param aMemoryAddress
   1.341 + * @param aBlockLength
   1.342 + * @param aStopTransmission
   1.343 + * @param aDir
   1.344 + * @param aCommandClass
   1.345 + * @todo Complete the parameter descriptions
   1.346 + */
   1.347 +	{
   1.348 +	OstTraceExt5( TRACE_FLOW, DMMCSESSION_SETUPDTCOMMAND_ENTRY1, "DMMCSession::SetupDTCommand;aCommand=%d;anArgument=%x;aTotalLength=%x;aMemoryAddress=%x;this=%x", (TInt) aCommand, (TUint) anArgument, (TUint) aTotalLength, (TUint) aMemoryAddress, (TUint) this );
   1.349 +	OstTraceExt5( TRACE_FLOW, DMMCSESSION_SETUPDTCOMMAND_ENTRY2, "DMMCSession::SetupDTCommand;aBlockLength=%x;aStopTransmission=%d;aDir=%d;aCommandClass=%x;this=%x", (TUint) aBlockLength, (TInt) aStopTransmission, (TInt) aDir, (TUint) aCommandClass , (TUint) this );
   1.350 +	ResetCommandStack();
   1.351 +	FillCommandDesc(aCommand);
   1.352 +	FillCommandArgs(anArgument, aTotalLength, aMemoryAddress, aBlockLength);
   1.353 +	TMMCCommandDesc& cmd = Command();
   1.354 +
   1.355 +	if( aBlockLength == 0 )
   1.356 +		cmd.iBlockLength = aTotalLength;
   1.357 +
   1.358 +	cmd.iSpec.iMultipleBlocks = (cmd.iBlockLength != aTotalLength);
   1.359 +
   1.360 +	if( aStopTransmission )
   1.361 +		cmd.iSpec.iUseStopTransmission = ETrue;
   1.362 +
   1.363 +	if( aDir != EDirNone )
   1.364 +		{
   1.365 +		cmd.iSpec.iUseStopTransmission = aStopTransmission;
   1.366 +		cmd.iSpec.iDirection = aDir;
   1.367 +		}
   1.368 +
   1.369 +	if( aCommandClass != KMMCCmdClassNone )
   1.370 +		cmd.iSpec.iCommandClass = aCommandClass;
   1.371 +
   1.372 +	iSessionID = ECIMNakedSession;
   1.373 +	OstTraceFunctionExit1( DMMCSESSION_SETUPDTCOMMAND_EXIT, this );
   1.374 +	}
   1.375 +
   1.376 +void DMMCSession::SetupCIMControl(TInt aSessID)
   1.377 +//
   1.378 +// find matching macro function for supplied session
   1.379 +//
   1.380 +	{
   1.381 +	OstTraceFunctionEntryExt( DMMCSESSION_SETUPCIMCONTROL_ENTRY, this );
   1.382 +	TMMCSMSTFunc f = GetMacro(aSessID);
   1.383 +
   1.384 +	if (f == 0)
   1.385 +		f = DMMCStack::NoSessionSMST;
   1.386 +
   1.387 +	iSessionID = (TMMCSessionTypeEnum) aSessID;
   1.388 +	iBytesTransferred = 0;
   1.389 +	iMMCExitCode = KMMCErrNone;
   1.390 +	iState = 0;
   1.391 +	iInitContext = 0;
   1.392 +	iGlobalRetries = 0;
   1.393 +	iDoAbort = iDoStop = iDoComplete = EFalse;
   1.394 +	iBlockOn = 0;
   1.395 +
   1.396 +	ResetCommandStack();
   1.397 +
   1.398 +	iMachine.Setup(f, iStackP);
   1.399 +	OstTraceFunctionExit1( DMMCSESSION_SETUPCIMCONTROL_EXIT, this );
   1.400 +	}
   1.401 +
   1.402 +EXPORT_C TMMCSMSTFunc DMMCSession::GetMacro(TInt aSessNum) const
   1.403 +	{
   1.404 +	TMMCSMSTFunc f = 0;
   1.405 +
   1.406 +	static const TMMCSMSTFunc macros[KMMCMaxSessionTypeNumber] =
   1.407 +		{
   1.408 +		DMMCStack::NakedSessionSMST,
   1.409 +		DMMCStack::CIMUpdateAcqSMST,
   1.410 +		DMMCStack::CIMInitStackSMST,
   1.411 +		DMMCStack::CIMCheckStackSMST,
   1.412 +		DMMCStack::CIMSetupCardSMST,
   1.413 +		DMMCStack::CIMReadWriteBlocksSMST,			// CIMReadBlock
   1.414 +		DMMCStack::CIMReadWriteBlocksSMST,			// CIMWriteBlock
   1.415 +		DMMCStack::CIMReadWriteBlocksSMST,			// CIMReadMBlock
   1.416 +		DMMCStack::CIMReadWriteBlocksSMST,			// CIMWriteMBlock
   1.417 +		DMMCStack::CIMEraseSMST,
   1.418 +		DMMCStack::CIMEraseSMST,
   1.419 +		DMMCStack::CIMReadWriteIOSMST,
   1.420 +		DMMCStack::CIMReadWriteIOSMST,
   1.421 +		DMMCStack::CIMLockUnlockSMST,				// CIMLockUnlock
   1.422 +		DMMCStack::NoSessionSMST,					// CIMLockStack is never really executed as a session
   1.423 +		DMMCStack::InitStackAfterUnlockSMST,
   1.424 +		DMMCStack::CIMAutoUnlockSMST,
   1.425 +		DMMCStack::ExecSleepCommandSMST				// CIMSleep
   1.426 +		};
   1.427 +
   1.428 +	if (aSessNum >= 0 && aSessNum < (TInt) KMMCMaxSessionTypeNumber)
   1.429 +		f = macros[aSessNum];
   1.430 +
   1.431 +	return f;
   1.432 +	}
   1.433 +
   1.434 +EXPORT_C TInt DMMCSession::Engage()
   1.435 +/**
   1.436 + * Enque this session for execution on the DMMCStack object which is serving it.
   1.437 + * @return KErrBadDriver if no stack is associated with the session
   1.438 + * @return KErrServerBusy if the stack is currently locked (and KMMCModeEnqueIfLocked flag is cleared)
   1.439 + * @return KErrNotReady if the media is not present
   1.440 + * @return KErrNone if successful
   1.441 + */
   1.442 +	{
   1.443 +	OstTraceFunctionEntry1( DMMCSESSION_ENGAGE_ENTRY, this );
   1.444 +	__KTRACE_OPT(KPBUS1,Kern::Printf(">ms:eng"));
   1.445 +
   1.446 +	if( iStackP == NULL )
   1.447 +	    {
   1.448 +		OstTraceFunctionExitExt( DMMCSESSION_ENGAGE_EXIT, this, KErrBadDriver );
   1.449 +		return KErrBadDriver;
   1.450 +	    }
   1.451 +
   1.452 +	if( iStackP->iLockingSessionP != NULL && iStackP->iLockingSessionP != this &&
   1.453 +		(iStackP->EffectiveModes(iConfig) & KMMCModeEnqueIfLocked) == 0 )
   1.454 +	    {
   1.455 +		OstTraceFunctionExitExt( DUP1_DMMCSESSION_ENGAGE_EXIT, this, KErrServerBusy );
   1.456 +		return KErrServerBusy;
   1.457 +	    }
   1.458 +
   1.459 +	const TMediaState doorState=iStackP->MMCSocket()->iMediaChange->MediaState();
   1.460 +
   1.461 +	__KTRACE_OPT(KPBUS1,Kern::Printf(">MMC:Eng ds = %x", doorState));
   1.462 +	OstTrace1( TRACE_INTERNALS, DMMCSESSION_ENGAGE, "doorState = 0x%x", doorState);
   1.463 +
   1.464 +	if (doorState == EDoorOpen)
   1.465 +	    {
   1.466 +		OstTraceFunctionExitExt( DUP2_DMMCSESSION_ENGAGE_EXIT, this, KErrNotReady );
   1.467 +		return KErrNotReady;
   1.468 +	    }
   1.469 +
   1.470 +	SetupCIMControl(iSessionID);
   1.471 +
   1.472 +	iStackP->Add(this);
   1.473 +
   1.474 +	__KTRACE_OPT(KPBUS1,Kern::Printf("<ms:eng"));
   1.475 +	OstTraceFunctionExitExt( DUP3_DMMCSESSION_ENGAGE_EXIT, this, KErrNone );
   1.476 +	return KErrNone;
   1.477 +	}
   1.478 +
   1.479 +// Command specification table for standard MMC commands (CMD0 - CMD63)
   1.480 +extern const TMMCCommandSpec CommandTable[KMMCCommandMask+1] =
   1.481 +	{//  Class				  Type			Dir			MBlk	StopT	Rsp Type		  Len	Cmd No
   1.482 +	{KMMCCmdClassBasic,		ECmdTypeBC,		EDirNone,	EFalse, EFalse, ERespTypeNone,		0}, //CMD0
   1.483 +	{KMMCCmdClassBasic,		ECmdTypeBCR,	EDirNone,	EFalse, EFalse, ERespTypeR3,		4}, //CMD1
   1.484 +	{KMMCCmdClassBasic,		ECmdTypeBCR,	EDirNone,	EFalse, EFalse, ERespTypeR2,		16},//CMD2
   1.485 +	{KMMCCmdClassBasic,		ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD3
   1.486 +	{KMMCCmdClassBasic,		ECmdTypeBC,		EDirNone,	EFalse, EFalse, ERespTypeNone,		0}, //CMD4
   1.487 +	{KMMCCmdClassBasic,		ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeR1B,		0}, //CMD5 - SLEEP/AWAKE
   1.488 +	{KMMCCmdClassBasic,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1B,		0}, //CMD6
   1.489 +	{KMMCCmdClassBasic,		ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeR1B,		4}, //CMD7
   1.490 +	{KMMCCmdClassBasic,		ECmdTypeADTCS,	EDirRead,	EFalse, EFalse, ERespTypeR1,		512}, //CMD8
   1.491 +	{KMMCCmdClassBasic,		ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeR2,		16},//CMD9
   1.492 +	{KMMCCmdClassBasic,		ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeR2,		16},//CMD10
   1.493 +	{KMMCCmdClassStreamRead,ECmdTypeADTCS,	EDirRead,	EFalse, ETrue,	ERespTypeR1,		4}, //CMD11
   1.494 +	{KMMCCmdClassBasic,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1B,		4}, //CMD12
   1.495 +	{KMMCCmdClassBasic,		ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD13
   1.496 +	{KMMCCmdClassBlockRead,	ECmdTypeADTCS,	EDirRead,	EFalse, EFalse, ERespTypeR1,		4}, //CMD14 - BUSTEST_R
   1.497 +	{KMMCCmdClassBasic,		ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeNone,		0}, //CMD15
   1.498 +	{KMMCCmdClassBlockRead,	ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD16
   1.499 +	{KMMCCmdClassBlockRead,	ECmdTypeADTCS,	EDirRead,	EFalse, EFalse, ERespTypeR1,		4}, //CMD17
   1.500 +	{KMMCCmdClassBlockRead,	ECmdTypeADTCS,	EDirRead,	ETrue,	ETrue,	ERespTypeR1,		4}, //CMD18
   1.501 +	{KMMCCmdClassBlockWrite,ECmdTypeADTCS,	EDirWrite,	EFalse, EFalse, ERespTypeR1,		4}, //CMD19 - BUSTEST_W
   1.502 +	{KMMCCmdClassStreamWrite,ECmdTypeADTCS, EDirWrite,	EFalse, ETrue,	ERespTypeR1,		4}, //CMD20
   1.503 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD21
   1.504 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD22
   1.505 +	{KMMCCmdClassBlockRead | 
   1.506 +	 KMMCCmdClassBlockWrite,ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,	4}, //CMD23
   1.507 +	{KMMCCmdClassBlockWrite,ECmdTypeADTCS,	EDirWrite,	EFalse, EFalse, ERespTypeR1,		4}, //CMD24
   1.508 +	{KMMCCmdClassBlockWrite,ECmdTypeADTCS,	EDirWrite,	ETrue,	ETrue,	ERespTypeR1,		4}, //CMD25
   1.509 +	{KMMCCmdClassBlockWrite,ECmdTypeADTCS,	EDirWrite,	EFalse, EFalse, ERespTypeR1,		4}, //CMD26
   1.510 +	{KMMCCmdClassBlockWrite,ECmdTypeADTCS,	EDirWrite,	EFalse, EFalse, ERespTypeR1,		4}, //CMD27
   1.511 +	{KMMCCmdClassWriteProtection,ECmdTypeACS,EDirNone,	EFalse, EFalse, ERespTypeR1B,		4}, //CMD28
   1.512 +	{KMMCCmdClassWriteProtection,ECmdTypeACS,EDirNone,	EFalse, EFalse, ERespTypeR1B,		4}, //CMD29
   1.513 +	{KMMCCmdClassWriteProtection,ECmdTypeADTCS,EDirRead,EFalse, EFalse, ERespTypeR1,		4}, //CMD30
   1.514 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD31
   1.515 +	{KMMCCmdClassErase,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD32
   1.516 +	{KMMCCmdClassErase,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD33
   1.517 +	{KMMCCmdClassErase,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD34
   1.518 +	{KMMCCmdClassErase,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD35
   1.519 +	{KMMCCmdClassErase,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD36
   1.520 +	{KMMCCmdClassErase,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD37
   1.521 +	{KMMCCmdClassErase,		ECmdTypeACS,	EDirNone,	EFalse, EFalse, ERespTypeR1B,		4}, //CMD38
   1.522 +	{KMMCCmdClassIOMode,	ECmdTypeAC,		EDirNone,	EFalse, EFalse, ERespTypeR4,		4}, //CMD39
   1.523 +	{KMMCCmdClassIOMode,	ECmdTypeBCR,	EDirNone,	EFalse, EFalse, ERespTypeR5,		4}, //CMD40
   1.524 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD41
   1.525 +	{KMMCCmdClassLockCard,	ECmdTypeADTCS,	EDirWrite,	EFalse, EFalse, ERespTypeR1B,		4}, //CMD42
   1.526 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD43
   1.527 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD44
   1.528 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD45
   1.529 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD46
   1.530 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD47
   1.531 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD48
   1.532 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD49
   1.533 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD50
   1.534 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD51
   1.535 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD52
   1.536 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD53
   1.537 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD54
   1.538 +	{KMMCCmdClassApplication,ECmdTypeAC,	EDirNone,	EFalse, EFalse, ERespTypeR1,		4}, //CMD55
   1.539 +	{KMMCCmdClassApplication,ECmdTypeADTCS,	EDirRBit0,	EFalse, EFalse, ERespTypeR1B,		4}, //CMD56
   1.540 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD57
   1.541 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD58
   1.542 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD59
   1.543 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD60
   1.544 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD61
   1.545 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}, //CMD62
   1.546 +	{KMMCCmdClassNone,		ECmdTypeUK,		EDirNone,	EFalse, EFalse, ERespTypeUnknown,	0}	//CMD63
   1.547 +	};
   1.548 +
   1.549 +
   1.550 +EXPORT_C void DMMCSession::FillCommandDesc()
   1.551 +/**
   1.552 + * Fills the current command descriptor with the default data according to MMC spec V2.1
   1.553 + */
   1.554 +	{
   1.555 +	OstTraceFunctionEntry1( DMMCSESSION_FILLCOMMANDDESC1_ENTRY, this );
   1.556 +	TMMCCommandDesc& cmd = Command();
   1.557 +	cmd.iSpec = CommandTable[cmd.iCommand & KMMCCommandMask];
   1.558 +
   1.559 +	cmd.iFlags = 0;
   1.560 +	cmd.iBytesDone = 0;
   1.561 +	OstTraceFunctionExit1( DMMCSESSION_FILLCOMMANDDESC1_EXIT, this );
   1.562 +	}
   1.563 +
   1.564 +EXPORT_C void DMMCSession::FillCommandDesc(TMMCCommandEnum aCommand)
   1.565 +/**
   1.566 + * Initialises the current command according to whether it is a normal
   1.567 + * or an application command.
   1.568 + * @param aCommand Contains the command.
   1.569 + */
   1.570 +	{
   1.571 +	OstTraceExt2(TRACE_FLOW, DMMCSESSION_FILLCOMMANDDESC2_ENTRY, "DMMCSession::FillCommandDesc;aCommand=%d;this=%x", (TInt) aCommand, (TUint) this);
   1.572 +	Command().iCommand = aCommand;
   1.573 +	Command().iArgument = 0;					// set stuff bits to zero
   1.574 +	FillCommandDesc();
   1.575 +	OstTraceFunctionExit1( DMMCSESSION_FILLCOMMANDDESC2_EXIT, this );
   1.576 +	}
   1.577 +
   1.578 +EXPORT_C void DMMCSession::FillCommandDesc(TMMCCommandEnum aCommand, TMMCArgument anArgument)
   1.579 +/**
   1.580 + * Initialises the current command with an argument according to whether
   1.581 + * it is a normal or an application command.
   1.582 + * @param aCommand Contains the command.
   1.583 + * @param anArgument Specifies the argument.
   1.584 + */
   1.585 +	{
   1.586 +	OstTraceExt3(TRACE_FLOW, DMMCSESSION_FILLCOMMANDDESC3_ENTRY, "DMMCSession::FillCommandDesc;aCommand=%d;anArgument=%x;this=%x", (TInt) aCommand, (TUint) anArgument, (TUint) this);
   1.587 +	TMMCCommandDesc& cmd = Command();
   1.588 +	cmd.iCommand = aCommand;
   1.589 +	FillCommandDesc();
   1.590 +	cmd.iArgument = anArgument;
   1.591 +	OstTraceFunctionExit1( DMMCSESSION_FILLCOMMANDDESC3_EXIT, this );
   1.592 +	}
   1.593 +
   1.594 +EXPORT_C void DMMCSession::FillCommandArgs(TMMCArgument anArgument, TUint32 aLength, TUint8* aMemoryP,
   1.595 +								  TUint32 aBlkLen)
   1.596 +/**
   1.597 + * Initialises the current commands arguments with the specified parameters
   1.598 + * It is necessary to have set the command arguments with this command prior
   1.599 + * to engaging a read/write macro or command.
   1.600 + * @param anArgument Command specific argument.
   1.601 + * @param aLength aLength Total number of bytes to read/write.
   1.602 + * @param aMemoryP Host source/destination address
   1.603 + * @param aBlkLen Block length
   1.604 + */
   1.605 +	{
   1.606 +	OstTraceExt5(TRACE_FLOW, DMMCSESSION_FILLCOMMANDARGS_ENTRY ,"DMMCSession::FillCommandArgs;anArgument=%x;aLength=%x;aMemoryP=%x;aBlkLen=%x;this=%x", (TUint) anArgument, (TUint) aLength, (TUint) aMemoryP, (TUint) aBlkLen, (TUint) this);
   1.607 +	TMMCCommandDesc& cmd = Command();
   1.608 +
   1.609 +	cmd.iArgument = anArgument;
   1.610 +	cmd.iTotalLength = aLength;
   1.611 +	cmd.iDataMemoryP = aMemoryP;
   1.612 +	cmd.iBlockLength = aBlkLen;
   1.613 +	cmd.iFlags = 0;
   1.614 +	OstTraceFunctionExit1( DMMCSESSION_FILLCOMMANDARGS_EXIT, this );
   1.615 +	}
   1.616 +
   1.617 +const TMMCCommandSpec& DMMCSession::FindCommandSpec(const TMMCIdxCommandSpec aSpecs[], TInt aIdx)
   1.618 +/**
   1.619 + * Searches the supplied command specification list for the specification corresponding to the
   1.620 + * supplied command.
   1.621 + * @param aSpecs The command specification list to be searched.
   1.622 + * @param aIdx The requested command.
   1.623 + */
   1.624 +	{
   1.625 +	OstTraceFunctionEntry0( DMMCSESSION_FINDCOMMANDSPEC_ENTRY );	
   1.626 +	TInt i = 0;
   1.627 +	while (aSpecs[i].iIdx != aIdx)
   1.628 +		++i;
   1.629 +	OstTraceFunctionExit0( DMMCSESSION_FINDCOMMANDSPEC_EXIT );
   1.630 +	return aSpecs[i].iSpec;
   1.631 +	}
   1.632 +
   1.633 +void DMMCSession::SynchBlock(TUint32 aFlag)
   1.634 +//
   1.635 +// Blocks a session synchronously (within scheduler context)
   1.636 +//
   1.637 +	{
   1.638 +	OstTraceFunctionEntryExt( DMMCSESSION_SYNCHBLOCK_ENTRY, this );
   1.639 +	(void)__e32_atomic_ior_ord32(&iBlockOn, aFlag);
   1.640 +	OstTraceFunctionExit1( DMMCSESSION_SYNCHBLOCK_EXIT, this );
   1.641 +	}
   1.642 +
   1.643 +void DMMCSession::SynchUnBlock(TUint32 aFlag)
   1.644 +//
   1.645 +// Unblocks a session synchronously (within scheduler context)
   1.646 +//
   1.647 +	{
   1.648 +	OstTraceFunctionEntryExt( DMMCSESSION_SYNCHUNBLOCK_ENTRY, this );
   1.649 +	if( (iBlockOn & aFlag) == 0 )
   1.650 +	    {
   1.651 +		OstTraceFunctionExit1( DMMCSESSION_SYNCHUNBLOCK_EXIT, this );
   1.652 +		return;
   1.653 +	    }
   1.654 +
   1.655 +	(void)__e32_atomic_and_ord32(&iBlockOn, ~aFlag);
   1.656 +	OstTraceFunctionExit1( DUP1_DMMCSESSION_SYNCHUNBLOCK_EXIT, this );
   1.657 +	}
   1.658 +
   1.659 +EXPORT_C TRCA DMMCSession::CardRCA()
   1.660 +/**
   1.661 + * Checks that the card is still the same and ready
   1.662 + * @return A TRCA object containing the card's RCA (or 0 if the card is not ready)
   1.663 + */
   1.664 +	{
   1.665 +
   1.666 +	// Rely on 'CardIsGone' bit rather than a CID comparison	
   1.667 +	if ( iCardP != NULL && iCardP->IsPresent() && !(iState & KMMCSessStateCardIsGone) ) 
   1.668 +		return( iCardP->RCA() );
   1.669 +	return(0);
   1.670 +	}
   1.671 +
   1.672 +#ifdef __EPOC32__
   1.673 +void DMMCSession::ProgramTimerCallBack(TAny* aSessP)
   1.674 +	{
   1.675 +	OstTraceFunctionEntry0( DMMCSESSION_PROGRAMTIMERCALLBACK_ENTRY );
   1.676 +	__KTRACE_OPT(KPBUS1,Kern::Printf("=mss:pgtcb"));
   1.677 +	
   1.678 +    static_cast<DMMCSession *>(aSessP)->iState |= KMMCSessStateDoDFC;
   1.679 +	static_cast<DMMCSession *>(aSessP)->UnBlock(KMMCBlockOnPgmTimer, KMMCErrNone);
   1.680 +	OstTraceFunctionExit0( DMMCSESSION_PROGRAMTIMERCALLBACK_EXIT );
   1.681 +	}
   1.682 +
   1.683 +void DMMCSession::PollTimerCallBack(TAny* aSessP)
   1.684 +	{
   1.685 +	OstTraceFunctionEntry0( DMMCSESSION_POLLTIMERCALLBACK_ENTRY );
   1.686 +	__KTRACE_OPT(KPBUS1,Kern::Printf("=mss:ptcb"));
   1.687 +
   1.688 +    static_cast<DMMCSession *>(aSessP)->iState |= KMMCSessStateDoDFC;
   1.689 +	static_cast<DMMCSession *>(aSessP)->UnBlock(KMMCBlockOnPollTimer, KMMCErrNone);
   1.690 +	OstTraceFunctionExit0( DMMCSESSION_POLLTIMERCALLBACK_EXIT );
   1.691 +	}
   1.692 +
   1.693 +void DMMCSession::RetryTimerCallBack(TAny* aSessP)
   1.694 +	{
   1.695 +	OstTraceFunctionEntry0( DMMCSESSION_RETRYTIMERCALLBACK_ENTRY );
   1.696 +	__KTRACE_OPT(KPBUS1,Kern::Printf("=mss:rtcb"));
   1.697 +
   1.698 +    static_cast<DMMCSession *>(aSessP)->iState |= KMMCSessStateDoDFC;
   1.699 +	static_cast<DMMCSession *>(aSessP)->UnBlock(KMMCBlockOnRetryTimer, KMMCErrNone);
   1.700 +	OstTraceFunctionExit0( DMMCSESSION_RETRYTIMERCALLBACK_EXIT );
   1.701 +	}
   1.702 +
   1.703 +#endif	// #ifdef __EPOC32__
   1.704 +
   1.705 +EXPORT_C TInt DMMCSession::EpocErrorCode() const
   1.706 +/**
   1.707 + * Returns the last Symbian OS style error code returned in this session. 
   1.708 + * The Symbian OS error code is derived from both the last MMC specific exit code MMCExitCode()
   1.709 + * and the last status information from the card (iLastStatus).
   1.710 + * @return Standard Symbian OS error code
   1.711 + */
   1.712 +	{
   1.713 +	OstTraceFunctionEntry1( DMMCSESSION_EPOCERRORCODE_ENTRY, this );
   1.714 +	__KTRACE_OPT(KPBUS1,Kern::Printf("=mss:eee:%08x,%08x", MMCExitCode(), LastStatus().State() ));
   1.715 +	OstTraceExt2( TRACE_INTERNALS, DMMCSESSION_EPOCERRORCODE, "MMCExitCode = 0x%08x; LastStatus State = 0x%08x", (TUint) MMCExitCode(), (TUint) LastStatus().State());
   1.716 +	
   1.717 +	struct errorTableEntry
   1.718 +		{
   1.719 +		TUint32 iMask;
   1.720 +		TInt iErrorCode;
   1.721 +		};
   1.722 +
   1.723 +	static const errorTableEntry mmcTable[] = 
   1.724 +		{
   1.725 +		{KMMCErrNotSupported,									KErrNotSupported},
   1.726 +		{KMMCErrStackNotReady,									KErrBadPower},
   1.727 +		{KMMCErrArgument,										KErrArgument},
   1.728 +		{KMMCErrBrokenLock | KMMCErrPowerDown | KMMCErrAbort,	KErrAbort},
   1.729 +		{KMMCErrNoCard | KMMCErrResponseTimeOut | KMMCErrDataTimeOut |
   1.730 +			KMMCErrBusyTimeOut | KMMCErrBusTimeOut,				KErrNotReady},
   1.731 +		{KMMCErrResponseCRC|KMMCErrDataCRC|KMMCErrCommandCRC,	KErrCorrupt},
   1.732 +		{KMMCErrLocked,											KErrLocked},
   1.733 +		{KMMCErrNotFound,										KErrNotFound},
   1.734 +		{KMMCErrAlreadyExists,									KErrAlreadyExists},
   1.735 +		{KMMCErrGeneral,										KErrGeneral},
   1.736 +		{~0UL,													KErrUnknown}
   1.737 +		};
   1.738 +
   1.739 +	static const errorTableEntry statusTable[] = 
   1.740 +		{
   1.741 +		{KMMCStatErrOverrun|KMMCStatErrUnderrun|
   1.742 +			KMMCStatErrCardECCFailed|KMMCStatErrComCRCError,	KErrGeneral},
   1.743 +		{KMMCStatErrCSDOverwrite|KMMCStatErrWPViolation,		KErrWrite},
   1.744 +		{KMMCStatErrLockUnlock,									KErrLocked},
   1.745 +		{KMMCStatErrIllegalCommand,								KErrNotSupported},
   1.746 +		{KMMCStatErrEraseParam|KMMCStatErrEraseSeqError|
   1.747 +			KMMCStatErrBlockLenError|KMMCStatErrAddressError|
   1.748 +			KMMCStatErrOutOfRange,								KErrArgument},
   1.749 +		{~0UL,													KErrUnknown}
   1.750 +		};
   1.751 +
   1.752 +	TUint32 errCode = MMCExitCode();
   1.753 +
   1.754 +	if( errCode == 0 )
   1.755 +	    {
   1.756 +		OstTraceFunctionExitExt( DMMCSESSION_EPOCERRORCODE_EXIT, this, KErrNone );
   1.757 +		return KErrNone;
   1.758 +	    }
   1.759 +
   1.760 +	const errorTableEntry* ptr = &mmcTable[0];
   1.761 +
   1.762 +	if( errCode == KMMCErrStatus )
   1.763 +		{
   1.764 +		ptr = &statusTable[0];
   1.765 +
   1.766 +		if( (errCode = LastStatus()) == 0 )
   1.767 +		    {
   1.768 +			OstTraceFunctionExitExt( DUP1_DMMCSESSION_EPOCERRORCODE_EXIT, this, KErrUnknown );
   1.769 +			return KErrUnknown;
   1.770 +		    }
   1.771 +		}
   1.772 +
   1.773 +	for( ;; )
   1.774 +		if( (errCode & ptr->iMask) != 0 )
   1.775 +		    {
   1.776 +		    TInt ret = ptr->iErrorCode; 
   1.777 +			OstTraceFunctionExitExt( DUP2_DMMCSESSION_EPOCERRORCODE_EXIT, this, ret );
   1.778 +			return ret;
   1.779 +		    }
   1.780 +		else
   1.781 +			ptr++;
   1.782 +	}