|
1 // Copyright (c) 1996-2009 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 // e32\drivers\medlfs\flash_media.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include <drivers/flash_media.h> |
|
19 #include "variantmediadef.h" |
|
20 |
|
21 _LIT(KPddName, "Media.Flash"); |
|
22 _LIT(KFlashThreadName,"FlashThread"); |
|
23 |
|
24 const TInt KFlashThreadPriority=24; // same as file server |
|
25 |
|
26 GLDEF_C TDfcQue FlashDfcQ; |
|
27 |
|
28 class DPhysicalDeviceMediaFlash : public DPhysicalDevice |
|
29 { |
|
30 public: |
|
31 DPhysicalDeviceMediaFlash(); |
|
32 virtual TInt Install(); |
|
33 virtual void GetCaps(TDes8& aDes) const; |
|
34 virtual TInt Create(DBase*& aChannel, TInt aMediaId, const TDesC8* anInfo, const TVersion& aVer); |
|
35 virtual TInt Validate(TInt aDeviceType, const TDesC8* anInfo, const TVersion& aVer); |
|
36 virtual TInt Info(TInt aFunction, TAny* a1); |
|
37 }; |
|
38 |
|
39 DPhysicalDeviceMediaFlash::DPhysicalDeviceMediaFlash() |
|
40 // |
|
41 // Constructor |
|
42 // |
|
43 { |
|
44 iUnitsMask=0x2; |
|
45 iVersion=TVersion(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion); |
|
46 } |
|
47 |
|
48 TInt DPhysicalDeviceMediaFlash::Install() |
|
49 // |
|
50 // Install the media drives PDD. |
|
51 // |
|
52 { |
|
53 |
|
54 return SetName(&KPddName); |
|
55 } |
|
56 |
|
57 void DPhysicalDeviceMediaFlash::GetCaps(TDes8& /*aDes*/) const |
|
58 // |
|
59 // Return the media drivers capabilities. |
|
60 // |
|
61 { |
|
62 } |
|
63 |
|
64 TInt DPhysicalDeviceMediaFlash::Create(DBase*& aChannel, TInt aMediaId, const TDesC8* /* anInfo */,const TVersion &aVer) |
|
65 // |
|
66 // Create an LFFS media driver. |
|
67 // |
|
68 { |
|
69 if (!Kern::QueryVersionSupported(iVersion,aVer)) |
|
70 return KErrNotSupported; |
|
71 DMediaDriverFlash *pD=DMediaDriverFlash::New(aMediaId); |
|
72 aChannel=pD; |
|
73 TInt r=KErrNoMemory; |
|
74 if (pD) |
|
75 r=pD->DoCreate(aMediaId); |
|
76 if (r==KErrNone) |
|
77 pD->OpenMediaDriverComplete(KErrNone); |
|
78 return r; |
|
79 } |
|
80 |
|
81 TInt DPhysicalDeviceMediaFlash::Validate(TInt aDeviceType, const TDesC8* /*anInfo*/, const TVersion& aVer) |
|
82 { |
|
83 if (!Kern::QueryVersionSupported(iVersion,aVer)) |
|
84 return KErrNotSupported; |
|
85 if (aDeviceType!=MEDIA_DEVICE_LFFS) |
|
86 return KErrNotSupported; |
|
87 return KErrNone; |
|
88 } |
|
89 |
|
90 TInt DPhysicalDeviceMediaFlash::Info(TInt aFunction, TAny*) |
|
91 // |
|
92 // Return the priority of this media driver |
|
93 // |
|
94 { |
|
95 if (aFunction==EPriority) |
|
96 return KMediaDriverPriorityNormal; |
|
97 return KErrNotSupported; |
|
98 } |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 /** |
|
104 @internalComponent |
|
105 */ |
|
106 DMediaDriverFlash::DMediaDriverFlash(TInt aMediaId) |
|
107 // |
|
108 // Constructor. |
|
109 // |
|
110 : DMediaDriver(aMediaId) |
|
111 {} |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 /** |
|
117 @internalComponent |
|
118 */ |
|
119 TInt DMediaDriverFlash::DoCreate(TInt /*aMediaId*/) |
|
120 // |
|
121 // Create the media driver. |
|
122 // |
|
123 { |
|
124 |
|
125 TInt r=Initialise(); // interrogate FLASH etc. |
|
126 if (r==KErrNone) |
|
127 { |
|
128 TUint32 size=TotalSize(); |
|
129 SetTotalSizeInBytes(size); |
|
130 } |
|
131 return r; |
|
132 } |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 /** |
|
138 A function called by the local media subsystem to deal with a request; |
|
139 this is implemented by the generic layer of the LFFS media driver. |
|
140 |
|
141 The implementation delegates the handling of reading, writing and erasing |
|
142 to the specific layer's DoRead(), DoWrite() and DoErase() functions |
|
143 respectively. |
|
144 |
|
145 @param aRequest An object that encapsulates information about the request. |
|
146 |
|
147 @return A value indicating the result: |
|
148 KErrNone, if the request has been sucessfully initiated; |
|
149 KErrNotSupported, if the request cannot be handled by the device; |
|
150 KMediaDriverDeferRequest, if the request cannot be handled |
|
151 immediately because of an outstanding request (this request will be |
|
152 deferred until the outstanding request has completed); |
|
153 otherwise one of the other system-wide error codes. |
|
154 |
|
155 @see DMediaDriverFlash::DoRead() |
|
156 @see DMediaDriverFlash::DoWrite() |
|
157 @see DMediaDriverFlash::DoErase() |
|
158 */ |
|
159 TInt DMediaDriverFlash::Request(TLocDrvRequest& m) |
|
160 { |
|
161 TInt r=KErrNotSupported; |
|
162 TInt id=m.Id(); |
|
163 __KTRACE_OPT(KLOCDRV,Kern::Printf(">DMediaDriverFlash::Request %d",id)); |
|
164 if (id==DLocalDrive::ECaps) |
|
165 { |
|
166 TLocalDriveCapsV2& c=*(TLocalDriveCapsV2*)m.RemoteDes(); |
|
167 r=Caps(c); |
|
168 c.iSize=m.Drive()->iPartitionLen; |
|
169 c.iPartitionType=m.Drive()->iPartitionType; |
|
170 return r; |
|
171 } |
|
172 switch (id) |
|
173 { |
|
174 case DLocalDrive::ERead: |
|
175 if (iReadReq) |
|
176 return KMediaDriverDeferRequest; // read already in progress so defer this one |
|
177 iReadReq=&m; |
|
178 r=DoRead(); |
|
179 if (r!=KErrNone) |
|
180 iReadReq=NULL; |
|
181 break; |
|
182 case DLocalDrive::EWrite: |
|
183 if (iWriteReq) |
|
184 return KMediaDriverDeferRequest; // write already in progress so defer this one |
|
185 iWriteReq=&m; |
|
186 r=DoWrite(); |
|
187 if (r!=KErrNone) |
|
188 iWriteReq=NULL; |
|
189 break; |
|
190 case DLocalDrive::EFormat: |
|
191 if (iEraseReq) |
|
192 return KMediaDriverDeferRequest; // erase already in progress so defer this one |
|
193 iEraseReq=&m; |
|
194 r=DoErase(); |
|
195 if (r!=KErrNone) |
|
196 iEraseReq=NULL; |
|
197 break; |
|
198 case DLocalDrive::EEnlarge: |
|
199 case DLocalDrive::EReduce: |
|
200 default: |
|
201 r=KErrNotSupported; |
|
202 break; |
|
203 } |
|
204 __KTRACE_OPT(KLOCDRV,Kern::Printf("<DMediaDriverFlash::Request %d",r)); |
|
205 if (r<0) |
|
206 DMediaDriver::Complete(m,r); |
|
207 return r; |
|
208 } |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 /** |
|
214 A function called by the local media subsystem to inform the driver |
|
215 that the device should power down. |
|
216 |
|
217 The default implementation does nothing. |
|
218 */ |
|
219 void DMediaDriverFlash::NotifyPowerDown() |
|
220 { |
|
221 // no action required |
|
222 } |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 /** |
|
228 A function called by the local media subsystem to inform the driver |
|
229 that the device is to be immediately powered down. |
|
230 |
|
231 The default implementation does nothing. |
|
232 */ |
|
233 void DMediaDriverFlash::NotifyEmergencyPowerDown() |
|
234 { |
|
235 // no action required |
|
236 } |
|
237 |
|
238 |
|
239 |
|
240 |
|
241 /** |
|
242 Called by the specific layer of the LFFS media driver to inform |
|
243 the generic layer that a request is complete. |
|
244 |
|
245 @param aRequest The type of the request that is complete. This is one of |
|
246 the TRequest enum values: |
|
247 EReqRead, EReqWrite or EReqErase as appropriate. |
|
248 @param aResult KErrNone, if the request has been completed successfully, |
|
249 otherwise one if the other system-wide error codes. |
|
250 |
|
251 @see DMediaDriverFlash::TRequest |
|
252 */ |
|
253 void DMediaDriverFlash::Complete(TInt aRequest, TInt aResult) |
|
254 { |
|
255 __KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:Complete(%d,%d)",aRequest,aResult)); |
|
256 TLocDrvRequest* pR=iRequests[aRequest]; |
|
257 iRequests[aRequest]=NULL; |
|
258 DMediaDriver::Complete(*pR,aResult); |
|
259 } |
|
260 |
|
261 |
|
262 |
|
263 /** |
|
264 Called by the generic layer to get the capabilities of the flash device. |
|
265 |
|
266 The default implementation is synchronous, and returns KErrCompletion. |
|
267 |
|
268 @param aCaps On return, descriptor data contains capability information |
|
269 about the flash device, in the form of a class derived from |
|
270 TLocalDriveCapsV2. The size of the derived class should not exceed |
|
271 KMaxLocalDriveCapsLength which is defined and used in |
|
272 e32\drivers\locmedia\locmedia.cpp. If a larger sized capabilities |
|
273 class is used, and this code is modified to write to member data |
|
274 beyond KMaxLocalDriveCapsLength this will cause a fault. |
|
275 |
|
276 @return KErrCompletion, if the operation has been done synchronously and is successful; |
|
277 one of the other system wide error codes (not KErrNone), if |
|
278 the operation has been done synchronously but UNSUCCESSFULLY; |
|
279 KErrNone, if the operation is being done asynchronously. |
|
280 @see TLocalDriveCapsV2 |
|
281 */ |
|
282 |
|
283 TInt DMediaDriverFlash::Caps(TLocalDriveCapsV2& caps) |
|
284 { |
|
285 caps.iType=EMediaFlash; |
|
286 caps.iBattery=EBatNotSupported; |
|
287 caps.iDriveAtt=KDriveAttLocal|KDriveAttInternal; |
|
288 caps.iMediaAtt=KMediaAttFormattable; |
|
289 caps.iBaseAddress=(TUint8*)TInternalRamDrive::Base(); |
|
290 caps.iFileSystemId=KDriveFileSysLFFS; |
|
291 caps.iHiddenSectors=0; |
|
292 caps.iEraseBlockSize=EraseBlockSize(); |
|
293 |
|
294 __KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) type=%d", caps.iType) ); |
|
295 __KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) battery=%d", caps.iBattery) ); |
|
296 __KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) driveatt=0x%x", caps.iDriveAtt) ); |
|
297 __KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) mediaatt=0x%x", caps.iMediaAtt) ); |
|
298 __KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) filesystemid=0x%x", caps.iFileSystemId) ); |
|
299 __KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) eraseblocksize=0x%x", caps.iEraseBlockSize) ); |
|
300 |
|
301 return KErrCompletion; // synchronous completion |
|
302 } |
|
303 |
|
304 |
|
305 |
|
306 |
|
307 /** |
|
308 A function called by the local media subsystem to get partition information |
|
309 for the flash device. |
|
310 |
|
311 It is called once the subsystem has been notified that the media driver |
|
312 is open and has been succesfully initialised. |
|
313 |
|
314 The function should be overriden by the specific layer of |
|
315 the LFFS media driver. |
|
316 |
|
317 The default implementation is synchronous |
|
318 and sets: |
|
319 |
|
320 - the partition count to 1, meaning that there is only the one partition. |
|
321 - the partition base address to 0. |
|
322 - the partition length to the total size of the flash device. |
|
323 - the size of the media to the total size of the flash device. |
|
324 - the partition type to KPartitionTypeEneaLFFS. |
|
325 |
|
326 @param anInfo An object that, on successful return, contains |
|
327 the partition information. |
|
328 |
|
329 @return KErrNone, if retrieval of partition information is to be |
|
330 done asynchronously; |
|
331 KErrCompletion, if retrieval of partition information has been |
|
332 done synchronously, and successfully; |
|
333 one of the other system-wide error codes, if retrieval of partition |
|
334 information has been done synchronously, but unsuccessfully. |
|
335 */ |
|
336 TInt DMediaDriverFlash::PartitionInfo(TPartitionInfo& aInfo) |
|
337 { |
|
338 aInfo.iPartitionCount = 1; |
|
339 aInfo.iEntry[0].iPartitionBaseAddr = 0; |
|
340 aInfo.iEntry[0].iPartitionLen = TotalSizeInBytes(); |
|
341 aInfo.iEntry[0].iPartitionType = KPartitionTypeEneaLFFS; |
|
342 |
|
343 aInfo.iMediaSizeInBytes = TotalSizeInBytes(); |
|
344 return KErrCompletion; |
|
345 } |
|
346 |
|
347 |
|
348 DECLARE_EXTENSION_PDD() |
|
349 { |
|
350 return new DPhysicalDeviceMediaFlash; |
|
351 } |
|
352 |
|
353 static const TInt LffsDriveNumbers[LFFS_DRIVECOUNT]={LFFS_DRIVELIST}; |
|
354 _LIT(KFlashDriveName,LFFS_DRIVENAME); |
|
355 |
|
356 DECLARE_STANDARD_EXTENSION() |
|
357 { |
|
358 __KTRACE_OPT(KBOOT,Kern::Printf("Registering FLASH drive")); |
|
359 if (Kern::SuperPage().iCpuId & KCpuIdISS) |
|
360 return KErrNone; // no FLASH on ARMULATOR |
|
361 |
|
362 TInt r=Kern::DfcQInit(&FlashDfcQ,KFlashThreadPriority,&KFlashThreadName); |
|
363 if (r==KErrNone) |
|
364 { |
|
365 DPrimaryMediaBase* pM=new DPrimaryMediaBase; |
|
366 if (pM) |
|
367 { |
|
368 pM->iDfcQ=&FlashDfcQ; |
|
369 r=LocDrv::RegisterMediaDevice(EFixedMedia1,LFFS_DRIVECOUNT,&LffsDriveNumbers[0],pM,LFFS_NUMMEDIA,KFlashDriveName); |
|
370 if (r==KErrNone) |
|
371 pM->iMsgQ.Receive(); |
|
372 } |
|
373 } |
|
374 __KTRACE_OPT(KBOOT,Kern::Printf("Registering FLASH drive - return %d",r)); |
|
375 return r; |
|
376 } |
|
377 |