kernel/eka/drivers/medmmc/medmmc.cpp
changeset 287 ddfd5aa0d58f
parent 271 dc268b18d709
child 293 0659d0e1a03c
--- a/kernel/eka/drivers/medmmc/medmmc.cpp	Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/medmmc/medmmc.cpp	Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1999-2010 Nokia Corporation and/or its subsidiary(-ies).
 // All rights reserved.
 // This component and the accompanying materials are made available
 // under the terms of the License "Eclipse Public License v1.0"
@@ -50,6 +50,7 @@
 #define __ASSERT_CACHE(c,p)
 #endif
 
+#include "medmmc.h"
 
 GLREF_C TInt GetMediaDefaultPartitionInfo(TMBRPartitionEntry& aPartitionEntry, TUint16& aReservedSectors, const TMMCard* aCardP);
 GLREF_C TBool MBRMandatory(const TMMCard* aCardP);
@@ -59,11 +60,10 @@
 extern  TInt GetCardFormatInfo(const TMMCard* aCardP, TLocalDriveCapsV5& aCaps);
 
 
+IMPORT_C extern const TUint KTRIMEnabled;
+
 const TInt KStackNumber = 0;
 
-const TInt KDiskSectorSize=512;
-const TInt KDiskSectorShift=9;
-
 const TInt KIdleCurrentInMilliAmps = 1;
 
 const TInt KMBRFirstPartitionEntry=0x1BE;
@@ -90,237 +90,6 @@
 const TInt64 KInvalidBlock = -1;
 const TInt KNoCacheBlock = -1;
 
