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 + }