Update contrib.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include <drivers/mmc.h>
17 #include "OstTraceDefinitions.h"
18 #ifdef OST_TRACE_COMPILER_IN_USE
19 #include "locmedia_ost.h"
21 #pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
23 #include "sessionTraces.h"
28 // -------- class DMMCSession --------
30 EXPORT_C DMMCSession::DMMCSession(const TMMCCallBack& aCallBack)
32 * Constructor - initializes callbacks and timers.
33 * Once the session has been engaged, the completion of the request is signalled by calling
34 * the function provided in aCallback. A session will be completed in this way if it has completed
35 * normally, an error has occurred or the session has been stopped by this or another client.
36 * @param aCallBack reference to a TMMCCallback object to be called upon completion.
38 : iCallBack(aCallBack),
40 iPollTimer(DMMCSession::PollTimerCallBack, this),
41 iRetryTimer(DMMCSession::RetryTimerCallBack, this),
42 iProgramTimer(DMMCSession::ProgramTimerCallBack, this),
43 #endif // #ifdef __EPOC32__
46 OstTraceFunctionEntry1( DMMCSESSION_DMMCSESSION_ENTRY, this );
49 EXPORT_C DMMCSession::~DMMCSession()
54 OstTraceFunctionEntry1( DUP1_DMMCSESSION_DMMCSESSION_ENTRY, this );
55 // Ensure that the stack isn't currently running in another thread's context, otherwise this session won't be
56 // removed from the stack's workset until some time later - by which time the session will have been deleted
57 __ASSERT_ALWAYS(!iStackP->StackRunning(), DMMCSocket::Panic(DMMCSocket::EMMCNotInDfcContext));
60 OstTraceFunctionExit1( DUP1_DMMCSESSION_DMMCSESSION_EXIT, this );
63 EXPORT_C void DMMCSession::SetCard(TMMCard* aCardP)
65 * Assigns a card to the session. The card pointer would normally be obtained via a call of DMMCStack::CardP().
66 * Assigning a card to the session is the means by which a particular card in the stack is targeted for a
67 * particular request. Some requests involve broadcasting to the entire stack. However, the majority involve
68 * an individual card at some stage of the process and so an attempt to engage the session before a card has
69 * been assigned to it will generally fail straight away. It is possible to change the card assigned to the
70 * session as long as this is not attempted while the session is engaged.
71 * @param aCardP A pointer to the card to be assigned to the session.
74 OstTraceFunctionEntryExt( DMMCSESSION_SETCARD_ENTRY, this );
77 OstTraceFunctionExit1( DMMCSESSION_SETCARD_EXIT, this );
80 EXPORT_C void DMMCSession::SetupCIMReadBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP)
82 * Sets the session up to perform the CIM_READ_BLOCK macro as outlined by the MMCA.
83 * Having set-up the session for this operation, the client must then engage the session before the operation can commence.
84 * The CIM_READ_BLOCK macro reads a single block from the card. It starts by setting the block length (CMD16) as specified
85 * in 'aLength'. It then reads a single block of data (CMD17) from the card at offset 'aDevAddr' on the card into system
86 * memory starting at address 'aMemoryP'.
87 * @param aDevAddr Contains offset to the block to be read from the card
88 * @param aLength Block length
89 * @param aMemoryP host destination address
92 OstTraceExt4(TRACE_FLOW, DMMCSESSION_SETUPCIMREADBLOCK_ENTRY, "DMMCSession::SetupCIMReadBlock;aDevAddr=%x;aLength=%x;aMemoryP=%x;this=%x", (TUint) aDevAddr, (TUint) aLength, (TUint) aMemoryP, (TUint) this);
94 FillCommandArgs(aDevAddr, aLength, aMemoryP, aLength);
95 iSessionID = ECIMReadBlock;
96 OstTraceFunctionExit1( DMMCSESSION_SETUPCIMREADBLOCK_EXIT, this );
99 EXPORT_C void DMMCSession::SetupCIMWriteBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP)
101 * Set up the session to perform the CIM_WRITE_BLOCK macro as outlined by the MMCA.
102 * Having set-up the session for this operation, the client must then engage the session before the operation can commence.
103 * The CIM_WRITE_BLOCK macro writes a single block to the card. It starts by setting the block length (CMD16) as specified
104 * in 'aLength'. It then writes a single block of data (CMD24) to the card at offset 'aDevAddr' on the card reading from system
105 * memory starting at address 'aMemoryP'.
106 * @param aDevAddr Contains offset to the block to be written on the card
107 * @param aLength Block length
108 * @param aMemoryP Host source address
111 OstTraceExt4(TRACE_FLOW, DMMCSESSION_SETUPCIMWRITEBLOCK_ENTRY, "DMMCSession::SetupCIMWriteBlock;aDevAddr=%x;aLength=%x;aMemoryP=%x;this=%x", (TUint) aDevAddr, (TUint) aLength, (TUint) aMemoryP, (TUint) this);
113 FillCommandArgs(aDevAddr, aLength, aMemoryP, aLength);
114 iSessionID = ECIMWriteBlock;
115 OstTraceFunctionExit1( DMMCSESSION_SETUPCIMWRITEBLOCK_EXIT, this );
118 EXPORT_C void DMMCSession::SetupCIMReadMBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP, TUint32 aBlkLen)
120 * Set up the session to perform the CIM_READ_MBLOCK macro as outlined by the MMCA.
121 * Having set-up the session for this operation, the client must then engage the session before the operation can commence.
122 * The CIM_READ_MBLOCK macro reads a series of blocks from the card. It starts by setting the block length (CMD16) as specified
123 * in 'aBlkLen'. It then issues the read multiple block command (CMD18) to continually transfer blocks from the card to host
124 * starting at offset 'aDevAddr' on the card into system memory starting at address 'aMemoryP'. This continues until 'aLength'
125 * bytes have been read at which point the Controller issues the stop command (CMD12) to halt the transfer.
126 * @param aDevAddr Contains offset to the block to be read from the card
127 * @param aLength Total number of bytes to read.
128 * @param aMemoryP Host destination address
129 * @param aBlkLen Block length
132 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);
134 FillCommandArgs(aDevAddr, aLength, aMemoryP, aBlkLen);
135 iSessionID = ECIMReadMBlock;
136 OstTraceFunctionExit1( DMMCSESSION_SETUPCIMREADMBLOCK_EXIT, this );
139 EXPORT_C void DMMCSession::SetupCIMWriteMBlock(TMMCArgument aDevAddr, TUint32 aLength, TUint8* aMemoryP, TUint32 aBlkLen)
141 * Set up the session to perform the CIM_WRITE_MBLOCK macro as outlined by the MMCA.
142 * Having set-up the session for this operation, the client must then engage the session before the operation can commence.
143 * The CIM_WRITE_MBLOCK macro writes a series of blocks to the card. It starts by setting the block length (CMD16) as specified
144 * in 'aBlkLen'. It then issues the write multiple block command (CMD25) to continually transfer blocks from host to the card
145 * starting at address 'aMemoryP' in system memory and offset 'aDevAddr' on the card.. This continues until 'aLength' bytes have
146 * been written at which point the Controller issues the stop command (CMD12) to halt the transfer
147 * @param aDevAddr Contains offset to the block to be written on the card
148 * @param aLength Total number of bytes to write.
149 * @param aMemoryP Host source address
150 * @param aBlkLen Block length
153 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);
155 FillCommandArgs(aDevAddr, aLength, aMemoryP, aBlkLen);
156 iSessionID = ECIMWriteMBlock;
157 OstTraceFunctionExit1( DMMCSESSION_SETUPCIMWRITEMBLOCK_EXIT, this );
160 EXPORT_C void DMMCSession::SetupCIMEraseSector(TMMCArgument aDevAddr, TUint32 aLength)
162 * Set up the session to perform the CIM_ERASE_SECTOR macro broadly as outlined by the MMCA.
163 * However, the macro only performs a sector erase of a contiguous area and doesn't support the un-tagging of particular sectors
164 * within the initial tagged area. Having set-up the session for this operation, the client must then engage the session before
165 * the operation can commence.
166 * The CIM_ERASE_SECTOR macro erases a range of sectors on the card starting at offset 'aDevAddr' on the card and ending at offset
167 * 'aDevAdd'+'aLength'. The entire area specified must lie within a single erase group. (The erase group size can be read from the CSD).
168 * The specified start offset and end offset need not coincide exactly with a sector boundary since the card will ignore LSBs below
169 * the sector size. The tag sector start command (CMD32) is first issued setting the address of the first sector to be erased.
170 * This is followed by the tag sector end command (CMD33) setting the address of the last sector to be erased. Now that the erase
171 * sectors are tagged, the erase command (CMD38) is sent followed by a send status command (CMD13) to read any additional status
172 * information from the card.
173 * @param aDevAddr Contains offset to the first block to be erased
174 * @param aLength Total number of bytes to erase
177 OstTraceExt3(TRACE_FLOW, DMMCSESSION_SETUPCIMERASESECTOR_ENTRY, "DMMCSession::SetupCIMEraseSector;aDevAddr=%x;aLength=%x;this=%x", (TUint) aDevAddr, (TUint) aLength, (TUint) this);
179 FillCommandArgs(aDevAddr, aLength, NULL, 0);
180 iSessionID = ECIMEraseSector;
181 OstTraceFunctionExit1( DMMCSESSION_SETUPCIMERASESECTOR_EXIT, this );
184 EXPORT_C void DMMCSession::SetupCIMEraseGroup(TMMCArgument aDevAddr, TUint32 aLength)
186 * Set up the session to perform the CIM_ERASE_GROUP macro broadly as outlined by the MMCA.
187 * However, the macro only performs an erase group erase of a contiguous area and doesn't support the un-tagging of particular
188 * erase groups within the initial tagged area. Having set-up the session for this operation, the client must then engage the
189 * session before the operation can commence.
190 * The CIM_ERASE_GROUP macro erases a range of erase groups on the card starting at offset 'aDevAddr' on the card and ending at
191 * offset 'aDevAdd'+'aLength'. The specified start offset and end offset need not coincide exactly with an erase group boundary
192 * since the card will ignore LSBs below the erase group size. The tag ease group start command (CMD35) is first issued setting
193 * the address of the first erase group to be erased. This is followed by the tag erase group end command (CMD36) setting the
194 * address of the last erase group to be erased. Now that the erase groups are tagged, the erase command (CMD38) is sent followed
195 * by a send status command (CMD13) to read any additional status information from the card.
196 * @param aDevAddr Contains offset to the first block to be erased
197 * @param aLength Total number of bytes to erase
200 OstTraceExt3(TRACE_FLOW, DMMCSESSION_SETUPCIMERASEGROUP_ENTRY, "DMMCSession::SetupCIMEraseGroup;aDevAddr=%x;aLength=%x;this=%x", (TUint) aDevAddr, (TUint) aLength, (TUint) this);
202 FillCommandArgs(aDevAddr, aLength, NULL, 0);
203 iSessionID = ECIMEraseGroup;
204 OstTraceFunctionExit1( DMMCSESSION_SETUPCIMERASEGROUP_EXIT, this );
207 EXPORT_C void DMMCSession::SetupCIMReadIO(TUint8 aRegAddr, TUint32 aLength, TUint8* aMemoryP)
209 * Set up the session to perform the read i/o macro (CMD39).
210 * 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,
211 * reading 'aLength' bytes of data from I/O register 'aRegAddr' on the card into system memory starting at address 'aMemoryP'.
212 * Having set-up the session for this operation, the client must then engage the session before the operation can commence.
213 * @param aRegAddr Address of IO register
214 * @param aLength Total number of bytes to read
215 * @param aMemoryP Host destination address
218 OstTraceFunctionEntryExt( DMMCSESSION_SETUPCIMREADIO_ENTRY, this );
220 FillCommandArgs(aRegAddr, aLength, aMemoryP, 0);
221 iSessionID = ECIMReadIO;
222 OstTraceFunctionExit1( DMMCSESSION_SETUPCIMREADIO_EXIT, this );
225 EXPORT_C void DMMCSession::SetupCIMWriteIO(TUint8 aRegAddr, TUint32 aLength, TUint8* aMemoryP)
227 * Set up the session to perform the write i/o macro (CMD39).
228 * 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,
229 * writing 'aLength' bytes of data to I/O register 'aRegAddr' on the card from system memory starting at address 'aMemoryP'.
230 * Having set-up the session for this operation, the client must then engage the session before the operation can commence.
231 * @param aRegAddr Address of IO register
232 * @param aLength Total number of bytes to write
233 * @param aMemoryP Host source address
236 OstTraceFunctionEntryExt( DMMCSESSION_SETUPCIMWRITEIO_ENTRY, this );
238 FillCommandArgs(aRegAddr, aLength, aMemoryP, 0);
239 iSessionID = ECIMWriteIO;
240 OstTraceFunctionExit1( DMMCSESSION_SETUPCIMWRITEIO_EXIT, this );
243 EXPORT_C void DMMCSession::SetupCIMLockUnlock(TUint32 aLength, TUint8* aMemoryP)
245 * Set up the session to perform the lock-unlock macro (CMD42).
246 * This macro is used to manage the password protection feature (if supported) on a MultiMediaCard.
247 * This same macro is used to lock or unlock a card, set or clear a password or force erase a card.
248 * Having set-up the session for the required operation, the client must then engage the session before
249 * the operation can commence.
250 * The block length (CMD16) as specified in 'aLength' is first set. The lock unlock command (CMD42) is
251 * then issued. This command has the same structure as a regular single block write command.
252 * A data block is written to the card from system memory starting at address 'aMemoryP'. The transferred
253 * data block should contain the password setting mode, the password length and the password data if appropriate.
254 * @param aLength Block length
255 * @param aMemoryP Host source address containing password data
258 OstTraceFunctionEntryExt( DMMCSESSION_SETUPCIMLOCKUNLOCK_ENTRY, this );
259 __KTRACE_OPT(KPBUS1, Kern::Printf("ms:slu%08x", aLength));
262 FillCommandDesc(ECmdLockUnlock);
263 FillCommandArgs(0, aLength, aMemoryP, aLength);
264 iSessionID = ECIMLockUnlock;
265 OstTraceFunctionExit1( DMMCSESSION_SETUPCIMLOCKUNLOCK_EXIT, this );
268 EXPORT_C void DMMCSession::SetupCommand(TMMCCommandEnum aCommand, TMMCArgument anArgument)
270 * Set up the session to issue a raw command to the card.
271 * This raw command function should be used when issuing a known command with or without an argument.
272 * Having set-up the session for this operation, the client must then engage this session before
273 * the operation can commence.
274 * @param aCommand Command to be sent
275 * @param anArgument Associated argument
278 OstTraceExt3(TRACE_FLOW, DMMCSESSION_SETUPCOMMAND_ENTRY, "DMMCSession::SetupCommand;aCommand=%d;anArgument=%x;this=%x", (TInt) aCommand, (TUint) anArgument, (TUint) this);
280 FillCommandDesc(aCommand, anArgument);
281 iSessionID = ECIMNakedSession;
282 OstTraceFunctionExit1( DMMCSESSION_SETUPCOMMAND_EXIT, this );
285 EXPORT_C void DMMCSession::SetupRSCommand(TMMCCommandEnum aCommand, TMMCArgument anArgument,
286 TUint32 aResponseLength, TMMCCommandTypeEnum aCommandType,
287 TMMCResponseTypeEnum aResponseType,
288 TUint32 aCommandClass)
290 * Set up the session to issue a raw command to the card.
291 * This raw command function should be used when issuing an unknown command, an argument and an unknown response type.
292 * Having set-up the session for this operation, the client must then engage this session before the operation can commence.
295 * @param aResponseLength
296 * @param aCommandType
297 * @param aResponseType
298 * @param aCommandClass
299 * @todo Complete the parameter descriptions
302 OstTraceExt4( TRACE_FLOW, DMMCSESSION_SETUPRSCOMMAND_ENTRY1, "DMMCSession::SetupRSCommand;aCommand=%d;anArgument=%x;aResponseLength=%x;this=%x", (TInt) aCommand, (TUint) anArgument, (TUint) aResponseLength, (TUint) this );
303 OstTraceExt4( TRACE_FLOW, DMMCSESSION_SETUPRSCOMMAND_ENTRY2, "DMMCSession::SetupRSCommand;aCommandType=%d;aResponseType=%d;aCommandClass=%x;this=%x", (TInt) aCommandType, (TInt) aResponseType, (TUint) aCommandClass, (TUint) this );
305 FillCommandDesc(aCommand, anArgument);
306 TMMCCommandSpec& cmdSpec = Command().iSpec;
307 cmdSpec.iDirection = EDirNone;
309 if( aResponseLength <= KMMCMaxResponseLength )
310 cmdSpec.iResponseLength = aResponseLength;
312 if( aCommandType != ECmdTypeUK )
313 cmdSpec.iCommandType = aCommandType;
315 if( aResponseType != ERespTypeUnknown )
316 cmdSpec.iResponseType = aResponseType;
318 if( aCommandClass != KMMCCmdClassNone )
319 cmdSpec.iCommandClass = aCommandClass;
321 iSessionID = ECIMNakedSession;
322 OstTraceFunctionExit1( DMMCSESSION_SETUPRSCOMMAND_EXIT, this );
325 EXPORT_C void DMMCSession::SetupDTCommand(TMMCCommandEnum aCommand, TMMCArgument anArgument,
326 TUint32 aTotalLength, TUint8* aMemoryAddress, TUint32 aBlockLength,
327 TBool aStopTransmission, TMMCCmdDirEnum aDir,
328 TUint32 aCommandClass)
330 * Set up the session to issue a raw command to the card.
331 * This raw command function should be used when issuing a generic transfer command and argument.
332 * Having set-up the session for this operation, the client must then engage this session before
333 * the operation can commence.
336 * @param aTotalLength
337 * @param aMemoryAddress
338 * @param aBlockLength
339 * @param aStopTransmission
341 * @param aCommandClass
342 * @todo Complete the parameter descriptions
345 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 );
346 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 );
348 FillCommandDesc(aCommand);
349 FillCommandArgs(anArgument, aTotalLength, aMemoryAddress, aBlockLength);
350 TMMCCommandDesc& cmd = Command();
352 if( aBlockLength == 0 )
353 cmd.iBlockLength = aTotalLength;
355 cmd.iSpec.iMultipleBlocks = (cmd.iBlockLength != aTotalLength);
357 if( aStopTransmission )
358 cmd.iSpec.iUseStopTransmission = ETrue;
360 if( aDir != EDirNone )
362 cmd.iSpec.iUseStopTransmission = aStopTransmission;
363 cmd.iSpec.iDirection = aDir;
366 if( aCommandClass != KMMCCmdClassNone )
367 cmd.iSpec.iCommandClass = aCommandClass;
369 iSessionID = ECIMNakedSession;
370 OstTraceFunctionExit1( DMMCSESSION_SETUPDTCOMMAND_EXIT, this );
373 void DMMCSession::SetupCIMControl(TInt aSessID)
375 // find matching macro function for supplied session
378 OstTraceFunctionEntryExt( DMMCSESSION_SETUPCIMCONTROL_ENTRY, this );
379 TMMCSMSTFunc f = GetMacro(aSessID);
382 f = DMMCStack::NoSessionSMST;
384 iSessionID = (TMMCSessionTypeEnum) aSessID;
385 iBytesTransferred = 0;
386 iMMCExitCode = KMMCErrNone;
390 iDoAbort = iDoStop = iDoComplete = EFalse;
395 iMachine.Setup(f, iStackP);
396 OstTraceFunctionExit1( DMMCSESSION_SETUPCIMCONTROL_EXIT, this );
399 EXPORT_C TMMCSMSTFunc DMMCSession::GetMacro(TInt aSessNum) const
403 static const TMMCSMSTFunc macros[KMMCMaxSessionTypeNumber] =
405 DMMCStack::NakedSessionSMST,
406 DMMCStack::CIMUpdateAcqSMST,
407 DMMCStack::CIMInitStackSMST,
408 DMMCStack::CIMCheckStackSMST,
409 DMMCStack::CIMSetupCardSMST,
410 DMMCStack::CIMReadWriteBlocksSMST, // CIMReadBlock
411 DMMCStack::CIMReadWriteBlocksSMST, // CIMWriteBlock
412 DMMCStack::CIMReadWriteBlocksSMST, // CIMReadMBlock
413 DMMCStack::CIMReadWriteBlocksSMST, // CIMWriteMBlock
414 DMMCStack::CIMEraseSMST,
415 DMMCStack::CIMEraseSMST,
416 DMMCStack::CIMReadWriteIOSMST,
417 DMMCStack::CIMReadWriteIOSMST,
418 DMMCStack::CIMLockUnlockSMST, // CIMLockUnlock
419 DMMCStack::NoSessionSMST, // CIMLockStack is never really executed as a session
420 DMMCStack::InitStackAfterUnlockSMST,
421 DMMCStack::CIMAutoUnlockSMST,
422 DMMCStack::ExecSleepCommandSMST // CIMSleep
425 if (aSessNum >= 0 && aSessNum < (TInt) KMMCMaxSessionTypeNumber)
426 f = macros[aSessNum];
431 EXPORT_C TInt DMMCSession::Engage()
433 * Enque this session for execution on the DMMCStack object which is serving it.
434 * @return KErrBadDriver if no stack is associated with the session
435 * @return KErrServerBusy if the stack is currently locked (and KMMCModeEnqueIfLocked flag is cleared)
436 * @return KErrNotReady if the media is not present
437 * @return KErrNone if successful
440 OstTraceFunctionEntry1( DMMCSESSION_ENGAGE_ENTRY, this );
441 __KTRACE_OPT(KPBUS1,Kern::Printf(">ms:eng"));
443 if( iStackP == NULL )
445 OstTraceFunctionExitExt( DMMCSESSION_ENGAGE_EXIT, this, KErrBadDriver );
446 return KErrBadDriver;
449 if( iStackP->iLockingSessionP != NULL && iStackP->iLockingSessionP != this &&
450 (iStackP->EffectiveModes(iConfig) & KMMCModeEnqueIfLocked) == 0 )
452 OstTraceFunctionExitExt( DUP1_DMMCSESSION_ENGAGE_EXIT, this, KErrServerBusy );
453 return KErrServerBusy;
456 const TMediaState doorState=iStackP->MMCSocket()->iMediaChange->MediaState();
458 __KTRACE_OPT(KPBUS1,Kern::Printf(">MMC:Eng ds = %x", doorState));
459 OstTrace1( TRACE_INTERNALS, DMMCSESSION_ENGAGE, "doorState = 0x%x", doorState);
461 if (doorState == EDoorOpen)
463 OstTraceFunctionExitExt( DUP2_DMMCSESSION_ENGAGE_EXIT, this, KErrNotReady );
467 SetupCIMControl(iSessionID);
471 __KTRACE_OPT(KPBUS1,Kern::Printf("<ms:eng"));
472 OstTraceFunctionExitExt( DUP3_DMMCSESSION_ENGAGE_EXIT, this, KErrNone );
476 // Command specification table for standard MMC commands (CMD0 - CMD63)
477 extern const TMMCCommandSpec CommandTable[KMMCCommandMask+1] =
478 {// Class Type Dir MBlk StopT Rsp Type Len Cmd No
479 {KMMCCmdClassBasic, ECmdTypeBC, EDirNone, EFalse, EFalse, ERespTypeNone, 0}, //CMD0
480 {KMMCCmdClassBasic, ECmdTypeBCR, EDirNone, EFalse, EFalse, ERespTypeR3, 4}, //CMD1
481 {KMMCCmdClassBasic, ECmdTypeBCR, EDirNone, EFalse, EFalse, ERespTypeR2, 16},//CMD2
482 {KMMCCmdClassBasic, ECmdTypeAC, EDirNone, EFalse, EFalse, ERespTypeR1, 4}, //CMD3
483 {KMMCCmdClassBasic, ECmdTypeBC, EDirNone, EFalse, EFalse, ERespTypeNone, 0}, //CMD4
484 {KMMCCmdClassBasic, ECmdTypeAC, EDirNone, EFalse, EFalse, ERespTypeR1B, 0}, //CMD5 - SLEEP/AWAKE
485 {KMMCCmdClassBasic, ECmdTypeACS, EDirNone, EFalse, EFalse, ERespTypeR1B, 0}, //CMD6
486 {KMMCCmdClassBasic, ECmdTypeAC, EDirNone, EFalse, EFalse, ERespTypeR1B, 4}, //CMD7
487 {KMMCCmdClassBasic, ECmdTypeADTCS, EDirRead, EFalse, EFalse, ERespTypeR1, 512}, //CMD8
488 {KMMCCmdClassBasic, ECmdTypeAC, EDirNone, EFalse, EFalse, ERespTypeR2, 16},//CMD9
489 {KMMCCmdClassBasic, ECmdTypeAC, EDirNone, EFalse, EFalse, ERespTypeR2, 16},//CMD10
490 {KMMCCmdClassStreamRead,ECmdTypeADTCS, EDirRead, EFalse, ETrue, ERespTypeR1, 4}, //CMD11
491 {KMMCCmdClassBasic, ECmdTypeACS, EDirNone, EFalse, EFalse, ERespTypeR1B, 4}, //CMD12
492 {KMMCCmdClassBasic, ECmdTypeAC, EDirNone, EFalse, EFalse, ERespTypeR1, 4}, //CMD13
493 {KMMCCmdClassBlockRead, ECmdTypeADTCS, EDirRead, EFalse, EFalse, ERespTypeR1, 4}, //CMD14 - BUSTEST_R
494 {KMMCCmdClassBasic, ECmdTypeAC, EDirNone, EFalse, EFalse, ERespTypeNone, 0}, //CMD15
495 {KMMCCmdClassBlockRead, ECmdTypeACS, EDirNone, EFalse, EFalse, ERespTypeR1, 4}, //CMD16
496 {KMMCCmdClassBlockRead, ECmdTypeADTCS, EDirRead, EFalse, EFalse, ERespTypeR1, 4}, //CMD17
497 {KMMCCmdClassBlockRead, ECmdTypeADTCS, EDirRead, ETrue, ETrue, ERespTypeR1, 4}, //CMD18
498 {KMMCCmdClassBlockWrite,ECmdTypeADTCS, EDirWrite, EFalse, EFalse, ERespTypeR1, 4}, //CMD19 - BUSTEST_W
499 {KMMCCmdClassStreamWrite,ECmdTypeADTCS, EDirWrite, EFalse, ETrue, ERespTypeR1, 4}, //CMD20
500 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD21
501 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD22
502 {KMMCCmdClassBlockRead |
503 KMMCCmdClassBlockWrite,ECmdTypeACS, EDirNone, EFalse, EFalse, ERespTypeR1, 4}, //CMD23
504 {KMMCCmdClassBlockWrite,ECmdTypeADTCS, EDirWrite, EFalse, EFalse, ERespTypeR1, 4}, //CMD24
505 {KMMCCmdClassBlockWrite,ECmdTypeADTCS, EDirWrite, ETrue, ETrue, ERespTypeR1, 4}, //CMD25
506 {KMMCCmdClassBlockWrite,ECmdTypeADTCS, EDirWrite, EFalse, EFalse, ERespTypeR1, 4}, //CMD26
507 {KMMCCmdClassBlockWrite,ECmdTypeADTCS, EDirWrite, EFalse, EFalse, ERespTypeR1, 4}, //CMD27
508 {KMMCCmdClassWriteProtection,ECmdTypeACS,EDirNone, EFalse, EFalse, ERespTypeR1B, 4}, //CMD28
509 {KMMCCmdClassWriteProtection,ECmdTypeACS,EDirNone, EFalse, EFalse, ERespTypeR1B, 4}, //CMD29
510 {KMMCCmdClassWriteProtection,ECmdTypeADTCS,EDirRead,EFalse, EFalse, ERespTypeR1, 4}, //CMD30
511 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD31
512 {KMMCCmdClassErase, ECmdTypeACS, EDirNone, EFalse, EFalse, ERespTypeR1, 4}, //CMD32
513 {KMMCCmdClassErase, ECmdTypeACS, EDirNone, EFalse, EFalse, ERespTypeR1, 4}, //CMD33
514 {KMMCCmdClassErase, ECmdTypeACS, EDirNone, EFalse, EFalse, ERespTypeR1, 4}, //CMD34
515 {KMMCCmdClassErase, ECmdTypeACS, EDirNone, EFalse, EFalse, ERespTypeR1, 4}, //CMD35
516 {KMMCCmdClassErase, ECmdTypeACS, EDirNone, EFalse, EFalse, ERespTypeR1, 4}, //CMD36
517 {KMMCCmdClassErase, ECmdTypeACS, EDirNone, EFalse, EFalse, ERespTypeR1, 4}, //CMD37
518 {KMMCCmdClassErase, ECmdTypeACS, EDirNone, EFalse, EFalse, ERespTypeR1B, 4}, //CMD38
519 {KMMCCmdClassIOMode, ECmdTypeAC, EDirNone, EFalse, EFalse, ERespTypeR4, 4}, //CMD39
520 {KMMCCmdClassIOMode, ECmdTypeBCR, EDirNone, EFalse, EFalse, ERespTypeR5, 4}, //CMD40
521 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD41
522 {KMMCCmdClassLockCard, ECmdTypeADTCS, EDirWrite, EFalse, EFalse, ERespTypeR1B, 4}, //CMD42
523 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD43
524 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD44
525 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD45
526 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD46
527 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD47
528 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD48
529 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD49
530 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD50
531 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD51
532 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD52
533 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD53
534 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD54
535 {KMMCCmdClassApplication,ECmdTypeAC, EDirNone, EFalse, EFalse, ERespTypeR1, 4}, //CMD55
536 {KMMCCmdClassApplication,ECmdTypeADTCS, EDirRBit0, EFalse, EFalse, ERespTypeR1B, 4}, //CMD56
537 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD57
538 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD58
539 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD59
540 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD60
541 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD61
542 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0}, //CMD62
543 {KMMCCmdClassNone, ECmdTypeUK, EDirNone, EFalse, EFalse, ERespTypeUnknown, 0} //CMD63
547 EXPORT_C void DMMCSession::FillCommandDesc()
549 * Fills the current command descriptor with the default data according to MMC spec V2.1
552 OstTraceFunctionEntry1( DMMCSESSION_FILLCOMMANDDESC1_ENTRY, this );
553 TMMCCommandDesc& cmd = Command();
554 cmd.iSpec = CommandTable[cmd.iCommand & KMMCCommandMask];
558 OstTraceFunctionExit1( DMMCSESSION_FILLCOMMANDDESC1_EXIT, this );
561 EXPORT_C void DMMCSession::FillCommandDesc(TMMCCommandEnum aCommand)
563 * Initialises the current command according to whether it is a normal
564 * or an application command.
565 * @param aCommand Contains the command.
568 OstTraceExt2(TRACE_FLOW, DMMCSESSION_FILLCOMMANDDESC2_ENTRY, "DMMCSession::FillCommandDesc;aCommand=%d;this=%x", (TInt) aCommand, (TUint) this);
569 Command().iCommand = aCommand;
570 Command().iArgument = 0; // set stuff bits to zero
572 OstTraceFunctionExit1( DMMCSESSION_FILLCOMMANDDESC2_EXIT, this );
575 EXPORT_C void DMMCSession::FillCommandDesc(TMMCCommandEnum aCommand, TMMCArgument anArgument)
577 * Initialises the current command with an argument according to whether
578 * it is a normal or an application command.
579 * @param aCommand Contains the command.
580 * @param anArgument Specifies the argument.
583 OstTraceExt3(TRACE_FLOW, DMMCSESSION_FILLCOMMANDDESC3_ENTRY, "DMMCSession::FillCommandDesc;aCommand=%d;anArgument=%x;this=%x", (TInt) aCommand, (TUint) anArgument, (TUint) this);
584 TMMCCommandDesc& cmd = Command();
585 cmd.iCommand = aCommand;
587 cmd.iArgument = anArgument;
588 OstTraceFunctionExit1( DMMCSESSION_FILLCOMMANDDESC3_EXIT, this );
591 EXPORT_C void DMMCSession::FillCommandArgs(TMMCArgument anArgument, TUint32 aLength, TUint8* aMemoryP,
594 * Initialises the current commands arguments with the specified parameters
595 * It is necessary to have set the command arguments with this command prior
596 * to engaging a read/write macro or command.
597 * @param anArgument Command specific argument.
598 * @param aLength aLength Total number of bytes to read/write.
599 * @param aMemoryP Host source/destination address
600 * @param aBlkLen Block length
603 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);
604 TMMCCommandDesc& cmd = Command();
606 cmd.iArgument = anArgument;
607 cmd.iTotalLength = aLength;
608 cmd.iDataMemoryP = aMemoryP;
609 cmd.iBlockLength = aBlkLen;
611 OstTraceFunctionExit1( DMMCSESSION_FILLCOMMANDARGS_EXIT, this );
614 const TMMCCommandSpec& DMMCSession::FindCommandSpec(const TMMCIdxCommandSpec aSpecs[], TInt aIdx)
616 * Searches the supplied command specification list for the specification corresponding to the
618 * @param aSpecs The command specification list to be searched.
619 * @param aIdx The requested command.
622 OstTraceFunctionEntry0( DMMCSESSION_FINDCOMMANDSPEC_ENTRY );
624 while (aSpecs[i].iIdx != aIdx)
626 OstTraceFunctionExit0( DMMCSESSION_FINDCOMMANDSPEC_EXIT );
627 return aSpecs[i].iSpec;
630 void DMMCSession::SynchBlock(TUint32 aFlag)
632 // Blocks a session synchronously (within scheduler context)
635 OstTraceFunctionEntryExt( DMMCSESSION_SYNCHBLOCK_ENTRY, this );
636 (void)__e32_atomic_ior_ord32(&iBlockOn, aFlag);
637 OstTraceFunctionExit1( DMMCSESSION_SYNCHBLOCK_EXIT, this );
640 void DMMCSession::SynchUnBlock(TUint32 aFlag)
642 // Unblocks a session synchronously (within scheduler context)
645 OstTraceFunctionEntryExt( DMMCSESSION_SYNCHUNBLOCK_ENTRY, this );
646 if( (iBlockOn & aFlag) == 0 )
648 OstTraceFunctionExit1( DMMCSESSION_SYNCHUNBLOCK_EXIT, this );
652 (void)__e32_atomic_and_ord32(&iBlockOn, ~aFlag);
653 OstTraceFunctionExit1( DUP1_DMMCSESSION_SYNCHUNBLOCK_EXIT, this );
656 EXPORT_C TRCA DMMCSession::CardRCA()
658 * Checks that the card is still the same and ready
659 * @return A TRCA object containing the card's RCA (or 0 if the card is not ready)
663 // Rely on 'CardIsGone' bit rather than a CID comparison
664 if ( iCardP != NULL && iCardP->IsPresent() && !(iState & KMMCSessStateCardIsGone) )
665 return( iCardP->RCA() );
670 void DMMCSession::ProgramTimerCallBack(TAny* aSessP)
672 OstTraceFunctionEntry0( DMMCSESSION_PROGRAMTIMERCALLBACK_ENTRY );
673 __KTRACE_OPT(KPBUS1,Kern::Printf("=mss:pgtcb"));
675 static_cast<DMMCSession *>(aSessP)->iState |= KMMCSessStateDoDFC;
676 static_cast<DMMCSession *>(aSessP)->UnBlock(KMMCBlockOnPgmTimer, KMMCErrNone);
677 OstTraceFunctionExit0( DMMCSESSION_PROGRAMTIMERCALLBACK_EXIT );
680 void DMMCSession::PollTimerCallBack(TAny* aSessP)
682 OstTraceFunctionEntry0( DMMCSESSION_POLLTIMERCALLBACK_ENTRY );
683 __KTRACE_OPT(KPBUS1,Kern::Printf("=mss:ptcb"));
685 static_cast<DMMCSession *>(aSessP)->iState |= KMMCSessStateDoDFC;
686 static_cast<DMMCSession *>(aSessP)->UnBlock(KMMCBlockOnPollTimer, KMMCErrNone);
687 OstTraceFunctionExit0( DMMCSESSION_POLLTIMERCALLBACK_EXIT );
690 void DMMCSession::RetryTimerCallBack(TAny* aSessP)
692 OstTraceFunctionEntry0( DMMCSESSION_RETRYTIMERCALLBACK_ENTRY );
693 __KTRACE_OPT(KPBUS1,Kern::Printf("=mss:rtcb"));
695 static_cast<DMMCSession *>(aSessP)->iState |= KMMCSessStateDoDFC;
696 static_cast<DMMCSession *>(aSessP)->UnBlock(KMMCBlockOnRetryTimer, KMMCErrNone);
697 OstTraceFunctionExit0( DMMCSESSION_RETRYTIMERCALLBACK_EXIT );
700 #endif // #ifdef __EPOC32__
702 EXPORT_C TInt DMMCSession::EpocErrorCode() const
704 * Returns the last Symbian OS style error code returned in this session.
705 * The Symbian OS error code is derived from both the last MMC specific exit code MMCExitCode()
706 * and the last status information from the card (iLastStatus).
707 * @return Standard Symbian OS error code
710 OstTraceFunctionEntry1( DMMCSESSION_EPOCERRORCODE_ENTRY, this );
711 __KTRACE_OPT(KPBUS1,Kern::Printf("=mss:eee:%08x,%08x", MMCExitCode(), LastStatus().State() ));
712 OstTraceExt2( TRACE_INTERNALS, DMMCSESSION_EPOCERRORCODE, "MMCExitCode = 0x%08x; LastStatus State = 0x%08x", (TUint) MMCExitCode(), (TUint) LastStatus().State());
714 struct errorTableEntry
720 static const errorTableEntry mmcTable[] =
722 {KMMCErrNotSupported, KErrNotSupported},
723 {KMMCErrStackNotReady, KErrBadPower},
724 {KMMCErrArgument, KErrArgument},
725 {KMMCErrBrokenLock | KMMCErrPowerDown | KMMCErrAbort, KErrAbort},
726 {KMMCErrNoCard | KMMCErrResponseTimeOut | KMMCErrDataTimeOut |
727 KMMCErrBusyTimeOut | KMMCErrBusTimeOut, KErrNotReady},
728 {KMMCErrResponseCRC|KMMCErrDataCRC|KMMCErrCommandCRC, KErrCorrupt},
729 {KMMCErrLocked, KErrLocked},
730 {KMMCErrNotFound, KErrNotFound},
731 {KMMCErrAlreadyExists, KErrAlreadyExists},
732 {KMMCErrGeneral, KErrGeneral},
736 static const errorTableEntry statusTable[] =
738 {KMMCStatErrOverrun|KMMCStatErrUnderrun|
739 KMMCStatErrCardECCFailed|KMMCStatErrComCRCError, KErrGeneral},
740 {KMMCStatErrCSDOverwrite|KMMCStatErrWPViolation, KErrWrite},
741 {KMMCStatErrLockUnlock, KErrLocked},
742 {KMMCStatErrIllegalCommand, KErrNotSupported},
743 {KMMCStatErrEraseParam|KMMCStatErrEraseSeqError|
744 KMMCStatErrBlockLenError|KMMCStatErrAddressError|
745 KMMCStatErrOutOfRange, KErrArgument},
749 TUint32 errCode = MMCExitCode();
753 OstTraceFunctionExitExt( DMMCSESSION_EPOCERRORCODE_EXIT, this, KErrNone );
757 const errorTableEntry* ptr = &mmcTable[0];
759 if( errCode == KMMCErrStatus )
761 ptr = &statusTable[0];
763 if( (errCode = LastStatus()) == 0 )
765 OstTraceFunctionExitExt( DUP1_DMMCSESSION_EPOCERRORCODE_EXIT, this, KErrUnknown );
771 if( (errCode & ptr->iMask) != 0 )
773 TInt ret = ptr->iErrorCode;
774 OstTraceFunctionExitExt( DUP2_DMMCSESSION_EPOCERRORCODE_EXIT, this, ret );