-class DMmcMediaDriverFlash : public DMediaDriver
-	{
-public:
-	DMmcMediaDriverFlash(TInt aMediaId);
-	~DMmcMediaDriverFlash();
-	// ...from DMediaDriver
-	virtual void Close();
-	// replacing pure virtual
-	virtual void Disconnect(DLocalDrive* aLocalDrive, TThreadMessage*);
-	virtual TInt Request(TLocDrvRequest& aRequest);
-	virtual TInt PartitionInfo(TPartitionInfo& anInfo);
-	virtual void NotifyPowerDown();
-	virtual void NotifyEmergencyPowerDown();
-	// For creation by DPhysicalDeviceMediaMmcFlash
-	TInt DoCreate(TInt aMediaId);
-
-private:
-	enum TPanic
-		{
-		EDRInUse		= 0x0000,	EDRStart, EDRNotPositive, EDREnd,
-		ELRRequest		= 0x0010,	ELRStart, ELRNotPositive, ELREnd, ELRCached,
-		EDWInUse		= 0x0020,	EDWStart, EDWNotPositive, EDWEnd,
-		EDFInUse		= 0x0030,	EDFStart, EDFNotPositive, EDFEnd, ENotMmcSocket,
-		ELWRequest		= 0x0040,	ELWStart, ELWFmtStAlign, ELWNotPositive, ELWEnd, ELWFmtEndAlign, 
-									ELWLength, ELFStart, ELFEnd, ELFNotPositive,
-		ERPIInUse		= 0x0050,
-		EPCInUse		= 0x0060,	EPCFunc,
-		ESECBQueued		= 0x0070,
-		EDSEDRequest	= 0x0080,	EDSEDNotErrComplete,
-		ECRReqIdle		= 0x0090,	ECRRequest,
-		ERRBStAlign		= 0x00a0,	ERRBStPos, ERRBNotPositive, ERRBEndAlign, ERRBEndPos,
-									ERRBOverflow, ERRBCchInv, ERRBExist,
-		ERWBStPos		= 0x00b0,	ERWBNotPositive, ERWBEndPos, ERWBOverflow, ERWBCchInv,
-		EMBStPos		= 0x00c0,	EMBStAlign, EMBNotPositive, EMBEndPos, EMBEndAlign,
-									EMBOverflow, EMBCchInvPre, EMBCchInvPost,
-		EBGAStPos		= 0x00d0,	EBGAStAlign, EBGANotPositive, EBGAEndPos, EBGAEndAlign,
-									EBGAOverflow, EBGACchInv,
-		EICMNegative	= 0x00e0,	EICMOverflow, ECMIOverflow,
-		EGCBAlign		= 0x00f0,	EGCBPos, EGCBCchInv,
-		
-		ECFSessPtrNull	= 0x0100,	// Code Fault - session pointer NULL
-
-		EDBNotEven		= 0x0110,	// Not and even number of blocks in the buffer cache
-		EDBCBQueued		= 0x0111,	// The data transfer callback is already queued
-		EDBLength		= 0x0112,	// The length of data to transfer in data transfer callback is not positive
-		EDBLengthTooBig	= 0x0113,	// The length of data to transfer in data transfer callback is too big
-		EDBOffsetTooBig = 0x0114,	// The Offset into the user data buffer is too big
-		EDBCacheInvalid	= 0x0115,	// The cache is invalid at the end of data transfer
-		EDBNotOptimal	= 0x0116,	// Due to Cache size DB functionality will never be utilised
-		ENoDBSupport	= 0x0120,	// DMA request arrived but PSL does not support double buffering
-		ENotDMAAligned  = 0x0121,
-		};
-	static void Panic(TPanic aPnc);
-
-	enum TMediaRequest
-		{
-		EMReqRead = 0,
-		EMReqWrite = 1,
-		EMReqFormat = 2,
-		EMReqPtnInfo,
-		EMReqPswdCtrl,
-		EMReqForceErase,
-		EMReqUpdatePtnInfo,
-		EMReqWritePasswordData,
-		EMReqIdle,
-		EMReqEMMCPtnInfo,
-		};
-	enum TMediaReqType {EMReqTypeNormalRd,EMReqTypeNormalWr,EMReqTypeUnlockPswd,EMReqTypeChangePswd};
-
-	enum {KWtRBMFst = 0x00000001, 	// iWtRBM - Read First Block only
-		  KWtRBMLst = 0x00000002,	// iWtRBM - Read Last Block only
-		  KWtMinFst = 0x00000004,	// iWtRBM - Write First Block only
-		  KWtMinLst = 0x00000008,	// iWtRBM - Write Last Block only
-		  KIPCSetup = 0x00000010,	// iRdROB - IPC Setup Next Iteration
-		  KIPCWrite = 0x00000020};	// iRdROB - IPC Write Next Iteration
-
-private:
-	// MMC device specific stuff
-	TInt DoRead();
-	TInt DoWrite();
-	TInt DoFormat();
-	TInt Caps(TLocDrv& aDrive, TLocalDriveCapsV6& aInfo);
-
-	inline DMMCStack& Stack() const;
-	inline TInt CardNum() const;
-	inline TMediaRequest CurrentRequest() const;
-
-	TInt LaunchRead(TInt64 aStart, TUint32 aLength);
-	TInt LaunchDBRead();
-	TInt LaunchPhysRead(TInt64 aStart, TUint32 aLength);
-	
-	TInt LaunchWrite(TInt64 aStart, TUint32 aLength, TMediaRequest aMedReq);
-	TInt LaunchFormat(TInt64 aStart, TUint32 aLength);
-
-	TInt LaunchRPIUnlock(TLocalDrivePasswordData& aData);
-	TInt LaunchRPIRead();
-	TInt LaunchRPIErase();
-	TInt DecodePartitionInfo();
-	TInt WritePartitionInfo();
-	TInt GetDefaultPartitionInfo(TMBRPartitionEntry& aPartitionEntry);
-	TInt CreateDefaultPartition();
-
-
-#if defined __TEST_PAGING_MEDIA_DRIVER__
-	TInt HandleControlIORequest();
-#endif
-
-	static void SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors);
-
-	TInt CheckDevice(TMediaReqType aReqType);
-
-	static void SessionEndCallBack(TAny* aMediaDriver);
-	static void SessionEndDfc(TAny* aMediaDriver);
-	void DoSessionEndDfc();
-
-	static void DataTransferCallBack(TAny* aMediaDriver);
-	static void DataTransferCallBackDfc(TAny* aMediaDriver);
-
-	void DoReadDataTransferCallBack();
-	void DoWriteDataTransferCallBack();
-	void DoPhysReadDataTransferCallBack();
-	void DoPhysWriteDataTransferCallBack();
-	
-	TInt AdjustPhysicalFragment(TPhysAddr &physAddr, TInt &physLength);
-	TInt PrepareFirstPhysicalFragment(TPhysAddr &aPhysAddr, TInt &aPhysLength, TUint32 aLength);
-	void PrepareNextPhysicalFragment();
-
-	TInt EngageAndSetReadRequest(TMediaRequest aRequest);
-	TInt EngageAndSetWriteRequest(TMediaRequest aRequest);
-	TInt EngageAndSetRequest(TMediaRequest aRequest, TInt aCurrent);
-	void CompleteRequest(TInt aReason);
-
-	TInt ReadDataUntilCacheExhausted(TBool* aAllDone);
-	TInt WriteDataToUser(TUint8* aBufPtr);
-	TInt ReadDataFromUser(TDes8& aDes, TInt aOffset);
-	TUint8* ReserveReadBlocks(TInt64 aStart, TInt64 aEnd, TUint32* aLength);
-	TUint8* ReserveWriteBlocks(TInt64 aMedStart, TInt64 aMedEnd, TUint* aRBM);
-	void MarkBlocks(TInt64 aStart, TInt64 aEnd, TInt aStartIndex);
-	void BuildGammaArray(TInt64 aStart, TInt64 aEnd);
-	void InvalidateCache();
-	void InvalidateCache(TInt64 aStart, TInt64 aEnd);
-	TUint8* IdxToCchMem(TInt aIdx) const;
-	TInt CchMemToIdx(TUint8* aMemP) const;
-
-	TInt DoPasswordOp();
-	void PasswordControl(TInt aFunc, TLocalDrivePasswordData& aData);
-	void Reset();
-	TInt AllocateSession();  
-
-#ifdef _DEBUG_CACHE
-	TBool CacheInvariant();
-	TUint8* GetCachedBlock(TInt64 aAddr);
-#endif
-private:
-	DMMCStack* iStack;			 				// controller objects
-	TMMCard* iCard;
-	DMMCSession* iSession;
-	DMMCSocket* iSocket;
-
-	TInt iCardNumber;
-
-	TUint iBlkLenLog2;							// cached CSD data
-	TUint32 iBlkLen;
-	TInt64 iBlkMsk;
-	TBool iReadBlPartial;
-	TUint32 iPrWtGpLen;							// preferred write group size in bytes,
-	TInt64 iPrWtGpMsk;
-
-	TInt iReadCurrentInMilliAmps;				// power management
-	TInt iWriteCurrentInMilliAmps;
-
-	TUint8* iMinorBuf;							// MBR, CMD42, partial read
-	TUint8* iCacheBuf;							// cached buffer
-	TUint32 iMaxBufSize;
-	TInt iBlocksInBuffer;
-	TInt64* iCachedBlocks;
-	TInt* iGamma;								// B lookup, ReserveReadBlocks()
-	TUint8* iIntBuf;							// start of current buffer region
-	TInt iLstUsdCchEnt;							// index of last used cache entry
-
-	TLocDrvRequest* iCurrentReq;				// Current Request
-	TMediaRequest iMedReq;
-	
-	TInt64 iReqStart;							// user-requested start region
-	TInt64 iReqCur;								// Currently requested start region
-	TInt64 iReqEnd;							    // user-requested end region
-	TInt64 iPhysStart;							// physical region for one operation
-	TInt64 iPhysEnd;						    // physical end point for one operation
-	TInt64 iDbEnd;								// Double buffer end point for one operation
-
-	TUint64 iEraseUnitMsk;
-
-	TUint iWtRBM;								// Write - Read Before Modify Flags
-	TUint iRdROB;								// Read  - Read Odd Blocks Flags
-	
-	TInt iFragOfset;			
-	TUint32 iIPCLen;
-	TUint32 iNxtIPCLen;
-	TUint32 iBufOfset;
-	
-	TUint iHiddenSectors;						// bootup / password
-
-	TMMCCallBack iSessionEndCallBack;
-	TDfc iSessionEndDfc;
-
-	TPartitionInfo* iPartitionInfo;
-	TMMCMediaTypeEnum iMediaType;
-	TMMCEraseInfo iEraseInfo;
-	TBool iMbrMissing;
-	TInt iMediaId;
-
-	DMMCStack::TDemandPagingInfo iDemandPagingInfo;
-
-#if defined(__TEST_PAGING_MEDIA_DRIVER__)
-	SMmcStats iMmcStats;
-#endif // __TEST_PAGING_MEDIA_DRIVER__
-
-	TMMCCallBack iDataTransferCallBack;	// Callback registered with the MMC stack to perform double-buffering
-	TDfc iDataTransferCallBackDfc;		// ...and the associated DFC queue.
-
-	TBool iSecondBuffer;				// Specified the currently active buffer
-	TBool iDoLastRMW;					// ETrue if the last double-buffer transfer requires RMW modification
-	TBool iDoDoubleBuffer;				// ETrue if double-buffering is currently active
-	TBool iDoPhysicalAddress;			// ETrue if Physical Addressing is currently active
-	TBool iCreateMbr;
-	TBool iReadToEndOfCard;				// {Read Only} ETrue if Reading to end of Card
-
-	TBool iInternalSlot;
-
-	DEMMCPartitionInfo* iMmcPartitionInfo;  // Responsible for decoding partitions for embedded devices
-	};
 	
 // ======== DPhysicalDeviceMediaMmcFlash ========
 
