|
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 // drivers/medmmc/medmmc.h |
|
15 // |
|
16 // |
|
17 |
|
18 #ifndef MEDMMC_H |
|
19 #define MEDMMC_H |
|
20 |
|
21 #include <drivers/locmedia.h> |
|
22 #include <e32const.h> |
|
23 |
|
24 #if defined(__DEMAND_PAGING__) |
|
25 // If in debug mode, enable paging stats and their retrieval using DLocalDrive::EControlIO |
|
26 #if defined( _DEBUG) |
|
27 #define __TEST_PAGING_MEDIA_DRIVER__ |
|
28 #endif |
|
29 #include "mmcdp.h" |
|
30 #endif |
|
31 |
|
32 // Enable this macro to debug cache: |
|
33 // NB The greater the number of blocks, the slower this is... |
|
34 //#define _DEBUG_CACHE |
|
35 #ifdef _DEBUG_CACHE |
|
36 #define __ASSERT_CACHE(c,p) (void)((c)||(p,0)) |
|
37 #else |
|
38 #define __ASSERT_CACHE(c,p) |
|
39 #endif |
|
40 |
|
41 const TInt KDiskSectorSize = 512; |
|
42 const TInt KDiskSectorShift = 9; |
|
43 |
|
44 |
|
45 class DMmcMediaDriverFlash : public DMediaDriver |
|
46 { |
|
47 public: |
|
48 DMmcMediaDriverFlash(TInt aMediaId); |
|
49 ~DMmcMediaDriverFlash(); |
|
50 // ...from DMediaDriver |
|
51 virtual void Close(); |
|
52 // replacing pure virtual |
|
53 virtual void Disconnect(DLocalDrive* aLocalDrive, TThreadMessage*); |
|
54 virtual TInt Request(TLocDrvRequest& aRequest); |
|
55 virtual TInt PartitionInfo(TPartitionInfo& anInfo); |
|
56 virtual void NotifyPowerDown(); |
|
57 virtual void NotifyEmergencyPowerDown(); |
|
58 // For creation by DPhysicalDeviceMediaMmcFlash |
|
59 TInt DoCreate(TInt aMediaId); |
|
60 |
|
61 |
|
62 private: |
|
63 enum TPanic |
|
64 { |
|
65 EDRInUse = 0x0000, EDRStart, EDRNotPositive, EDREnd, |
|
66 ELRRequest = 0x0010, ELRStart, ELRNotPositive, ELREnd, ELRCached, |
|
67 EDWInUse = 0x0020, EDWStart, EDWNotPositive, EDWEnd, |
|
68 EDFInUse = 0x0030, EDFStart, EDFNotPositive, EDFEnd, ENotMmcSocket, |
|
69 ELWRequest = 0x0040, ELWStart, ELWFmtStAlign, ELWNotPositive, ELWEnd, ELWFmtEndAlign, |
|
70 ELWLength, ELFStart, ELFEnd, ELFNotPositive, |
|
71 ERPIInUse = 0x0050, |
|
72 EPCInUse = 0x0060, EPCFunc, |
|
73 ESECBQueued = 0x0070, |
|
74 EDSEDRequest = 0x0080, EDSEDNotErrComplete, |
|
75 ECRReqIdle = 0x0090, ECRRequest, |
|
76 ERRBStAlign = 0x00a0, ERRBStPos, ERRBNotPositive, ERRBEndAlign, ERRBEndPos, |
|
77 ERRBOverflow, ERRBCchInv, ERRBExist, |
|
78 ERWBStPos = 0x00b0, ERWBNotPositive, ERWBEndPos, ERWBOverflow, ERWBCchInv, |
|
79 EMBStPos = 0x00c0, EMBStAlign, EMBNotPositive, EMBEndPos, EMBEndAlign, |
|
80 EMBOverflow, EMBCchInvPre, EMBCchInvPost, |
|
81 EBGAStPos = 0x00d0, EBGAStAlign, EBGANotPositive, EBGAEndPos, EBGAEndAlign, |
|
82 EBGAOverflow, EBGACchInv, |
|
83 EICMNegative = 0x00e0, EICMOverflow, ECMIOverflow, |
|
84 EGCBAlign = 0x00f0, EGCBPos, EGCBCchInv, |
|
85 |
|
86 ECFSessPtrNull = 0x0100, // Code Fault - session pointer NULL |
|
87 |
|
88 EDBNotEven = 0x0110, // Not and even number of blocks in the buffer cache |
|
89 EDBCBQueued = 0x0111, // The data transfer callback is already queued |
|
90 EDBLength = 0x0112, // The length of data to transfer in data transfer callback is not positive |
|
91 EDBLengthTooBig = 0x0113, // The length of data to transfer in data transfer callback is too big |
|
92 EDBOffsetTooBig = 0x0114, // The Offset into the user data buffer is too big |
|
93 EDBCacheInvalid = 0x0115, // The cache is invalid at the end of data transfer |
|
94 EDBNotOptimal = 0x0116, // Due to Cache size DB functionality will never be utilised |
|
95 ENoDBSupport = 0x0120, // DMA request arrived but PSL does not support double buffering |
|
96 ENotDMAAligned = 0x0121, |
|
97 EArrayBoundsExc = 0x0122 // Array bounds exceeded (either too small or too large) |
|
98 }; |
|
99 static void Panic(TPanic aPnc); |
|
100 |
|
101 enum TMediaRequest |
|
102 { |
|
103 EMReqRead = 0, |
|
104 EMReqWrite = 1, |
|
105 EMReqFormat = 2, |
|
106 EMReqPtnInfo, |
|
107 EMReqPswdCtrl, |
|
108 EMReqForceErase, |
|
109 EMReqUpdatePtnInfo, |
|
110 EMReqWritePasswordData, |
|
111 EMReqIdle, |
|
112 EMReqEMMCPtnInfo, |
|
113 }; |
|
114 enum TMediaReqType {EMReqTypeNormalRd,EMReqTypeNormalWr,EMReqTypeUnlockPswd,EMReqTypeChangePswd}; |
|
115 |
|
116 enum {KWtRBMFst = 0x00000001, // iWtRBM - Read First Block only |
|
117 KWtRBMLst = 0x00000002, // iWtRBM - Read Last Block only |
|
118 KWtMinFst = 0x00000004, // iWtRBM - Write First Block only |
|
119 KWtMinLst = 0x00000008, // iWtRBM - Write Last Block only |
|
120 KIPCSetup = 0x00000010, // iRdROB - IPC Setup Next Iteration |
|
121 KIPCWrite = 0x00000020}; // iRdROB - IPC Write Next Iteration |
|
122 |
|
123 public: |
|
124 inline void SetEMmcPartitionMapping(TInt aLocalPtn, TInt aEMmcPtn) |
|
125 { |
|
126 __ASSERT_DEBUG((aLocalPtn >= 0) && (aLocalPtn < KMaxLocalDrives), Kern::Fault("Mmc: Array bounds exception", __LINE__)); |
|
127 iEMmcPartitionMappings[aLocalPtn] = aEMmcPtn; |
|
128 }; |
|
129 |
|
130 inline TInt GetEMmcPartitionMapping(TInt aLocalPtn) const |
|
131 { |
|
132 __ASSERT_DEBUG((aLocalPtn >= 0) && (aLocalPtn < KMaxLocalDrives), Kern::Fault("Mmc: Array bounds exception", __LINE__)); |
|
133 return iEMmcPartitionMappings[aLocalPtn]; |
|
134 }; |
|
135 |
|
136 |
|
137 private: |
|
138 // MMC device specific stuff |
|
139 TInt DoRead(); |
|
140 TInt DoWrite(); |
|
141 TInt DoFormat(); |
|
142 TInt Caps(TLocDrv& aDrive, TLocalDriveCapsV6& aInfo); |
|
143 |
|
144 inline DMMCStack& Stack() const; |
|
145 inline TInt CardNum() const; |
|
146 inline TMediaRequest CurrentRequest() const; |
|
147 |
|
148 TInt LaunchRead(TInt64 aStart, TUint32 aLength); |
|
149 TInt LaunchDBRead(); |
|
150 TInt LaunchPhysRead(TInt64 aStart, TUint32 aLength); |
|
151 |
|
152 TInt LaunchWrite(TInt64 aStart, TUint32 aLength, TMediaRequest aMedReq); |
|
153 TInt LaunchFormat(TInt64 aStart, TUint32 aLength); |
|
154 |
|
155 TInt LaunchRPIUnlock(TLocalDrivePasswordData& aData); |
|
156 TInt LaunchRPIRead(); |
|
157 TInt LaunchRPIErase(); |
|
158 TInt DecodePartitionInfo(); |
|
159 TInt WritePartitionInfo(); |
|
160 TInt GetDefaultPartitionInfo(TMBRPartitionEntry& aPartitionEntry); |
|
161 TInt CreateDefaultPartition(); |
|
162 |
|
163 |
|
164 #if defined __TEST_PAGING_MEDIA_DRIVER__ |
|
165 TInt HandleControlIORequest(); |
|
166 #endif |
|
167 |
|
168 static void SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors); |
|
169 |
|
170 TInt CheckDevice(TMediaReqType aReqType); |
|
171 |
|
172 static void SessionEndCallBack(TAny* aMediaDriver); |
|
173 static void SessionEndDfc(TAny* aMediaDriver); |
|
174 void DoSessionEndDfc(); |
|
175 |
|
176 static void DataTransferCallBack(TAny* aMediaDriver); |
|
177 static void DataTransferCallBackDfc(TAny* aMediaDriver); |
|
178 |
|
179 void DoReadDataTransferCallBack(); |
|
180 void DoWriteDataTransferCallBack(); |
|
181 void DoPhysReadDataTransferCallBack(); |
|
182 void DoPhysWriteDataTransferCallBack(); |
|
183 |
|
184 TInt AdjustPhysicalFragment(TPhysAddr &physAddr, TInt &physLength); |
|
185 TInt PrepareFirstPhysicalFragment(TPhysAddr &aPhysAddr, TInt &aPhysLength, TUint32 aLength); |
|
186 void PrepareNextPhysicalFragment(); |
|
187 |
|
188 TInt EngageAndSetReadRequest(TMediaRequest aRequest); |
|
189 TInt EngageAndSetWriteRequest(TMediaRequest aRequest); |
|
190 TInt EngageAndSetRequest(TMediaRequest aRequest, TInt aCurrent); |
|
191 void CompleteRequest(TInt aReason); |
|
192 |
|
193 TInt ReadDataUntilCacheExhausted(TBool* aAllDone); |
|
194 TInt WriteDataToUser(TUint8* aBufPtr); |
|
195 TInt ReadDataFromUser(TDes8& aDes, TInt aOffset); |
|
196 TUint8* ReserveReadBlocks(TInt64 aStart, TInt64 aEnd, TUint32* aLength); |
|
197 TUint8* ReserveWriteBlocks(TInt64 aMedStart, TInt64 aMedEnd, TUint* aRBM); |
|
198 void MarkBlocks(TInt64 aStart, TInt64 aEnd, TInt aStartIndex); |
|
199 void BuildGammaArray(TInt64 aStart, TInt64 aEnd); |
|
200 void InvalidateCache(); |
|
201 void InvalidateCache(TInt64 aStart, TInt64 aEnd); |
|
202 TUint8* IdxToCchMem(TInt aIdx) const; |
|
203 TInt CchMemToIdx(TUint8* aMemP) const; |
|
204 |
|
205 TInt DoPasswordOp(); |
|
206 void PasswordControl(TInt aFunc, TLocalDrivePasswordData& aData); |
|
207 void Reset(); |
|
208 TInt AllocateSession(); |
|
209 |
|
210 #ifdef _DEBUG_CACHE |
|
211 TBool CacheInvariant(); |
|
212 TUint8* GetCachedBlock(TInt64 aAddr); |
|
213 #endif |
|
214 private: |
|
215 DMMCStack* iStack; // controller objects |
|
216 TMMCard* iCard; |
|
217 DMMCSession* iSession; |
|
218 DMMCSocket* iSocket; |
|
219 |
|
220 TInt iCardNumber; |
|
221 |
|
222 TUint iBlkLenLog2; // cached CSD data |
|
223 TUint32 iBlkLen; |
|
224 TInt64 iBlkMsk; |
|
225 TBool iReadBlPartial; |
|
226 TUint32 iPrWtGpLen; // preferred write group size in bytes, |
|
227 TInt64 iPrWtGpMsk; |
|
228 |
|
229 TInt iReadCurrentInMilliAmps; // power management |
|
230 TInt iWriteCurrentInMilliAmps; |
|
231 |
|
232 TUint8* iMinorBuf; // MBR, CMD42, partial read |
|
233 TUint8* iCacheBuf; // cached buffer |
|
234 TUint32 iMaxBufSize; |
|
235 TInt iBlocksInBuffer; |
|
236 TInt64* iCachedBlocks; |
|
237 TInt* iGamma; // B lookup, ReserveReadBlocks() |
|
238 TUint8* iIntBuf; // start of current buffer region |
|
239 TInt iLstUsdCchEnt; // index of last used cache entry |
|
240 |
|
241 TLocDrvRequest* iCurrentReq; // Current Request |
|
242 TMediaRequest iMedReq; |
|
243 |
|
244 TInt64 iReqStart; // user-requested start region |
|
245 TInt64 iReqCur; // Currently requested start region |
|
246 TInt64 iReqEnd; // user-requested end region |
|
247 TInt64 iPhysStart; // physical region for one operation |
|
248 TInt64 iPhysEnd; // physical end point for one operation |
|
249 TInt64 iDbEnd; // Double buffer end point for one operation |
|
250 |
|
251 TUint64 iEraseUnitMsk; |
|
252 |
|
253 TUint iWtRBM; // Write - Read Before Modify Flags |
|
254 TUint iRdROB; // Read - Read Odd Blocks Flags |
|
255 |
|
256 TInt iFragOfset; |
|
257 TUint32 iIPCLen; |
|
258 TUint32 iNxtIPCLen; |
|
259 TUint32 iBufOfset; |
|
260 |
|
261 TUint iHiddenSectors; // bootup / password |
|
262 |
|
263 TMMCCallBack iSessionEndCallBack; |
|
264 TDfc iSessionEndDfc; |
|
265 |
|
266 TPartitionInfo* iPartitionInfo; |
|
267 TMMCMediaTypeEnum iMediaType; |
|
268 TMMCEraseInfo iEraseInfo; |
|
269 TBool iMbrMissing; |
|
270 TInt iMediaId; |
|
271 |
|
272 DMMCStack::TDemandPagingInfo iDemandPagingInfo; |
|
273 |
|
274 #if defined(__TEST_PAGING_MEDIA_DRIVER__) |
|
275 SMmcStats iMmcStats; |
|
276 #endif // __TEST_PAGING_MEDIA_DRIVER__ |
|
277 |
|
278 TMMCCallBack iDataTransferCallBack; // Callback registered with the MMC stack to perform double-buffering |
|
279 TDfc iDataTransferCallBackDfc; // ...and the associated DFC queue. |
|
280 |
|
281 TBool iSecondBuffer; // Specified the currently active buffer |
|
282 TBool iDoLastRMW; // ETrue if the last double-buffer transfer requires RMW modification |
|
283 TBool iDoDoubleBuffer; // ETrue if double-buffering is currently active |
|
284 TBool iDoPhysicalAddress; // ETrue if Physical Addressing is currently active |
|
285 TBool iCreateMbr; |
|
286 TBool iReadToEndOfCard; // {Read Only} ETrue if Reading to end of Card |
|
287 |
|
288 TBool iInternalSlot; |
|
289 |
|
290 DEMMCPartitionInfo* iMmcPartitionInfo; // Responsible for decoding partitions for embedded devices |
|
291 TInt iEMmcPartitionMappings[KMaxLocalDrives]; // holds the mapping of emmc partitions |
|
292 }; |
|
293 |
|
294 #endif |
|
295 |