kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdio/sdiostack.cpp
changeset 0 a41df078684a
child 19 4a8fed1c0ef6
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <drivers/sdio/sdio.h>
       
    17 #include <drivers/sdio/cisreader.h>
       
    18 #include <drivers/sdio/function.h>
       
    19 #include <drivers/sdio/regifc.h>
       
    20 #include "utraceepbussdio.h"
       
    21 
       
    22 #ifdef __SMP__
       
    23 TSpinLock SDIOLock(TSpinLock::EOrderGenericIrqHigh0);
       
    24 #endif
       
    25 
       
    26 #if !defined(__WINS__)
       
    27 #define DISABLEPREEMPTION TUint irq = __SPIN_LOCK_IRQSAVE(SDIOLock);
       
    28 #define RESTOREPREEMPTION __SPIN_UNLOCK_IRQRESTORE(SDIOLock,irq);
       
    29 #else
       
    30 #define DISABLEPREEMPTION
       
    31 #define RESTOREPREEMPTION										   
       
    32 #endif
       
    33 
       
    34 // Some SDIO cards don't respond to an I/O reset command, but sending ECmdGoIdleState 
       
    35 // after the timeout has the effect of putting the card into SPI mode.
       
    36 // Undefine this macro for these cards.
       
    37 #define __SEND_CMD0_AFTER_RESETIO_TIMEOUT__
       
    38 
       
    39 // The ReadWriteExtendSM can handle fragmented RAM, this functionity may not be required 
       
    40 // with the introduction of defragment RAM/3rd party driver support features
       
    41 #define __FRAGMENTED_RAM_SUPPORT
       
    42 
       
    43 // Temporarily override the MMC version of SMF_BEGIN to add Tracing to the state machine
       
    44 #undef SMF_BEGIN 
       
    45 #define SMF_BEGIN TMMCStateMachine& m=Machine();const TMMCErr err=m.SetExitCode(0);\
       
    46  	for(;;){SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EState), "SDIOStack state change, m.State = %d", m.State()));/*//@SymTraceDataInternalTechnology*/\
       
    47         switch(m.State()){case EStBegin:{if(err) (void)0;
       
    48 
       
    49 // ======== DSDIOStack ========
       
    50 
       
    51 EXPORT_C TInt DSDIOStack::Init()
       
    52 /**	
       
    53 @publishedPartner
       
    54 @released
       
    55 
       
    56 Initialize the stack
       
    57 */
       
    58 	{
       
    59 	return DStackBase::Init();
       
    60 	}
       
    61 
       
    62 
       
    63 TMMCErr DSDIOStack::ConfigureIoCardSMST(TAny* aStackP)
       
    64 	{ return static_cast<DSDIOStack*>(aStackP)->ConfigureIoCardSM(); }
       
    65 
       
    66 TMMCErr DSDIOStack::CIMGetIoCommonConfigSMST(TAny* aStackP)
       
    67 	{ return static_cast<DSDIOStack*>(aStackP)->GetIoCommonConfigSM(); }
       
    68 
       
    69 TMMCErr DSDIOStack::CIMReadFunctionBasicRegistersSMST(TAny* aStackP)
       
    70 	{ return static_cast<DSDIOStack*>(aStackP)->ReadFunctionBasicRegistersSM(); }
       
    71 
       
    72 TMMCErr DSDIOStack::CIMIoIssueCommandCheckResponseSMST(TAny* aStackP)
       
    73 	{ return( static_cast<DSDIOStack *>(aStackP)->CIMIoIssueCommandCheckResponseSM() ); }
       
    74 
       
    75 TMMCErr DSDIOStack::CIMIoReadWriteDirectSMST(TAny* aStackP)
       
    76 	{ return static_cast<DSDIOStack*>(aStackP)->CIMIoReadWriteDirectSM(); }
       
    77 	
       
    78 TMMCErr DSDIOStack::CIMIoReadWriteExtendedSMST(TAny* aStackP)
       
    79 	{return static_cast<DSDIOStack*>(aStackP)->CIMIoReadWriteExtendedSM(); }
       
    80 
       
    81 TMMCErr DSDIOStack::CIMIoModifySMST(TAny* aStackP)
       
    82 	{ return static_cast<DSDIOStack*>(aStackP)->CIMIoModifySM(); }
       
    83 
       
    84 TMMCErr DSDIOStack::CIMIoInterruptHandlerSMST(TAny* aStackP)
       
    85 	{ return static_cast<DSDIOStack*>(aStackP)->CIMIoInterruptHandlerSM(); }
       
    86 
       
    87 TMMCErr DSDIOStack::CIMIoFindTupleSMST(TAny* aStackP)
       
    88 	{ return static_cast<DSDIOStack*>(aStackP)->CIMIoFindTupleSM(); }
       
    89 
       
    90 TMMCErr DSDIOStack::CIMIoSetBusWidthSMST(TAny* aStackP)
       
    91 	{ return static_cast<DSDIOStack*>(aStackP)->CIMIoSetBusWidthSM(); }
       
    92 
       
    93 TMMCErr DSDIOStack::CIMReadWriteMemoryBlocksSMST(TAny* aStackP)
       
    94 	{ return( static_cast<DSDIOStack *>(aStackP)->DSDStack::CIMReadWriteBlocksSM() ); }
       
    95 
       
    96 
       
    97 const TInt  KMaxRCASendLoops=3;
       
    98 
       
    99 const TUint32 KDefaultFn0BlockSize     = 0x40;
       
   100 const TUint8 KSDIONoTranSpeed		   = 0x00;
       
   101 const TUint8 KSDIODefaultLowTranSpeed  = 0x48;
       
   102 const TUint8 KSDIODefaultHighTranSpeed = 0x32;
       
   103 
       
   104 
       
   105 EXPORT_C TMMCErr DSDIOStack::AcquireStackSM()
       
   106 /**
       
   107 This macro acquires new cards in an SDIO Card stack.
       
   108 
       
   109 This is an extension of the DSDStack::AcquireStackSM state machine
       
   110 function, and handles the SDIO initialisation procedure as described
       
   111 in Version 1.10f of the the SDIO Card Specification.
       
   112 
       
   113 @return TMMCErr Error Code
       
   114 */
       
   115 	{
       
   116 	TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackAcquireStack, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
   117 
       
   118 	enum states
       
   119 			{
       
   120 			EStBegin=0,
       
   121 			EStInitIOReset,
       
   122 			EStIOReset,
       
   123 			EStCheckIOResetResponse,
       
   124 			EStInitIOSendOpCond,
       
   125 			EStInitIOCheckResponse,
       
   126 			EStInitIOSetWorkingOCR,
       
   127 			EStInitIOCheckOcrResponse,
       
   128 			EStInitMemoryCard,
       
   129 			EStHandleRcaForCardType,
       
   130 			EStIssueSendRCA,
       
   131 			EStIssueSetRCA,
       
   132 			EStSendRCACheck,
       
   133 			EStRCADone,
       
   134 			EStConfigureMemoryCardDone,
       
   135 			EStGoInactive,
       
   136 			EStCheckNextCard,
       
   137 			EStEnd
       
   138 			};
       
   139 
       
   140 		DSDIOSession& s=SDIOSession();
       
   141 		DMMCPsu* psu=(DMMCPsu*)MMCSocket()->iVcc;
       
   142 		
       
   143 	SMF_BEGIN
       
   144 
       
   145 		iRCAPool.ReleaseUnlocked();
       
   146 
       
   147 		iCxCardCount=0; 		// Reset current card number
       
   148 		
       
   149 		CardArray().Card(iCxCardCount).RCA() = 0x0000;
       
   150 
       
   151 	SMF_STATE(EStInitIOReset)
       
   152 
       
   153 		// EStInitIOReset : Reset the IO Card.	
       
   154 		//
       
   155 		// We expect the card to be reset before enumeration in order for the
       
   156 		// card to be in the default state (ie- functions disabled, 1-bit mode)
       
   157 		//
       
   158 		// Resets the IO card by setting RES bit in IO_ABORT reg of the CCCR
       
   159 		// 
       
   160 
       
   161 		iFunctionCount  = 0;
       
   162 		iMemoryPresent  = EFalse;
       
   163 
       
   164 		if (!CardDetect(iCxCardCount))
       
   165 			{
       
   166 			SMF_GOTOS(EStCheckNextCard)
       
   167 			}
       
   168 
       
   169 		TRACE2(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackPSLCalledAddressCard, reinterpret_cast<TUint32>(this), iCxCardCount); // @SymTraceDataPublishedTvk
       
   170 		AddressCard(iCxCardCount);
       
   171 		TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackPSLAddressCardReturned, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
   172 		
       
   173 	SMF_STATE(EStIOReset)
       
   174 
       
   175 		// EStResetIo
       
   176 		m.SetTraps(KMMCErrAll);
       
   177 		s.iCardP = static_cast<TSDIOCard*>(CardArray().CardP(iCxCardCount));
       
   178 		s.FillDirectCommandDesc(Command(), ECIMIoWriteDirect, 0x00, KCCCRRegIoAbort, KSDIOCardIoAbortReset, NULL);
       
   179 		SMF_INVOKES(IssueCommandCheckResponseSMST, EStCheckIOResetResponse)
       
   180 
       
   181 	SMF_STATE(EStCheckIOResetResponse)
       
   182 
       
   183 		// EStCheckIOResetResponse
       
   184 		
       
   185 		DoSetBusWidth(KSDBusWidth1);
       
   186 
       
   187 #ifdef __SEND_CMD0_AFTER_RESETIO_TIMEOUT__
       
   188 
       
   189 		if(err)
       
   190 			{
       
   191 			m.SetTraps(KMMCErrAll);
       
   192 			SMF_INVOKES(GoIdleSMST, EStInitIOSendOpCond)
       
   193 			}
       
   194 #endif
       
   195 
       
   196 		// Drop through to EStInitIOSendOpCond if reset OK
       
   197 
       
   198 	SMF_STATE(EStInitIOSendOpCond)
       
   199 		
       
   200 		// EStInitIOSendOpCond : Determine the capabilities of the card.
       
   201 		//														
       
   202 		// Determine the basic capabilities of the card by sending the card
       
   203 		// IO_SEND_OP_COND (CMD5) with ARG=0x0000, which should respond with
       
   204 		// the number of supported IO functions and the supported OCR.
       
   205 		
       
   206 		if(err)
       
   207 			{
       
   208 			SMF_GOTOS(EStInitMemoryCard)
       
   209 			}
       
   210 
       
   211 		iCxPollRetryCount=0;
       
   212 		
       
   213 		iConfig.RemoveMode( KMMCModeEnableTimeOutRetry );
       
   214 		m.SetTraps(KMMCErrResponseTimeOut);
       
   215 
       
   216 		DSDIOSession::FillAppCommandDesc(Command(), ESDIOCmdOpCond, 0x0000);
       
   217 		SMF_INVOKES(ExecCommandSMST, EStInitIOCheckResponse)
       
   218 		
       
   219 	SMF_STATE(EStInitIOCheckResponse)
       
   220 
       
   221 		// EStInitIOCheckResponse : Check the response to IO_SEND_OP_COND (CMD5)				
       
   222 		//																				
       
   223 		// The R4 response shall contain the following information:									
       
   224 		//																				
       
   225 		// 1. Number of IO Functions : 0 = no IO present, 1 = Single Function, >1 = Multi-Function Card
       
   226 		// 2. Memory Present		 : 1 = Memory is present (if nIO>0, then this is a Combo Card)	
       
   227 		// 3. IO OCR				 : The OCR for the IO portion of the card (Use ACMD41 for Memory OCR)
       
   228 
       
   229 		//
       
   230 		// If the CMD5 response has timed out, then this can't be an SDIO card.
       
   231 		// We should now continue and try to detect the presence of a memory card.
       
   232 		
       
   233 		if (err & KMMCErrResponseTimeOut)
       
   234 			{
       
   235 			SMF_GOTOS(EStInitMemoryCard)
       
   236 			}
       
   237 
       
   238 		//
       
   239 		// Check the R4 response for the number of IO functions and presence of Memory
       
   240 		//
       
   241 		iFunctionCount = 0;
       
   242 		iMemoryPresent = EFalse;
       
   243 
       
   244 		TUint32 ioOCR = 0x00000000;
       
   245 		
       
   246 		//
       
   247 		// No need to test IO_READY yet, as we have not yet set the OCR
       
   248 		//
       
   249 		(void)ExtractSendOpCondResponse(TMMC::BigEndian32(s.ResponseP()), iFunctionCount, iMemoryPresent, ioOCR);
       
   250 
       
   251 		if(iFunctionCount == 0)
       
   252 			{
       
   253 			// F=0, MP=1 => Initialise Memory Controller
       
   254 			// F=0, MP=0 => Go Inactive
       
   255 			SMF_GOTOS(iMemoryPresent ? EStInitMemoryCard : EStGoInactive)
       
   256 			}
       
   257 		else
       
   258 			{
       
   259 			//
       
   260 			// IO is ready and there is at least one function present, so now determine a
       
   261 			// suitable setting for the IO OCR based on the capabilities of our hardware.
       
   262 			//
       
   263 			iCurrentOpRange &= ioOCR;
       
   264 			if (iCurrentOpRange==0)
       
   265 				{
       
   266 				// The card is incompatible with our h/w
       
   267 				SMF_GOTOS(iMemoryPresent ? EStInitMemoryCard : EStGoInactive)
       
   268 				}
       
   269 			}
       
   270 
       
   271 		// Reset retry count. Timeout to 1S
       
   272 		iCxPollRetryCount=0;  
       
   273 		
       
   274 		//...drop through to next state (EStInitIOSetWorkingOCR)
       
   275 			
       
   276 	SMF_STATE(EStInitIOSetWorkingOCR)
       
   277 		
       
   278 		// EStInitIOSetWorkingOCR :	
       
   279 		//
       
   280 		// The OCR range is supported by our hardware, so re-issue 
       
   281 		// IO_SEND_OP_COND (CMD5) with our chosen voltage range
       
   282 		//
       
   283 
       
   284 		m.SetTraps(KMMCErrResponseTimeOut);
       
   285 		DSDIOSession::FillAppCommandDesc(Command(), ESDIOCmdOpCond, TMMCArgument(iCurrentOpRange));
       
   286 		SMF_INVOKES(ExecCommandSMST, EStInitIOCheckOcrResponse)
       
   287 
       
   288 	SMF_STATE(EStInitIOCheckOcrResponse)
       
   289 		
       
   290 		// EStInitIOCheckOcrResponse : Verify the response to IO_SEND_OP_COND (CMD5) with ARG=IO_OCR
       
   291 		//										
       
   292 		// Verifies that the OCR has been successfully accepted by the SDIO Card (within 1 Second)
       
   293 		
       
   294 		if(err == KMMCErrResponseTimeOut)
       
   295 			{
       
   296 			// Previous CMD5 (Arg=0000) worked, but this one failed
       
   297 			// with no response, so give up and go inactive.
       
   298 			SMF_GOTOS(EStGoInactive)
       
   299 			}
       
   300 		//
       
   301 		// Check the R4 response for the number of IO functions and presence of Memory
       
   302 		//
       
   303 		TUint32 ioOCR = 0x00000000;
       
   304 		if(ExtractSendOpCondResponse(TMMC::BigEndian32(s.ResponseP()), iFunctionCount, iMemoryPresent, ioOCR) != KErrNotReady)
       
   305 			{
       
   306 			//
       
   307 			// The OCR has been communicated successfully to the card,
       
   308 			// so now adjust the hardware's PSU accordingly
       
   309 			//
       
   310 			psu->SetVoltage(iCurrentOpRange);
       
   311 			if (psu->SetState(EPsuOnFull) != KErrNone)
       
   312 				{
       
   313 				return(KMMCErrHardware);
       
   314 				}
       
   315 
       
   316 			// We can be sure that this is at least an IO Card
       
   317 			CardArray().CardP(iCxCardCount)->iFlags |= KSDIOCardIsIOCard;
       
   318 			
       
   319 			//
       
   320 			// Restore the original error conditions and timeout settings
       
   321 			//
       
   322 			iConfig.SetMode( EffectiveModes(s.iConfig) & KMMCModeEnableTimeOutRetry );
       
   323 			iConfig.SetPollAttempts(KMMCMaxPollAttempts);
       
   324 
       
   325 			//
       
   326 			// Initialise memory if present, otherwise configure the IO Card
       
   327 			//
       
   328 			iCxPollRetryCount = 0;	// Re-Initialise for RCA poll check
       
   329 			SMF_GOTOS(iMemoryPresent ? EStInitMemoryCard : EStIssueSendRCA)
       
   330 			}
       
   331 		else
       
   332 			{
       
   333 			//
       
   334 			// IO Not Ready (IORDY=0) - Still powering up
       
   335 			//
       
   336 			m.ResetTraps();
       
   337 
       
   338 			if ( ++iCxPollRetryCount > iConfig.OpCondBusyTimeout() )
       
   339 				{
       
   340 				// IO Timeout - Try to initialise memory
       
   341 				SMF_GOTOS(iMemoryPresent ? EStInitMemoryCard : EStGoInactive)
       
   342 				}
       
   343 
       
   344 			SMF_INVOKES(RetryGapTimerSMST, EStInitIOSetWorkingOCR)
       
   345 			}
       
   346 
       
   347 	SMF_STATE(EStInitMemoryCard)
       
   348 
       
   349 		// EStInitMemoryCard										
       
   350 		//														
       
   351 		// Initialise the Memory Card or the Memory portion of a Combo Card
       
   352 		//													
       
   353 		// If the IO portion of a Combo Card has just been initialised,
       
   354 		// then the card shall already be stored in the Card Array and the
       
   355 		// supported voltage settings present in iCurrentOpRange, which
       
   356 		// shall be used in the SDCARD Initialisation state machine
       
   357 		
       
   358 		m.SetTraps(KMMCErrResponseTimeOut);
       
   359 		SMF_INVOKES(InitialiseMemoryCardSMST, EStHandleRcaForCardType)
       
   360 	
       
   361 	SMF_STATE(EStHandleRcaForCardType)
       
   362 
       
   363 		// EStHandleRcaForCardType
       
   364 		//	
       
   365 		// At this stage, the SDIO controller should have determined if
       
   366 		// the card contains IO functionality, and the SD controller should
       
   367 		// have determined the type of memory present.  We now combine these
       
   368 		// two factors to work out the actual card type.
       
   369 
       
   370 		m.ResetTraps();
       
   371 
       
   372 		if(err)
       
   373 			{
       
   374 			// Memory timeout - check next card
       
   375 			SMF_GOTOS(EStConfigureMemoryCardDone);
       
   376 			}
       
   377 
       
   378 		TSDIOCard& ioCard = CardArray().Card(iCxCardCount);
       
   379 
       
   380 		if(!(ioCard.IsSDCard() || ioCard.IsIOCard()))
       
   381 			{
       
   382 			SMF_GOTOS(EStIssueSetRCA)
       
   383 			}
       
   384 
       
   385  		ioCard.iCID=s.ResponseP();
       
   386 		iCxPollRetryCount = 0;	// Re-Initialise for RCA poll check
       
   387 		
       
   388 		// Drop through to EStIssueSendRCA if the card is an SD or IO card
       
   389 
       
   390 	SMF_STATE(EStIssueSendRCA)
       
   391 
       
   392 		// EStIssueSendRCA				
       
   393 		//								
       
   394 		// Sends SEND_RCA (CMD3) in SD Mode
       
   395 		
       
   396 		s.FillCommandDesc(ECmdSetRelativeAddr,0);
       
   397 		// override default MMC settings
       
   398 		Command().iSpec.iCommandType=ECmdTypeBCR;
       
   399 		Command().iSpec.iResponseType=ERespTypeR6;
       
   400 		m.ResetTraps();
       
   401 
       
   402 		SMF_INVOKES(ExecCommandSMST,EStSendRCACheck)
       
   403 
       
   404 	SMF_STATE(EStIssueSetRCA)
       
   405 
       
   406 		// EStIssueSetRCA						
       
   407 		//									
       
   408 		// Sends SET_RCA (CMD3) for MMC Cards
       
   409 		//
       
   410 		// The card array allocates an RCA, either the old RCA
       
   411 		// if we have seen this card before, or a new one.
       
   412 		
       
   413 		TRCA rca;
       
   414 		CardArray().AddCardSDMode(iCxCardCount, s.ResponseP(), &rca);
       
   415 
       
   416 		// Now assign the new RCA to the card
       
   417 		s.FillCommandDesc(ECmdSetRelativeAddr,TMMCArgument(rca));
       
   418 		SMF_INVOKES(ExecCommandSMST,EStRCADone)
       
   419 
       
   420 	SMF_STATE(EStSendRCACheck)
       
   421 
       
   422 		// EStIssueSendRCA									
       
   423 		//													
       
   424 		// Checks response to SEND_RCA (CMD3) and selects the card	
       
   425 		//
       
   426 		// We need to check that the RCA recieved from the card doesn't clash
       
   427 		// with any others in this stack. RCA is first 2 bytes of response buffer (in big endian)
       
   428 
       
   429 		TInt err = KErrNone;	
       
   430 		TSDIOCard& ioCard = CardArray().Card(iCxCardCount);
       
   431 		
       
   432 		TRCA rca=(TUint16)((s.ResponseP()[0]<<8) | s.ResponseP()[1]);
       
   433 
       
   434 		if(ioCard.IsIOCard())
       
   435 			{
       
   436 			err = CardArray().AddSDIOCard(iCxCardCount, rca, iFunctionCount);
       
   437 			}
       
   438 		else
       
   439 			{
       
   440 			err = CardArray().AddSDCard(iCxCardCount, rca);
       
   441 			}
       
   442 
       
   443 		if(err != KErrNone)
       
   444 			{
       
   445 			if(++iCxPollRetryCount<KMaxRCASendLoops)
       
   446 				{
       
   447 				SMF_GOTOS(EStIssueSendRCA)
       
   448 				}
       
   449 			else
       
   450 				{
       
   451 				// Memory only cards cannot accept CMD15 until CMD3 has been succesfully
       
   452 				// recieved and we have entered STBY state.  IO Cards can accept RCA=0000
       
   453 				SMF_GOTOS(ioCard.IsIOCard() ? EStGoInactive : EStCheckNextCard)
       
   454 				}
       
   455 			}
       
   456 
       
   457 		// ...drop through to next state (EStRCADone)
       
   458 
       
   459 	SMF_STATE(EStRCADone)
       
   460 
       
   461 		// Cards is initialised so get its CSD
       
   462 		m.ResetTraps();	// We are no longer processing any errors
       
   463 
       
   464 		TSDIOCard& ioCard = CardArray().Card(iCxCardCount);
       
   465 
       
   466 		if(ioCard.IsIOCard() && !ioCard.IsSDCard())
       
   467 			{
       
   468 			// IO Only Card - Jump straight to the IO Configuration SM
       
   469 			SMF_INVOKES(ConfigureIoCardSMST, EStCheckNextCard)
       
   470 			}
       
   471 		else
       
   472 			{
       
   473 			// Initialise cards containing memory first, then configure IO.
       
   474 			// This ensures that the memory portion will have set the 
       
   475 			// bus with via ACMD6 prior to setting the width of the IO controller.
       
   476 			// The SDIO specification states that the bus width of a combo card
       
   477 			// shall not change until BOTH controllers have been notified.
       
   478 			// (ie - ACMD6 + IO_BUS_WIDTH)
       
   479 			SMF_INVOKES(ConfigureMemoryCardSMST, EStConfigureMemoryCardDone)
       
   480 			}
       
   481 
       
   482 	SMF_STATE(EStConfigureMemoryCardDone)
       
   483 
       
   484 		if(CardArray().Card(iCxCardCount).IsComboCard())
       
   485 			{
       
   486 			// Combo Card - Need to initialise IO after Memory			
       
   487 			SMF_INVOKES(ConfigureIoCardSMST, EStCheckNextCard)
       
   488 			}
       
   489 	
       
   490 		SMF_GOTOS(EStCheckNextCard)
       
   491 
       
   492 	SMF_STATE(EStGoInactive)
       
   493 
       
   494 		// EStGoInactive
       
   495 		//				
       
   496 		// Issues CMD15 to enter Inactive state in case of initialisation errors
       
   497 		// IO Cards accept CMD15 with RCA=0, so it's OK if we enter here before
       
   498 		// issuing CMD3 - However, this is not true for Memory Only Cards
       
   499 
       
   500 		TSDIOCard& ioCard = CardArray().Card(iCxCardCount);
       
   501 		s.FillCommandDesc(ECmdGoInactiveState, TMMCArgument(ioCard.iRCA));
       
   502 		SMF_INVOKES(ExecCommandSMST, EStCheckNextCard)
       
   503 
       
   504 	SMF_STATE(EStCheckNextCard)
       
   505 
       
   506 		// EStCheckNextCard
       
   507 		//				
       
   508 		// Checks the next card in the stack (or exits)
       
   509 
       
   510 		if (++iCxCardCount < (TInt)iMaxCardsInStack)
       
   511 			{
       
   512 			// Check the next card
       
   513 			SMF_GOTOS(EStInitIOReset)
       
   514 			}
       
   515 		else
       
   516 			{
       
   517 			 // Set back to broadcast mode and exit
       
   518 			TRACE2(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackPSLCalledAddressCard, reinterpret_cast<TUint32>(this), KBroadcastToAllCards); // @SymTraceDataPublishedTvk
       
   519 			AddressCard(KBroadcastToAllCards);
       
   520 			TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackPSLAddressCardReturned, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
   521 			}
       
   522 
       
   523 		TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackAcquireStackReturning, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk	
       
   524 	
       
   525 	SMF_END
       
   526 	}
       
   527 
       
   528 
       
   529 TMMCErr DSDIOStack::ConfigureIoCardSM()
       
   530 /**
       
   531 */
       
   532 	{
       
   533 		enum states
       
   534 			{
       
   535 			EStBegin=0,
       
   536 			EStSetDefaultBusWidth,
       
   537 			EStGetCommonConfig,
       
   538 			EStReadFunctionBasicRegisters,
       
   539 			EStDeselectCard,
       
   540 			EStDone,
       
   541 			EStEnd
       
   542 			};		
       
   543         
       
   544 		DSDIOSession& s=SDIOSession();        
       
   545         
       
   546 	SMF_BEGIN
       
   547 
       
   548         SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), ">DSDIOStack::ConfigureIoCardSM()")); // @SymTraceDataInternalTechnology
       
   549         
       
   550 		// Cards is initialised so get its CSD
       
   551 		m.ResetTraps();	// We are no longer processing any errors
       
   552 
       
   553 		TSDIOCard* ioCardP = static_cast<TSDIOCard*>(s.iCardP);
       
   554 		TRACE2(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackPSLCalledAddressCard, reinterpret_cast<TUint32>(this), ioCardP->iIndex-1); // @SymTraceDataPublishedTvk
       
   555 		AddressCard(ioCardP->iIndex-1);
       
   556 		TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackPSLAddressCardReturned, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
   557 
       
   558 		// Successfully added the card, so now select so we can interrogate further
       
   559 		TUint32 arg = TUint32(CardArray().Card(iCxCardCount).RCA()) << 16;
       
   560 		s.FillCommandDesc(ECmdSelectCard, arg);
       
   561 		SMF_INVOKES(ExecCommandSMST, EStSetDefaultBusWidth)
       
   562 
       
   563 	SMF_STATE(EStSetDefaultBusWidth)
       
   564 
       
   565 		// EStSetDefaultBusWidth								
       
   566 		//													
       
   567 		// All commands so far have relied on transfer over CMD	line.
       
   568 		// This state ensures that the card transfers data in 1-bit mode
       
   569 		// (in-case the card was not powered down for some reason)
       
   570 		// (This also verifies that the previous steps have succeeded)
       
   571 		
       
   572 		s.iCardP = static_cast<TSDIOCard*>(CardArray().CardP(iCxCardCount));
       
   573 		s.FillIoModifyCommandDesc(Command(), 0, KCCCRRegBusInterfaceControl, 0x00, KSDIOCardBicMaskBusWidth, NULL);
       
   574 		SMF_INVOKES(CIMIoModifySMST, EStGetCommonConfig)	
       
   575 
       
   576 	SMF_STATE(EStGetCommonConfig)
       
   577 
       
   578 		// EStGetCommonConfig								
       
   579 		//													
       
   580 		// Interrogate the IO capabilities (uses GetIoCommonConfigSM)
       
   581 
       
   582 		DoSetBusWidth(KSDBusWidth1);
       
   583 
       
   584 		SMF_INVOKES(CIMGetIoCommonConfigSMST, EStReadFunctionBasicRegisters);
       
   585 
       
   586 	SMF_STATE(EStReadFunctionBasicRegisters)
       
   587 
       
   588 		// EStReadFunctionBasicRegisters
       
   589 		//							
       
   590 		// Interrogate the FBR of each function (uses GetFunctionBasicRegistersSM)
       
   591 		
       
   592 		SMF_INVOKES(CIMReadFunctionBasicRegistersSMST, EStDeselectCard);
       
   593 
       
   594 	SMF_STATE(EStDeselectCard)
       
   595 
       
   596 		// EStDeselectCard	
       
   597 		
       
   598 		s.FillCommandDesc(ECmdSelectCard, 0);
       
   599 		SMF_INVOKES(ExecCommandSMST, EStDone)
       
   600 
       
   601 	SMF_STATE(EStDone)
       
   602         
       
   603         SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "<DSDIOStack::ConfigureIoCardSM()")); // @SymTraceDataInternalTechnology
       
   604 		// All Done
       
   605 
       
   606 	SMF_END
       
   607 	}
       
   608 
       
   609 
       
   610 TMMCErr DSDIOStack::GetIoCommonConfigSM()
       
   611 /**
       
   612 This macro interrogates the card and performs some IO initialisation.
       
   613 
       
   614 In particular, we use the following during initialisation:
       
   615 
       
   616 1. Finds the mandatory CIS Tuples
       
   617 2. CCCR Revision, SDIO Revision
       
   618 3. LSC     - Low Speed Device (used to determine FMax)
       
   619 4. 4BLS    - If LSC, then this determines if 4-Bit mode is supported
       
   620 5. BW[1:0] - Bus Width (Selects between 1 and 4-bit bus)
       
   621 6. SHS     - Supports High Speed Mode 
       
   622 
       
   623 The remaining information retained in the card class for further use
       
   624 (ie - Supports Multi-Block, CIS Pointer etc..)
       
   625 
       
   626 This state machine first searches for the Common Function Extension Tuple
       
   627 int the CIS (Which is MANDATORY for SDIO cards) in order to determine
       
   628 the FN0 Maximum Block/Byte Count.
       
   629 
       
   630 This state machine also makes use of IO_RW_EXTENDED (CMD53) to read the
       
   631 entire CCCR, rather than issuing single IO_RW_DIRECT (CMD52) commands.
       
   632 This is more efficient than transferring 4x48-Bit commands and the response
       
   633 (4 registers is the minimum number of registers that we need to read), and
       
   634 also reduces the complexity of the state machine.
       
   635 
       
   636 @return TMMCErr Error Code
       
   637 */
       
   638 	{
       
   639 		enum states
       
   640 			{
       
   641 			EStBegin=0,
       
   642 			EStGotCommonCisPointer,
       
   643 			EStFindCommonTuple,
       
   644 			EStFoundCommonTuple,
       
   645 			EStGotTupleExtensionType,
       
   646 			EStGotFn0BlockSize,
       
   647 			EStGotMaxTranSpeed,
       
   648 			EStIOReadCCCR,
       
   649 			EStIOParseCCCR,
       
   650 			EStSetE4MI,
       
   651 			EStTestSHS,
       
   652 			EStSetEHS,
       
   653 			EStDone,
       
   654 			EStEnd
       
   655 			};
       
   656 		
       
   657 		DSDIOSession& s=SDIOSession();
       
   658 		TSDIOCard* ioCardP = static_cast<TSDIOCard*>(CardArray().CardP(iCxCardCount));
       
   659 
       
   660 	SMF_BEGIN
       
   661 	
       
   662         SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), ">DSDIOStack::GetIoCommonConfigSM()")); // @SymTraceDataInternalTechnology
       
   663 	
       
   664 		// EStBegin
       
   665 		//
       
   666 		// Start off by reading the common CIS pointer from the CCCR
       
   667 
       
   668 		ioCardP->iCommonConfig.iCommonCisP = 0;
       
   669 		s.FillDirectCommandDesc(Command(), ECIMIoReadDirect, 0, KCCCRRegCisPtrLo, 0x00, (TUint8*)&ioCardP->iCommonConfig.iCommonCisP, 3);
       
   670 		s.iSessionID = (TMMCSessionTypeEnum)ECIMIoReadDirect;
       
   671 		SMF_INVOKES(CIMIoReadWriteDirectSMST, EStGotCommonCisPointer)
       
   672 
       
   673 	SMF_STATE(EStGotCommonCisPointer)
       
   674 	
       
   675 		// EStGotCommonCisPointer
       
   676 		//
       
   677 		// Verify the CIS pointer and set up for the tuple walk
       
   678 
       
   679 		if(ioCardP->iCommonConfig.iCommonCisP == 0)
       
   680 			{
       
   681 			// Common CIS Pointer is Mandatory for IO Cards
       
   682 			SMF_RETURN(KMMCErrNotSupported)
       
   683 			}		
       
   684 		
       
   685 		TSDIOTupleInfo* tupleInfoP = (TSDIOTupleInfo*)iBufCCCR;
       
   686 
       
   687 		tupleInfoP->iTupleId = KSdioCisTplFunce;
       
   688 		tupleInfoP->iLength  = 0;
       
   689 		tupleInfoP->iAddress = ioCardP->iCommonConfig.iCommonCisP;
       
   690 
       
   691 	SMF_STATE(EStFindCommonTuple)
       
   692 	
       
   693 		// EStFindCommonTuple
       
   694 		//
       
   695 		// Find the Function 0 Extension Tuple
       
   696 
       
   697 		// Set up some sensible defaults
       
   698 		// Low-Speed Card  - Maximum speed = 400KHz (SDIO Card Compliance #1-4)
       
   699 		// High-Speed Card - Maximum speed = 25MHz (SDIO Card Compliance #1-2)			
       
   700 		ioCardP->iCommonConfig.iFn0MaxBlockSize = KDefaultFn0BlockSize;		
       
   701 		ioCardP->iCommonConfig.iMaxTranSpeed	= KSDIONoTranSpeed;
       
   702 		ioCardP->iCommonConfig.iCardCaps	   |= KSDIOCardCapsBitLSC;
       
   703 
       
   704 		m.SetTraps(KMMCErrNotFound);
       
   705 		
       
   706 		TSDIOTupleInfo* tupleInfoP = (TSDIOTupleInfo*)iBufCCCR;
       
   707 		s.FillCommandArgs(0, 0, (TUint8*)tupleInfoP, 0);
       
   708 		
       
   709 		s.iSessionID = (TMMCSessionTypeEnum) ECIMIoFindTuple;
       
   710 		SMF_INVOKES(CIMIoFindTupleSMST, EStFoundCommonTuple)
       
   711 
       
   712 	SMF_STATE(EStFoundCommonTuple)
       
   713 
       
   714 		// EStFoundCommonTuple
       
   715 
       
   716 		if(err == KMMCErrNotFound)
       
   717 			{
       
   718 			m.ResetTraps();
       
   719 			s.PushCommandStack();
       
   720 			SMF_GOTOS(EStIOReadCCCR);
       
   721 			}
       
   722 			
       
   723 		TSDIOTupleInfo* tupleInfoP = (TSDIOTupleInfo*)iBufCCCR;
       
   724 		
       
   725 		if(tupleInfoP->iLength < KSdioCisTplExtCmnLen)
       
   726 			{			
       
   727 			// Invalid length for this type of tuple, so try again
       
   728 			tupleInfoP->iAddress += (KSdioTupleOffsetLink + tupleInfoP->iLength);
       
   729 			SMF_GOTOS(EStFindCommonTuple)
       
   730 			}
       
   731 
       
   732 		m.ResetTraps();
       
   733 		
       
   734 		// Now read the TPLFE_TYPE value to ensure that this is the Common Tuple
       
   735 
       
   736 		s.PushCommandStack();
       
   737 		s.FillDirectCommandDesc(Command(), ECIMIoReadDirect, 0, tupleInfoP->iAddress + KSdioExtOffIdent, 0x00, NULL);
       
   738 		s.iSessionID = (TMMCSessionTypeEnum)ECIMIoReadDirect;
       
   739 		SMF_INVOKES(CIMIoReadWriteDirectSMST, EStGotTupleExtensionType)
       
   740 		
       
   741 	SMF_STATE(EStGotTupleExtensionType)
       
   742 
       
   743 		// EStGotTupleExtensionType
       
   744 		//
       
   745 		// Verify the contents of the extension tuple type code
       
   746 
       
   747 		const TSDIOResponseR5 response(s.ResponseP());
       
   748 		TUint8 readVal = response.Data();
       
   749 		
       
   750 		s.PopCommandStack();
       
   751 		
       
   752 		TSDIOTupleInfo* tupleInfoP = (TSDIOTupleInfo*)iBufCCCR;
       
   753 		
       
   754 		if(readVal != KSdioExtCmnIdent)
       
   755 			{
       
   756 			tupleInfoP->iAddress += (KSdioTupleOffsetLink + tupleInfoP->iLength);
       
   757 			SMF_GOTOS(EStFindCommonTuple)
       
   758 			}
       
   759 
       
   760 		// Found the common extension tuple. Now read the FN0 block size.
       
   761 		
       
   762 		s.PushCommandStack();
       
   763 		
       
   764 		s.FillDirectCommandDesc(Command(), ECIMIoReadDirect, 0, tupleInfoP->iAddress + KSdioExtCmnOffFn0MBSLo, 0x00, (TUint8*)&ioCardP->iCommonConfig.iFn0MaxBlockSize, 2);
       
   765 		s.iSessionID = (TMMCSessionTypeEnum)ECIMIoReadDirect;
       
   766 		SMF_INVOKES(CIMIoReadWriteDirectSMST, EStGotFn0BlockSize)
       
   767 		
       
   768 	SMF_STATE(EStGotFn0BlockSize)
       
   769 
       
   770 		// EStGotFn0BlockSize
       
   771 		//
       
   772 		// Validates the FN0 Block Size, and reads the MAX_TRAN_SPEED tuple entry
       
   773 
       
   774 		if(ioCardP->iCommonConfig.iFn0MaxBlockSize == 0)
       
   775 			{
       
   776 			// This is an invalid block/byte size for Function Zero
       
   777 			// (This maintains compatability with some early SDIO devices)
       
   778 			ioCardP->iCommonConfig.iFn0MaxBlockSize = KDefaultFn0BlockSize;
       
   779 			}
       
   780 
       
   781 		TSDIOTupleInfo* tupleInfoP = (TSDIOTupleInfo*)iBufCCCR;				
       
   782 		s.FillDirectCommandDesc(Command(), ECIMIoReadDirect, 0, tupleInfoP->iAddress + KSdioExtCmnOffMaxTranSpeed, 0x00, (TUint8*)&ioCardP->iCommonConfig.iMaxTranSpeed, 1);
       
   783 		s.iSessionID = (TMMCSessionTypeEnum)ECIMIoReadDirect;
       
   784 		SMF_INVOKES(CIMIoReadWriteDirectSMST, EStGotMaxTranSpeed)
       
   785 		
       
   786 	SMF_STATE(EStGotMaxTranSpeed)
       
   787 
       
   788 		// EStGotMaxTranSpeed
       
   789 		//
       
   790 		// Validates the MAX_TRAN_SPEED tuple entry
       
   791 
       
   792 		if((ioCardP->iCommonConfig.iMaxTranSpeed & 0x80) != 0)
       
   793 			{
       
   794 			ioCardP->iCommonConfig.iMaxTranSpeed = KSDIONoTranSpeed;
       
   795 			}
       
   796 
       
   797 		// ...drop through to next state
       
   798 
       
   799 	SMF_STATE(EStIOReadCCCR)
       
   800 
       
   801 		// EStIOReadCCCR										
       
   802 		//													
       
   803 		// Reads the CCCR using IO_RW_EXTENDED (CMD53) command
       
   804 		// (This will use byte mode as we have not yet read the SMB bit)
       
   805 
       
   806 		s.PopCommandStack();	
       
   807 				
       
   808 		memclr(iBufCCCR, KSDIOCccrLength);
       
   809 
       
   810 		s.iCardP = ioCardP;		
       
   811 		s.PushCommandStack();
       
   812 
       
   813 #ifdef SYMBIAN_FUNCTION0_CMD53_NOTSUPPORTED
       
   814 		s.FillDirectCommandDesc(Command(), ECIMIoReadDirect, 0, 0, 0x00, iBufCCCR, KSDIOCccrLength);
       
   815 		s.iSessionID = (TMMCSessionTypeEnum)ECIMIoReadDirect;
       
   816 		SMF_INVOKES(CIMIoReadWriteDirectSMST, EStIOParseCCCR)
       
   817 #else
       
   818 		s.FillExtendedCommandDesc(Command(), ECIMIoReadMultiple, 0, 0, KSDIOCccrLength, iBufCCCR, ETrue);
       
   819 		SMF_INVOKES(CIMIoReadWriteExtendedSMST,EStIOParseCCCR)
       
   820 #endif
       
   821 	SMF_STATE(EStIOParseCCCR)
       
   822 		
       
   823 		// EStIOParseCCCR									
       
   824 		//													
       
   825 		// Parse the contents of the CCCR and extract the usefil info.
       
   826 
       
   827 		s.PopCommandStack();
       
   828 
       
   829 		TRACE_CCCR_INFO()
       
   830 		
       
   831 		//
       
   832 		// Store the important information obtained from the CCCR
       
   833 		//
       
   834 		ioCardP->iCommonConfig.iRevision	= iBufCCCR[KCCCRRegSdioRevision];
       
   835 		ioCardP->iCommonConfig.iSDFormatVer = iBufCCCR[KCCCRRegSdSpec];
       
   836 		ioCardP->iCommonConfig.iCardCaps	= iBufCCCR[KCCCRRegCardCapability];
       
   837 		ioCardP->iCommonConfig.iCommonCisP  = iBufCCCR[KCCCRRegCisPtrHi] << 16 | iBufCCCR[KCCCRRegCisPtrMid] << 8 | iBufCCCR[KCCCRRegCisPtrLo];
       
   838 		
       
   839 		// If we have not yet deduced the Maximum Tran. Speed, base it on the device capabilities
       
   840 		if(ioCardP->iCommonConfig.iMaxTranSpeed == KSDIONoTranSpeed)
       
   841 			{
       
   842 			ioCardP->iCommonConfig.iMaxTranSpeed = (ioCardP->iCommonConfig.iCardCaps & KSDIOCardCapsBitLSC) ? KSDIODefaultLowTranSpeed : KSDIODefaultHighTranSpeed;
       
   843 			}
       
   844 			
       
   845 		//
       
   846 		// We can now set the bus width, depending on the values reported in the CCCR
       
   847 		// (4-Bit Support is Mandatory for High Speed Cards, and optional for Low Speed Cards)
       
   848 		//
       
   849 		// This assumes that the memory portion of a Combo Card has been initialised first.
       
   850 		//
       
   851 		// ...also disable the CD Pullup using CD_DISABLE bit
       
   852 		//
       
   853 		TUint8 busInterfaceControl = (TUint8)((iBufCCCR[KCCCRRegBusInterfaceControl] & ~KSDIOCardBicMaskBusWidth) | KSDIOCardBicBitCdDisable);
       
   854 
       
   855 		const TUint8 lowSpeed4BitMask = KSDIOCardCapsBitLSC | KSDIOCardCapsBit4BLS;
       
   856 		if((ioCardP->IsComboCard() && (ioCardP->BusWidth() == 4)) || ioCardP->IsIOCard())
       
   857 			{
       
   858 			if(((ioCardP->iCommonConfig.iCardCaps & lowSpeed4BitMask) == lowSpeed4BitMask) ||
       
   859 				(!(ioCardP->iCommonConfig.iCardCaps & KSDIOCardCapsBitLSC)))
       
   860 				{
       
   861 				busInterfaceControl |= KSDIOCardBicBitBusWidth4;
       
   862 				}
       
   863 			}
       
   864 
       
   865 		// Gets the High Speed register
       
   866 		ioCardP->iCommonConfig.iHighSpeed  = iBufCCCR[KCCCRRegHighSpeed];
       
   867 		
       
   868 		// Notify the PSL of the required bus width
       
   869 		DoSetBusWidth((busInterfaceControl & KSDIOCardBicBitBusWidth4) ? KSDBusWidth4 : KSDBusWidth1);
       
   870 		
       
   871 		// Write to the Bus Interface Control[Offset 7] in the CCCR
       
   872 		s.PushCommandStack();
       
   873 		s.FillDirectCommandDesc(Command(), ECIMIoWriteDirect, 0x00, KCCCRRegBusInterfaceControl, busInterfaceControl, NULL);
       
   874 		SMF_INVOKES(CIMIoReadWriteDirectSMST, (iBufCCCR[KCCCRRegCardCapability] & KSDIOCardCapsBitS4MI) ? EStSetE4MI : EStTestSHS)
       
   875 
       
   876 	SMF_STATE(EStSetE4MI)
       
   877 
       
   878 		// EStSetE4MI
       
   879 		//
       
   880 		// Sets the E4MI bit in the CCCR (if the S4MI bit is set)
       
   881 
       
   882 		const TUint8 cardCapability = (TUint8)(iBufCCCR[KCCCRRegCardCapability] | KSDIOCardCapsBitE4MI);
       
   883 		s.FillDirectCommandDesc(Command(), ECIMIoWriteDirect, 0x00, KCCCRRegCardCapability, cardCapability, NULL);
       
   884 		SMF_INVOKES(CIMIoReadWriteDirectSMST, EStTestSHS)
       
   885 
       
   886 	SMF_STATE(EStTestSHS)
       
   887 		
       
   888 		// EStTestSHS
       
   889 		//
       
   890 		// Check the SHS bit in the CCCR 
       
   891 	
       
   892 		if (iBufCCCR[KCCCRRegHighSpeed] & KSDIOCardHighSpeedSHS)
       
   893 			SMF_GOTOS(EStSetEHS)
       
   894 		else
       
   895 			SMF_GOTOS(EStDone)
       
   896 		
       
   897 	SMF_STATE(EStSetEHS)
       
   898 
       
   899 #if defined(_DISABLE_HIGH_SPEED_MODE_)
       
   900 		SMF_GOTOS(EStDone)
       
   901 #else
       
   902 		// EStSetEHS
       
   903 		//
       
   904 		// Sets the EHS bit in the CCCR (if the SHS bit is set)
       
   905 
       
   906 		const TUint8 highSpeedMode = (TUint8)(iBufCCCR[KCCCRRegHighSpeed] | KSDIOCardHighSpeedEHS);
       
   907 		s.FillDirectCommandDesc(Command(), ECIMIoWriteDirect, 0x00, KCCCRRegHighSpeed, highSpeedMode, NULL);
       
   908 		SMF_INVOKES(CIMIoReadWriteDirectSMST, EStDone)
       
   909 #endif
       
   910 		
       
   911 	SMF_STATE(EStDone)
       
   912 
       
   913 		s.PopCommandStack();
       
   914 		
       
   915 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "<DSDIOStack::GetIoCommonConfigSM()")); // @SymTraceDataInternalTechnology
       
   916 	
       
   917 	SMF_END
       
   918 	}
       
   919 
       
   920 
       
   921 TMMCErr DSDIOStack::ReadFunctionBasicRegistersSM()
       
   922 /**
       
   923 This macro interrogates the FBR of each function.
       
   924 
       
   925 @return TMMCErr Error Code
       
   926 */
       
   927 	{
       
   928 		enum states
       
   929 			{
       
   930 			EStBegin=0,
       
   931 			EStReadFBR,
       
   932 			EStValidateCIS,
       
   933 			EStValidateFBR,
       
   934 			EStCheckNextFunction,
       
   935 			EStDone,
       
   936 			EStEnd
       
   937 			};
       
   938 
       
   939         
       
   940 
       
   941 		DSDIOSession& s=SDIOSession();
       
   942 		TSDIOCard* ioCardP = static_cast<TSDIOCard*>(CardArray().CardP(iCxCardCount));
       
   943 
       
   944 	SMF_BEGIN
       
   945 	
       
   946         SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), ">DSDIOStack::ReadFunctionBasicRegistersSM()")); // @SymTraceDataInternalTechnology
       
   947         
       
   948 		iFunctionScan = 1;
       
   949 		
       
   950 		if(iFunctionCount == 0)
       
   951 			{
       
   952 			// There are no functions to interrogate, so exit
       
   953 			SMF_EXIT
       
   954 			}
       
   955 
       
   956 		// From here on, iFunctionCount shall be modified so we must use ioCardP->FunctionCount()
       
   957 
       
   958 	SMF_STATE(EStReadFBR)
       
   959 
       
   960 		// EStReadFBR									
       
   961 		//												
       
   962 		// Read the Function Basic Register for the current function.
       
   963 		
       
   964 		s.iCardP = ioCardP;
       
   965 
       
   966 // Only read FBR upto the CSA Data Pointer and do not read the CSA Data Window.
       
   967 // Some non-compliant cards report OUT_OF_RANGE if the CSA Data window is read when CSA is not supported.
       
   968 #ifdef SYMBIAN_FUNCTION0_CMD53_NOTSUPPORTED
       
   969 		s.FillDirectCommandDesc(Command(), ECIMIoReadDirect, 0, KFBRFunctionOffset * iFunctionScan, 0x00, iPSLBuf, KSDIOFbrLength);
       
   970 		s.iSessionID = (TMMCSessionTypeEnum)ECIMIoReadDirect;
       
   971 		SMF_INVOKES(CIMIoReadWriteDirectSMST, EStValidateCIS)
       
   972 #else
       
   973 		s.FillExtendedCommandDesc(Command(), ECIMIoReadMultiple, 0, KFBRFunctionOffset * iFunctionScan, KSDIOFbrLength, iPSLBuf, ETrue);
       
   974 		SMF_INVOKES(CIMIoReadWriteExtendedSMST, EStValidateCIS)
       
   975 #endif
       
   976 
       
   977 	SMF_STATE(EStValidateCIS)
       
   978 
       
   979 		// EStValidateCIS
       
   980 		//				
       
   981 		// To cope with early cards that don't report functions in sequence,
       
   982 		// this checks for a non-zero CIS pointer and a valid tuple chain.
       
   983 
       
   984 		const TUint32 cisPtr = iPSLBuf[KFBRRegCisPtrHi] << 16 | iPSLBuf[KFBRRegCisPtrMid] << 8 | iPSLBuf[KFBRRegCisPtrLo];
       
   985 
       
   986 		if(cisPtr >= KSdioCisAreaMin && cisPtr <= KSdioCisAreaMax)
       
   987 			{
       
   988 			s.FillDirectCommandDesc(Command(), ECIMIoReadDirect, 0, cisPtr, 0x00, NULL);
       
   989 			s.iSessionID = (TMMCSessionTypeEnum)ECIMIoReadDirect;		
       
   990 			SMF_INVOKES(CIMIoReadWriteDirectSMST, EStValidateFBR)
       
   991 			}		
       
   992 			
       
   993 		SMF_GOTOS(EStCheckNextFunction)
       
   994 
       
   995 	SMF_STATE(EStValidateFBR)
       
   996 
       
   997 		// EStValidateFBR
       
   998 		//				
       
   999 		// Validate the first CIS tuple, extracts info from the FBR, and move on to the next function.
       
  1000 		
       
  1001 		const TSDIOResponseR5 response(s.ResponseP());
       
  1002 		TUint8 tupleId = response.Data();
       
  1003 
       
  1004 		if(tupleId != KSdioCisTplEnd)
       
  1005 			{
       
  1006 			iFunctionCount--;
       
  1007 
       
  1008 			if (NULL == ioCardP->IoFunction(iFunctionScan))
       
  1009 			    {
       
  1010     			if(ioCardP->CreateFunction(iFunctionScan) != KErrNone)
       
  1011 	    			{
       
  1012 			    	SMF_RETURN(KMMCErrGeneral)
       
  1013 				    }
       
  1014 			    }
       
  1015 
       
  1016 			TSDIOFunction* pFunction = ioCardP->IoFunction(iFunctionScan);
       
  1017 			
       
  1018 			if(pFunction)
       
  1019 				{
       
  1020 				SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:Validate Function(%d)",iFunctionScan)); // @SymTraceDataInternalTechnology
       
  1021 				
       
  1022 				pFunction->iCapabilities.iNumber     = iFunctionScan;
       
  1023 				pFunction->iCapabilities.iDevCodeEx	 = iPSLBuf[KFBRRegExtendedCode];
       
  1024 				pFunction->iCapabilities.iType       = (TSdioFunctionType)(iPSLBuf[KFBRRegInterfaceCode] & KFBRRegInterfaceCodeMask);
       
  1025 				pFunction->iCapabilities.iHasCSA     = (iPSLBuf[KFBRRegInterfaceCode] & KFBRRegSupportsCSA) ? ETrue : EFalse;
       
  1026 				pFunction->iCapabilities.iPowerFlags = (TUint8)(iPSLBuf[KFBRRegPowerFlags] & KFBRRegPowerSupportMask);
       
  1027 
       
  1028 				pFunction->iCisPtr = iPSLBuf[KFBRRegCisPtrHi] << 16 | iPSLBuf[KFBRRegCisPtrMid] << 8 | iPSLBuf[KFBRRegCisPtrLo];
       
  1029 				pFunction->iCsaPtr = iPSLBuf[KFBRRegCsaPtrHi] << 16 | iPSLBuf[KFBRRegCsaPtrMid] << 8 | iPSLBuf[KFBRRegCsaPtrLo];
       
  1030 				
       
  1031 				pFunction->iCurrentBlockSize = 0;
       
  1032 
       
  1033 				TRACE_FUNCTION_INFO(pFunction)
       
  1034 				}
       
  1035 			else
       
  1036 				{
       
  1037 				SMF_RETURN(KMMCErrNotFound)
       
  1038 				}
       
  1039 			}
       
  1040 
       
  1041 	SMF_STATE(EStCheckNextFunction)
       
  1042 		
       
  1043 		// EStCheckNextFunction
       
  1044 		//
       
  1045 		// Prepare to read the next function's FBR (unless we have exceeded the maximum possible number)
       
  1046 
       
  1047 		iFunctionScan++;
       
  1048 
       
  1049 		if (iFunctionCount && iFunctionScan <= KMaxSDIOFunctions)
       
  1050 			{
       
  1051 			SMF_GOTOS(EStReadFBR)
       
  1052 			}
       
  1053 
       
  1054 	SMF_STATE(EStDone)
       
  1055 
       
  1056 		// EStDone
       
  1057 		//
       
  1058 		// Check that we have found all functions and update the card if required.
       
  1059 
       
  1060 		if(iFunctionCount)
       
  1061 			{
       
  1062 			ioCardP->iFunctionCount = (TUint8)(ioCardP->iFunctionCount - iFunctionCount);
       
  1063 			}
       
  1064 
       
  1065 		iFunctionCount = ioCardP->FunctionCount();
       
  1066 
       
  1067 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "<DSDIOStack::ReadFunctionBasicRegistersSM() FunctionCount: %d",iFunctionCount)); // @SymTraceDataInternalTechnology
       
  1068 
       
  1069 	SMF_END
       
  1070 	}
       
  1071 
       
  1072 	
       
  1073 	
       
  1074 inline TInt DSDIOStack::ExtractSendOpCondResponse(TUint32 aResponseR4, TUint8& aFunctionCount, TBool& aMemPresent, TUint32& aIoOCR)
       
  1075 /**
       
  1076 Checks the contents of the R4 response for the 
       
  1077 number of IO functions, presence of Memory and OCR bits
       
  1078 
       
  1079 @param aResponseR4 The R4 response to be parsed.
       
  1080 @param aFunctionCount Number of IO functions.
       
  1081 @param aMemPresent ETrue is memory is present, EFalse otherwise
       
  1082 @param aIoOCR 24-Bit IO OCR
       
  1083 
       
  1084 @return KErrNone if IO is ready, KErrNotReady otherwise
       
  1085 */
       
  1086 	{
       
  1087 	aFunctionCount = (TUint8)((aResponseR4 & KSDIOFunctionCountMask) >> KSDIOFunctionCountShift);
       
  1088 	aIoOCR = aResponseR4 & KSDIOOCRMask;
       
  1089 	aMemPresent = (aResponseR4 & KSDIOMemoryPresent) ? ETrue : EFalse;
       
  1090 
       
  1091 	if(aResponseR4 & KSDIOReady)
       
  1092 		{
       
  1093 		return(KErrNone);
       
  1094 		}
       
  1095 
       
  1096 	// IO Not Ready
       
  1097 	return(KErrNotReady);
       
  1098 	}
       
  1099 
       
  1100 
       
  1101 EXPORT_C TMMCErr DSDIOStack::CIMIoReadWriteDirectSM()
       
  1102 /**
       
  1103 Implements the state machine for the IO_RW_DIRECT command (CMD52)
       
  1104 @return Standard TMMCErr error code
       
  1105 */
       
  1106 	{
       
  1107 	TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackIoReadWriteDirect, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  1108 
       
  1109 	enum states
       
  1110 			{
       
  1111 			EStBegin=0,
       
  1112 			EStSendCommand,
       
  1113 			EStCommandSent,
       
  1114 			EStDone,
       
  1115 			EStEnd
       
  1116 			};
       
  1117         
       
  1118 		DSDIOSession& s=SDIOSession();
       
  1119 		TMMCCommandDesc& cmd = s.Command();
       
  1120 
       
  1121 	SMF_BEGIN
       
  1122 	
       
  1123 	    SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), ">SDIO:CIMIoReadWriteDirectSM %x",TUint(s.iLastStatus))); // @SymTraceDataInternalTechnology
       
  1124 	    
       
  1125 		s.iState |= KMMCSessStateInProgress;
       
  1126 		
       
  1127 	SMF_STATE(EStSendCommand)
       
  1128 
       
  1129 		SMF_INVOKES(CIMIoIssueCommandCheckResponseSMST, EStCommandSent)
       
  1130 	
       
  1131 	SMF_STATE(EStCommandSent)
       
  1132 		
       
  1133 		if(cmd.iDataMemoryP)
       
  1134 			{
       
  1135 			// Enter here if we are performing RAW operation, or Multi-Byte Read
       
  1136 			const TSDIOResponseR5 response(s.ResponseP());
       
  1137 			*(cmd.iDataMemoryP) = response.Data();
       
  1138 			
       
  1139 			if(cmd.iTotalLength > 1)
       
  1140 				{
       
  1141 				SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:Multi-Byte Read"));				 // @SymTraceDataInternalTechnology
       
  1142 				// modify the address parameter to increment the address
       
  1143 
       
  1144 				cmd.iArgument = (cmd.iArgument & ~KSdioCmdAddressMaskShifted) | 
       
  1145 								((cmd.iArgument + KSdioCmdAddressAIncVal) & KSdioCmdAddressMaskShifted);
       
  1146 
       
  1147 				cmd.iDataMemoryP++;
       
  1148 				cmd.iTotalLength--;
       
  1149 				
       
  1150 				SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:iDataMemoryP: %d",cmd.iDataMemoryP)); // @SymTraceDataInternalTechnology
       
  1151 				SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:iTotalLength %d",cmd.iTotalLength)); // @SymTraceDataInternalTechnology
       
  1152 				
       
  1153 				SMF_GOTOS(EStSendCommand);
       
  1154 				}
       
  1155 			}
       
  1156 
       
  1157 		// No buffer for data, so only perform one byte transfer and return the data in the response
       
  1158 
       
  1159 	SMF_STATE(EStDone)
       
  1160 
       
  1161 		s.iState &= ~KMMCSessStateInProgress;
       
  1162 		
       
  1163 		TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackIoReadWriteDirectReturning, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  1164 
       
  1165 	SMF_END
       
  1166 	}
       
  1167 
       
  1168 EXPORT_C TMMCErr DSDIOStack::CIMIoReadWriteExtendedSM()
       
  1169 /**
       
  1170 Implements the state machine for the IO_RW_EXTENDED command (CMD53)
       
  1171 @return Standard TMMCErr error code
       
  1172 */
       
  1173 	{
       
  1174 	TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackIoReadWriteExtended, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  1175 
       
  1176 	enum states
       
  1177 			{
       
  1178 			EStBegin=0,
       
  1179 			EStFullPower,
       
  1180 			EStSetupBlockCommandLo,
       
  1181 			EStSetupBlockCommandHi,
       
  1182 			EStIssueFirstBlockCommand,
       
  1183 			EstProcessChunk,
       
  1184 			EstSetupNextMemFragment,
       
  1185 			EStIssueBlockCommand,
       
  1186 			EStIssueByteCommand,
       
  1187 			EStCommandSent,
       
  1188 			EStDone,
       
  1189 			EStEnd
       
  1190 			};
       
  1191 					
       
  1192 		DSDIOSession& s=SDIOSession();
       
  1193         TSDIOCard* cardP = static_cast<TSDIOCard*>(s.iCardP);		      
       
  1194 		
       
  1195 	SMF_BEGIN
       
  1196     	
       
  1197         SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), ">DSDIOStack:CIMIoReadWriteExtendedSM %x",TUint(s.iLastStatus))); // @SymTraceDataInternalTechnology
       
  1198         
       
  1199 		s.iState |= KMMCSessStateInProgress;
       
  1200 		
       
  1201 		// The same command is used for both Read and Write, so determine the dt
       
  1202 		// direction from the argument supplied (rather than the command table)
       
  1203 		TMMCCommandDesc& cmd = s.Command();
       
  1204 		
       
  1205 		if(cmd.iTotalLength == 0)
       
  1206 			{
       
  1207 			SMF_RETURN(KMMCErrArgument)
       
  1208 			}
       
  1209 		
       
  1210 		cmd.iSpec.iDirection = (cmd.iArgument & KSdioCmdWrite) ? EDirWrite : EDirRead;
       
  1211 		
       
  1212 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:Direction - %s",((cmd.iArgument & KSdioCmdWrite) ? "Write" : "Read"))); // @SymTraceDataInternalTechnology
       
  1213 	
       
  1214 		const TUint8 functionNumber = s.FunctionNumber();
       
  1215 
       
  1216 		if(functionNumber == 0)
       
  1217 			{
       
  1218 			// Function 0 is not stored in the function list as it a
       
  1219 			// special fixed function with limited capabilities.
       
  1220 			s.iMaxBlockSize = cardP->iCommonConfig.iFn0MaxBlockSize;
       
  1221 			}
       
  1222 		else
       
  1223 			{
       
  1224 			// If we are performing CMD53 on Functions 1:7, then we should have already
       
  1225 			// parsed the CIS and set up a Maximum Block Size.
       
  1226 			const TSDIOFunction* functionP = cardP->IoFunction(functionNumber);
       
  1227 
       
  1228 			if(functionP == NULL)
       
  1229 				{
       
  1230 				SMF_RETURN(KMMCErrNotSupported)
       
  1231 				}
       
  1232 				
       
  1233 			s.iMaxBlockSize = functionP->Capabilities().iMaxBlockSize;
       
  1234             SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:BlockSize:%d)", s.iMaxBlockSize)); // @SymTraceDataInternalTechnology
       
  1235 			}
       
  1236 			
       
  1237 		// maxBlockSize is the maximum block size (block mode), or byte count (byte mode)
       
  1238 		// so a value of zero is invalid (this is obtained from the CIS).
       
  1239 		if(s.iMaxBlockSize == 0)
       
  1240 			{
       
  1241 			SMF_RETURN(KMMCErrNotSupported)
       
  1242 			}
       
  1243 		
       
  1244 		// Ensure that the block size used is supported by the hardware
       
  1245 		TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackPSLCalledMaxBlockSize, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  1246 		const TUint32 pslMaxBlockSize = MaxBlockSize();
       
  1247 		TRACE2(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackPSLMaxBlockSizeReturned, reinterpret_cast<TUint32>(this), pslMaxBlockSize); // @SymTraceDataPublishedTvk
       
  1248 		if(s.iMaxBlockSize > pslMaxBlockSize)
       
  1249 			{
       
  1250 			s.iMaxBlockSize = pslMaxBlockSize;
       
  1251 			}
       
  1252 			
       
  1253 		s.iNumBlocks = (cmd.iTotalLength / s.iMaxBlockSize);
       
  1254 		s.iNumBytes = cmd.iTotalLength - (s.iNumBlocks * s.iMaxBlockSize);
       
  1255 
       
  1256 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:Blocks:%d, Bytes:%d)", s.iNumBlocks, s.iNumBytes)); // @SymTraceDataInternalTechnology
       
  1257 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:Total Bytes:%d)", cmd.iTotalLength)); // @SymTraceDataInternalTechnology
       
  1258 		
       
  1259 		// Disable Preemption until we have set the bus width
       
  1260 		s.iConfig.RemoveMode(KMMCModeEnablePreemption);
       
  1261 	    s.PushCommandStack();
       
  1262 	    
       
  1263 	    // Request BusWidth of 4 Bits
       
  1264 	    s.FillCommandArgs(4, 0, NULL, 0);
       
  1265 		m.SetTraps(KMMCErrNotSupported);
       
  1266 		
       
  1267 		SMF_INVOKES(CIMIoSetBusWidthSMST, EStFullPower)
       
  1268 		
       
  1269 	SMF_STATE(EStFullPower)
       
  1270 	
       
  1271 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:EstFullPower")); // @SymTraceDataInternalTechnology
       
  1272 		
       
  1273 		m.ResetTraps();
       
  1274 		s.PopCommandStack();
       
  1275 	
       
  1276 		if(err == KMMCErrNone || err == KMMCErrNotSupported)
       
  1277 			{
       
  1278 			SMF_GOTOS(((cardP->iCommonConfig.iCardCaps & KSDIOCardCapsBitSMB) && (s.iNumBlocks > 1)) ? EStSetupBlockCommandLo : EstProcessChunk)
       
  1279 			}
       
  1280 
       
  1281 		SMF_RETURN(err)
       
  1282 				
       
  1283 	SMF_STATE(EStSetupBlockCommandLo)
       
  1284 	
       
  1285 	    SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:EstSetupBlockCommandLo")); // @SymTraceDataInternalTechnology
       
  1286 		
       
  1287 		// EStSetupBlockCommand
       
  1288 		//
       
  1289 		// Sets up the block length (low byte) for CMD53 if not already set
       
  1290 						
       
  1291 		// There is no need to set the block size if already set
       
  1292 		const TUint8 functionNumber = s.FunctionNumber();	
       
  1293 		const TSDIOFunction* functionP = cardP->IoFunction(s.FunctionNumber());
       
  1294 
       
  1295 		const TUint16* currentBlockSizeP = (functionNumber == 0) ? &cardP->iCommonConfig.iCurrentBlockSize : &functionP->iCurrentBlockSize;
       
  1296 
       
  1297 		const TUint16 bsMatch = (TUint16)(*currentBlockSizeP ^ s.iMaxBlockSize);
       
  1298 		
       
  1299 		if(bsMatch == 0x0000)
       
  1300 			{
       
  1301 			s.PushCommandStack();
       
  1302 			SMF_GOTOS(EStIssueFirstBlockCommand)
       
  1303 			}
       
  1304 
       
  1305 		if(bsMatch & 0x00FF)
       
  1306 			{					
       
  1307 			const TUint8 blockSizeLo    = (TUint8)(s.iMaxBlockSize & 0xFF);
       
  1308 			const TUint32 bslAddr       = (KFBRFunctionOffset * functionNumber) + KCCCRRegFN0BlockSizeLo; // OK for Function0 and 1:7
       
  1309 
       
  1310 			s.PushCommandStack();		
       
  1311 			s.FillDirectCommandDesc(Command(), ECIMIoWriteDirect, 0x00, bslAddr, blockSizeLo, (TUint8*)currentBlockSizeP);
       
  1312 			SMF_INVOKES(CIMIoReadWriteDirectSMST, EStSetupBlockCommandHi)
       
  1313 			}
       
  1314 			
       
  1315 		s.PushCommandStack();	// ...to match up with the Pop in EStSetupBlockCommandHi
       
  1316 		
       
  1317 		// .. drop through to set Block Length (High)
       
  1318 
       
  1319 	SMF_STATE(EStSetupBlockCommandHi)
       
  1320 	
       
  1321 	    SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:EstSetupBlockCommandHi")); // @SymTraceDataInternalTechnology
       
  1322 	
       
  1323 		// EStSetupBlockCommand
       
  1324 		//
       
  1325 		// Sets up the block length (high byte) for CMD53 if not already set
       
  1326 
       
  1327 		s.PopCommandStack();
       
  1328 		
       
  1329 		const TUint8 functionNumber = s.FunctionNumber();
       
  1330 		const TSDIOFunction* functionP = cardP->IoFunction(functionNumber);
       
  1331 
       
  1332 		const TUint16* currentBlockSizeP = (functionNumber == 0) ? &cardP->iCommonConfig.iCurrentBlockSize : &functionP->iCurrentBlockSize;
       
  1333 		
       
  1334 		if((*currentBlockSizeP ^ s.iMaxBlockSize) & 0xFF00)
       
  1335 			{					
       
  1336 			const TUint8 blockSizeHi = (TUint8)((s.iMaxBlockSize >> 8) & 0xFF);
       
  1337 			const TUint32 bshAddr    = (KFBRFunctionOffset * functionNumber) + KCCCRRegFN0BlockSizeHi; // OK for Function0 and 1:7
       
  1338 			
       
  1339 			s.PushCommandStack();
       
  1340 			s.FillDirectCommandDesc(Command(), ECIMIoWriteDirect, 0x00, bshAddr, blockSizeHi, ((TUint8*)currentBlockSizeP)+1);
       
  1341 			SMF_INVOKES(CIMIoReadWriteDirectSMST, EStIssueFirstBlockCommand)
       
  1342 			}
       
  1343 			
       
  1344 		s.PushCommandStack();	// ...to match up with the Pop in EStIssueFirstBlockCommand
       
  1345 		
       
  1346 		// .. drop through if high byte OK
       
  1347 
       
  1348 	SMF_STATE(EStIssueFirstBlockCommand)
       
  1349 	
       
  1350 	    SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:EstIssueFirstBlockCommand")); // @SymTraceDataInternalTechnology
       
  1351 		
       
  1352 		s.PopCommandStack();				
       
  1353 		
       
  1354 		const TUint8 functionNumber = s.FunctionNumber();
       
  1355 		const TSDIOFunction* functionP = cardP->IoFunction(functionNumber);  
       
  1356     
       
  1357 		const TUint16 currentBlockSize = (functionNumber == 0) ? cardP->iCommonConfig.iCurrentBlockSize : functionP->iCurrentBlockSize;
       
  1358 		if(currentBlockSize != s.iMaxBlockSize)
       
  1359 			{
       
  1360 			// If the block size could not be set, then disable future Block Mode transfers
       
  1361 			// to avoid performing these tests again (this is a compatability check issue)
       
  1362 			cardP->iCommonConfig.iCardCaps &= ~KSDIOCardCapsBitSMB;
       
  1363 			}
       
  1364 		// .. drop through
       
  1365 		
       
  1366 	SMF_STATE(EstProcessChunk)
       
  1367 	    
       
  1368 	    SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:EstProcessChunk")); // @SymTraceDataInternalTechnology
       
  1369 	    s.iConfig.SetMode(KMMCModeEnablePreemption);
       
  1370 	    
       
  1371 	    TMMCCommandDesc& cmd = s.Command();
       
  1372 	    s.iCrrFrgRmn = cmd.iTotalLength;  	    		          	    
       
  1373       
       
  1374         if((cmd.iFlags & KMMCCmdFlagDMARamValid) && (s.iChunk != NULL))
       
  1375             {
       
  1376             //Chunk Params available for this command
       
  1377  	        	        	   
       
  1378     	    SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:SharedChunk Opened")); // @SymTraceDataInternalTechnology
       
  1379                 
       
  1380 	        TUint32 pageSize = Kern::RoundToPageSize(1);
       
  1381 	        
       
  1382 	        // calculate number of possible physical pages
       
  1383 	        // +1 for rounding & +1 for physical page spanning 
       
  1384 	        TUint32 totalPages = (cmd.iTotalLength/pageSize)+2;
       
  1385 	        
       
  1386 	        // Allocate array for list of physical pages
       
  1387 	        TUint32* physicalPages = new TPhysAddr[totalPages];
       
  1388 	        if(!physicalPages)
       
  1389 	            {
       
  1390 	            SMF_RETURN(KMMCErrGeneral)
       
  1391 	            }
       
  1392 	            
       
  1393 	        TInt r = KErrNone;
       
  1394 	        TUint32  offset = (TUint32)cmd.iDataMemoryP; //for chunk based transfer DataMemory pointer contains the chunk offset
       
  1395 	        TLinAddr kernAddr;
       
  1396 			TUint32  mapAttr;
       
  1397 			TUint32  physAddr;
       
  1398 						
       
  1399 			// Query Physical Structure of chunk
       
  1400 			r = Kern::ChunkPhysicalAddress(s.iChunk, offset, cmd.iTotalLength, kernAddr, mapAttr, physAddr, physicalPages);
       
  1401 			
       
  1402             if(r==KErrNone)
       
  1403                 {
       
  1404                 SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:Contiguous RAM Pages")); // @SymTraceDataInternalTechnology
       
  1405                 cmd.iDataMemoryP = (TUint8*)kernAddr;                   
       
  1406                 
       
  1407                 //No need to retain knowledge of underlying memory structure
       
  1408                 delete [] physicalPages;
       
  1409                 }
       
  1410                     
       
  1411 #ifndef __FRAGMENTED_RAM_SUPPORT
       
  1412             else
       
  1413                 {
       
  1414                 SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:Fragmented RAM Pages - Not supported")); // @SymTraceDataInternalTechnology
       
  1415                 
       
  1416                 delete [] physicalPages;
       
  1417                 
       
  1418                 SMF_RETURN(KMMCErrNotSupported)                
       
  1419                 }            
       
  1420 #else
       
  1421             else if(r==1)
       
  1422                 {
       
  1423                 SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:Fragmented RAM Pages (%d pages)", totalPages)); // @SymTraceDataInternalTechnology
       
  1424                 
       
  1425                 // Need to determine the fragments and their sizes
       
  1426                 // RAM pages may all be seperate so alloc a big enough array
       
  1427                 delete [] s.iFrgPgs;
       
  1428                 s.iFrgPgs = new TSDIOFragInfo[totalPages];
       
  1429                 if(!s.iFrgPgs)
       
  1430                     {
       
  1431                     delete [] physicalPages;
       
  1432                     SMF_RETURN(KMMCErrGeneral)                
       
  1433                     }
       
  1434                 
       
  1435                 TUint currFrg = 0;
       
  1436                 
       
  1437                 //Addresses must be converted back to virtual for the PSL
       
  1438                 s.iFrgPgs[currFrg].iAddr = (TUint8*)kernAddr;
       
  1439                 //Calculate the odd size for the first fragment
       
  1440                 s.iFrgPgs[currFrg].iSize = pageSize-(offset%pageSize);
       
  1441                 
       
  1442                 for(TUint i=1; i < totalPages; i++)
       
  1443                     {
       
  1444                     //Check if RAM pages are physically adjacent
       
  1445                     if ((physicalPages[i-1] + pageSize) == physicalPages[i])
       
  1446                         {
       
  1447                         // Pages are contiguous,                  
       
  1448                         s.iFrgPgs[currFrg].iSize += pageSize;                        
       
  1449                         }
       
  1450                     else
       
  1451                         {
       
  1452                         // Pages not contiguous                
       
  1453                         ++currFrg;
       
  1454                         //Calculate virtual memory address of next fragment
       
  1455                         s.iFrgPgs[currFrg].iAddr = s.iFrgPgs[currFrg-1].iAddr+s.iFrgPgs[currFrg-1].iSize;
       
  1456                         s.iFrgPgs[currFrg].iSize = pageSize;
       
  1457                         }
       
  1458                     }
       
  1459                     
       
  1460                 s.iCrrFrg = 0;    
       
  1461                 cmd.iDataMemoryP = s.iFrgPgs[0].iAddr;                    
       
  1462                 s.iCrrFrgRmn = cmd.iTotalLength = s.iFrgPgs[0].iSize;
       
  1463                 
       
  1464                 delete [] physicalPages;
       
  1465                 }          
       
  1466             else
       
  1467                 {                   
       
  1468                 delete [] physicalPages;                
       
  1469                 SMF_RETURN(KMMCErrGeneral)
       
  1470                 }
       
  1471 #endif //__FRAGMENTED_RAM_SUPPORT                
       
  1472 	        }
       
  1473 	    else    
       
  1474 	        {
       
  1475 	        SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:Not a Chunk"));    	         // @SymTraceDataInternalTechnology
       
  1476 	        s.iChunk = NULL;
       
  1477 	        //Ensure DMAable flag not set
       
  1478 	        cmd.iFlags &= ~KMMCCmdFlagDMARamValid;
       
  1479 	        } //END if (KMMCCmdFlagDMARamValid)
       
  1480 	    
       
  1481 	    // ..drop through
       
  1482     
       
  1483     SMF_STATE(EstSetupNextMemFragment)  
       
  1484         
       
  1485         SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:EstSetupNextMemFragment")); // @SymTraceDataInternalTechnology
       
  1486         
       
  1487 #ifdef __FRAGMENTED_RAM_SUPPORT
       
  1488         //Determine if fragment full and next fragment need to be allocated
       
  1489         if ((s.iFrgPgs!=NULL) && (s.iCrrFrgRmn == 0))
       
  1490             {
       
  1491             // Fragment full - Need to setup next page
       
  1492             TMMCCommandDesc& cmd = s.Command();
       
  1493             s.iCrrFrg++;
       
  1494 	        cmd.iDataMemoryP = s.iFrgPgs[s.iCrrFrg].iAddr;
       
  1495 	        s.iCrrFrgRmn = s.iFrgPgs[s.iCrrFrg].iSize;		        
       
  1496             }            
       
  1497 #endif //__FRAGMENTED_RAM_SUPPORT
       
  1498         
       
  1499         //Determine what the next transfer type is
       
  1500         if ((cardP->iCommonConfig.iCardCaps & KSDIOCardCapsBitSMB) && (s.iNumBlocks > 1))
       
  1501             {
       
  1502             
       
  1503 #ifdef __FRAGMENTED_RAM_SUPPORT            
       
  1504             //Determine if fragment has sufficient space for block transfers
       
  1505             if (s.iFrgPgs!=NULL)
       
  1506                 {
       
  1507                 if (s.iCrrFrgRmn < s.iMaxBlockSize )
       
  1508                     {
       
  1509                     //Insufficent space left...
       
  1510                     SMF_GOTOS(EStIssueByteCommand)
       
  1511                     }               
       
  1512                 }
       
  1513 #endif //__FRAGMENTED_RAM_SUPPORT
       
  1514 
       
  1515             SMF_GOTOS(EStIssueBlockCommand)
       
  1516             }
       
  1517         
       
  1518         SMF_GOTOS(EStIssueByteCommand)
       
  1519             	
       
  1520 
       
  1521 	SMF_STATE(EStIssueBlockCommand)
       
  1522 		
       
  1523 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:EstIssueBlockCommand")); // @SymTraceDataInternalTechnology
       
  1524 		
       
  1525 		// Performs data transfer using CMD53 in Block Mode.  This shall be invoked
       
  1526 		// several times if the data cannot be transferred using a single command.	    
       
  1527 		
       
  1528 		TUint32 blocksThisTransfer = 0;
       
  1529 		
       
  1530 		// Still have blocks worth of data to transfer.
       
  1531 		blocksThisTransfer = Min( (s.iNumBlocks & KSdioCmdCountMask),(s.iCrrFrgRmn/s.iMaxBlockSize));
       
  1532 		s.iNumBlocks -= blocksThisTransfer;
       
  1533 		s.iCrrFrgRmn -= (blocksThisTransfer * s.iMaxBlockSize);
       
  1534 		
       
  1535 		TMMCCommandDesc& cmd = s.Command();	
       
  1536 
       
  1537 		TUint32 arg = cmd.iArgument;
       
  1538 		arg &= ~KSdioCmdCountMask;
       
  1539 		arg |= (blocksThisTransfer & KSdioCmdCountMask);	// Set the new block count
       
  1540 		arg |= KSdioCmdBlockMode;							// Ensure Block Mode
       
  1541 		cmd.iArgument = arg;
       
  1542 
       
  1543 		// This is a Multi-Block command, so ensure that iBlockLength and iTotalLength
       
  1544 		// are calculated correctly for the underlying controller.
       
  1545 		cmd.iBlockLength = s.iMaxBlockSize;
       
  1546 		cmd.iTotalLength = blocksThisTransfer * s.iMaxBlockSize;
       
  1547 					
       
  1548 		// ...send the command
       
  1549 		SMF_INVOKES(CIMIoIssueCommandCheckResponseSMST, EStCommandSent)
       
  1550 
       
  1551 		
       
  1552 	SMF_STATE(EStIssueByteCommand)
       
  1553 	
       
  1554 	    SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:EstIssueByteCommand")); // @SymTraceDataInternalTechnology
       
  1555 		
       
  1556 		// EStIssueByteCommand
       
  1557 		//
       
  1558 		// Performs data transfer using CMD53 in Byte Mode.  This is used for transfering
       
  1559 		// 'blocks' of data (if block mode is not supported) and for transferring the last
       
  1560 		// non-block-aligned bytes after block mode transfer.
       
  1561 		
       
  1562 		TUint32 bytesThisTransfer = 0;
       
  1563 		if(s.iNumBlocks && (s.iCrrFrgRmn >= s.iMaxBlockSize))
       
  1564 			{
       
  1565 			SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "Still have blocks worth of data to transfer...")); // @SymTraceDataInternalTechnology
       
  1566 	        // Still have blocks worth of data to transfer...
       
  1567 			bytesThisTransfer = s.iMaxBlockSize;
       
  1568 			--s.iNumBlocks;			
       
  1569 			}
       
  1570 		else if(s.iNumBlocks && (s.iCrrFrgRmn < s.iMaxBlockSize))
       
  1571 		    {
       
  1572 		    SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "Still have blocks worth of data to transfer...but not enough room in the fragment")); // @SymTraceDataInternalTechnology
       
  1573 		    // Still have blocks worth of data to transfer...but not enough room in the fragment
       
  1574 		    // Use whats left in the fragment
       
  1575 		    bytesThisTransfer = s.iCrrFrgRmn;
       
  1576 		    if (s.iCrrFrgRmn > s.iNumBytes)
       
  1577 		        {
       
  1578 		        --s.iNumBlocks;
       
  1579 		        s.iNumBytes += (s.iMaxBlockSize-s.iCrrFrgRmn);
       
  1580 		        }
       
  1581 		    else
       
  1582 		        {
       
  1583 		        s.iNumBytes -= s.iCrrFrgRmn;
       
  1584 		        }
       
  1585 		    }
       
  1586 		else
       
  1587 			{
       
  1588 			SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "Still have partial blocks worth of data to transfer.."));		 // @SymTraceDataInternalTechnology
       
  1589 	        //	Still have partial blocks worth of data to transfer..
       
  1590 			bytesThisTransfer = Min(s.iNumBytes,s.iCrrFrgRmn);
       
  1591 			s.iNumBytes -= bytesThisTransfer;
       
  1592 			SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "s.iNumBytes %d",s.iNumBytes)); // @SymTraceDataInternalTechnology
       
  1593 			SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "bytesThisTransfer %d",bytesThisTransfer)); // @SymTraceDataInternalTechnology
       
  1594 			}
       
  1595 		
       
  1596 		s.iCrrFrgRmn -= bytesThisTransfer;		
       
  1597 		
       
  1598 		TMMCCommandDesc& cmd = s.Command();	
       
  1599 		
       
  1600 		TUint32 arg = cmd.iArgument;
       
  1601 		arg &= ~KSdioCmdCountMask;
       
  1602 		arg |= (bytesThisTransfer & KSdioCmdCountMask);	// Set the new transfer length
       
  1603 		arg &= ~KSdioCmdBlockMode;						// Ensure Byte Mode
       
  1604 		cmd.iArgument = arg;
       
  1605 
       
  1606 		// This is not a Multi-Block command (rather, it is a multiple issue of CMD53)
       
  1607 		// so ensure that iBlockLength == iTotalLength for consistency.
       
  1608 		cmd.iBlockLength = bytesThisTransfer;
       
  1609 		cmd.iTotalLength = bytesThisTransfer;				
       
  1610 			
       
  1611 		// ...send the command
       
  1612 		SMF_INVOKES(CIMIoIssueCommandCheckResponseSMST, EStCommandSent)
       
  1613 	
       
  1614 	SMF_STATE(EStCommandSent)
       
  1615 	
       
  1616         if ((s.iNumBlocks <= 0) && (s.iNumBytes <= 0))
       
  1617             {
       
  1618             // No Data left
       
  1619 		    SMF_GOTOS(EStDone);
       
  1620             }
       
  1621 		
       
  1622 		// Increment the data pointer (iTotalLength is the number of bytes transferred if the last command
       
  1623 		// was a byte mode transfer, or nBlocks*blockSize if it was a Block Mode transfer)
       
  1624     	TMMCCommandDesc& cmd = s.Command();
       
  1625     	
       
  1626 		cmd.iDataMemoryP += cmd.iTotalLength;
       
  1627 		
       
  1628 		if((cmd.iArgument & KSdioCmdAutoInc) == KSdioCmdAutoInc)
       
  1629 			{
       
  1630 			// ...and also increment the start address for the next byte/block transfer
       
  1631 
       
  1632 			const TUint32 KBlockAddressIncrementShifted = (cmd.iTotalLength << KSdioCmdAddressShift);
       
  1633 
       
  1634 			cmd.iArgument = (cmd.iArgument & ~KSdioCmdAddressMaskShifted) | 
       
  1635 							((cmd.iArgument + KBlockAddressIncrementShifted) & KSdioCmdAddressMaskShifted);				
       
  1636 			}
       
  1637 
       
  1638         // Data still to be transmitted
       
  1639 	    SMF_GOTOS(EstSetupNextMemFragment);
       
  1640 		
       
  1641 	SMF_STATE(EStDone)
       
  1642 
       
  1643         //Clean up memory allocated for physical pages if necessary
       
  1644         delete [] s.iFrgPgs;
       
  1645         s.iFrgPgs = NULL;
       
  1646 			
       
  1647 		s.iState &= ~KMMCSessStateInProgress;
       
  1648 
       
  1649 		TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackIoReadWriteExtended, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  1650 		
       
  1651 	SMF_END
       
  1652 
       
  1653 	}
       
  1654 
       
  1655 
       
  1656 TMMCErr DSDIOStack::CIMIoIssueCommandCheckResponseSM()
       
  1657 /**
       
  1658 Implements the state machine for the SDIO command sending (CMD52, CMD53)
       
  1659 @return Standard TMMCErr error code : KMMCErrResponseTimeOut
       
  1660 									  KMMCErrDataTimeOut
       
  1661 									  KMMCErrBusInconsistent
       
  1662 									  KMMCErrArgument
       
  1663 									  KMMCErrDataCRC
       
  1664 									  KMMCErrGeneral
       
  1665 */
       
  1666 	{
       
  1667 		enum states
       
  1668 			{
       
  1669 			EStBegin=0,
       
  1670 			EStRetry,
       
  1671 			EStCommandSent,
       
  1672 			EStRecover,
       
  1673 			EStDone,
       
  1674 			EStEnd
       
  1675 			};
       
  1676 
       
  1677 		DSDIOSession& s=SDIOSession();
       
  1678 		TMMCCommandDesc& cmd = s.Command();
       
  1679 
       
  1680 	SMF_BEGIN
       
  1681 	
       
  1682 	    SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), ">SDIO:CIMIoIssueCommandCheckResponseSM %x",TUint(s.iLastStatus))); // @SymTraceDataInternalTechnology
       
  1683 
       
  1684 		__ASSERT_ALWAYS(cmd.iCommand == ECmd52 || cmd.iCommand == ECmd53, DSDIOStack::Panic(DSDIOStack::ESDIOStackBadCommand));
       
  1685 
       
  1686 		s.iState |= KMMCSessStateInProgress;
       
  1687 		
       
  1688 	SMF_STATE(EStRetry)
       
  1689 
       
  1690 		// EStRetry
       
  1691 		//														
       
  1692 		// Retries the current command in the case of an R5 response error.
       
  1693 		//															
       
  1694 		// Note that errors such as CRC and Timeout errors are handled by the
       
  1695 		// underlying controller (via ExecCommandSMST).  This only handles
       
  1696 		// the errors specifically reported in the R5 response.				
       
  1697 		//
       
  1698 		// Expects the command paramaters to have been set up previously
       
  1699 		// (ie - by using FillDirectCommandDesc or similar method)
       
  1700 		
       
  1701 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:Issue SDIO Command (cmd:%d arg:0x%x)", cmd.iCommand, TUint32(cmd.iArgument))); // @SymTraceDataInternalTechnology
       
  1702 		
       
  1703 		// Prevent the MMC stack from retrying - not recommended for IO based devices
       
  1704 
       
  1705 		iConfig.RemoveMode(KMMCModeEnableRetries);	
       
  1706 
       
  1707 		m.SetTraps(KMMCErrStatus | KMMCErrDataTimeOut | KMMCErrResponseTimeOut | KMMCErrDataCRC | KMMCErrAbort);	
       
  1708 
       
  1709 		SMF_INVOKES(ExecCommandSMST, EStCommandSent)
       
  1710 
       
  1711 	SMF_STATE(EStCommandSent)
       
  1712 	
       
  1713 		// EStCommandSent
       
  1714 		//
       
  1715 		// Checks the R5 response and performs the necessary error handling
       
  1716 		
       
  1717 		s.iConfig.SetMode(KMMCModeEnablePreemption);
       
  1718 		
       
  1719 		m.ResetTraps();
       
  1720 		
       
  1721 		// The PSL should return with one of the following errors:
       
  1722 		//
       
  1723 		// KMMCErrResponseTimeOut : Response has timed out
       
  1724 		// KMMCErrDataTimeOut	  : Data transmission has timed out
       
  1725 		// KMMCErrStatus		  : General status error (to be decoded)
       
  1726 		
       
  1727 		if (err & KMMCErrResponseTimeOut)
       
  1728 			{
       
  1729 			// This could occur for any command, and it is unsafe to automatically retry
       
  1730 			// as we don't know how the specific function will behave.  However, we can be
       
  1731 			// sure about specific areas of Function 0 (apart from the CSA access windows)
       
  1732 
       
  1733 			SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:KMMCErrResponseTimeout")); // @SymTraceDataInternalTechnology
       
  1734 
       
  1735 			SMF_RETURN(KMMCErrResponseTimeOut)
       
  1736 			}
       
  1737 
       
  1738 		const TMMCErr KMMCErrAbortCondition = KMMCErrDataTimeOut | KMMCErrDataCRC;
       
  1739 
       
  1740 		if ((err & KMMCErrAbortCondition) && (cmd.iCommand == ECmd53))
       
  1741 			{
       
  1742 			// This occurs only for CMD53.  In this case, issue an IO_ABORT using CMD52
       
  1743 			// and use the response to determine the possible timeout reason.
       
  1744 			//
       
  1745 			// The PSL may set KMMCErrAbort to indicate that the transfer has already
       
  1746 			// been aborted at the generic layer, or the card has stoped data transfer already
       
  1747 			
       
  1748 			if(err & KMMCErrAbort)
       
  1749 				{
       
  1750 				SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:IO_ABORT Issued at PSL")); // @SymTraceDataInternalTechnology
       
  1751 				SMF_RETURN(err & ~KMMCErrAbort)
       
  1752 				}
       
  1753 			else
       
  1754 				{
       
  1755 				SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:Issue IO_ABORT")); // @SymTraceDataInternalTechnology
       
  1756 				
       
  1757 				// Store the last error in iExecNotHandle (we need this later if the abort succeeds)
       
  1758 				Command().iExecNotHandle = err;
       
  1759 				
       
  1760 				// Ensure that only this command gets through to the controller
       
  1761 				s.iConfig.RemoveMode(KMMCModeEnablePreemption);
       
  1762 				
       
  1763 				s.PushCommandStack();
       
  1764 				s.FillDirectCommandDesc(Command(), ECIMIoWriteDirect, 0x00, KCCCRRegIoAbort, s.FunctionNumber(), NULL);
       
  1765 				m.SetTraps(KMMCErrAll);
       
  1766 				SMF_INVOKES(CIMIoReadWriteDirectSMST, EStRecover)
       
  1767 				}
       
  1768 			}
       
  1769 
       
  1770 		if (err & KMMCErrStatus)
       
  1771 			{
       
  1772 			// Handles the following response errors in this order:
       
  1773 			//
       
  1774 			// KSDIOErrIllegalCommand : Command not legal for the current bus state
       
  1775 			// KSDIOErrFunctionNumber : Invalid function number specified
       
  1776 			// KSDIOErrOutOfRange	  : Command Argument is out of range
       
  1777 			// KSDIOErrCrc			  : CRC of the previous command failed
       
  1778 			// KSDIOErrGeneral		  : General or Unknown error
       
  1779 			
       
  1780 			const TSDIOResponseR5 response(s.ResponseP());
       
  1781 			const TUint32 error = response.Error();
       
  1782 			
       
  1783 			SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:KMMCErrStatus: %08x", error)); // @SymTraceDataInternalTechnology
       
  1784 			
       
  1785 			if(!error)
       
  1786 				{
       
  1787 				// The PSL reported an error, but not in the response!
       
  1788 				SMF_GOTOS(EStDone);
       
  1789 				}			
       
  1790 						
       
  1791 			if(error & KSDIOErrIllegalCommand)
       
  1792 				{
       
  1793 				SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:Illegal Command")); // @SymTraceDataInternalTechnology
       
  1794 				
       
  1795 				TBool validState = EFalse;
       
  1796 				
       
  1797 				switch(cmd.iCommand)
       
  1798 					{
       
  1799 					// Verify the bus state is valid for the command:
       
  1800 					//
       
  1801 					// ESDIOCardStateCmd : Data lines are free			: CMD52 or CMD53 valid
       
  1802 					// ESDIOCardStateTrn : Data transfer using DAT[3:0] : CMD52 valid
       
  1803 					
       
  1804 					case ECmd52:
       
  1805 						validState = ((response.State() == ESDIOCardStateCmd) || 
       
  1806 									  (response.State() == ESDIOCardStateTrn)) ? ETrue : EFalse;
       
  1807 						break;
       
  1808 					case ECmd53:
       
  1809 						validState = (response.State() == ESDIOCardStateCmd) ? ETrue : EFalse;
       
  1810 						break;
       
  1811 					default:
       
  1812 						DSDIOStack::Panic(DSDIOStack::ESDIOStackBadCommand);
       
  1813 						break;
       
  1814 					}
       
  1815 
       
  1816 #if defined _DEBUG
       
  1817 				if(!validState && (response.State() == ESDIOCardStateDis))
       
  1818 					SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "State = DIS")); // @SymTraceDataInternalTechnology
       
  1819 				if(!validState && (response.State() == ESDIOCardStateCmd))
       
  1820 					SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "State = CMD")); // @SymTraceDataInternalTechnology
       
  1821 				if(!validState && (response.State() == ESDIOCardStateTrn))
       
  1822 					SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "State = TRN")); // @SymTraceDataInternalTechnology
       
  1823 #endif
       
  1824 						
       
  1825 				if(validState == EFalse)
       
  1826 					{
       
  1827 					SMF_RETURN(KMMCErrBusInconsistent)
       
  1828 					}
       
  1829 				}
       
  1830 
       
  1831 			if(error & (KSDIOErrOutOfRange | KSDIOErrFunctionNumber))
       
  1832 				{
       
  1833 				// There's nothing we can do if an invalid function number is provided
       
  1834 				// or the address is out of range (which is a card-specific error)
       
  1835 				// except return control to the originator of the comand.
       
  1836 				SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:Invalid Argument")); // @SymTraceDataInternalTechnology
       
  1837 
       
  1838 				SMF_RETURN(KMMCErrArgument)
       
  1839 				}
       
  1840 					
       
  1841 			if(error & KSDIOErrCrc)
       
  1842 				{
       
  1843 				// The CRC check of the previous command failed.
       
  1844 				//
       
  1845 				// It is the responsibility of the PSL to handle the extended Memory Response
       
  1846 				// codes and forward these to the SDIO controller through the IO response.
       
  1847 				SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:CRC Error")); // @SymTraceDataInternalTechnology
       
  1848 
       
  1849 				SMF_RETURN(KMMCErrDataCRC)
       
  1850 				}
       
  1851 
       
  1852 			if(error & KSDIOErrGeneral)
       
  1853 				{
       
  1854 				// A CRC or general error occurred (for the previous command), so retry
       
  1855 				// in case of a random error due to noise on the bus and give up if not successful.
       
  1856 				SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:Unknown Error")); // @SymTraceDataInternalTechnology
       
  1857 
       
  1858 				SMF_RETURN(KMMCErrGeneral)
       
  1859 				}
       
  1860 			}
       
  1861 
       
  1862 		SMF_GOTOS(EStDone)
       
  1863 
       
  1864 	SMF_STATE(EStRecover)
       
  1865 	
       
  1866 		// EStRecover
       
  1867 		//														
       
  1868 		// Attempt any error recovery and returns the extended response code
       
  1869 		
       
  1870 		TMMCErr finalErr = KMMCErrNone;
       
  1871 		if(err & (KMMCErrBusInconsistent | KMMCErrResponseTimeOut | KMMCErrGeneral))
       
  1872 			{
       
  1873 			// Clients should de-register themselves if this condition is detected,
       
  1874 			// and force a media change to reset the card as we are unable to recover.
       
  1875 			SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:Abort Failed (err: %08x)", err)); // @SymTraceDataInternalTechnology
       
  1876 			finalErr = KMMCErrAbort;
       
  1877 			}
       
  1878 				
       
  1879 		s.PopCommandStack();
       
  1880 		m.ResetTraps();
       
  1881 		
       
  1882 		SMF_RETURN(finalErr | Command().iExecNotHandle);
       
  1883 		
       
  1884 	SMF_STATE(EStDone)
       
  1885 
       
  1886 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "<SDIO:CIMIoIssueCommandCheckResponseSM()")); // @SymTraceDataInternalTechnology
       
  1887 		
       
  1888 		s.iState &= ~KMMCSessStateInProgress;
       
  1889 
       
  1890 	SMF_END
       
  1891 	}
       
  1892 
       
  1893 
       
  1894 EXPORT_C TMMCErr DSDIOStack::CIMIoModifySM()
       
  1895 /**
       
  1896 @return Standard TMMCErr error code
       
  1897 */
       
  1898 	{
       
  1899 	TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackIoModify, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  1900 
       
  1901 	enum states
       
  1902 			{
       
  1903 			EStBegin=0,
       
  1904 			EStReadRegister,
       
  1905 			EStModifyWriteRegister,
       
  1906 			EStDone,
       
  1907 			EStEnd
       
  1908 			};
       
  1909 
       
  1910 		DSDIOSession& s=SDIOSession();
       
  1911 		TMMCCommandDesc& cmd = s.Command();
       
  1912 		
       
  1913 	SMF_BEGIN
       
  1914 	
       
  1915 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), ">SDIO:CIMIoModifySM %x",TUint(s.iLastStatus))); // @SymTraceDataInternalTechnology
       
  1916 		
       
  1917 		s.iState |= KMMCSessStateInProgress;
       
  1918 
       
  1919 	SMF_STATE(EStReadRegister)
       
  1920 	
       
  1921 		// EStReadRegister											
       
  1922 		//														
       
  1923 		// Disables pre-emption of this session and reads from the register
       
  1924 
       
  1925 		s.iConfig.RemoveMode(KMMCModeEnablePreemption);
       
  1926 
       
  1927 		TUint32 param = (cmd.iArgument &~ KSdioCmdDirMask) | KSdioCmdRead;
       
  1928 		DSDIOSession::FillAppCommandDesc(Command(), ESDIOCmdIoRwDirect, param);
       
  1929 		
       
  1930 		s.iSessionID = (TMMCSessionTypeEnum)ECIMIoReadDirect;
       
  1931 		SMF_INVOKES(CIMIoReadWriteDirectSMST,EStModifyWriteRegister)
       
  1932 		
       
  1933 	SMF_STATE(EStModifyWriteRegister)
       
  1934 
       
  1935 		// EStModifyWriteRegister									
       
  1936 		//														
       
  1937 		// Writes the modified data to the register	(still non-preemptable)
       
  1938 
       
  1939 		const TSDIOResponseR5 response(s.ResponseP());
       
  1940 		TUint8 readVal = response.Data();
       
  1941 
       
  1942 		s.ModifyBits(readVal);
       
  1943 
       
  1944 		TUint32 param = (cmd.iArgument &~ (KSdioCmdDirMask | KSdioCmdDataMask));
       
  1945 		param |= KSdioCmdWrite;
       
  1946 		param |= readVal;
       
  1947 
       
  1948 		if(cmd.iDataMemoryP)
       
  1949 			{
       
  1950 			param |= KSdioCmdRAW;
       
  1951 			}
       
  1952 
       
  1953 		DSDIOSession::FillAppCommandDesc(Command(), ESDIOCmdIoRwDirect, param);
       
  1954 
       
  1955 		s.iSessionID = (TMMCSessionTypeEnum)ECIMIoWriteDirect;
       
  1956 		SMF_INVOKES(CIMIoReadWriteDirectSMST,EStDone)		
       
  1957 
       
  1958 	SMF_STATE(EStDone)
       
  1959 	
       
  1960 		// EStDone	
       
  1961 		//			
       
  1962 		// CIMIoReadWriteDirectSM should have aready written the RAW data to the buffer.
       
  1963 		s.iState &= ~KMMCSessStateInProgress;
       
  1964 
       
  1965 		TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackIoModifyReturning, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  1966 		
       
  1967 	SMF_END
       
  1968 
       
  1969 	}
       
  1970 
       
  1971 
       
  1972 TMMCErr DSDIOStack::CIMIoFindTupleSM()
       
  1973 /**
       
  1974 This state machine walks a tuple chain (within a single CIS) searching
       
  1975 for the desired tuple code.  The command argument will have been set up to
       
  1976 contain the CMD52 parameters for the start of the search, and the data shall
       
  1977 point to the Tuple ID structure.
       
  1978 @return Standard TMMCErr error code
       
  1979 */
       
  1980 	{
       
  1981 		enum states
       
  1982 			{
       
  1983 			EStBegin=0,
       
  1984 			EStReadTupleId,
       
  1985 			EStGotTupleId,
       
  1986 			EStFoundTuple,
       
  1987 			EStReadNextTuple,
       
  1988 			EStDone,
       
  1989 			EStEnd
       
  1990 			};
       
  1991 
       
  1992 		DSDIOSession& s=SDIOSession();
       
  1993 
       
  1994 	SMF_BEGIN
       
  1995 	
       
  1996 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), ">SDIO:CIMIoFindTupleSM %x",TUint(s.iLastStatus))); // @SymTraceDataInternalTechnology
       
  1997 		
       
  1998 		s.iState |= KMMCSessStateInProgress;
       
  1999 
       
  2000 		if(s.Command().iDataMemoryP == NULL)
       
  2001 			{
       
  2002 			SMF_RETURN(KMMCErrArgument)
       
  2003 			}
       
  2004 			
       
  2005 	SMF_STATE(EStReadTupleId)
       
  2006 	
       
  2007 		// Set up to read the tuple ID
       
  2008 		TMMCCommandDesc& cmd = s.Command();
       
  2009 		TSDIOTupleInfo* tupleInfoP = (TSDIOTupleInfo*)cmd.iDataMemoryP;
       
  2010 		
       
  2011 		if(tupleInfoP->iAddress < KSdioCisAreaMin || tupleInfoP->iAddress > KSdioCisAreaMax)
       
  2012 			{
       
  2013 			SMF_RETURN(KMMCErrNotFound)
       
  2014 			}
       
  2015 			
       
  2016 		s.PushCommandStack();
       
  2017 		s.FillDirectCommandDesc(Command(), ECIMIoReadDirect, 0, tupleInfoP->iAddress, 0x00, NULL);
       
  2018 		s.iSessionID = (TMMCSessionTypeEnum)ECIMIoReadDirect;		
       
  2019 		SMF_INVOKES(CIMIoReadWriteDirectSMST, EStGotTupleId)
       
  2020 
       
  2021 	SMF_STATE(EStGotTupleId)
       
  2022 	
       
  2023 		const TSDIOResponseR5 response(s.ResponseP());
       
  2024 		TUint8 tupleId = response.Data();
       
  2025 
       
  2026 		s.PopCommandStack();		
       
  2027 		TMMCCommandDesc& cmd = s.Command();
       
  2028 		TSDIOTupleInfo* tupleInfoP = (TSDIOTupleInfo*)cmd.iDataMemoryP;
       
  2029 
       
  2030 		if(tupleId == tupleInfoP->iTupleId)
       
  2031 			{
       
  2032 			SMF_NEXTS(EStFoundTuple)
       
  2033 			}
       
  2034 		else if(tupleId != KSdioCisTplEnd)
       
  2035 			{
       
  2036 			SMF_NEXTS(EStReadNextTuple)
       
  2037 			}
       
  2038 		else
       
  2039 			{
       
  2040 			SMF_RETURN(KMMCErrNotFound);
       
  2041 			}
       
  2042 			
       
  2043 		// Setup the command to read the length, and invoke the relevant state
       
  2044 		s.PushCommandStack();
       
  2045 		s.FillDirectCommandDesc(Command(), ECIMIoReadDirect, 0, tupleInfoP->iAddress + 1, 0x00, NULL);
       
  2046 		s.iSessionID = (TMMCSessionTypeEnum)ECIMIoReadDirect;
       
  2047 		SMF_CALL(CIMIoReadWriteDirectSMST)			
       
  2048 
       
  2049 	SMF_STATE(EStReadNextTuple)
       
  2050 	
       
  2051 		const TSDIOResponseR5 response(s.ResponseP());
       
  2052 		TUint8 tupleLink = response.Data();
       
  2053 
       
  2054 		s.PopCommandStack();
       
  2055 		
       
  2056 		if(tupleLink == 0xFF)
       
  2057 			{
       
  2058 			SMF_RETURN(KMMCErrNotFound);
       
  2059 			}
       
  2060 			
       
  2061 		TMMCCommandDesc& cmd = s.Command();
       
  2062 		TSDIOTupleInfo* tupleInfoP = (TSDIOTupleInfo*)cmd.iDataMemoryP;
       
  2063 		
       
  2064 		tupleInfoP->iAddress += (2 + tupleLink);
       
  2065 
       
  2066 		SMF_GOTOS(EStReadTupleId)
       
  2067 		
       
  2068 	
       
  2069 	SMF_STATE(EStFoundTuple)
       
  2070 
       
  2071 		const TSDIOResponseR5 response(s.ResponseP());
       
  2072 		TUint8 tupleLink = response.Data();
       
  2073 
       
  2074 		s.PopCommandStack();
       
  2075 		TMMCCommandDesc& cmd = s.Command();
       
  2076 		TSDIOTupleInfo* tupleInfoP = (TSDIOTupleInfo*)cmd.iDataMemoryP;
       
  2077 		
       
  2078 		tupleInfoP->iLength = tupleLink;
       
  2079 		
       
  2080 	SMF_STATE(EStDone)
       
  2081 	
       
  2082 	    SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "<SDIO:CIMIoFindTupleSM()")); // @SymTraceDataInternalTechnology
       
  2083 	
       
  2084 		s.iState &= ~KMMCSessStateInProgress;
       
  2085 
       
  2086 	SMF_END
       
  2087 	}
       
  2088 
       
  2089 
       
  2090 TMMCErr DSDIOStack::CIMIoInterruptHandlerSM()
       
  2091 /**
       
  2092 @return Standard TMMCErr error code
       
  2093 */
       
  2094 	{
       
  2095 		enum states
       
  2096 			{
       
  2097 			EStBegin=0,
       
  2098 			EStEnableMasterInterrupt,
       
  2099 			EStEnableInterruptsAtPSL,
       
  2100 			EStReadPendingInterrupts,
       
  2101 			EStDisablePendingInterrupts,
       
  2102 			EStNotifyClients,
       
  2103 			EStDone,
       
  2104 			EStEnd
       
  2105 			};
       
  2106 
       
  2107 		DSDIOSession& s=SDIOSession();
       
  2108 
       
  2109 	SMF_BEGIN
       
  2110 	
       
  2111 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), ">SDIO:CIMIoInterruptHandlerSM %x",TUint(s.iLastStatus))); // @SymTraceDataInternalTechnology
       
  2112 		
       
  2113 		// The only way to stop this session is to abort it.
       
  2114 		m.SetTraps(KMMCErrAbort);
       
  2115 	
       
  2116 		s.iState |= KMMCSessStateInProgress;
       
  2117 		s.PushCommandStack();  // Save context for after interrupt occurs
       
  2118 		
       
  2119 		s.iConfig.RemoveMode(KMMCModeEnablePreemption);
       
  2120 
       
  2121 	SMF_STATE(EStEnableMasterInterrupt)
       
  2122             
       
  2123 		// EStEnableMasterInterrupt
       
  2124 		//														
       
  2125 		// Enable MIEN bit using safe Read/Modify/Write state machine.
       
  2126 
       
  2127 		if(err & KMMCErrAbort)
       
  2128 			SMF_EXIT
       
  2129 			
       
  2130 		s.FillIoModifyCommandDesc(Command(), 0, KCCCRRegIntEnable, KSDIOCardIntEnMaster, 0x00, NULL);
       
  2131 		
       
  2132 		SMF_INVOKES(CIMIoModifySMST,EStEnableInterruptsAtPSL)	
       
  2133 
       
  2134 	SMF_STATE(EStEnableInterruptsAtPSL)
       
  2135 	
       
  2136 		// EStEnableInterruptsAtPSL												
       
  2137 		//	
       
  2138 		// If MIEN bit set successfully, inform the PSL to enable interrupts	
       
  2139 		// (Sets the session to wait on the KMMCBlockOnInterrupt)				
       
  2140 
       
  2141 		if(err & KMMCErrAbort)
       
  2142 			SMF_EXIT
       
  2143 		
       
  2144 		s.iConfig.SetMode(KMMCModeEnablePreemption);
       
  2145 
       
  2146 		BlockCurrentSession(KMMCBlockOnInterrupt);
       
  2147 		
       
  2148 		TRACE2(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackPSLCalledEnableSDIOInterrupts, reinterpret_cast<TUint32>(this), 1); // @SymTraceDataPublishedTvk
       
  2149 		EnableSDIOInterrupt(ETrue);
       
  2150 		TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackPSLEnableSDIOInterruptsReturned, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  2151 
       
  2152 		SMF_WAITS(EStReadPendingInterrupts)
       
  2153 			
       
  2154 	SMF_STATE(EStReadPendingInterrupts)
       
  2155 
       
  2156 		// EStReadPendingInterrupts												
       
  2157 		//																		
       
  2158 		// Reads the pending interrupts that require service.					
       
  2159 
       
  2160 		TRACE2(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackPSLCalledEnableSDIOInterrupts, reinterpret_cast<TUint32>(this), 0); // @SymTraceDataPublishedTvk
       
  2161 		EnableSDIOInterrupt(EFalse);
       
  2162 		TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackPSLEnableSDIOInterruptsReturned, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  2163 		
       
  2164 		if(err & KMMCErrAbort)
       
  2165 			SMF_EXIT
       
  2166 			
       
  2167 		s.iConfig.RemoveMode(KMMCModeEnablePreemption);
       
  2168 
       
  2169 		s.FillDirectCommandDesc(Command(), ECIMIoReadDirect, 0, KCCCRRegIntPending, 0x00, NULL);
       
  2170 		
       
  2171 		s.iSessionID = (TMMCSessionTypeEnum)ECIMIoReadDirect;
       
  2172 		SMF_INVOKES(CIMIoReadWriteDirectSMST,EStDisablePendingInterrupts)
       
  2173 
       
  2174 	SMF_STATE(EStDisablePendingInterrupts)
       
  2175 	
       
  2176 		// EStDisablePendingInterrupts											
       
  2177 		//																		
       
  2178 		// Disables the the pending interrupts that require service.			
       
  2179 		// (it is the responsibility of the client to re-enable after service)	
       
  2180 
       
  2181 		if(err & KMMCErrAbort)
       
  2182 			SMF_EXIT
       
  2183 	
       
  2184 		const TSDIOResponseR5 response(s.ResponseP());
       
  2185 		const TUint8 pending = (TUint8)(response.Data() & KSDIOCardIntPendMask);
       
  2186 
       
  2187 		// if this is a stray interrrupt then there are no interrupts to disable 
       
  2188 		// and no point in calling any client interrupt handlers
       
  2189 		if (pending == 0)
       
  2190 			{
       
  2191 			SMF_GOTOS(EStEnableInterruptsAtPSL);
       
  2192 			}
       
  2193 
       
  2194 		s.PopCommandStack();
       
  2195 		Command().iDataMemoryP[0] = pending;
       
  2196 		s.PushCommandStack();
       
  2197 
       
  2198 		s.FillIoModifyCommandDesc(Command(), 0, KCCCRRegIntEnable, 0x00, pending, NULL);		
       
  2199 		SMF_INVOKES(CIMIoModifySMST,EStNotifyClients)
       
  2200 
       
  2201 	SMF_STATE(EStNotifyClients)
       
  2202 	
       
  2203 		// EStNotifyClients														
       
  2204 		//																		
       
  2205 		// Notifies the clients of the pending interrupts and re-start session	
       
  2206 
       
  2207 		if(err & KMMCErrAbort)
       
  2208 			SMF_EXIT
       
  2209 			
       
  2210 		TSDIOCard* cardP = static_cast<TSDIOCard*>(s.iCardP);
       
  2211 
       
  2212 		cardP->InterruptController().Service();
       
  2213 
       
  2214 		SMF_GOTOS(EStEnableInterruptsAtPSL);
       
  2215 
       
  2216 	SMF_STATE(EStDone)
       
  2217 
       
  2218 		// EStDone
       
  2219 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "<SDIO:CIMIoInterruptHandlerSM()")); // @SymTraceDataInternalTechnology
       
  2220 		
       
  2221 		s.iState &= ~KMMCSessStateInProgress;
       
  2222 
       
  2223 	SMF_END
       
  2224 	}
       
  2225 
       
  2226 
       
  2227 TMMCErr DSDIOStack::CIMIoSetBusWidthSM()
       
  2228 /**
       
  2229 @return Standard TMMCErr error code
       
  2230 */
       
  2231 	{
       
  2232 		enum states
       
  2233 			{
       
  2234 			EStBegin=0,
       
  2235 			EStCleanCardSelect,
       
  2236 			EStCardSelected,
       
  2237 			EStCheckMasterInterrupt,
       
  2238 			EStDisableMasterInterrupt,
       
  2239 			EStSetBusWidthIO,
       
  2240 			EStSetBusWidthSDApp,
       
  2241 			EStSetBusWidthSDCommand,
       
  2242 			EStEnableMasterInterrupt,
       
  2243 			EStFinishUp,
       
  2244 			EStDone,
       
  2245 			EStEnd
       
  2246 			};       
       
  2247 
       
  2248 		DSDIOSession& s=SDIOSession();
       
  2249 		TSDIOCard* ioCardP = static_cast<TSDIOCard*>(s.iCardP);
       
  2250 		
       
  2251 		const TUint32 KEnableInterruptFlag = 0x80;
       
  2252 
       
  2253 	SMF_BEGIN
       
  2254 
       
  2255 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), ">SDIO:CIMIoSetBusWidthSM %x",TUint(s.iLastStatus))); // @SymTraceDataInternalTechnology
       
  2256 
       
  2257 		s.SetCard(ioCardP);
       
  2258 		TRCA targetRCA = ioCardP->RCA();
       
  2259 		TRACE2(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackPSLCalledAddressCard, reinterpret_cast<TUint32>(this), ioCardP->iIndex-1); // @SymTraceDataPublishedTvk
       
  2260 		AddressCard(ioCardP->iIndex-1);
       
  2261 		TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackPSLAddressCardReturned, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  2262 		if (targetRCA == SelectedCard())
       
  2263 			{
       
  2264 			SMF_GOTOS(EStCardSelected)
       
  2265 			}
       
  2266 			
       
  2267 		s.PushCommandStack();
       
  2268 		s.FillCommandDesc(ECmdSelectCard, targetRCA);
       
  2269 		
       
  2270 		SMF_INVOKES(ExecCommandSMST,EStCleanCardSelect)
       
  2271 
       
  2272 	SMF_STATE(EStCleanCardSelect)
       
  2273 	
       
  2274 		s.PopCommandStack();
       
  2275 		//drop through...
       
  2276 
       
  2277 	SMF_STATE(EStCardSelected)
       
  2278 	
       
  2279 	    SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack::EstCardSelected")); // @SymTraceDataInternalTechnology
       
  2280 
       
  2281 		s.iState |= KMMCSessStateInProgress;
       
  2282 		
       
  2283 		// This state machine must not be interrupted
       
  2284 		s.iConfig.RemoveMode(KMMCModeEnablePreemption);
       
  2285 		
       
  2286 		// Validate some parameters
       
  2287 		TMMCCommandDesc& cmd = s.Command();
       
  2288 		const TInt requestWidth = cmd.iArgument;
       
  2289 
       
  2290 		if(requestWidth == ioCardP->BusWidth())
       
  2291 			{
       
  2292 			// Width already set, so exit
       
  2293 			SMF_GOTOS(EStDone);
       
  2294 			}
       
  2295 		
       
  2296 		if(!(ioCardP->IsIOCard() || ioCardP->IsSDCard()))
       
  2297 			{
       
  2298 			// Non-IO/SD Cards don't support change of bus width
       
  2299 			s.iConfig.SetMode(KMMCModeEnablePreemption);
       
  2300 			s.iState &= ~KMMCSessStateInProgress;
       
  2301 			SMF_RETURN(KMMCErrNotSupported)
       
  2302 			}
       
  2303 		
       
  2304 		if(ioCardP->IsSDCard() && ioCardP->IsLocked())
       
  2305 			{
       
  2306 			SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:SD Card is Locked")); // @SymTraceDataInternalTechnology
       
  2307 			// Don't perform the change
       
  2308 			s.iConfig.SetMode(KMMCModeEnablePreemption);
       
  2309 			s.iState &= ~KMMCSessStateInProgress;
       
  2310 			SMF_RETURN(KMMCErrNotSupported)
       
  2311 			}
       
  2312 		
       
  2313 		if(ioCardP->IsIOCard())
       
  2314 			{
       
  2315 			SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:IsSDIOCard requestedWidth: %d",requestWidth)); // @SymTraceDataInternalTechnology
       
  2316 			
       
  2317 			switch(requestWidth)
       
  2318 				{
       
  2319 				case 1:
       
  2320 					// Requesting entry to 1-bit mode.  This is always supported.
       
  2321 					// Drops through to EStCheckMasterInterrupt
       
  2322 					break;
       
  2323 					
       
  2324 				case 4:
       
  2325 					// 
       
  2326 					// Requesting entry to 4-bit mode.  Dependant on the values reported in the CCCR
       
  2327 					// (4-Bit Support is Mandatory for High Speed Cards, and optional for Low Speed Cards)
       
  2328 					//
       
  2329 					// This assumes that the memory portion of a Combo Card has been initialised first.
       
  2330 					//					
       
  2331 						{
       
  2332 						const TUint8 lowSpeed4BitMask = KSDIOCardCapsBitLSC | KSDIOCardCapsBit4BLS;
       
  2333 						if(((ioCardP->iCommonConfig.iCardCaps & lowSpeed4BitMask) == lowSpeed4BitMask) ||
       
  2334 							(!(ioCardP->iCommonConfig.iCardCaps & KSDIOCardCapsBitLSC)))
       
  2335 							{
       
  2336 							// OK.  Drops through to EStCheckMasterInterrupt
       
  2337 							}
       
  2338 						else
       
  2339 							{
       
  2340 							SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:4-Bit Mode Not Supported")); // @SymTraceDataInternalTechnology
       
  2341 							s.iConfig.SetMode(KMMCModeEnablePreemption);
       
  2342 							s.iState &= ~KMMCSessStateInProgress;
       
  2343 							SMF_RETURN(KMMCErrNotSupported)
       
  2344 							}
       
  2345 						}
       
  2346 					break;
       
  2347 					
       
  2348 				default:
       
  2349 					SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:Invalid Argument")); // @SymTraceDataInternalTechnology
       
  2350 					s.iConfig.SetMode(KMMCModeEnablePreemption);
       
  2351 					s.iState &= ~KMMCSessStateInProgress;
       
  2352 					SMF_RETURN(KMMCErrArgument)
       
  2353 					//break;
       
  2354 				}
       
  2355 			}
       
  2356 		else
       
  2357 			{
       
  2358 			// If this is not an IO card, go directly to SD configuration
       
  2359 			s.PushCommandStack();
       
  2360 			SMF_GOTOS(EStSetBusWidthSDApp)
       
  2361 			}			
       
  2362 
       
  2363 	SMF_STATE(EStCheckMasterInterrupt)
       
  2364 
       
  2365 		// EStCheckMasterInterrupt
       
  2366 		//														
       
  2367 		// Checks if MIEN requires disable before changing the bus width
       
  2368 
       
  2369 		s.PushCommandStack();
       
  2370 		
       
  2371 		s.FillDirectCommandDesc(Command(), ECIMIoReadDirect, 0, KCCCRRegIntEnable, 0x00, NULL);
       
  2372 		s.iSessionID = (TMMCSessionTypeEnum)ECIMIoReadDirect;
       
  2373 		SMF_INVOKES(CIMIoReadWriteDirectSMST, EStDisableMasterInterrupt)
       
  2374 
       
  2375 	SMF_STATE(EStDisableMasterInterrupt)
       
  2376 
       
  2377 		// EStDisableMasterInterrupt
       
  2378 		//														
       
  2379 		// Disable MIEN before changing the bus width
       
  2380 
       
  2381 		const TSDIOResponseR5 response(s.ResponseP());
       
  2382 		if(response.Data() & KSDIOCardIntEnMaster)
       
  2383 			{
       
  2384 			s.PopCommandStack();
       
  2385 			TMMCCommandDesc& cmd = s.Command();
       
  2386 			const TUint32 arg = cmd.iArgument | KEnableInterruptFlag;
       
  2387 			cmd.iArgument = arg;
       
  2388 			s.PushCommandStack();
       
  2389 			
       
  2390 			s.FillIoModifyCommandDesc(Command(), 0, KCCCRRegIntEnable, 0x00, KSDIOCardIntEnMaster, NULL);		
       
  2391 			SMF_INVOKES(CIMIoModifySMST, EStSetBusWidthIO)
       
  2392 			}
       
  2393 			
       
  2394 		// MIEN not enabled, so drop through and change the bus width
       
  2395 
       
  2396 	SMF_STATE(EStSetBusWidthIO)
       
  2397 
       
  2398 		// EStSetDefaultBusWidthIO
       
  2399 		//
       
  2400 		// Modify the Bus Width in the CCCR to 1-Bit mode
       
  2401 
       
  2402 		s.PopCommandStack();
       
  2403 		TMMCCommandDesc& cmd = s.Command();		
       
  2404 		s.PushCommandStack();
       
  2405 
       
  2406 		if((cmd.iArgument & ~KEnableInterruptFlag) == 1)
       
  2407 			{
       
  2408 			s.FillIoModifyCommandDesc(Command(), 0, KCCCRRegBusInterfaceControl, 0x00, KSDIOCardBicMaskBusWidth, NULL);
       
  2409 			}
       
  2410 		else
       
  2411 			{
       
  2412 			s.FillIoModifyCommandDesc(Command(), 0, KCCCRRegBusInterfaceControl, KSDIOCardBicBitBusWidth4, KSDIOCardBicMaskBusWidth & ~KSDIOCardBicBitBusWidth4, NULL);
       
  2413 			}
       
  2414 		
       
  2415 		if(ioCardP->IsComboCard() || ioCardP->IsSDCard())
       
  2416 			{
       
  2417 			SMF_INVOKES(CIMIoModifySMST, EStSetBusWidthSDApp)
       
  2418 			}
       
  2419 		else
       
  2420 			{
       
  2421 			const TBool enableMIEN = (cmd.iArgument & KEnableInterruptFlag) ? ETrue : EFalse;
       
  2422 			SMF_INVOKES(CIMIoModifySMST, enableMIEN ? EStEnableMasterInterrupt : EStFinishUp)
       
  2423 			}
       
  2424 		
       
  2425 	SMF_STATE(EStSetBusWidthSDApp)
       
  2426 
       
  2427 		// EStSetDefaultBusWidthSDApp
       
  2428 		//
       
  2429 		// Modify the Bus Width of the SD portion of the card (App Command Stage)				
       
  2430 
       
  2431 		TUint32 arg = TUint32(CardArray().Card(0).RCA()) << 16;
       
  2432 		s.FillCommandDesc(ECmdAppCmd, arg);
       
  2433 		SMF_INVOKES(IssueCommandCheckResponseSMST, EStSetBusWidthSDCommand)
       
  2434 
       
  2435 	SMF_STATE(EStSetBusWidthSDCommand)
       
  2436 
       
  2437 		// EStSetBusWidthSDCommand
       
  2438 		//
       
  2439 		// Modify the Bus Width of the SD portion of the card (Command Stage)				
       
  2440 
       
  2441 		s.PopCommandStack();
       
  2442 		TMMCCommandDesc& cmd = s.Command();
       
  2443 		const TBool enableMIEN = (cmd.iArgument & KEnableInterruptFlag) ? ETrue : EFalse;
       
  2444 		s.PushCommandStack();
       
  2445 		
       
  2446 		DSDSession::FillAppCommandDesc(Command(), ESDACmdSetBusWidth, cmd.iArgument == 1 ? KSDBusWidth1 : KSDBusWidth4);
       
  2447 		SMF_INVOKES(IssueCommandCheckResponseSMST, (ioCardP->IsIOCard() && enableMIEN) ? EStEnableMasterInterrupt : EStFinishUp)
       
  2448 
       
  2449 	SMF_STATE(EStEnableMasterInterrupt)
       
  2450 
       
  2451 		// EStEnableMasterInterrupt
       
  2452 		//														
       
  2453 		// Re-Enable Master Interrupts
       
  2454 
       
  2455 		s.FillIoModifyCommandDesc(Command(), 0, KCCCRRegIntEnable, KSDIOCardIntEnMaster, 0x00, NULL);
       
  2456 		SMF_INVOKES(CIMIoModifySMST, EStFinishUp)
       
  2457 
       
  2458 	SMF_STATE(EStFinishUp)
       
  2459 
       
  2460 		// EStFinishUp
       
  2461 		//														
       
  2462 		// Informs the PSL of the final bus width
       
  2463 		
       
  2464 		s.PopCommandStack();
       
  2465 
       
  2466 		TMMCCommandDesc& cmd = s.Command();
       
  2467 		cmd.iArgument = TUint32(cmd.iArgument &~ KEnableInterruptFlag);
       
  2468 		ioCardP->SetBusWidth(cmd.iArgument);		
       
  2469 		DoSetBusWidth(cmd.iArgument == 1 ? KSDBusWidth1 : KSDBusWidth4);
       
  2470 		
       
  2471 		if(cmd.iArgument == 4)
       
  2472 			{
       
  2473 			// Bring the socket out of sleep mode if we have just set 4-bit
       
  2474 			static_cast<DSDIOSocket*>(MMCSocket())->SetSleep(EFalse);
       
  2475 			}
       
  2476 
       
  2477 	SMF_STATE(EStDone)
       
  2478 		
       
  2479 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "<DSDIOStack:CIMIoSetBusWidthSM()")); // @SymTraceDataInternalTechnology
       
  2480 		
       
  2481 		s.iConfig.SetMode(KMMCModeEnablePreemption);
       
  2482 		s.iState &= ~KMMCSessStateInProgress;
       
  2483 
       
  2484 	SMF_END
       
  2485 	}
       
  2486 
       
  2487 
       
  2488 EXPORT_C TMMCErr DSDIOStack::CIMReadWriteBlocksSM()
       
  2489 //
       
  2490 // This macro provides the virtual Memory R/W state machine.
       
  2491 // Since SDIO supports sleep mode, the bus width may be set to 1-bit
       
  2492 // before memory access.  This machine ensures that the bus width
       
  2493 // is set to 4-bit mode prior to performing the SD R/W state machine.
       
  2494 //
       
  2495 	{
       
  2496 	TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackIoReadWriteBlock, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  2497 
       
  2498 		enum states
       
  2499 			{
       
  2500 			EStBegin=0,
       
  2501 			EStFullPower,
       
  2502 			EStDone,
       
  2503 			EStEnd
       
  2504 			};
       
  2505 
       
  2506 		DMMCSession& s=Session();
       
  2507 
       
  2508 	SMF_BEGIN
       
  2509 	
       
  2510 	    SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), ">DSDIOStack:RWBlocksSM %x",TUint(s.iLastStatus))); // @SymTraceDataInternalTechnology
       
  2511 	    
       
  2512 		s.iState |= KMMCSessStateInProgress;
       
  2513 		
       
  2514 		// Disable Preemption until we have set the bus width
       
  2515 		s.iConfig.RemoveMode(KMMCModeEnablePreemption);
       
  2516 		
       
  2517 	    s.PushCommandStack();
       
  2518 	    s.FillCommandArgs(4, 0, NULL, 0);
       
  2519 		m.SetTraps(KMMCErrNotSupported);
       
  2520 		SMF_INVOKES(CIMIoSetBusWidthSMST, EStFullPower)
       
  2521 		
       
  2522 	SMF_STATE(EStFullPower)
       
  2523 		
       
  2524 		m.ResetTraps();
       
  2525 		s.PopCommandStack();
       
  2526 		s.iConfig.SetMode(KMMCModeEnablePreemption);
       
  2527 	
       
  2528 		if(err == KMMCErrNone || err == KMMCErrNotSupported)
       
  2529 			{
       
  2530 			SMF_INVOKES(CIMReadWriteMemoryBlocksSMST, EStDone);			
       
  2531 			}
       
  2532 			
       
  2533 		SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "DSDIOStack:RWBlocksSM() - Err: %d",err)); // @SymTraceDataInternalTechnology
       
  2534 
       
  2535 		SMF_RETURN(err)
       
  2536 				
       
  2537 	SMF_STATE(EStDone)
       
  2538 
       
  2539 		s.iState &= ~KMMCSessStateInProgress;
       
  2540 
       
  2541 		TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackIoReadWriteBlockReturning, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk	
       
  2542 		
       
  2543 	SMF_END
       
  2544 
       
  2545 	}
       
  2546 
       
  2547 
       
  2548 EXPORT_C TMMCErr DSDIOStack::ModifyCardCapabilitySM()
       
  2549 /**
       
  2550 @publishedPartner
       
  2551 @released
       
  2552 
       
  2553 This function provides a chance to modify the capability of paticular cards.
       
  2554 Licensee may overide this function to modify certain card's capability as needed.
       
  2555 A state machine is needed in derived function and function of base class should be
       
  2556 called in order to act more generic behaviour.
       
  2557 */
       
  2558     {
       
  2559 	TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackModifyCardCapability, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  2560 
       
  2561 	enum states
       
  2562 			{
       
  2563 			EStBegin=0,
       
  2564 			EStDone,
       
  2565 			EStEnd
       
  2566 			}; 
       
  2567 
       
  2568     SMF_BEGIN
       
  2569     
       
  2570         SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), ">DSDIOStack:ModifyCardCapabilitySM()")); // @SymTraceDataInternalTechnology
       
  2571         
       
  2572     	SMF_INVOKES( DStackBase::BaseModifyCardCapabilitySMST, EStDone )
       
  2573 
       
  2574     SMF_STATE(EStDone)
       
  2575         
       
  2576     	TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackModifyCardCapabilityReturning, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  2577 
       
  2578     SMF_END
       
  2579 
       
  2580     }
       
  2581 
       
  2582 
       
  2583 EXPORT_C void DSDIOStack::HandleSDIOInterrupt(TUint aCardIndex)
       
  2584 /**
       
  2585 @publishedPartner
       
  2586 @released
       
  2587 
       
  2588 Called from the variant layer to indicate that an SDIO interrupt has occurred.
       
  2589 SDIO cards do not share the data bus, so it is the responsibility of the PSL
       
  2590 to determine the card that generated the interrupt.
       
  2591 
       
  2592 @param aCardIndex The index of the card that generated the interrupt.
       
  2593 
       
  2594 @see DSDIOStack::EnableSDIOInterrupt
       
  2595 */
       
  2596 	{
       
  2597 	//
       
  2598 	// Pass the interrupt onto the interrupt controller
       
  2599 	//
       
  2600 	TSDIOCard& ioCard = CardArray().Card(aCardIndex);
       
  2601 	ioCard.iInterruptController.Schedule();
       
  2602 	}
       
  2603 
       
  2604 
       
  2605 EXPORT_C void DSDIOStack::BlockIOSession(TSDIOBlockingCondition aBlockCond)
       
  2606 /**
       
  2607 Blocks the current IO session.
       
  2608 
       
  2609 This is used to support the sending of Direct Commands during Data Transfer,
       
  2610 and is part of the implementation of the Read/Wait protocol.
       
  2611 
       
  2612 @param aBlockCond The requested blocking condition
       
  2613 */
       
  2614 	{
       
  2615 	TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackBlockIoSession, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  2616 
       
  2617 	DSDIOSession* bSessP = NULL;	
       
  2618 	TBool allowPremption = EFalse;
       
  2619 	
       
  2620 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), ">SDIO:BlockIOSession()")); // @SymTraceDataInternalTechnology
       
  2621 	
       
  2622 	switch(aBlockCond)
       
  2623 		{
       
  2624 		case ESDIOBlockOnCommand:
       
  2625 			{
       
  2626 			// Requesting to block in command mode:
       
  2627 			// The stack must be fully blocked under this condition
       
  2628 			SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:ESDIOBlockOnCommand")); // @SymTraceDataInternalTechnology
       
  2629 			
       
  2630 			__ASSERT_ALWAYS((iBlockedSessions & KCommandSessionBlocked) == 0, Panic(ESDIOStackOverlappedSession));
       
  2631 
       
  2632 			bSessP = &SDIOSession();
       
  2633 			iCmdSessionP = bSessP;
       
  2634 			iBlockedSessions |= KCommandSessionBlocked;
       
  2635 
       
  2636 			break;
       
  2637 			}
       
  2638 			
       
  2639 		case ESDIOBlockOnData:
       
  2640 			{
       
  2641 			// Requesting to block in data transfer:
       
  2642 			// Check the card capabilities to determine the blocking conditions.
       
  2643             SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:ESDIOBlockOnData")); // @SymTraceDataInternalTechnology
       
  2644             
       
  2645 			__ASSERT_ALWAYS((iBlockedSessions & KDataSessionBlocked) == 0, Panic(ESDIOStackOverlappedSession));
       
  2646 			
       
  2647 			bSessP = &SDIOSession();
       
  2648 	
       
  2649 			const TSDIOCard* ioCardP = static_cast<TSDIOCard*>(bSessP->iCardP);			
       
  2650 			const TBool supportsDC = (ioCardP->iCommonConfig.iCardCaps & KSDIOCardCapsBitSDC) ? ETrue : EFalse;
       
  2651 			
       
  2652 			if(supportsDC)
       
  2653 				{
       
  2654 				allowPremption = ETrue;
       
  2655 				}
       
  2656 								
       
  2657 			iDataSessionP = bSessP;
       
  2658 			iBlockedSessions |= KDataSessionBlocked;
       
  2659 			
       
  2660 			break;
       
  2661 			}
       
  2662 			
       
  2663 		default:			
       
  2664 			break;
       
  2665 		}
       
  2666 	
       
  2667 	if(bSessP)
       
  2668 		{
       
  2669 		DISABLEPREEMPTION		
       
  2670 
       
  2671 		if(allowPremption)
       
  2672 			{
       
  2673 			bSessP->iState |= KMMCSessStateAllowDirectCommands;
       
  2674 			}
       
  2675 		else
       
  2676 			{
       
  2677 			bSessP->iState &= ~KMMCSessStateAllowDirectCommands;
       
  2678 			}
       
  2679 		
       
  2680 		Block(bSessP, KMMCBlockOnDataTransfer);
       
  2681 
       
  2682 		RESTOREPREEMPTION		
       
  2683 		}
       
  2684 		
       
  2685 	TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackBlockIoSessionReturning, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  2686 	}
       
  2687 	
       
  2688 
       
  2689 EXPORT_C DSDIOSession* DSDIOStack::UnblockIOSession(TSDIOBlockingCondition aBlockCond, TMMCErr aError)
       
  2690 /**
       
  2691 Unblocks the current IO session.
       
  2692 
       
  2693 This is used to support the sending of Direct Commands during Data Transfer,
       
  2694 and is part of the implementation of the Read/Wait protocol.
       
  2695 
       
  2696 @param aBlockCond The requested unblocking condition
       
  2697 @param aError Standard MMC error code
       
  2698 @return The previously blocked session
       
  2699 */
       
  2700 	{
       
  2701 	TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackUnblockIoSession, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  2702 
       
  2703 	DSDIOSession* ubSessP = NULL;
       
  2704 	
       
  2705 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), ">SDIO:UnblockIOSession()")); // @SymTraceDataInternalTechnology
       
  2706 	
       
  2707 	DISABLEPREEMPTION		
       
  2708 
       
  2709 	switch(aBlockCond)
       
  2710 		{
       
  2711 		case ESDIOBlockOnCommand:
       
  2712 			{
       
  2713 			SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:ESDIOBlockOnCommand")); // @SymTraceDataInternalTechnology
       
  2714 			ubSessP = iCmdSessionP;
       
  2715 			iBlockedSessions &= ~KCommandSessionBlocked;
       
  2716 			iCmdSessionP = NULL;
       
  2717 			break;
       
  2718 			}
       
  2719 			
       
  2720 		case ESDIOBlockOnData:
       
  2721 			{
       
  2722 			SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SDIO:ESDIOBlockOnData")); // @SymTraceDataInternalTechnology
       
  2723 			ubSessP = iDataSessionP;
       
  2724 			iBlockedSessions &= ~KDataSessionBlocked;
       
  2725 			iDataSessionP = NULL;			
       
  2726 			break;
       
  2727 			}
       
  2728 			
       
  2729 		default:			
       
  2730 			break;
       
  2731 		}
       
  2732 
       
  2733 	if (ubSessP) 
       
  2734 		{
       
  2735 		ubSessP->iState &= ~KMMCSessStateAllowDirectCommands;
       
  2736 		RESTOREPREEMPTION
       
  2737 		UnBlock(ubSessP, KMMCBlockOnDataTransfer, aError);
       
  2738 		}	
       
  2739 	else
       
  2740 		{
       
  2741 		RESTOREPREEMPTION
       
  2742 		}
       
  2743 		
       
  2744 	TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackUnblockIoSessionReturning, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  2745 	return ubSessP;
       
  2746 	}
       
  2747 
       
  2748 
       
  2749 EXPORT_C DMMCSession* DSDIOStack::AllocSession(const TMMCCallBack& aCallBack) const
       
  2750 /**
       
  2751 Used by clients of the SDIO controller to allocate the appropriate DMMCSession derived session 
       
  2752 object (in this case, a DSDIOSession object).
       
  2753 
       
  2754 Rather than clients directly using this function, it is recommended that the session 
       
  2755 be accessed indirectly using the functionality provided by the DSDIORegisterInterface class.
       
  2756 
       
  2757 @param aCallBack Callback function to notify the client that a session has completed
       
  2758 
       
  2759 @return A pointer to the new session
       
  2760 
       
  2761 @see DSDIORegisterInterface
       
  2762 */
       
  2763 	{
       
  2764 	TRACE1(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackAllocateNewSession, reinterpret_cast<TUint32>(this)); // @SymTraceDataPublishedTvk
       
  2765 	DMMCSession* session = new DSDIOSession(aCallBack);
       
  2766 	TRACE2(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackAllocateNewSessionReturning, reinterpret_cast<TUint32>(this), reinterpret_cast<TUint32>(session)); // @SymTraceDataPublishedTvk
       
  2767 	return session;
       
  2768 	}
       
  2769 
       
  2770 
       
  2771 void DSDIOStack::Panic(DSDIOStack::TPanic aPanic)
       
  2772 /**
       
  2773 Session Panic
       
  2774 */
       
  2775 	{
       
  2776 	Kern::Fault("SDIO_SESS", aPanic);
       
  2777 	}
       
  2778 
       
  2779 	
       
  2780 #ifdef _DEBUG
       
  2781 void DSDIOStack::TraceCCCRInfo()
       
  2782 /**
       
  2783 Debug function to output the contents of the FBR
       
  2784 */
       
  2785 	{
       
  2786 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "\nCCCR/SDIO Revision    : %02xH (CCCR Rev: %d, SDIO Rev: %d) ",	iBufCCCR[0x00], iBufCCCR[0x00] & 0x0F, (iBufCCCR[0x00] & 0xF0) >> 4)); // @SymTraceDataInternalTechnology
       
  2787 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "SD Spec Revision      : %02xH", iBufCCCR[0x01])); // @SymTraceDataInternalTechnology
       
  2788 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "I/O Enable            : %02xH", iBufCCCR[0x02])); // @SymTraceDataInternalTechnology
       
  2789 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "I/O Ready             : %02xH", iBufCCCR[0x03])); // @SymTraceDataInternalTechnology
       
  2790 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "Int Enable            : %02xH", iBufCCCR[0x04])); // @SymTraceDataInternalTechnology
       
  2791 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "Int Pending           : %02xH", iBufCCCR[0x05])); // @SymTraceDataInternalTechnology
       
  2792 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "I/O Abort             : %02xH", iBufCCCR[0x06])); // @SymTraceDataInternalTechnology
       
  2793 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "Bus Interface Control : %02xH - CD Disable : %db (Disconnect CD Pullup))",		 iBufCCCR[0x07], (iBufCCCR[0x07] & 0x80) ? ETrue : EFalse)); // @SymTraceDataInternalTechnology
       
  2794 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "                            - SCSI       : %db (Supports Cont. SPI Interrupts)",	(iBufCCCR[0x07] & 0x40) ? ETrue : EFalse)); // @SymTraceDataInternalTechnology
       
  2795 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "                            - ECSI       : %db (Cont. SPI Interrupts Enable)",	(iBufCCCR[0x07] & 0x20) ? ETrue : EFalse)); // @SymTraceDataInternalTechnology
       
  2796 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "                            - Bus Width  : %d-bit",								(iBufCCCR[0x07] & 0x03) ? 4 : 1)); // @SymTraceDataInternalTechnology
       
  2797 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "Card Capability       : %02xH - 4BLS       : %db (LSC supports 4-bit)",			iBufCCCR[0x08], iBufCCCR[0x08] & 0x80 ? ETrue : EFalse)); // @SymTraceDataInternalTechnology
       
  2798 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "                            - LSC        : %db (Low Speed Card)",					iBufCCCR[0x08] & 0x40 ? ETrue : EFalse)); // @SymTraceDataInternalTechnology
       
  2799 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "                            - E4MI       : %db (Enable Int. in 4-bit blocks)",	iBufCCCR[0x08] & 0x20 ? ETrue : EFalse)); // @SymTraceDataInternalTechnology
       
  2800 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "                            - S4MI       : %db (Supports Int. in 4-bit blocks)",	iBufCCCR[0x08] & 0x10 ? ETrue : EFalse)); // @SymTraceDataInternalTechnology
       
  2801 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "                            - SBS        : %db (Supports Suspend/Resume)",		iBufCCCR[0x08] & 0x08 ? ETrue : EFalse)); // @SymTraceDataInternalTechnology
       
  2802 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "                            - SRW        : %db (Supports Read/Wait)",				iBufCCCR[0x08] & 0x04 ? ETrue : EFalse)); // @SymTraceDataInternalTechnology
       
  2803 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "                            - SMB        : %db (Supports Multi-Block)",			iBufCCCR[0x08] & 0x02 ? ETrue : EFalse)); // @SymTraceDataInternalTechnology
       
  2804 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "                            - SDC        : %db (Supports CMD52 in mult-ibyte)",	iBufCCCR[0x08] & 0x01 ? ETrue : EFalse)); // @SymTraceDataInternalTechnology
       
  2805 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "Bus Suspend           : %02xH", iBufCCCR[0x0c])); // @SymTraceDataInternalTechnology
       
  2806 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "Function Select       : %02xH", iBufCCCR[0x0d])); // @SymTraceDataInternalTechnology
       
  2807 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "Exec Flags            : %02xH", iBufCCCR[0x0e])); // @SymTraceDataInternalTechnology
       
  2808 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "Ready Flags           : %02xH\n", iBufCCCR[0x0f])); // @SymTraceDataInternalTechnology
       
  2809 	SYMBIAN_TRACE_SDIO_VERBOSE_ONLY(Printf(TTraceContext(EInternals), "High Speed Flags      : %02xH\n", iBufCCCR[0x13])); // @SymTraceDataInternalTechnology
       
  2810 	}
       
  2811 
       
  2812 #endif
       
  2813 
       
  2814 EXPORT_C void DSDIOStack::Dummy1() {}
       
  2815 EXPORT_C void DSDIOStack::Dummy2() {}
       
  2816 EXPORT_C void DSDIOStack::Dummy3() {}
       
  2817 EXPORT_C void DSDIOStack::Dummy4() {}