@@ -471,6 +240,10 @@
 	// NB aMedia Id = the media ID of the primary media, iMediaId = the media ID of this media
 	__KTRACE_OPT(KPBUSDRV, Kern::Printf("DMmcMediaDriverFlash(), iMediaId %d, aMediaId %d\n", iMediaId, aMediaId));
 	OstTraceExt2( TRACE_FLOW, DMMCMEDIADRIVERFLASH_DMMCMEDIADRIVERFLASH, "> DMmcMediaDriverFlash::DMmcMediaDriverFlash;aMediaId=%d;iMediaId=%d", (TInt) aMediaId, (TInt) iMediaId );
+	for(TInt drv = 0; drv < KMaxLocalDrives; drv++)
+		{
+		SetEMmcPartitionMapping(drv, TExtendedCSD::ESelectUserArea);
+		}
 	
 	}
 
@@ -540,12 +313,13 @@
 
 	iMinorBuf = buf;
 	
+	// reserve KRpmbOneFramePacketLength bytes after the minor buffer for RPMB requests / responses
 	// cache buffer can use rest of blocks in buffer.  Does not have to be power of 2.
-	iCacheBuf = iMinorBuf + minorBufLen;
+	iCacheBuf = iMinorBuf + minorBufLen + KRpmbOneFramePacketLength;
 
 	// We need to devide up the buffer space between the media drivers.
 	// The number of buffer sub-areas = number of physical card slots * number of media
