|
1 // Copyright (c) 1997-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 // e32test\pccd\t_pccdsk.cpp |
|
15 // Soak test the Compact Flash card (ATA). |
|
16 // |
|
17 // |
|
18 |
|
19 |
|
20 // One of these |
|
21 #define USE_MEDIA_CHANGE |
|
22 //#define USE_POWER_OFF_ON |
|
23 |
|
24 #include <e32test.h> |
|
25 #include <e32svr.h> |
|
26 #include <e32hal.h> |
|
27 #include <e32uid.h> |
|
28 #include <hal.h> |
|
29 |
|
30 #define ATA_PDD_NAME _L("MEDATA") |
|
31 |
|
32 const TInt KAtaSectorSize=512; |
|
33 const TInt KMaxSectors=16; |
|
34 const TInt KMaxRdWrBufLen=(KAtaSectorSize*KMaxSectors); // 8K |
|
35 const TInt KMaxErrPos=5; |
|
36 |
|
37 LOCAL_D TBusLocalDrive TheDrive; |
|
38 LOCAL_D TBool ChangedFlag; |
|
39 RTest test(_L("Local Drive Soak Test")); |
|
40 LOCAL_D TBuf8<KMaxRdWrBufLen> wrBuf1,wrBuf2,rdBuf; |
|
41 |
|
42 class TResult |
|
43 { |
|
44 public: |
|
45 enum TResTest {EWrite,ERead,ECompare,EFormat,EReMount}; |
|
46 TResult(); |
|
47 void Display(CConsoleBase *aConsole, TInt aCycles); |
|
48 void Add(TResTest aTst,TInt anErr,TInt anErrPos); |
|
49 inline void SetMemStillFree(TInt aVal) |
|
50 {iFreeMem=aVal;} |
|
51 inline void WriteAborted() |
|
52 {iAbortedWrites++;} |
|
53 inline TInt WriteFails() |
|
54 {return(iWriteTimeoutFails+iWriteWriteFails+iWriteGeneralFails+iWriteCorruptFails+iWriteBatLowFails+iWriteOtherFails);} |
|
55 inline TInt ReadFails() |
|
56 {return(iReadTimeoutFails+iReadCorruptFails+iReadOtherFails);} |
|
57 inline TInt CompareFails() |
|
58 {return(iCompareFails);} |
|
59 inline TInt FormatFails() |
|
60 {return(iFormatTimeoutFails+iFormatEmergencyFails+iFormatBatLowFails+iFormatOtherFails);} |
|
61 inline TInt ReMountFails() |
|
62 {return(iReMountFails);} |
|
63 public: |
|
64 TInt iWriteTimeoutFails; |
|
65 TInt iWriteWriteFails; |
|
66 TInt iWriteGeneralFails; |
|
67 TInt iWriteCorruptFails; |
|
68 TInt iWriteBatLowFails; |
|
69 TInt iWriteOtherFails; |
|
70 TInt iReadTimeoutFails; |
|
71 TInt iReadCorruptFails; |
|
72 TInt iReadOtherFails; |
|
73 TInt iCompareFails; |
|
74 TInt iFormatTimeoutFails; |
|
75 TInt iFormatEmergencyFails; |
|
76 TInt iFormatBatLowFails; |
|
77 TInt iFormatOtherFails; |
|
78 TInt iReMountFails; |
|
79 TInt iLastErrorPos[KMaxErrPos]; |
|
80 TInt iLastErrorPtr; |
|
81 TInt iFreeMem; |
|
82 TInt iAbortedWrites; |
|
83 }; |
|
84 |
|
85 |
|
86 LOCAL_C void StatusBar(TInt aPos,TInt anEndPos,TInt aYPos,const TPtrC &aTitle) |
|
87 // |
|
88 // Display progress of local drive operation on screen (1-16 dots) |
|
89 // |
|
90 { |
|
91 static TInt prev; |
|
92 TInt curr; |
|
93 if ((curr=(aPos-1)/(anEndPos>>4))>prev) |
|
94 { // Update progress bar |
|
95 test.Console()->SetPos(0,aYPos); |
|
96 test.Printf(_L(" ")); |
|
97 test.Console()->SetPos(2); |
|
98 test.Printf(_L("%S "),&aTitle); |
|
99 for (TInt i=curr;i>=0;i--) |
|
100 test.Printf(_L(".")); |
|
101 } |
|
102 prev=curr; |
|
103 } |
|
104 |
|
105 TResult::TResult() |
|
106 // |
|
107 // Constructor |
|
108 // |
|
109 { |
|
110 |
|
111 iWriteTimeoutFails=0; |
|
112 iWriteWriteFails=0; |
|
113 iWriteGeneralFails=0; |
|
114 iWriteCorruptFails=0; |
|
115 iWriteBatLowFails=0; |
|
116 iWriteOtherFails=0; |
|
117 iReadTimeoutFails=0; |
|
118 iReadCorruptFails=0; |
|
119 iReadOtherFails=0; |
|
120 iCompareFails=0; |
|
121 iFormatTimeoutFails=0; |
|
122 iFormatEmergencyFails=0; |
|
123 iFormatBatLowFails=0; |
|
124 iFormatOtherFails=0; |
|
125 iReMountFails=0; |
|
126 for (TInt i=0;i<KMaxErrPos;i++) |
|
127 iLastErrorPos[i]=0; |
|
128 iLastErrorPtr=0; |
|
129 iFreeMem=0; |
|
130 iAbortedWrites=0; |
|
131 } |
|
132 |
|
133 void TResult::Display(CConsoleBase *aConsole, TInt aCycles) |
|
134 // |
|
135 // Display test results |
|
136 // |
|
137 { |
|
138 |
|
139 TInt xStartPos=3; |
|
140 TInt yStartPos=8; |
|
141 |
|
142 aConsole->SetPos(xStartPos,yStartPos); |
|
143 test.Printf(_L("Cycles(%08xH) : %d"),iFreeMem,aCycles); |
|
144 |
|
145 aConsole->SetPos(xStartPos,yStartPos+1); |
|
146 if (WriteFails()) |
|
147 test.Printf(_L("Write Fails : %d (TO:%d BT:%d WR:%d GE:%d CU:%d OT:%d)"),WriteFails(),iWriteTimeoutFails,\ |
|
148 iWriteBatLowFails,iWriteWriteFails,iWriteGeneralFails,iWriteCorruptFails,iWriteOtherFails); |
|
149 else |
|
150 test.Printf(_L("Write Fails : 0")); |
|
151 |
|
152 aConsole->SetPos(xStartPos,yStartPos+2); |
|
153 if (ReadFails()) |
|
154 test.Printf(_L("Read Fails : %d (TO:%d CU:%d OT:%d)"),ReadFails(),iReadTimeoutFails,iReadCorruptFails,iReadOtherFails); |
|
155 else |
|
156 test.Printf(_L("Read Fails : 0")); |
|
157 |
|
158 aConsole->SetPos(xStartPos,yStartPos+3); |
|
159 test.Printf(_L("Compare Fails : %d"),CompareFails()); |
|
160 |
|
161 aConsole->SetPos(xStartPos,yStartPos+4); |
|
162 if (FormatFails()) |
|
163 test.Printf(_L("Format Fails : %d (TO:%d EM:%d BT:%d OT:%d)"),FormatFails(),iFormatTimeoutFails,iFormatEmergencyFails,iFormatBatLowFails,iFormatOtherFails); |
|
164 else |
|
165 test.Printf(_L("Format Fails : 0")); |
|
166 |
|
167 aConsole->SetPos(xStartPos,yStartPos+5); |
|
168 #if defined (USE_MEDIA_CHANGE) |
|
169 test.Printf(_L("MediaChange Fails : %d"),ReMountFails()); |
|
170 #else |
|
171 test.Printf(_L("Pwr off/on Fails : %d"),ReMountFails()); |
|
172 #endif |
|
173 |
|
174 aConsole->SetPos(xStartPos,yStartPos+6); |
|
175 test.Printf(_L("Last failures at : ")); |
|
176 for (TInt i=iLastErrorPtr;i>0;i--) |
|
177 test.Printf(_L("%xH "),iLastErrorPos[i-1]); |
|
178 aConsole->SetPos(xStartPos,yStartPos+7); |
|
179 test.Printf(_L("Writes aborted : %d"),iAbortedWrites); |
|
180 test.Printf(_L("\r\n")); |
|
181 } |
|
182 |
|
183 void TResult::Add(TResTest aTst,TInt anErr,TInt anErrPos) |
|
184 // |
|
185 // Add a test result |
|
186 // |
|
187 { |
|
188 |
|
189 if (anErr!=KErrNone) |
|
190 { |
|
191 RDebug::Print(_L("%d) %d(%x)"),aTst,anErr,anErrPos); |
|
192 // Save start sector involved in operation which failed |
|
193 if (anErrPos>=0) |
|
194 { |
|
195 if (iLastErrorPtr>=KMaxErrPos) |
|
196 { |
|
197 TInt i; |
|
198 for (i=0;i<(KMaxErrPos-1);i++) |
|
199 iLastErrorPos[i]=iLastErrorPos[i+1]; |
|
200 iLastErrorPos[i]=anErrPos; |
|
201 } |
|
202 else |
|
203 { |
|
204 iLastErrorPtr++; |
|
205 iLastErrorPos[iLastErrorPtr-1]=anErrPos; |
|
206 } |
|
207 } |
|
208 |
|
209 // Save error type |
|
210 switch (aTst) |
|
211 { |
|
212 case EWrite: |
|
213 if (anErr==KErrTimedOut) |
|
214 iWriteTimeoutFails++; |
|
215 else if (anErr==KErrWrite) |
|
216 iWriteWriteFails++; |
|
217 else if (anErr==KErrGeneral) |
|
218 iWriteGeneralFails++; |
|
219 else if (anErr==KErrCorrupt) |
|
220 iWriteCorruptFails++; |
|
221 else if (anErr==KErrBadPower) |
|
222 iWriteBatLowFails++; |
|
223 else |
|
224 iWriteOtherFails++; |
|
225 break; |
|
226 case ERead: |
|
227 if (anErr==KErrTimedOut) |
|
228 iReadTimeoutFails++; |
|
229 else if (anErr==KErrCorrupt) |
|
230 iReadCorruptFails++; |
|
231 else |
|
232 iReadOtherFails++; |
|
233 break; |
|
234 case ECompare: |
|
235 iCompareFails++; |
|
236 break; |
|
237 case EFormat: |
|
238 if (anErr==KErrTimedOut) |
|
239 iFormatTimeoutFails++; |
|
240 else if (anErr==KErrAbort) |
|
241 iFormatEmergencyFails++; |
|
242 else if (anErr==KErrBadPower) |
|
243 iFormatBatLowFails++; |
|
244 else |
|
245 iFormatOtherFails++; |
|
246 break; |
|
247 case EReMount: |
|
248 iReMountFails++; |
|
249 break; |
|
250 } |
|
251 } |
|
252 } |
|
253 |
|
254 LOCAL_C TUint GetTUintFromConsole(const TDesC &aText) |
|
255 // |
|
256 // Get a TUint value from the console |
|
257 // |
|
258 { |
|
259 |
|
260 TBuf<10> buf(0); |
|
261 TKeyCode kc; |
|
262 TUint pos=0; |
|
263 test.Printf(aText); |
|
264 TUint linePos=(aText.Length()+2); |
|
265 test.Console()->SetPos(linePos); |
|
266 FOREVER |
|
267 { |
|
268 switch((kc=test.Getch())) |
|
269 { |
|
270 case EKeyEscape: case EKeyEnter: |
|
271 { |
|
272 TLex lex(buf); |
|
273 TUint v; |
|
274 if (lex.Val(v,EDecimal)==KErrNone) |
|
275 return(v); |
|
276 return(0); |
|
277 } |
|
278 case EKeyBackspace: case EKeyDelete: |
|
279 pos--; |
|
280 buf.Delete(pos,1); |
|
281 linePos--; |
|
282 test.Console()->SetPos(linePos); |
|
283 test.Printf(_L(" ")); |
|
284 test.Console()->SetPos(linePos); |
|
285 break; |
|
286 default: |
|
287 TChar ch=(TUint)kc; |
|
288 if (ch.IsDigit() && pos<9) |
|
289 { |
|
290 buf.Append(ch); |
|
291 pos++; |
|
292 test.Printf(_L("%c"),(TUint)ch); |
|
293 linePos++; |
|
294 } |
|
295 break; |
|
296 } |
|
297 } |
|
298 } |
|
299 |
|
300 GLDEF_C TInt E32Main() |
|
301 { |
|
302 TBuf<64> b; |
|
303 |
|
304 test.Title(); |
|
305 TDriveInfoV1Buf diBuf; |
|
306 UserHal::DriveInfo(diBuf); |
|
307 TDriveInfoV1 &di=diBuf(); |
|
308 test.Printf(_L("Select Local Drive (C-%c): "),'C'+(di.iTotalSupportedDrives-1)); |
|
309 TChar c; |
|
310 TInt drv; |
|
311 FOREVER |
|
312 { |
|
313 c=(TUint)test.Getch(); |
|
314 c.UpperCase(); |
|
315 drv=((TUint)c)-'C'; |
|
316 if (drv>=0&&drv<di.iTotalSupportedDrives) |
|
317 break; |
|
318 } |
|
319 test.Printf(_L("%c:\r\n"),'C'+drv); |
|
320 |
|
321 test.Printf(_L("Select Test Sequence (Sector 1-R,2-WR,3-WRF)/(SubSector 4-R,5-WR,6-WRF): ")); |
|
322 TInt testSeq; |
|
323 FOREVER |
|
324 { |
|
325 c=(TUint)test.Getch(); |
|
326 testSeq=((TUint)c)-'0'; |
|
327 if (testSeq>=0&&testSeq<=6) |
|
328 break; |
|
329 } |
|
330 test.Printf(_L("%d\r\n"),testSeq); |
|
331 |
|
332 TInt RdWrLen=(TInt)GetTUintFromConsole(_L("Select Buffer Size In Sectors: ")); |
|
333 RdWrLen*=KAtaSectorSize; |
|
334 |
|
335 test.Start(_L("Load Ata Media Driver")); |
|
336 TInt r; |
|
337 r=User::LoadPhysicalDevice(ATA_PDD_NAME); |
|
338 test(r==KErrNone || r==KErrAlreadyExists); |
|
339 #if defined (USE_POWER_OFF_ON) |
|
340 RTimer timer; |
|
341 test(timer.CreateLocal()==KErrNone); |
|
342 TRequestStatus prs; |
|
343 TTime tim; |
|
344 #endif |
|
345 TInt muid=0; |
|
346 r=HAL::Get(HAL::EMachineUid, muid); |
|
347 test(r==KErrNone); |
|
348 TBool reMountTestSupported=ETrue; |
|
349 // if (machineName.MatchF(_L("SNOWBALL*"))>=0) // snowball is ancient history |
|
350 // reMountTestSupported=EFalse; |
|
351 |
|
352 b.Format(_L("Connect to drive %c:"),'C'+drv); |
|
353 test.Next(b); |
|
354 ChangedFlag=EFalse; |
|
355 TheDrive.Connect(drv,ChangedFlag); |
|
356 |
|
357 test.Next(_L("ATA drive: Capabilities")); |
|
358 TLocalDriveCapsV2Buf info; |
|
359 test(TheDrive.Caps(info)==KErrNone); |
|
360 test(info().iType==EMediaHardDisk); |
|
361 TInt diskSize=I64LOW(info().iSize); |
|
362 |
|
363 wrBuf1.SetLength(RdWrLen); |
|
364 TInt j; |
|
365 for (j=0;j<RdWrLen;j++) |
|
366 wrBuf1[j]=(TUint8)j; |
|
367 wrBuf2.SetLength(RdWrLen); |
|
368 for (j=0;j<RdWrLen;j++) |
|
369 wrBuf2[j]=(TUint8)((RdWrLen-1)-j); |
|
370 |
|
371 TUint *p; |
|
372 TDes8* wrBuf; |
|
373 TInt cycles=0; |
|
374 TResult results; |
|
375 TBool decendPat=EFalse; |
|
376 |
|
377 TRequestStatus kStat; |
|
378 test.Console()->Read(kStat); |
|
379 FOREVER |
|
380 { |
|
381 wrBuf=(decendPat)?&wrBuf2:&wrBuf1; |
|
382 p=(decendPat)?(TUint*)&wrBuf2[0]:(TUint*)&wrBuf1[0]; |
|
383 TInt i,j,len,res; |
|
384 |
|
385 // Recalculate amount of free memory |
|
386 TMemoryInfoV1Buf membuf; |
|
387 UserHal::MemoryInfo(membuf); |
|
388 TMemoryInfoV1 &memoryInfo=membuf(); |
|
389 results.SetMemStillFree(memoryInfo.iFreeRamInBytes); |
|
390 results.Display(test.Console(),cycles); |
|
391 |
|
392 // Write test |
|
393 RDebug::Print(_L("0")); |
|
394 if (testSeq==2||testSeq==3||testSeq==5||testSeq==6) |
|
395 { |
|
396 for (i=0,j=0;i<diskSize;i+=len,j++) |
|
397 { |
|
398 StatusBar(i,diskSize,16,_L("WRITING ")); |
|
399 if (testSeq>3) |
|
400 len=Min(RdWrLen-3,(diskSize-i)); // Not on sector boundary |
|
401 else |
|
402 len=Min(RdWrLen,(diskSize-i)); |
|
403 (*p)=j; |
|
404 wrBuf->SetLength(len); |
|
405 do |
|
406 { |
|
407 res=TheDrive.Write(i,*wrBuf); |
|
408 if (res==KErrAbort) |
|
409 { |
|
410 results.WriteAborted(); |
|
411 results.Display(test.Console(),cycles); |
|
412 } |
|
413 } while (res==KErrNotReady||res==KErrAbort); |
|
414 results.Add(TResult::EWrite,res,i); |
|
415 if (res!=KErrNone) |
|
416 break; |
|
417 } |
|
418 results.Display(test.Console(),cycles); |
|
419 } |
|
420 |
|
421 // Read test |
|
422 RDebug::Print(_L("1")); |
|
423 if (testSeq>=1) |
|
424 { |
|
425 for (i=0,j=0;i<diskSize;i+=len,j++) |
|
426 { |
|
427 StatusBar(i,diskSize,16,_L("READING ")); |
|
428 if (testSeq>3) |
|
429 len=Min(RdWrLen-3,(diskSize-i)); // Not on sector boundary |
|
430 else |
|
431 len=Min(RdWrLen,(diskSize-i)); |
|
432 rdBuf.Fill(0,len); |
|
433 do |
|
434 { |
|
435 res=TheDrive.Read(i,len,rdBuf); |
|
436 } while (res==KErrNotReady); |
|
437 |
|
438 results.Add(TResult::ERead,res,i); |
|
439 if (res!=KErrNone) |
|
440 break; |
|
441 if (testSeq==2||testSeq==3||testSeq==5||testSeq==6) |
|
442 { |
|
443 (*p)=j; |
|
444 wrBuf->SetLength(len); |
|
445 if (rdBuf.Compare(*wrBuf)!=0) |
|
446 { |
|
447 results.Add(TResult::ECompare,KErrGeneral,-1); |
|
448 break; |
|
449 } |
|
450 } |
|
451 } |
|
452 results.Display(test.Console(),cycles); |
|
453 } |
|
454 |
|
455 // Format test |
|
456 RDebug::Print(_L("3")); |
|
457 if (testSeq==3||testSeq==6) |
|
458 { |
|
459 TFormatInfo fi; |
|
460 FOREVER |
|
461 { |
|
462 StatusBar((fi.i512ByteSectorsFormatted<<9),diskSize,16,_L("FORMATTING")); |
|
463 do |
|
464 { |
|
465 res=TheDrive.Format(fi); |
|
466 } while (res==KErrNotReady); |
|
467 if (res==KErrEof) |
|
468 break; |
|
469 results.Add(TResult::EFormat,res,(fi.i512ByteSectorsFormatted<<9)); |
|
470 if (res!=KErrNone) |
|
471 break; |
|
472 } |
|
473 results.Display(test.Console(),cycles); |
|
474 } |
|
475 |
|
476 RDebug::Print(_L("4")); |
|
477 if (reMountTestSupported) |
|
478 { |
|
479 // Media change test / power off-on test |
|
480 #if defined (USE_MEDIA_CHANGE) |
|
481 TheDrive.ForceMediaChange(); |
|
482 if (ChangedFlag==EFalse) |
|
483 results.Add(TResult::EReMount,KErrGeneral,-1); |
|
484 #else |
|
485 tim.HomeTime(); |
|
486 tim+=TTimeIntervalSeconds(8); |
|
487 timer.At(prs,tim); |
|
488 UserHal::SwitchOff(); // Switch off |
|
489 User::WaitForRequest(prs); // Switch back on |
|
490 if (prs.Int()!=KErrNone) |
|
491 results.Add(TResult::EReMount,KErrGeneral,-1); |
|
492 #endif |
|
493 else |
|
494 { |
|
495 do |
|
496 { |
|
497 res=TheDrive.Caps(info); |
|
498 } while (res==KErrNotReady); |
|
499 if (res==KErrNone) |
|
500 { |
|
501 if (info().iType!=EMediaHardDisk) |
|
502 results.Add(TResult::EReMount,KErrGeneral,-1); |
|
503 } |
|
504 else |
|
505 results.Add(TResult::EReMount,res,-1); |
|
506 } |
|
507 ChangedFlag=EFalse; |
|
508 } |
|
509 |
|
510 cycles++; |
|
511 decendPat^=0x01; |
|
512 |
|
513 if (kStat!=KRequestPending) |
|
514 { |
|
515 TKeyCode c=test.Console()->KeyCode(); |
|
516 if (c==EKeySpace) |
|
517 break; |
|
518 test.Console()->Read(kStat); |
|
519 } |
|
520 RDebug::Print(_L("<<")); |
|
521 } |
|
522 |
|
523 b.Format(_L("Disconnect from local drive (%c:)"),'C'+drv); |
|
524 test.Next(b); |
|
525 TheDrive.Disconnect(); |
|
526 |
|
527 test.End(); |
|
528 return(0); |
|
529 } |
|
530 |