287
|
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 |
// f32test/bench/t_fsysbm.cpp
|
|
15 |
//
|
|
16 |
//
|
|
17 |
|
|
18 |
#define __E32TEST_EXTENSION__
|
|
19 |
|
|
20 |
#include <f32file.h>
|
|
21 |
#include <e32test.h>
|
|
22 |
#include <e32hal.h>
|
|
23 |
#include <hal.h>
|
|
24 |
#include <e32math.h>
|
|
25 |
#include <e32ldr.h>
|
|
26 |
#include <e32ldr_private.h>
|
|
27 |
#include "t_server.h"
|
|
28 |
#include "../../e32test/mmu/d_sharedchunk.h"
|
|
29 |
#include "../../e32utils/pccd/d_mmcif.h"
|
|
30 |
|
|
31 |
#define SYMBIAN_TEST_EXTENDED_BUFFER_SIZES // test using a greater number of buffer sizes
|
|
32 |
|
|
33 |
RTest test(_L("eMMC 4.4 TRIM Benchmark"));
|
|
34 |
|
|
35 |
static const TUint K1K = 1024; // 1K
|
|
36 |
static const TUint K1M = K1K * K1K ; // 1M
|
|
37 |
static const TUint K2M = 2 * K1M; // 2M
|
|
38 |
|
|
39 |
|
|
40 |
#if defined(__WINS__)
|
|
41 |
static TInt KMaxFileSize = 256 * K1K; // 256K
|
|
42 |
#else
|
|
43 |
static TInt KMaxFileSize = K2M; // 2M
|
|
44 |
#endif
|
|
45 |
|
|
46 |
const TTimeIntervalMicroSeconds32 KFloatingPointTestTime = 10000000; // 10 seconds
|
|
47 |
|
|
48 |
static TPtr8 DataBuf(NULL, KMaxFileSize,KMaxFileSize);
|
|
49 |
|
|
50 |
static RSharedChunkLdd Ldd;
|
|
51 |
static RChunk TheChunk;
|
|
52 |
|
|
53 |
GLDEF_D RFs TheFs;
|
|
54 |
GLDEF_D TFileName gSessionPath;
|
|
55 |
GLDEF_D TChar gDriveToTest;
|
|
56 |
|
|
57 |
static RMmcCntrlIf iDriver;
|
|
58 |
static TInt iStack = 0;
|
|
59 |
static TInt iCard = 0;
|
|
60 |
static TBool iDriverOpen = EFalse;
|
|
61 |
|
|
62 |
enum TPanic {ECreatingConsole,ELoaderCheck,ELoadingMmcDriver,EStartingMmcDriver};
|
|
63 |
|
|
64 |
LOCAL_C void Panic(TPanic aPanic)
|
|
65 |
//
|
|
66 |
// Panic
|
|
67 |
//
|
|
68 |
{
|
|
69 |
User::Panic(_L("MMCTEST"),aPanic);
|
|
70 |
}
|
|
71 |
|
|
72 |
|
|
73 |
static RFile File;
|
|
74 |
|
|
75 |
static TInt gFastCounterFreq;
|
|
76 |
|
|
77 |
const TUint KMMCExtendedCSDLength=512;
|
|
78 |
class TExtendedCSD
|
|
79 |
{
|
|
80 |
public:
|
|
81 |
enum TExtCSDAccessBits {ECmdSet, ESetBits, EClearBits, EWriteByte};
|
|
82 |
enum TExtCSDModesFieldIndex
|
|
83 |
{
|
|
84 |
ECmdSetIndex = 191,
|
|
85 |
ECmdSetRevIndex = 189,
|
|
86 |
EPowerClassIndex = 187,
|
|
87 |
EHighSpeedInterfaceTimingIndex = 185,
|
|
88 |
EBusWidthModeIndex = 183
|
|
89 |
};
|
|
90 |
enum TExtCSDBusWidths
|
|
91 |
{
|
|
92 |
EExtCsdBusWidth1 = 0x00,
|
|
93 |
EExtCsdBusWidth4 = 0x01,
|
|
94 |
EExtCsdBusWidth8 = 0x02
|
|
95 |
};
|
|
96 |
enum TCardTypes
|
|
97 |
{
|
|
98 |
EHighSpeedCard26Mhz = 0x01,
|
|
99 |
EHighSpeedCard52Mhz = 0x02
|
|
100 |
};
|
|
101 |
public:
|
|
102 |
inline TExtendedCSD(); // Default constructor
|
|
103 |
inline TExtendedCSD(const TUint8*);
|
|
104 |
inline TExtendedCSD& operator=(const TExtendedCSD&);
|
|
105 |
inline TExtendedCSD& operator=(const TUint8*);
|
|
106 |
inline TUint8 At(TUint anIndex) const; // Byte from CSD at anIndex
|
|
107 |
public:
|
|
108 |
inline TUint SupportedCmdSet() const;
|
|
109 |
inline TUint MinPerfWrite8Bit52Mhz() const;
|
|
110 |
inline TUint MinPerfRead8Bit52Mhz() const;
|
|
111 |
inline TUint MinPerfWrite8Bit26Mhz_4Bit52Mhz() const;
|
|
112 |
inline TUint MinPerfRead8Bit26Mhz_4Bit52Mhz() const;
|
|
113 |
inline TUint MinPerfWrite4Bit26Mhz() const;
|
|
114 |
inline TUint MinPerfRead4Bit26Mhz() const;
|
|
115 |
inline TUint PowerClass26Mhz360V() const;
|
|
116 |
inline TUint PowerClass52Mhz360V() const;
|
|
117 |
inline TUint PowerClass26Mhz195V() const;
|
|
118 |
inline TUint PowerClass52Mhz195V() const;
|
|
119 |
inline TUint CardType() const;
|
|
120 |
inline TUint CSDStructureVer() const;
|
|
121 |
inline TUint ExtendedCSDRev() const;
|
|
122 |
inline TUint CmdSet() const;
|
|
123 |
inline TUint CmdSetRev() const;
|
|
124 |
inline TUint PowerClass() const;
|
|
125 |
inline TUint HighSpeedTiming() const;
|
|
126 |
inline TUint BusWidth() const;
|
|
127 |
|
|
128 |
inline TUint TrimMultiplier() const;
|
|
129 |
inline TUint SecureFeatureSupport() const;
|
|
130 |
inline TUint SecureEraseMultiplier() const;
|
|
131 |
inline TUint SecureTrimMultiplier() const;
|
|
132 |
|
|
133 |
private:
|
|
134 |
/**< @internalComponent little endian 512 byte field representing extended CSD */
|
|
135 |
TUint8 iData[KMMCExtendedCSDLength];
|
|
136 |
};
|
|
137 |
|
|
138 |
inline TExtendedCSD::TExtendedCSD() // Default constructor
|
|
139 |
{}
|
|
140 |
inline TExtendedCSD::TExtendedCSD(const TUint8* aPtr)
|
|
141 |
{memcpy(&iData[0], aPtr, KMMCExtendedCSDLength);}
|
|
142 |
inline TExtendedCSD& TExtendedCSD::operator=(const TExtendedCSD& aCSD)
|
|
143 |
{memcpy(&iData[0], &aCSD.iData[0], KMMCExtendedCSDLength); return(*this);}
|
|
144 |
inline TExtendedCSD& TExtendedCSD::operator=(const TUint8* aPtr)
|
|
145 |
{memcpy(&iData[0], aPtr, KMMCExtendedCSDLength); return(*this);}
|
|
146 |
// field accessors.
|
|
147 |
// "Properties Segment" of Extended CSD - i.e. read-only fields
|
|
148 |
inline TUint TExtendedCSD::SupportedCmdSet() const {return iData[504];}
|
|
149 |
inline TUint TExtendedCSD::MinPerfWrite8Bit52Mhz() const {return iData[210];}
|
|
150 |
inline TUint TExtendedCSD::MinPerfRead8Bit52Mhz() const {return iData[209];}
|
|
151 |
inline TUint TExtendedCSD::MinPerfWrite8Bit26Mhz_4Bit52Mhz() const {return iData[208];}
|
|
152 |
inline TUint TExtendedCSD::MinPerfRead8Bit26Mhz_4Bit52Mhz() const {return iData[207];}
|
|
153 |
inline TUint TExtendedCSD::MinPerfWrite4Bit26Mhz() const {return iData[206];}
|
|
154 |
inline TUint TExtendedCSD::MinPerfRead4Bit26Mhz() const {return iData[205];}
|
|
155 |
inline TUint TExtendedCSD::PowerClass26Mhz360V() const {return iData[203];}
|
|
156 |
inline TUint TExtendedCSD::PowerClass52Mhz360V() const {return iData[202];}
|
|
157 |
inline TUint TExtendedCSD::PowerClass26Mhz195V() const {return iData[201];}
|
|
158 |
inline TUint TExtendedCSD::PowerClass52Mhz195V() const {return iData[200];}
|
|
159 |
inline TUint TExtendedCSD::CardType() const {return iData[196];}
|
|
160 |
inline TUint TExtendedCSD::CSDStructureVer() const {return iData[194];}
|
|
161 |
inline TUint TExtendedCSD::ExtendedCSDRev() const {return iData[192];}
|
|
162 |
|
|
163 |
inline TUint TExtendedCSD::TrimMultiplier() const {return iData[232]; }
|
|
164 |
inline TUint TExtendedCSD::SecureFeatureSupport() const {return iData[231]; }
|
|
165 |
inline TUint TExtendedCSD::SecureEraseMultiplier() const {return iData[230]; }
|
|
166 |
inline TUint TExtendedCSD::SecureTrimMultiplier() const {return iData[229]; }
|
|
167 |
|
|
168 |
|
|
169 |
// "Modes Segment" of Extended CSD - i.e. modifiable fields
|
|
170 |
inline TUint TExtendedCSD::CmdSet() const {return iData[191];}
|
|
171 |
inline TUint TExtendedCSD::CmdSetRev() const {return iData[189];}
|
|
172 |
inline TUint TExtendedCSD::PowerClass() const {return iData[187];}
|
|
173 |
inline TUint TExtendedCSD::HighSpeedTiming() const {return iData[185];}
|
|
174 |
typedef TPckg<TExtendedCSD> TExtendedCSDPckg;
|
|
175 |
|
|
176 |
static TExtendedCSD extCSD;
|
|
177 |
|
|
178 |
GLDEF_C TInt CurrentDrive()
|
|
179 |
//
|
|
180 |
// Return the current drive number
|
|
181 |
//
|
|
182 |
{
|
|
183 |
|
|
184 |
TInt driveNum;
|
|
185 |
TInt r=TheFs.CharToDrive(gSessionPath[0],driveNum);
|
|
186 |
test_KErrNone(r);
|
|
187 |
return(driveNum);
|
|
188 |
}
|
|
189 |
|
|
190 |
GLDEF_C void Format(TInt aDrive)
|
|
191 |
//
|
|
192 |
// Format current drive
|
|
193 |
//
|
|
194 |
{
|
|
195 |
|
|
196 |
TUint initTicks = User::FastCounter();
|
|
197 |
TUint finalTicks = 0;
|
|
198 |
|
|
199 |
TBuf<4> driveBuf=_L("?:\\");
|
|
200 |
driveBuf[0]=(TText)(aDrive+'A');
|
|
201 |
RFormat format;
|
|
202 |
TInt count;
|
|
203 |
|
|
204 |
TInt r=format.Open(TheFs,driveBuf, EFullFormat,count); // EQuickFormat
|
|
205 |
test_KErrNone(r);
|
|
206 |
while(count)
|
|
207 |
{
|
|
208 |
TInt r=format.Next(count);
|
|
209 |
test_KErrNone(r);
|
|
210 |
}
|
|
211 |
format.Close();
|
|
212 |
|
|
213 |
finalTicks = User::FastCounter();
|
|
214 |
TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
|
|
215 |
|
|
216 |
TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
|
|
217 |
test.Printf(_L("Time taken to format %d ms)\n"), timeTakenInMs);
|
|
218 |
}
|
|
219 |
|
|
220 |
|
|
221 |
|
|
222 |
static TInt getExtendedCSD()
|
|
223 |
{
|
|
224 |
|
|
225 |
if (!iDriverOpen)
|
|
226 |
return(KErrNotSupported);
|
|
227 |
|
|
228 |
|
|
229 |
// Power the stack down & up to make sure the CardInfo is up to date
|
|
230 |
iDriver.Reset();
|
|
231 |
User::After(1000);
|
|
232 |
iDriver.PwrDownStack();
|
|
233 |
User::After(1000);
|
|
234 |
TRequestStatus status;
|
|
235 |
iDriver.PwrUpAndInitStack(status);
|
|
236 |
User::WaitForRequest(status);
|
|
237 |
TInt err;
|
|
238 |
if ((err=status.Int())!=KErrNone)
|
|
239 |
{
|
|
240 |
test.Printf(_L("Error Powering Stack"),err);
|
|
241 |
return(err);
|
|
242 |
}
|
|
243 |
iDriver.SelectCard(iCard);
|
|
244 |
|
|
245 |
// Get the CSD first to check whether the ExtCSD is supported
|
|
246 |
TMmcCardInfo ci;
|
|
247 |
if ((err = iDriver.CardInfo(ci))!=KErrNone)
|
|
248 |
{
|
|
249 |
test.Printf(_L("Error getting card info"),err);
|
|
250 |
return(err);
|
|
251 |
}
|
|
252 |
//test.Printf(_L("CSD Spec version: %u\n"), ci.iSpecVers);
|
|
253 |
|
|
254 |
if (ci.iSpecVers < 4)
|
|
255 |
{
|
|
256 |
test.Printf(_L("Error: Extended CSD not supported\n"));
|
|
257 |
return KErrNotSupported;
|
|
258 |
}
|
|
259 |
|
|
260 |
TExtendedCSDPckg extCSDPckg(extCSD);
|
|
261 |
|
|
262 |
iDriver.ReadExtCSD(status, extCSDPckg);
|
|
263 |
|
|
264 |
User::WaitForRequest(status);
|
|
265 |
|
|
266 |
if (status.Int() != KErrNone)
|
|
267 |
{
|
|
268 |
test.Printf(_L("Error getting Extended CSD\n"));
|
|
269 |
return(KErrGeneral);
|
|
270 |
}
|
|
271 |
return err;
|
|
272 |
}
|
|
273 |
|
|
274 |
|
|
275 |
static TUint GetSecEraseMultValue(void)
|
|
276 |
{
|
|
277 |
TUint retVal = 0;
|
|
278 |
|
|
279 |
getExtendedCSD();
|
|
280 |
retVal = extCSD.SecureEraseMultiplier();
|
|
281 |
|
|
282 |
return retVal;
|
|
283 |
}
|
|
284 |
|
|
285 |
static TUint GetSecTrimMultValue(void)
|
|
286 |
{
|
|
287 |
TUint retVal = 0;
|
|
288 |
|
|
289 |
getExtendedCSD();
|
|
290 |
retVal = extCSD.SecureTrimMultiplier();
|
|
291 |
|
|
292 |
return retVal;
|
|
293 |
}
|
|
294 |
|
|
295 |
static TUint GetTrimMultValue(void)
|
|
296 |
{
|
|
297 |
TUint retVal = 0;
|
|
298 |
|
|
299 |
getExtendedCSD();
|
|
300 |
retVal = extCSD.TrimMultiplier();
|
|
301 |
|
|
302 |
return retVal;
|
|
303 |
}
|
|
304 |
|
|
305 |
static TInt64 DiskSize(TInt aDrive)
|
|
306 |
//
|
|
307 |
//
|
|
308 |
//
|
|
309 |
{
|
|
310 |
TVolumeInfo v;
|
|
311 |
TInt r=TheFs.Volume(v,aDrive);
|
|
312 |
test_KErrNone(r);
|
|
313 |
return(v.iSize);
|
|
314 |
}
|
|
315 |
|
|
316 |
static TInt CalcEntries(TInt64 aDiskSize, TUint& aEntrySize)
|
|
317 |
{
|
|
318 |
|
|
319 |
aEntrySize = KMaxFileSize;
|
|
320 |
TInt numFiles = (TInt)(aDiskSize / aEntrySize);
|
|
321 |
|
|
322 |
while ( numFiles > 1000 )
|
|
323 |
{
|
|
324 |
aEntrySize = aEntrySize << 2 ;
|
|
325 |
numFiles = (TUint)(aDiskSize / aEntrySize);
|
|
326 |
}
|
|
327 |
return numFiles;
|
|
328 |
|
|
329 |
}
|
|
330 |
|
|
331 |
static void WriteFull(TInt aDrive)
|
|
332 |
{
|
|
333 |
TInt64 diskSize = DiskSize(aDrive);
|
|
334 |
|
|
335 |
RFile f;
|
|
336 |
TUint initTicks = 0;
|
|
337 |
TUint finalTicks = 0;
|
|
338 |
|
|
339 |
TFileName sessionPath;
|
|
340 |
TInt r=TheFs.SessionPath(sessionPath);
|
|
341 |
test_KErrNone(r);
|
|
342 |
TBuf8<8> WriteData =_L8("Wibbleuy");
|
|
343 |
|
|
344 |
r=TheFs.MkDirAll(gSessionPath);
|
|
345 |
|
|
346 |
|
|
347 |
TUint entrySize = KMaxFileSize;
|
|
348 |
TInt numFiles = CalcEntries(diskSize, entrySize);
|
|
349 |
test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ;
|
|
350 |
test.Printf(_L("Create %d entries\n"),numFiles);
|
|
351 |
|
|
352 |
test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
|
|
353 |
test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
|
|
354 |
test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
|
|
355 |
initTicks = User::FastCounter();
|
|
356 |
|
|
357 |
for( TInt i = 0; i < numFiles; ++i)
|
|
358 |
{
|
|
359 |
|
|
360 |
test.Printf(_L("Create FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
|
|
361 |
TFileName baseName= gSessionPath;
|
|
362 |
baseName.Append(_L("FILE"));
|
|
363 |
baseName.AppendNum(i);
|
|
364 |
r=f.Replace(TheFs,baseName,EFileWrite);
|
|
365 |
test_KErrNone(r);
|
|
366 |
r = f.SetSize(entrySize);
|
|
367 |
if( r == KErrDiskFull)
|
|
368 |
{
|
|
369 |
numFiles = i;
|
|
370 |
break;
|
|
371 |
}
|
|
372 |
test_Value(r, r == KErrNone || r==KErrDiskFull);
|
|
373 |
r=f.Write((entrySize-30),WriteData);
|
|
374 |
test_KErrNone(r);
|
|
375 |
f.Flush();
|
|
376 |
f.Close();
|
|
377 |
}
|
|
378 |
|
|
379 |
test.Printf(_L("\nTRIM_MULT :%d\n"), GetTrimMultValue());
|
|
380 |
test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
|
|
381 |
test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
|
|
382 |
|
|
383 |
test.Printf(_L("Test all entries have been created successfully\n"));
|
|
384 |
TBuf8<8> ReadData;
|
|
385 |
TInt Size=0;
|
|
386 |
for (TInt j=0; j < numFiles; j++)
|
|
387 |
{
|
|
388 |
|
|
389 |
test.Printf(_L("Check FILE%d\t(%3d%%)\r"), j, (100*j/numFiles) );
|
|
390 |
TFileName baseName = gSessionPath;
|
|
391 |
baseName.Append(_L("FILE"));
|
|
392 |
baseName.AppendNum(j);
|
|
393 |
|
|
394 |
TInt r=f.Open(TheFs,baseName,EFileRead);
|
|
395 |
if (r!=KErrNone)
|
|
396 |
{
|
|
397 |
test_Value(r, r == KErrNotFound && j==numFiles);
|
|
398 |
return;
|
|
399 |
}
|
|
400 |
ReadData.FillZ();
|
|
401 |
r=f.Read((entrySize-30),ReadData);
|
|
402 |
test_KErrNone(r);
|
|
403 |
test(f.Size(Size)==KErrNone);
|
|
404 |
test(entrySize == (TUint)Size);
|
|
405 |
test(ReadData==WriteData);
|
|
406 |
f.Close();
|
|
407 |
}
|
|
408 |
|
|
409 |
finalTicks = User::FastCounter();
|
|
410 |
TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
|
|
411 |
|
|
412 |
TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
|
|
413 |
test.Printf(_L("Time taken to create %d entries = %d ms (%d ms/entry)\n"), numFiles, timeTakenInMs, timeTakenInMs/numFiles );
|
|
414 |
test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
|
|
415 |
test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
|
|
416 |
test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
|
|
417 |
}
|
|
418 |
|
|
419 |
static void ReWriteHalf(TInt aDrive)
|
|
420 |
{
|
|
421 |
TInt64 diskSize = DiskSize(aDrive);
|
|
422 |
|
|
423 |
RFile f;
|
|
424 |
TUint initTicks = 0;
|
|
425 |
TUint finalTicks = 0;
|
|
426 |
|
|
427 |
TFileName sessionPath;
|
|
428 |
TInt r=TheFs.SessionPath(sessionPath);
|
|
429 |
test_KErrNone(r);
|
|
430 |
TBuf8<8> WriteData =_L8("Wibbleuy");
|
|
431 |
|
|
432 |
r=TheFs.MkDirAll(gSessionPath);
|
|
433 |
|
|
434 |
|
|
435 |
TUint entrySize = KMaxFileSize;
|
|
436 |
TInt numFiles = CalcEntries(diskSize, entrySize);
|
|
437 |
test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ;
|
|
438 |
test.Printf(_L("Create %d entries\n"),numFiles/2);
|
|
439 |
|
|
440 |
test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
|
|
441 |
test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
|
|
442 |
test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
|
|
443 |
initTicks = User::FastCounter();
|
|
444 |
|
|
445 |
for( TInt i = 0; i < numFiles; i += 2)
|
|
446 |
{
|
|
447 |
|
|
448 |
test.Printf(_L("Create FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
|
|
449 |
TFileName baseName= gSessionPath;
|
|
450 |
baseName.Append(_L("FILE"));
|
|
451 |
baseName.AppendNum(i);
|
|
452 |
r=f.Replace(TheFs,baseName,EFileWrite);
|
|
453 |
test_KErrNone(r);
|
|
454 |
r = f.SetSize(entrySize);
|
|
455 |
if( r == KErrDiskFull)
|
|
456 |
{
|
|
457 |
numFiles = i;
|
|
458 |
break;
|
|
459 |
}
|
|
460 |
test_Value(r, r == KErrNone || r==KErrDiskFull);
|
|
461 |
r=f.Write((entrySize-30),WriteData);
|
|
462 |
test_KErrNone(r);
|
|
463 |
f.Flush();
|
|
464 |
f.Close();
|
|
465 |
}
|
|
466 |
|
|
467 |
test.Printf(_L("\nTRIM_MULT :%d\n"), GetTrimMultValue());
|
|
468 |
test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
|
|
469 |
test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
|
|
470 |
|
|
471 |
test.Printf(_L("Test all entries have been created successfully\n"));
|
|
472 |
TBuf8<8> ReadData;
|
|
473 |
TInt Size=0;
|
|
474 |
for (TInt j=0; j < numFiles; j += 2)
|
|
475 |
{
|
|
476 |
|
|
477 |
test.Printf(_L("Check FILE%d\t(%3d%%)\r"), j, (100*j/numFiles) );
|
|
478 |
TFileName baseName = gSessionPath;
|
|
479 |
baseName.Append(_L("FILE"));
|
|
480 |
baseName.AppendNum(j);
|
|
481 |
|
|
482 |
TInt r=f.Open(TheFs,baseName,EFileRead);
|
|
483 |
if (r!=KErrNone)
|
|
484 |
{
|
|
485 |
test_Value(r, r == KErrNotFound && j==numFiles);
|
|
486 |
return;
|
|
487 |
}
|
|
488 |
ReadData.FillZ();
|
|
489 |
r=f.Read((entrySize-30),ReadData);
|
|
490 |
test_KErrNone(r);
|
|
491 |
test(f.Size(Size)==KErrNone);
|
|
492 |
test(entrySize == (TUint)Size);
|
|
493 |
test(ReadData==WriteData);
|
|
494 |
f.Close();
|
|
495 |
}
|
|
496 |
|
|
497 |
finalTicks = User::FastCounter();
|
|
498 |
TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
|
|
499 |
|
|
500 |
TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
|
|
501 |
test.Printf(_L("Time taken to create %d entries = %d ms (%d ms/entry)\n"), numFiles/2, timeTakenInMs, timeTakenInMs/numFiles/2 );
|
|
502 |
test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
|
|
503 |
test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
|
|
504 |
test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
|
|
505 |
}
|
|
506 |
|
|
507 |
|
|
508 |
|
|
509 |
static void DeleteAll(TInt aDrive)
|
|
510 |
{
|
|
511 |
TInt64 diskSize = DiskSize(aDrive);
|
|
512 |
|
|
513 |
TUint initTicks = 0;
|
|
514 |
TUint finalTicks = 0;
|
|
515 |
|
|
516 |
TFileName sessionPath;
|
|
517 |
TInt r=TheFs.SessionPath(sessionPath);
|
|
518 |
test_KErrNone(r);
|
|
519 |
|
|
520 |
TUint entrySize = KMaxFileSize;
|
|
521 |
TInt numFiles = CalcEntries(diskSize, entrySize);
|
|
522 |
test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ;
|
|
523 |
test.Printf(_L("Delete %d entries\n"),numFiles);
|
|
524 |
|
|
525 |
test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
|
|
526 |
test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
|
|
527 |
test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
|
|
528 |
|
|
529 |
initTicks = User::FastCounter();
|
|
530 |
|
|
531 |
for( TInt i = 2; i < numFiles; ++i)
|
|
532 |
{
|
|
533 |
test.Printf(_L("Delete FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
|
|
534 |
TFileName baseName = gSessionPath;
|
|
535 |
baseName.Append(_L("FILE"));
|
|
536 |
baseName.AppendNum(i);
|
|
537 |
TInt r=TheFs.Delete(baseName);
|
|
538 |
test_Value(r, r == KErrNotFound || r == KErrNone);
|
|
539 |
}
|
|
540 |
|
|
541 |
finalTicks = User::FastCounter();
|
|
542 |
TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
|
|
543 |
|
|
544 |
TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
|
|
545 |
test.Printf(_L("Time taken to delete %d entries = %d ms (%d ms/entry)\n"), numFiles, timeTakenInMs, timeTakenInMs/numFiles);
|
|
546 |
test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
|
|
547 |
test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
|
|
548 |
test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
|
|
549 |
}
|
|
550 |
|
|
551 |
static void DeleteHalf(TInt aDrive)
|
|
552 |
{
|
|
553 |
TInt64 diskSize = DiskSize(aDrive);
|
|
554 |
|
|
555 |
TUint initTicks = 0;
|
|
556 |
TUint finalTicks = 0;
|
|
557 |
|
|
558 |
TFileName sessionPath;
|
|
559 |
TInt r=TheFs.SessionPath(sessionPath);
|
|
560 |
test_KErrNone(r);
|
|
561 |
|
|
562 |
TUint entrySize = KMaxFileSize;
|
|
563 |
TInt numFiles = CalcEntries(diskSize, entrySize);
|
|
564 |
test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ;
|
|
565 |
test.Printf(_L("Delete %d entries\n"),numFiles/2);
|
|
566 |
|
|
567 |
test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
|
|
568 |
test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
|
|
569 |
test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
|
|
570 |
|
|
571 |
initTicks = User::FastCounter();
|
|
572 |
|
|
573 |
for( TInt i = 0; i < numFiles; i +=2)
|
|
574 |
{
|
|
575 |
test.Printf(_L("Delete FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
|
|
576 |
TFileName baseName = gSessionPath;
|
|
577 |
baseName.Append(_L("FILE"));
|
|
578 |
baseName.AppendNum(i);
|
|
579 |
TInt r=TheFs.Delete(baseName);
|
|
580 |
test_Value(r, r == KErrNotFound || r == KErrNone);
|
|
581 |
}
|
|
582 |
|
|
583 |
finalTicks = User::FastCounter();
|
|
584 |
TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
|
|
585 |
|
|
586 |
TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
|
|
587 |
test.Printf(_L("Time taken to delete %d entries = %d ms (%d ms/entry)\n"), numFiles/2, timeTakenInMs, timeTakenInMs/numFiles/2);
|
|
588 |
test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
|
|
589 |
test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
|
|
590 |
test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
|
|
591 |
}
|
|
592 |
|
|
593 |
|
|
594 |
static void WaitUntilTrimDone()
|
|
595 |
{
|
|
596 |
|
|
597 |
TUint initTicks = User::FastCounter();
|
|
598 |
TUint finalTicks = 0;
|
|
599 |
|
|
600 |
#define READ_TO_KEEP_CARD_ON
|
|
601 |
#ifdef READ_TO_KEEP_CARD_ON
|
|
602 |
|
|
603 |
const TInt readSize = 4096;
|
|
604 |
const TInt timeToRead = 30;
|
|
605 |
|
|
606 |
test.Printf(_L("Read a file for %d sec to keep card power on\n"), timeToRead );
|
|
607 |
TBuf8<4096> ReadData;
|
|
608 |
|
|
609 |
RTimer timer;
|
|
610 |
timer.CreateLocal();
|
|
611 |
TRequestStatus reqStat;
|
|
612 |
|
|
613 |
//test.Printf(_L("Timer started.\n"));
|
|
614 |
|
|
615 |
TFileName baseName = gSessionPath;
|
|
616 |
baseName.Append(_L("FILE1"));
|
|
617 |
|
|
618 |
RFile f;
|
|
619 |
TInt r=f.Open(TheFs,baseName,EFileRead);
|
|
620 |
if (r!=KErrNone)
|
|
621 |
{
|
|
622 |
return;
|
|
623 |
}
|
|
624 |
TInt alreadyRead = 0;
|
|
625 |
TInt fileSize;
|
|
626 |
test(f.Size(fileSize)==KErrNone);
|
|
627 |
|
|
628 |
//test.Printf(_L("File size:%d.\n"), fileSize);
|
|
629 |
|
|
630 |
timer.After(reqStat, timeToRead*1000000); // After 30 secs
|
|
631 |
|
|
632 |
while( reqStat==KRequestPending )
|
|
633 |
{
|
|
634 |
|
|
635 |
test.Printf(_L("Read pos:%d\r"), alreadyRead );
|
|
636 |
ReadData.FillZ();
|
|
637 |
r=f.Read(readSize,ReadData);
|
|
638 |
|
|
639 |
test_KErrNone(r);
|
|
640 |
alreadyRead += readSize;
|
|
641 |
if( alreadyRead == fileSize)
|
|
642 |
{
|
|
643 |
alreadyRead = 0;
|
|
644 |
f.Seek(ESeekStart, alreadyRead);
|
|
645 |
}
|
|
646 |
User::After(1000); // 1 ms
|
|
647 |
}
|
|
648 |
|
|
649 |
timer.Close();
|
|
650 |
|
|
651 |
f.Close();
|
|
652 |
|
|
653 |
test.Printf(_L("\n"));
|
|
654 |
|
|
655 |
#else
|
|
656 |
|
|
657 |
TInt trimMult = GetTrimMultValue(); // Get TRIM_MULT value from eMMC Extended CSD
|
|
658 |
test.Printf(_L("TRIM_MULT:%d\r"), trimMult);
|
|
659 |
while( trimMult-- > 0 )
|
|
660 |
{
|
|
661 |
// Wait for a while
|
|
662 |
User::After(300000); // TRIM Timeout = 300ms x TRIM_MULT
|
|
663 |
test.Printf(_L("TRIM_MULT:%d\r"), trimMult);
|
|
664 |
TInt trim = GetTrimMultValue();
|
|
665 |
}
|
|
666 |
|
|
667 |
#endif
|
|
668 |
|
|
669 |
finalTicks = User::FastCounter();
|
|
670 |
TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
|
|
671 |
|
|
672 |
TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
|
|
673 |
test.Printf(_L("Time taken to TRIM done = %d ms\n"), timeTakenInMs);
|
|
674 |
}
|
|
675 |
|
|
676 |
|
|
677 |
|
|
678 |
void doExit()
|
|
679 |
{
|
|
680 |
iDriver.Close();
|
|
681 |
|
|
682 |
User::FreeLogicalDevice(_L("MmcIf"));
|
|
683 |
|
|
684 |
test.End();
|
|
685 |
test.Close();
|
|
686 |
|
|
687 |
}
|
|
688 |
|
|
689 |
GLDEF_C void CallTestsL(void)
|
|
690 |
//
|
|
691 |
// Call all tests
|
|
692 |
//
|
|
693 |
{
|
|
694 |
|
|
695 |
test.Next(gSessionPath);
|
|
696 |
|
|
697 |
TInt err;
|
|
698 |
err=User::LoadLogicalDevice(_L("D_MMCIF"));
|
|
699 |
__ASSERT_ALWAYS((err==KErrNone||err==KErrAlreadyExists),Panic(ELoadingMmcDriver));
|
|
700 |
test.Printf(_L("MMCIF driver loaded\n"));
|
|
701 |
|
|
702 |
|
|
703 |
iDriver.Close();
|
|
704 |
TInt r=iDriver.Open(iStack,iDriver.VersionRequired());
|
|
705 |
iDriverOpen=(r==KErrNone)?(TBool)ETrue:(TBool)EFalse;
|
|
706 |
test.Printf(_L("iDriverOpen %d\n"), iDriverOpen);
|
|
707 |
if( !iDriverOpen )
|
|
708 |
{
|
|
709 |
doExit();
|
|
710 |
return;
|
|
711 |
}
|
|
712 |
|
|
713 |
test.Next(_L("Get extended CSD"));
|
|
714 |
r = getExtendedCSD();
|
|
715 |
|
|
716 |
if( r != KErrNone )
|
|
717 |
{
|
|
718 |
test.Next(_L("Extended CSD doesn't exists. Exit."));
|
|
719 |
doExit();
|
|
720 |
return;
|
|
721 |
}
|
|
722 |
|
|
723 |
if( extCSD.ExtendedCSDRev() < 5 )
|
|
724 |
{
|
|
725 |
test.Next(_L("TRIM feature doesn't exists. Exit!"));
|
|
726 |
}
|
|
727 |
|
|
728 |
|
|
729 |
r = HAL::Get(HAL::EFastCounterFrequency, gFastCounterFreq);
|
|
730 |
test_KErrNone(r);
|
|
731 |
test.Printf(_L("HAL::EFastCounterFrequency %d\n"), gFastCounterFreq);
|
|
732 |
|
|
733 |
|
|
734 |
TInt currentDrive = CurrentDrive();
|
|
735 |
|
|
736 |
// 1. Format drive
|
|
737 |
test.Next(_L("Format drive"));
|
|
738 |
Format(currentDrive);
|
|
739 |
|
|
740 |
// 2. Set TRIM off
|
|
741 |
//test.Next(_L("Set TRIM off"));
|
|
742 |
|
|
743 |
|
|
744 |
// 3. Write full with files and measure elapsed time
|
|
745 |
test.Next(_L("Write full"));
|
|
746 |
WriteFull(currentDrive);
|
|
747 |
|
|
748 |
// 4. Delete all files and measure elapsed time
|
|
749 |
test.Next(_L("Delete all files"));
|
|
750 |
DeleteAll(currentDrive);
|
|
751 |
|
|
752 |
// 5. Rewrite all (or a set of) files and measure elapsed time
|
|
753 |
test.Next(_L("Write full"));
|
|
754 |
WriteFull(currentDrive);
|
|
755 |
|
|
756 |
// 6. Format drive
|
|
757 |
test.Next(_L("Format drive"));
|
|
758 |
Format(currentDrive);
|
|
759 |
|
|
760 |
// 7. Set TRIM on
|
|
761 |
//test.Next(_L("Set TRIM on"));
|
|
762 |
|
|
763 |
// 8. Write full with files and measure elapsed time
|
|
764 |
test.Next(_L("Write full"));
|
|
765 |
WriteFull(currentDrive);
|
|
766 |
|
|
767 |
// 9. Delete all files and measure elapsed time
|
|
768 |
test.Next(_L("Delete all files"));
|
|
769 |
DeleteAll(currentDrive);
|
|
770 |
|
|
771 |
// 10. Wait for a while (give time to eMMC to do its TRIM job)
|
|
772 |
test.Next(_L("Wait for TRIM done"));
|
|
773 |
WaitUntilTrimDone();
|
|
774 |
|
|
775 |
// 11. Rewrite all (or same set of) files and measure elapsed time
|
|
776 |
test.Next(_L("Write full"));
|
|
777 |
WriteFull(currentDrive);
|
|
778 |
|
|
779 |
// 12. Format drive
|
|
780 |
test.Next(_L("Format drive"));
|
|
781 |
Format(currentDrive);
|
|
782 |
|
|
783 |
// 13. Write full with files and measure elapsed time
|
|
784 |
test.Next(_L("Write full"));
|
|
785 |
WriteFull(currentDrive);
|
|
786 |
|
|
787 |
// 14. Delete half of files and measure elapsed time
|
|
788 |
test.Next(_L("Delete half of files"));
|
|
789 |
DeleteHalf(currentDrive);
|
|
790 |
|
|
791 |
// 15. Re-write half of files and measure elapsed time
|
|
792 |
test.Next(_L("Re-write half"));
|
|
793 |
ReWriteHalf(currentDrive);
|
|
794 |
|
|
795 |
|
|
796 |
// 16. Format drive
|
|
797 |
test.Next(_L("Format drive"));
|
|
798 |
Format(currentDrive);
|
|
799 |
|
|
800 |
// 17. Write full with files and measure elapsed time
|
|
801 |
test.Next(_L("Write full"));
|
|
802 |
WriteFull(currentDrive);
|
|
803 |
|
|
804 |
// 18. Delete half of files and measure elapsed time
|
|
805 |
test.Next(_L("Delete half of files"));
|
|
806 |
DeleteHalf(currentDrive);
|
|
807 |
|
|
808 |
// 19. Wait for a while (give time to eMMC to do its TRIM job)
|
|
809 |
test.Next(_L("Wait for TRIM done"));
|
|
810 |
WaitUntilTrimDone();
|
|
811 |
|
|
812 |
// 20. Re-write half of files and measure elapsed time
|
|
813 |
test.Next(_L("Re-write half"));
|
|
814 |
ReWriteHalf(currentDrive);
|
|
815 |
|
|
816 |
// 21. Format drive
|
|
817 |
test.Next(_L("Format drive"));
|
|
818 |
Format(currentDrive);
|
|
819 |
|
|
820 |
doExit();
|
|
821 |
|
|
822 |
return;
|
|
823 |
}
|
|
824 |
|
|
825 |
GLDEF_C TInt E32Main()
|
|
826 |
{
|
|
827 |
TInt r=TheFs.Connect();
|
|
828 |
test_KErrNone(r);
|
|
829 |
|
|
830 |
test.Title();
|
|
831 |
test.Start(_L("Start Benchmarking ..."));
|
|
832 |
|
|
833 |
TInt theDrive;
|
|
834 |
gDriveToTest='E';
|
|
835 |
r=TheFs.CharToDrive(gDriveToTest,theDrive);
|
|
836 |
test_KErrNone(r);
|
|
837 |
|
|
838 |
gSessionPath=_L("?:\\TRIMTEST\\");
|
|
839 |
TChar driveLetter;
|
|
840 |
r=TheFs.DriveToChar(theDrive,driveLetter);
|
|
841 |
test_KErrNone(r);
|
|
842 |
gSessionPath[0]=(TText)driveLetter;
|
|
843 |
r=TheFs.SetSessionPath(gSessionPath);
|
|
844 |
test_KErrNone(r);
|
|
845 |
|
|
846 |
r=TheFs.MkDirAll(gSessionPath);
|
|
847 |
if(r == KErrCorrupt)
|
|
848 |
{
|
|
849 |
test.Printf(_L("Attempting to create directory \'%S\' failed, KErrCorrupt\n"), &gSessionPath);
|
|
850 |
test.Printf(_L("This could be caused by a previous failing test, or a test media defect\n"));
|
|
851 |
test.Printf(_L("Formatting drive, retrying MkDirall\nShould subsequent tests fail with KErrCorrupt (%d) as well, replace test medium !\n"),
|
|
852 |
r);
|
|
853 |
Format(theDrive);
|
|
854 |
r=TheFs.MkDirAll(gSessionPath);
|
|
855 |
test_KErrNone(r);
|
|
856 |
}
|
|
857 |
else if (r == KErrNotReady)
|
|
858 |
{
|
|
859 |
TDriveInfo d;
|
|
860 |
r=TheFs.Drive(d, theDrive);
|
|
861 |
test_KErrNone(r);
|
|
862 |
if (d.iType == EMediaNotPresent)
|
|
863 |
test.Printf(_L("%c: Medium not present - cannot perform test.\n"), (TUint)driveLetter);
|
|
864 |
else
|
|
865 |
test.Printf(_L("medium found (type %d) but drive %c: not ready\nPrevious test may have hung; else, check hardware.\n"), (TInt)d.iType, (TUint)driveLetter);
|
|
866 |
}
|
|
867 |
test_Value(r, r == KErrNone || r == KErrAlreadyExists);
|
|
868 |
|
|
869 |
|
|
870 |
CallTestsL();
|
|
871 |
|
|
872 |
TheFs.Close();
|
|
873 |
|
|
874 |
return(KErrNone);
|
|
875 |
}
|