-	bufLen-= minorBufLen;
+	bufLen-= (minorBufLen + KRpmbOneFramePacketLength);
 	DPBusPrimaryMedia* primaryMedia = (DPBusPrimaryMedia*) iPrimaryMedia;
 	TInt physicalCardSlots = iStack->iMaxCardsInStack;
 	TInt numMedia = primaryMedia->iLastMediaId - primaryMedia->iMediaId + 1;
@@ -1160,7 +934,8 @@
 				}
 
 			// Now, if the erase start/end points are aligned to a min. erase unit boundary, we can use an erase cmd.
-			if ((iPhysStart & minEraseSecMsk) == 0 && (iPhysEnd & minEraseSecMsk) == 0)
+			if ((iPhysStart & minEraseSecMsk) == 0 && (iPhysEnd & minEraseSecMsk) == 0 ||
+			      (iCurrentReq->Id() == DLocalDrive::EDeleteNotify && (iPhysStart - iPhysEnd) % KMMCardHighCapBlockSize == 0 )) // handle TRIM case where erase is aligned to 512 blocks
 				{
 				// Aligned erase
 				//  Check that erase commands are supported prior to issuing an erase command
@@ -1174,6 +949,10 @@
 					iSession->SetupCIMEraseMSector(I64LOW(iPhysStart >> KMMCardHighCapBlockSizeLog2),
 												   I64LOW((iPhysEnd - iPhysStart) >> KMMCardHighCapBlockSizeLog2)); // Use ACMD32/33/38 (Erase Sector)
 					}
