kerneltest/e32test/pccd/d_mmctest.cpp
changeset 279 957c583b417b
equal deleted inserted replaced
275:2b433474f2ba 279:957c583b417b
       
     1 // Copyright (c) 2010 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 // This LDD provides a set of direct interface functions with the kernel 
       
    15 // MultiMediaCard Controller
       
    16 // 
       
    17 //
       
    18 
       
    19 #include <kernel/kernel.h>
       
    20 #include <drivers/mmc.h>
       
    21 #include "d_mmctest.h"
       
    22 
       
    23 const TInt KMajorVersionNumber=1;
       
    24 const TInt KMinorVersionNumber=0;
       
    25 const TInt KBuildVersionNumber=0;
       
    26 
       
    27 const TInt KStackNumber  = 0;
       
    28 
       
    29 const TInt KMaxMMCCardsPerStack = 4;
       
    30 
       
    31 // global Dfc Que
       
    32 TDynamicDfcQue* gDfcQ;
       
    33 
       
    34 class DLddFactoryMmcCntrlInterface : public DLogicalDevice
       
    35 	{
       
    36 public:
       
    37 	DLddFactoryMmcCntrlInterface();
       
    38 	virtual ~DLddFactoryMmcCntrlInterface();
       
    39 	virtual TInt Install();
       
    40 	virtual void GetCaps(TDes8 &aDes) const;
       
    41 	virtual TInt Create(DLogicalChannelBase*& aChannel); 	//overriding pure virtual
       
    42 	};
       
    43 
       
    44 class DLddMmcCntrlInterface : public DLogicalChannel
       
    45 	{
       
    46 public:
       
    47 	DLddMmcCntrlInterface();
       
    48 	~DLddMmcCntrlInterface();
       
    49 protected:
       
    50 	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
       
    51 	virtual void HandleMsg(class TMessageBase *);
       
    52 private:
       
    53 	void DoCancel(TInt aReqNo);
       
    54 	TInt DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2);
       
    55 	TInt DoControl(TInt aFunction, TAny* a1, TAny* a2);
       
    56 	TInt PrintCardInfo();	
       
    57 private:
       
    58     void Reset();
       
    59     static void SessionEndCallBack(TAny *aPtr);
       
    60     static void SessionEndDfc(TAny *aPtr);
       
    61 	static void EventCallBack(TAny* aPtr, TInt aReason, TAny* a1, TAny* a2);
       
    62 
       
    63 private:
       
    64     enum TPanic {EReadDes,EWriteDes,EWriteTInt,EUnknownMmcSes};
       
    65     enum TMmcSessionCmd {EMmcSesNone,EMmcSesReadBlk,EMmcSesWriteBlk, EMmcSesReadExtCSD};
       
    66     TInt iStackNum;
       
    67 	DMMCSocket* iSocketP;
       
    68     DMMCStack* iStack;
       
    69     TMMCard* iCard;
       
    70     DMMCSession* iSession;
       
    71     TMmcSessionCmd iMmcSessionCmd;
       
    72     TAny* iClientDesPtr;
       
    73 	TUint32 iBlkOffet;
       
    74 	TRequestStatus* iReadWriteStatusP;
       
    75     TMMCCallBack iSessionEndCallBack;
       
    76 	TDfc iSessionEndDfc;
       
    77 	TPBusCallBack iBusEventCallback;
       
    78 	TRequestStatus* iPowerUpStatusP;
       
    79 //	TUint8 iBuf[KDrvBufSizeInBytes];	// iBuf now uses the MMC DMA buffer, until DT issue with H4 is resolved
       
    80 	TUint8* iBuf;
       
    81 	DThread* iClient;
       
    82 	TExtendedCSD iExtendedCSD;
       
    83     };
       
    84 
       
    85 DECLARE_STANDARD_LDD()
       
    86 	{
       
    87 	return new DLddFactoryMmcCntrlInterface;
       
    88 	}
       
    89 
       
    90 DLddFactoryMmcCntrlInterface::DLddFactoryMmcCntrlInterface()
       
    91 //
       
    92 // Constructor
       
    93 //
       
    94 	{
       
    95 
       
    96     iParseMask=KDeviceAllowUnit;  // Pass stack number as unit
       
    97 	iUnitsMask=0xffffffff;
       
    98 	iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
       
    99 	}
       
   100 
       
   101 TInt DLddFactoryMmcCntrlInterface::Create(DLogicalChannelBase*& aChannel)
       
   102 //
       
   103 // Create a new DLddFactoryMmcCntrlInterface on this logical device
       
   104 //
       
   105 	{
       
   106 	aChannel=new DLddMmcCntrlInterface;
       
   107 	return aChannel ? KErrNone : KErrNoMemory;
       
   108 	}
       
   109 
       
   110 const TInt KDMmcThreadPriority = 27;
       
   111 _LIT(KDMmcThread,"DMmcTestThread");
       
   112 
       
   113 TInt DLddFactoryMmcCntrlInterface::Install()
       
   114 //
       
   115 // Install the device driver.
       
   116 //
       
   117 	{
       
   118 	// Allocate a kernel thread to run the DFC 
       
   119 	TInt r = Kern::DynamicDfcQCreate(gDfcQ, KDMmcThreadPriority, KDMmcThread);
       
   120 
       
   121 	if (r != KErrNone)
       
   122 		return r; 	
       
   123 
       
   124     TPtrC name=_L("MmcTest");
       
   125 	return(SetName(&name));
       
   126 	}
       
   127 
       
   128 void DLddFactoryMmcCntrlInterface::GetCaps(TDes8 &aDes) const
       
   129 //
       
   130 // Return the Pc Card Contoller Interface ldd's capabilities.
       
   131 //
       
   132 	{
       
   133 
       
   134     TCapsMmcIfV01 b;
       
   135 	b.version=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
       
   136     Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
       
   137 	}
       
   138 
       
   139 /**
       
   140   Destructor
       
   141 */
       
   142 DLddFactoryMmcCntrlInterface::~DLddFactoryMmcCntrlInterface()
       
   143 	{
       
   144 	if (gDfcQ)
       
   145 		gDfcQ->Destroy();
       
   146 	}
       
   147 
       
   148 #pragma warning( disable : 4355 )	// this used in initializer list
       
   149 DLddMmcCntrlInterface::DLddMmcCntrlInterface()
       
   150 //
       
   151 // Constructor
       
   152 //
       
   153 	: iSessionEndCallBack(DLddMmcCntrlInterface::SessionEndCallBack,this),
       
   154 	  iSessionEndDfc(DLddMmcCntrlInterface::SessionEndDfc, this, 1),
       
   155 	  iBusEventCallback(DLddMmcCntrlInterface::EventCallBack, this)
       
   156 	{
       
   157 
       
   158 //	iMmcController=NULL;
       
   159 //  iStackNum=0;
       
   160 //  iStack=NULL;
       
   161 //  iCard=NULL;
       
   162 //  iSession=NULL;
       
   163 //  iMmcSessionCmd=EMmcSesNone;
       
   164 //  iClientDesPtr=NULL;
       
   165 //	iBlkOffet=0;
       
   166 
       
   167 	iClient=&Kern::CurrentThread();
       
   168 	((DObject*)iClient)->Open();	// can't fail since thread is running
       
   169     }
       
   170 #pragma warning( default : 4355 )
       
   171 
       
   172 DLddMmcCntrlInterface::~DLddMmcCntrlInterface()
       
   173 //
       
   174 // Destructor
       
   175 //
       
   176 	{
       
   177 
       
   178     Reset();
       
   179 	iBusEventCallback.Remove();
       
   180 	delete iSession;
       
   181 	Kern::SafeClose((DObject*&)iClient,NULL);
       
   182     }
       
   183 
       
   184 TInt DLddMmcCntrlInterface::DoCreate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& aVer)
       
   185 //
       
   186 // Create channel.
       
   187 //
       
   188 	{    
       
   189 	if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer))
       
   190 		return(KErrNotSupported);
       
   191 
       
   192 	//
       
   193 	// Obtain the appropriate card from the socket/stack
       
   194 	//
       
   195 	iSocketP = static_cast<DMMCSocket*>(DPBusSocket::SocketFromId(aUnit));
       
   196 	if(iSocketP == NULL)
       
   197 		return(KErrNoMemory);
       
   198 
       
   199 	iStack = static_cast<DMMCStack*>(iSocketP->Stack(KStackNumber));
       
   200 	if(iStack == NULL)
       
   201 		return(KErrNoMemory);
       
   202 
       
   203     // Create an MMC session object
       
   204 	iSession = iStack->AllocSession(iSessionEndCallBack);
       
   205     if (iSession==NULL)
       
   206 		return(KErrNoMemory);
       
   207 		
       
   208     iSession->SetStack(iStack);
       
   209    
       
   210 	TUint8* buf;
       
   211 	TInt bufLen;
       
   212 	TInt minorBufLen;
       
   213 	iStack->BufferInfo(buf, bufLen, minorBufLen);
       
   214 	iBuf = buf;
       
   215 
       
   216 	SetDfcQ(gDfcQ);
       
   217 	iMsgQ.Receive();
       
   218 	
       
   219 	iSessionEndDfc.SetDfcQ(gDfcQ);
       
   220 
       
   221 	iBusEventCallback.SetSocket(aUnit);
       
   222 	iBusEventCallback.Add();
       
   223 
       
   224     return(KErrNone);
       
   225 	}
       
   226 
       
   227 void DLddMmcCntrlInterface::DoCancel(TInt /*aReqNo*/)
       
   228 //
       
   229 // Cancel an outstanding request.
       
   230 //
       
   231 	{
       
   232 	}
       
   233 
       
   234 void DLddMmcCntrlInterface::HandleMsg(TMessageBase* aMsg)
       
   235     {
       
   236     TThreadMessage& m=*(TThreadMessage*)aMsg;
       
   237     TInt id=m.iValue;
       
   238     
       
   239 	if (id==(TInt)ECloseMsg)
       
   240 		{
       
   241 		m.Complete(KErrNone, EFalse);
       
   242 		return;
       
   243 		}
       
   244     else if (id==KMaxTInt)
       
   245 		{
       
   246 		// DoCancel
       
   247 		m.Complete(KErrNone,ETrue);
       
   248 		return;
       
   249 		}
       
   250 
       
   251     if (id<0)
       
   252 		{
       
   253 		// DoRequest
       
   254 		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
       
   255 		TInt r=DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
       
   256 		if (r!=KErrNone)
       
   257 	    	Kern::RequestComplete(iClient, pS, r);
       
   258 		m.Complete(KErrNone,ETrue);
       
   259 		}
       
   260     else
       
   261 		{
       
   262 		// DoControl
       
   263 		TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
       
   264 		if(r != KErrCompletion)
       
   265 			{
       
   266 			m.Complete(r,ETrue);
       
   267 			}
       
   268 		}
       
   269 	}
       
   270 
       
   271 TInt DLddMmcCntrlInterface::PrintCardInfo()
       
   272     {
       
   273     if(iCard == NULL)
       
   274         {
       
   275         return(KErrNotReady);
       
   276         }
       
   277     const TCSD& csd = iCard->CSD();
       
   278     Kern::Printf("CSD");    
       
   279     Kern::Printf("CSDStructure():                 %u",csd.CSDStructure());
       
   280     Kern::Printf("SpecVers():                     %u",csd.SpecVers());
       
   281     switch (csd.MediaType())
       
   282         {
       
   283         case EMultiMediaROM   : Kern::Printf("Read Only Media"); break;
       
   284         case EMultiMediaFlash : Kern::Printf("Writable Media"); break;
       
   285         case EMultiMediaIO    : Kern::Printf("IO Media Device"); break;
       
   286         case EMultiMediaOther : Kern::Printf("UNKNOWN Media type"); break;
       
   287         default : Kern::Printf("Media NOT SUPPORTED");
       
   288         }    
       
   289     Kern::Printf("----------------------------------");
       
   290     Kern::Printf("Reserved120():                  %u",csd.Reserved120());
       
   291     Kern::Printf("TAAC():                         %u", csd.TAAC());
       
   292     Kern::Printf("NSAC():                         %u", csd.NSAC());
       
   293     Kern::Printf("TranSpeed():                    %u", csd.TranSpeed());
       
   294     Kern::Printf("CCC():                          %u",csd.CCC());
       
   295     Kern::Printf("ReadBlLen():                    %u", csd.ReadBlLen());
       
   296     Kern::Printf("ReadBlPartial():                %u", (TUint)csd.ReadBlPartial());
       
   297     Kern::Printf("WriteBlkMisalign():             %u", (TUint) csd.WriteBlkMisalign());
       
   298     Kern::Printf("ReadBlkMisalign():              %u", (TUint) csd.ReadBlkMisalign());
       
   299     Kern::Printf("DSRImp():                       %u", (TUint) csd.DSRImp());
       
   300     Kern::Printf("Reserved74():                   %u", csd.Reserved74());
       
   301     Kern::Printf("CSize():                        %u", csd.CSize());
       
   302     Kern::Printf("VDDRCurrMin():                  %u", csd.VDDRCurrMin());
       
   303     Kern::Printf("VDDRCurrMax():                  %u", csd.VDDRCurrMax());
       
   304     Kern::Printf("VDDWCurrMin():                  %u", csd.VDDWCurrMin());
       
   305     Kern::Printf("VDDWCurrMax():                  %u", csd.VDDWCurrMax());
       
   306     Kern::Printf("CSizeMult():                    %u", csd.CSizeMult());
       
   307     Kern::Printf("EraseGrpSize():                 %u", csd.EraseGrpSize());
       
   308     Kern::Printf("EraseGrpMult():                 %u", csd.EraseGrpMult());
       
   309     Kern::Printf("WPGrpSize():                    %u", csd.WPGrpSize());
       
   310     Kern::Printf("WPGrpEnable():                  %u", csd.WPGrpEnable());            
       
   311     Kern::Printf("DefaultECC():                   %u", csd.DefaultECC());
       
   312     Kern::Printf("R2WFactor():                    %u", csd.R2WFactor());
       
   313     Kern::Printf("WriteBlLen():                   %u", csd.WriteBlLen());
       
   314     Kern::Printf("WriteBlPartial():               %u", (TUint) csd.WriteBlPartial());
       
   315     Kern::Printf("Reserved16():                   %u", csd.Reserved16());
       
   316     Kern::Printf("FileFormatGrp():                %u", (TUint) csd.FileFormatGrp());
       
   317     Kern::Printf("Copy():                         %u", (TUint) csd.Copy());
       
   318     Kern::Printf("PermWriteProtect():             %u", (TUint) csd.PermWriteProtect());
       
   319     Kern::Printf("TmpWriteProtect():              %u", (TUint) csd.TmpWriteProtect());
       
   320     Kern::Printf("FileFormat():                   %u", csd.FileFormat());
       
   321     Kern::Printf("ECC():                          %u", csd.ECC());
       
   322     Kern::Printf("CRC():                          %u", csd.CRC());
       
   323     Kern::Printf("DeviceSize():                   %u", csd.DeviceSize());   
       
   324     Kern::Printf("ReadBlockLength():              %u", csd.ReadBlockLength());
       
   325     Kern::Printf("WriteBlockLength():             %u", csd.WriteBlockLength());
       
   326     Kern::Printf("EraseSectorSize():              %u", csd.EraseSectorSize());
       
   327     Kern::Printf("EraseGroupSize():               %u", csd.EraseGroupSize());
       
   328     Kern::Printf("MinReadCurrentInMilliamps():    %u", csd.MinReadCurrentInMilliamps());
       
   329     Kern::Printf("MinWriteCurrentInMilliamps():   %u", csd.MinWriteCurrentInMilliamps());
       
   330     Kern::Printf("MaxReadCurrentInMilliamps():    %u", csd.MaxReadCurrentInMilliamps());
       
   331     Kern::Printf("MaxWriteCurrentInMilliamps():   %u", csd.MaxWriteCurrentInMilliamps());
       
   332     Kern::Printf("MaxTranSpeedInKilohertz():      %u", csd.MaxTranSpeedInKilohertz());
       
   333     
       
   334     const TExtendedCSD& extcsd = iCard->iExtendedCSD;
       
   335     Kern::Printf("\nExtended CSD");
       
   336     Kern::Printf("CSDStructureVer:                %u", extcsd.CSDStructureVer());
       
   337     Kern::Printf("ExtendedCSDRev:                 %u", extcsd.ExtendedCSDRev());
       
   338     Kern::Printf("----------------------------------");
       
   339     Kern::Printf("SupportedCmdSet:                %u", extcsd.SupportedCmdSet());
       
   340     Kern::Printf("SectorCount:                    %u", extcsd.SectorCount());
       
   341     Kern::Printf("MinPerfWrite8Bit52Mhz:          %u", extcsd.MinPerfWrite8Bit52Mhz());
       
   342     Kern::Printf("MinPerfRead8Bit52Mhz:           %u", extcsd.MinPerfRead8Bit52Mhz());
       
   343     Kern::Printf("MinPerfRead8Bit26Mhz_4Bit52Mhz: %u", extcsd.MinPerfRead8Bit26Mhz_4Bit52Mhz());
       
   344     Kern::Printf("MinPerfWrite4Bit26Mhz:          %u", extcsd.MinPerfWrite4Bit26Mhz());
       
   345     Kern::Printf("MinPerfRead4Bit26Mhz:           %u", extcsd.MinPerfRead4Bit26Mhz());
       
   346     Kern::Printf("PowerClass26Mhz360V:            0x%02X", extcsd.PowerClass26Mhz360V());
       
   347     Kern::Printf("PowerClass52Mhz360V:            0x%02X", extcsd.PowerClass52Mhz360V());
       
   348     Kern::Printf("PowerClass26Mhz195V:            0x%02X", extcsd.PowerClass26Mhz195V());
       
   349     Kern::Printf("PowerClass52Mhz195V:            0x%02X", extcsd.PowerClass52Mhz195V());
       
   350     Kern::Printf("CardType:                       %u", extcsd.CardType());
       
   351     Kern::Printf("CmdSet:                         %u", extcsd.CmdSet());
       
   352     Kern::Printf("CmdSetRev:                      %u", extcsd.CmdSetRev());
       
   353     Kern::Printf("PowerClass:                     %u", extcsd.PowerClass());
       
   354     Kern::Printf("HighSpeedTiming:                %u", extcsd.HighSpeedTiming());
       
   355     Kern::Printf("BusWidthMode:                   %u", extcsd.BusWidthMode());
       
   356     Kern::Printf("HighCapacityEraseGroupSize:     %u", extcsd.HighCapacityEraseGroupSize());
       
   357     Kern::Printf("AccessSize:                     %u", extcsd.AccessSize());
       
   358     Kern::Printf("BootInfo:                       %u", extcsd.BootInfo() );
       
   359     Kern::Printf("BootSizeMultiple:               %u", extcsd.BootSizeMultiple() );
       
   360     Kern::Printf("EraseTimeoutMultiple:           %u", extcsd.EraseTimeoutMultiple() );
       
   361     Kern::Printf("ReliableWriteSector:            %u", extcsd.ReliableWriteSector() );
       
   362     Kern::Printf("HighCapWriteProtGroupSize:      %u", extcsd.HighCapacityWriteProtectGroupSize() );
       
   363     Kern::Printf("SleepCurrentVcc:                %u", extcsd.SleepCurrentVcc() );
       
   364     Kern::Printf("SleepCurrentVccQ:               %u", extcsd.SleepCurrentVccQ());
       
   365     Kern::Printf("SleepAwakeTimeout:              %u", extcsd.SleepAwakeTimeout());
       
   366     Kern::Printf("BootConfig:                     %u", extcsd.BootConfig());
       
   367     Kern::Printf("BootBusWidth:                   %u", extcsd.BootBusWidth());
       
   368     Kern::Printf("EraseGroupDef:                  %u", extcsd.EraseGroupDef());
       
   369     
       
   370     return KErrNone;
       
   371     }
       
   372 
       
   373 TInt DLddMmcCntrlInterface::DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2)
       
   374 //
       
   375 // Most Async requests
       
   376 //
       
   377 	{
       
   378 
       
   379     if (iMmcSessionCmd!=EMmcSesNone)
       
   380 		{
       
   381 		return(KErrInUse);
       
   382 		}
       
   383 
       
   384     switch (aFunction)
       
   385 		{
       
   386         case RMmcCntrlIf::EReqPwrUp:
       
   387 			{
       
   388 			if(!iSocketP->CardIsPresent())
       
   389 				{
       
   390 				Kern::RequestComplete(iClient, aStatus, KErrNotReady);
       
   391 				}
       
   392 			else if(iSocketP->State() == EPBusOn)
       
   393 				{
       
   394 				Kern::RequestComplete(iClient, aStatus, KErrNone);
       
   395 				}
       
   396 			else
       
   397 				{
       
   398 				iPowerUpStatusP = aStatus;
       
   399 				iSocketP->PowerUp();
       
   400 				}
       
   401 			break;
       
   402 			}
       
   403         case RMmcCntrlIf::EReqReadSect:
       
   404             {
       
   405 			if(iCard == NULL)
       
   406 				{
       
   407 				return(KErrNotReady);
       
   408 				}
       
   409 
       
   410 			//TCSD csd=iCard->CSD();
       
   411 			iReadWriteStatusP = aStatus;
       
   412 			TUint32 srcAddr=((TUint32)a1)<<KSectorSizeShift;
       
   413 			TUint readBlLen = 1 << iCard->MaxReadBlLen();
       
   414 			TUint readBlMask=(readBlLen-1);
       
   415 			iBlkOffet=srcAddr-(srcAddr&(~readBlMask));
       
   416 			iClientDesPtr=a2;
       
   417 			iMmcSessionCmd=EMmcSesReadBlk;
       
   418 			srcAddr&=(~readBlMask);
       
   419 			TMMCArgument da(srcAddr);
       
   420 			iSession->SetupCIMReadBlock(da,readBlLen,&iBuf[0]);
       
   421 			iSession->Engage();
       
   422 			break;
       
   423             }
       
   424         case RMmcCntrlIf::EReqWriteSect:
       
   425             {
       
   426 			if(iCard == NULL)
       
   427 				{
       
   428 				return(KErrNotReady);
       
   429 				}
       
   430 
       
   431 			iReadWriteStatusP = aStatus;
       
   432 			TUint32 destAddr=((TUint32)a1)<<KSectorSizeShift;
       
   433 			TUint writeBlLen=1 << iCard->MaxWriteBlLen();
       
   434 			TUint writeBlMask=(writeBlLen-1);
       
   435 			iBlkOffet=destAddr-(destAddr&(~writeBlMask));
       
   436 			TPtr8* srcDes = (TPtr8*)a2;		
       
   437 			TPtr8 ptr(&iBuf[iBlkOffet],KSectorSizeInBytes,KSectorSizeInBytes);
       
   438 			TInt r = Kern::ThreadDesRead(iClient, srcDes, ptr, 0, KChunkShiftBy0);
       
   439 			if(r != KErrNone)
       
   440 				{
       
   441 				return(r);
       
   442 				}
       
   443 				
       
   444 			iMmcSessionCmd=EMmcSesWriteBlk;
       
   445 			destAddr&=(~writeBlMask);
       
   446 			iSession->SetupCIMWriteBlock(TMMCArgument(destAddr),writeBlLen,&iBuf[0]);
       
   447 			iSession->Engage();
       
   448 			break;
       
   449 			}
       
   450 
       
   451         case RMmcCntrlIf::EReqReadExtCSD:
       
   452             {
       
   453 			if(iCard == NULL)
       
   454 				{
       
   455 				return(KErrNotReady);
       
   456 				}
       
   457 
       
   458 			iClientDesPtr = a1;
       
   459 			iReadWriteStatusP = aStatus;
       
   460 			iMmcSessionCmd = EMmcSesReadExtCSD;
       
   461 
       
   462 			iSession->SetupDTCommand(
       
   463 				ECmdSendExtendedCSD, 
       
   464 				TMMCArgument(0),
       
   465 				KMMCExtendedCSDLength,
       
   466 				(TUint8*) &iExtendedCSD);
       
   467 
       
   468 			iSession->Engage();
       
   469 			break;
       
   470             }
       
   471             
       
   472         case RMmcCntrlIf::EReqMMCInfoPrint:
       
   473             {
       
   474             // Print CSD & Extended CSD values
       
   475             TInt r = PrintCardInfo();            
       
   476             Kern::RequestComplete(iClient, aStatus, r);
       
   477             break;
       
   478             }
       
   479 
       
   480         }
       
   481 	return(KErrNone);
       
   482 	}
       
   483 
       
   484 TInt DLddMmcCntrlInterface::DoControl(TInt aFunction,TAny* a1,TAny* /*a2*/)
       
   485 //
       
   486 // Mostly requests (but some kernel server async ones)
       
   487 //
       
   488 	{
       
   489 
       
   490 	TInt r=KErrNotSupported;
       
   491 	switch (aFunction)
       
   492 		{
       
   493         case RMmcCntrlIf::ESvReset:
       
   494             {
       
   495             Reset();
       
   496 			r=KErrNone;
       
   497 			break;
       
   498             }
       
   499         case RMmcCntrlIf::ESvPwrDown:
       
   500 			{
       
   501 //		    iStack->PowerDown(); ???
       
   502 //          iMmcController->SetPowerEvent(0,EPEventPwrDownNormal,0);
       
   503 			r=KErrNone;
       
   504 			break;
       
   505 			}
       
   506         case RMmcCntrlIf::EExecStackInfo:
       
   507             {
       
   508             // Determine the number of cards present
       
   509             TUint cardsPresentMask=0x00000000;
       
   510 	        TMMCard* card;
       
   511             for (TInt i=0;i<KMaxMMCCardsPerStack;i++)
       
   512                 {
       
   513                 card=iStack->CardP(i);
       
   514                 if (card!=NULL && card->IsPresent())
       
   515                     cardsPresentMask|=(0x1<<i);
       
   516                 }
       
   517 			r = Kern::ThreadRawWrite(iClient,a1,&cardsPresentMask,sizeof(TUint));
       
   518 			break;
       
   519             }
       
   520         case RMmcCntrlIf::ESvRegisterEvent:
       
   521             {
       
   522 			return(KErrNotSupported);
       
   523             }
       
   524         case RMmcCntrlIf::EExecSelectCard:
       
   525             {
       
   526             iCard=iStack->CardP((TUint)a1);
       
   527             iSession->SetCard(iCard);
       
   528 			r=KErrNone;
       
   529 			break;
       
   530             }
       
   531         case RMmcCntrlIf::EExecCardInfo:
       
   532             {
       
   533             if (iCard)
       
   534                 {
       
   535 				TMmcCardInfo ci;
       
   536 	            ci.iIsReady=iCard->IsPresent();
       
   537 	            ci.iIsLocked=iCard->IsLocked();
       
   538 				TCID* cid=(TCID*)&(iCard->CID());
       
   539 				TInt i;
       
   540 				for (i=0;i<16;i++)
       
   541 					ci.iCID[i]=cid->At(i);
       
   542 				const TCSD& csd = iCard->CSD();
       
   543 				for (i=0;i<16;i++)
       
   544 					ci.iCSD[i]=csd.At(i);
       
   545 	            ci.iRCA=TUint16(iCard->RCA());
       
   546 	            ci.iMediaType=(TMmcMediaType)iCard->MediaType();
       
   547                 ci.iCardSizeInBytes=iCard->DeviceSize64();
       
   548 	            ci.iReadBlLen=csd.ReadBlockLength();
       
   549 	            ci.iWriteBlLen=csd.WriteBlockLength();
       
   550 	            ci.iReadBlPartial=csd.ReadBlPartial();
       
   551 	            ci.iWriteBlPartial=csd.WriteBlPartial();
       
   552 	            ci.iReadBlkMisalign=csd.ReadBlkMisalign();
       
   553 	            ci.iWriteBlkMisalign=csd.WriteBlkMisalign();
       
   554                 ci.iReadCurrentInMilliAmps=csd.MaxReadCurrentInMilliamps();
       
   555                 ci.iWriteCurrentInMilliAmps=csd.MaxWriteCurrentInMilliamps();
       
   556 	            ci.iSpecVers=csd.SpecVers();
       
   557 	            ci.iTAAC=csd.TAAC();
       
   558 	            ci.iNSAC=csd.NSAC();
       
   559 	            ci.iTransferSpeed=csd.TranSpeed();
       
   560 	            ci.iCommandRegister=csd.CCC();
       
   561 	            ci.iHighCapacity = iCard->IsHighCapacity();
       
   562 				r = Kern::ThreadRawWrite(iClient, a1/*TAny *aDest*/, &ci/*const TAny *aSrc*/, sizeof(TMmcCardInfo));
       
   563                 }
       
   564             else
       
   565                 r=KErrGeneral;
       
   566 			break;
       
   567             }
       
   568 		}
       
   569 	return(r);
       
   570 	}
       
   571 
       
   572 void DLddMmcCntrlInterface::Reset()
       
   573 //
       
   574 // Release any resources 
       
   575 //
       
   576 	{
       
   577 	iSessionEndDfc.Cancel();
       
   578     }
       
   579 
       
   580 void DLddMmcCntrlInterface::SessionEndCallBack(TAny *aPtr)
       
   581 //
       
   582 // Session end callback
       
   583 //
       
   584 	{
       
   585 	DLddMmcCntrlInterface &mci=*(DLddMmcCntrlInterface*)aPtr;
       
   586 
       
   587 	// Signal request complete using DFC 
       
   588 	if (!mci.iSessionEndDfc.Queued())
       
   589 		mci.iSessionEndDfc.Enque();
       
   590 	}
       
   591 
       
   592 void DLddMmcCntrlInterface::SessionEndDfc(TAny *aPtr)
       
   593 //
       
   594 // Session end dfc
       
   595 //
       
   596 	{
       
   597 	DLddMmcCntrlInterface &mci=*(DLddMmcCntrlInterface*)aPtr;
       
   598     TInt err=mci.iSession->EpocErrorCode();
       
   599     switch (mci.iMmcSessionCmd)
       
   600 		{
       
   601         case EMmcSesReadBlk:
       
   602             {
       
   603 			TPtr8 ptr(&mci.iBuf[mci.iBlkOffet],KSectorSizeInBytes,KSectorSizeInBytes);
       
   604 			TPtrC8* srcDes = (TPtrC8*)mci.iClientDesPtr;
       
   605 			TInt r = Kern::ThreadDesWrite(mci.iClient,srcDes,ptr,0,mci.iClient);
       
   606 
       
   607 	    	Kern::RequestComplete(mci.iClient, mci.iReadWriteStatusP, (r == KErrNone) ? err : r);
       
   608             break;
       
   609             }
       
   610         case EMmcSesWriteBlk:
       
   611 			{
       
   612 			Kern::Printf("EMmcSesWriteBlk Complete");
       
   613 	    	Kern::RequestComplete(mci.iClient, mci.iReadWriteStatusP, err);
       
   614             break;
       
   615 			}
       
   616 		case EMmcSesReadExtCSD:
       
   617 			{
       
   618 			TPtr8 ptr((TUint8*) &mci.iExtendedCSD, KMMCExtendedCSDLength, KMMCExtendedCSDLength);
       
   619 			TPtrC8* dstDes = (TPtrC8*)mci.iClientDesPtr;
       
   620 			TInt r = Kern::ThreadDesWrite(mci.iClient, dstDes, ptr, 0,mci.iClient);
       
   621 
       
   622 	    	Kern::RequestComplete(mci.iClient, mci.iReadWriteStatusP, (r == KErrNone) ? err : r);
       
   623 			break;
       
   624 			}
       
   625         default:
       
   626         	break;
       
   627 		}
       
   628 	mci.iMmcSessionCmd=EMmcSesNone;
       
   629 	}
       
   630 
       
   631 void DLddMmcCntrlInterface::EventCallBack(TAny* aPtr, TInt aReason, TAny* a1, TAny* a2)
       
   632 	{
       
   633 	DLddMmcCntrlInterface &mci=*(DLddMmcCntrlInterface*)aPtr;
       
   634 
       
   635 	if(mci.iPowerUpStatusP)
       
   636 		{
       
   637 		TInt retCode = KErrCompletion;
       
   638 
       
   639 		switch(aReason)
       
   640 			{
       
   641 			case TPBusCallBack::EPBusStateChange:
       
   642 				{
       
   643 				TPBusState newState = (TPBusState)(TInt)a1;
       
   644 				TInt errorCode = (TInt)a2;
       
   645 
       
   646 				switch(newState)
       
   647 					{
       
   648 					case EPBusCardAbsent:	retCode = KErrNotFound;		break;			
       
   649 					case EPBusOff:			retCode = errorCode;		break;
       
   650 					case EPBusPsuFault:		retCode = KErrBadPower;		break;
       
   651 					case EPBusOn:			retCode = KErrNone;			break;
       
   652 					case EPBusPowerUpPending:
       
   653 					case EPBusPoweringUp:
       
   654 					default:	
       
   655 						break;
       
   656 					}
       
   657 
       
   658 				break;
       
   659 				}
       
   660 			}
       
   661 
       
   662 		if(retCode != KErrCompletion)
       
   663 			{
       
   664    			Kern::RequestComplete(mci.iClient, mci.iPowerUpStatusP, retCode);
       
   665 			mci.iPowerUpStatusP = NULL;
       
   666 			}
       
   667 		}
       
   668 	}
       
   669 
       
   670