--- 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;