+		        if(iCurrentReq->Id() == DLocalDrive::EDeleteNotify)   
+		            {
+		            iSession->Command().iFlags|= KMMCCmdFlagDeleteNotify;  //set flags for Trim
+		            }
 				}
 			else
 				{
@@ -1200,7 +979,7 @@
 			memset (iCacheBuf, 0x00, writeLen);
 			iSession->SetupCIMWriteBlock(I64LOW(iPhysStart >> KMMCardHighCapBlockSizeLog2), iCacheBuf, writeLen >> KMMCardHighCapBlockSizeLog2);
 			}
-		
+			
 		r = EngageAndSetWriteRequest(EMReqFormat);
 		}
 		OstTraceFunctionExitExt( DMMCMEDIADRIVERFLASH_LAUNCHFORMAT_EXIT, this, r );
@@ -2307,6 +2086,10 @@
 					{
 					iReqCur = iPhysEnd;
 					}
+				else if(iCurrentReq->Id() == DLocalDrive::EDeleteNotify) //handle DeleteNotify case
+				    {
+                    iReqCur = iPhysEnd;
+				    }
 				else
 					{
 					// Formating to a mis-aligned boundary, so we can't make best use of
@@ -2727,9 +2510,25 @@
 	iMedReq = aRequest;
 	SetCurrentConsumption(aCurrent);
 
+#ifdef EMMC_PARTITION_TEST_MODE_ENABLED
+	if((iSession->Partition() & TExtendedCSD::EPartitionTestMode) != 0)
+		{
+		// driver in test mode, target partition must be set by ControlIO() KMmcSwitchPartition
+		}
+	else
+#endif // EMMC_PARTITION_TEST_MODE_ENABLED	
+		if (iCurrentReq)
+			// if iCurrentReq is NULL then  it is assuned to be a request for a removable drive 
+			// multiple physical partitions are not supported on removable drives hence partition settting is not requied
+			{
+			TInt ptn = iCurrentReq->Drive()->iPartitionNumber;
+			TInt eMmcPtn = GetEMmcPartitionMapping(ptn);
+			iSession->SetPartition(eMmcPtn);
+			}
+	
 	// Reset the card pointer just in case the stack has changed it.
 	iSession->SetCard(iCard);
-
+		
 	TInt r = InCritical();
 	if (r == KErrNone)
 		{
@@ -2783,6 +2582,9 @@
 	aInfo.iConnectionBusType = EConnectionBusInternal;
 	aInfo.iDriveAtt = KDriveAttLocal;
 	aInfo.iMediaAtt	= KMediaAttFormattable;
+	   
+	if(iCard->ExtendedCSD().ExtendedCSDRev() >= 5 && KTRIMEnabled)   //TRIM support for v4.4+
+	   aInfo.iMediaAtt |= KMediaAttDeleteNotify;
 
 	if(iCard->iFlags & KMMCardIsLockable)
 		aInfo.iMediaAtt |= KMediaAttLockable;
@@ -2899,6 +2701,8 @@
 #if defined(__DEMAND_PAGING__) && !defined(__WINS__)
 	     || DMediaPagingDevice::PageInRequest(*iCurrentReq)
 #endif //DEMAND_PAGING 
+		// partition switching
+		|| (GetEMmcPartitionMapping(iCurrentReq->Drive()->iPartitionNumber) != iSession->Partition())
         )
 		{
 		*aAllDone = EFalse;
@@ -3745,6 +3549,12 @@
 				    }
 				r=DoWrite();
 				break;
+			case DLocalDrive::EDeleteNotify:
+			  if(iCard->ExtendedCSD().ExtendedCSDRev() <5)
+			      {
+			      r=KErrNotSupported;
+			      break;
+			      }
 			case DLocalDrive::EFormat:
 				if (readOnly)
 				    {
@@ -3908,6 +3718,13 @@
 				
 			break; 
 			}
+#ifdef EMMC_PARTITION_TEST_MODE_ENABLED			
+		case KMmcSwitchPartition:
+			__ASSERT_DEBUG(iSession != NULL, Panic(ECFSessPtrNull));
+			InvalidateCache();
+			iSession->SetPartition((TInt) aParam1);
+			break;
+#endif // EMMC_PARTITION_TEST_MODE_ENABLED
 		default:
 			r=KErrNotSupported;
 			break;