--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/medmmc/medmmc.h Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,295 @@
+// Copyright (c) 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"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// drivers/medmmc/medmmc.h
+//
+//
+
+#ifndef MEDMMC_H
+#define MEDMMC_H
+
+#include <drivers/locmedia.h>
+#include <e32const.h>
+
+#if defined(__DEMAND_PAGING__)
+ // If in debug mode, enable paging stats and their retrieval using DLocalDrive::EControlIO
+ #if defined( _DEBUG)
+ #define __TEST_PAGING_MEDIA_DRIVER__
+ #endif
+ #include "mmcdp.h"
+#endif
+
+// Enable this macro to debug cache:
+// NB The greater the number of blocks, the slower this is...
+//#define _DEBUG_CACHE
+#ifdef _DEBUG_CACHE
+#define __ASSERT_CACHE(c,p) (void)((c)||(p,0))
+#else
+#define __ASSERT_CACHE(c,p)
+#endif
+
+const TInt KDiskSectorSize = 512;
+const TInt KDiskSectorShift = 9;
+
+
+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,
+ EArrayBoundsExc = 0x0122 // Array bounds exceeded (either too small or too large)
+ };
+ 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
+
+public:
+ inline void SetEMmcPartitionMapping(TInt aLocalPtn, TInt aEMmcPtn)
+ {
+ __ASSERT_DEBUG((aLocalPtn >= 0) && (aLocalPtn < KMaxLocalDrives), Kern::Fault("Mmc: Array bounds exception", __LINE__));
+ iEMmcPartitionMappings[aLocalPtn] = aEMmcPtn;
+ };
+
+ inline TInt GetEMmcPartitionMapping(TInt aLocalPtn) const
+ {
+ __ASSERT_DEBUG((aLocalPtn >= 0) && (aLocalPtn < KMaxLocalDrives), Kern::Fault("Mmc: Array bounds exception", __LINE__));
+ return iEMmcPartitionMappings[aLocalPtn];
+ };
+
+
+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
+ TInt iEMmcPartitionMappings[KMaxLocalDrives]; // holds the mapping of emmc partitions
+ };
+
+#endif
+