First public contribution.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\lffs\t_lfsdrv2.cpp
15 // Test the LFFS Flash media driver
25 #include "..\misc\prbs.h"
27 _LIT(KTestName,"T_LFSDRV");
28 _LIT(KMediaDriverName,"MEDLFS");
32 RTest test(KTestName);
35 TLocalDriveCapsV7 DriveCaps; // Required for M18 devices
40 const TInt KBufferSize=4096;
41 const TInt KBigBufferSize=4096*4;
42 TUint8 Buffer[KBigBufferSize];
45 /***************************************************
46 * ControlIO command types - for debug builds, only
47 ***************************************************/
53 // Used only for the ControlIO tests
54 #define TYAX_PARTITION_SIZE 0x00200000 // Partition size for TYAX is 1MB; 2 devices in parallel
58 /******************************************************************************
59 * Extra thread for background erase
60 ******************************************************************************/
68 TInt EraseThreadFn(TAny* aPtr)
70 SEraseInfo& e=*(SEraseInfo*)aPtr;
72 for (Block=e.iFirstBlock; Block<e.iFirstBlock+e.iNumBlocks; ++Block)
74 TInt64 pos64 = MAKE_TINT64(0, Block*EbSz);
75 r=Drive.Format(pos64,EbSz);
84 TRequestStatus EraseStatus;
85 const TInt KHeapSize=0x4000;
87 _LIT(KEraseThreadName,"Eraser");
88 TInt StartAsyncErase(TInt aFirstBlock, TInt aNumBlocks)
90 EraseInfo.iFirstBlock=aFirstBlock;
91 EraseInfo.iNumBlocks=aNumBlocks;
92 TInt r=EraseThread.Create(KEraseThreadName,EraseThreadFn,0x4000,KHeapSize,KHeapSize,&EraseInfo,EOwnerThread);
95 EraseThread.Logon(EraseStatus);
100 TInt WaitForAsyncErase()
102 User::WaitForRequest(EraseStatus);
103 TInt exitType=EraseThread.ExitType();
104 TInt exitReason=EraseThread.ExitReason();
105 TBuf<16> exitCat=EraseThread.ExitCategory();
106 if((exitType!= EExitKill)||(exitReason!=KErrNone))
108 test.Printf(_L("Async erase error: %d, block %d\n"),EraseStatus.Int(),Block);
109 test.Printf(_L("Thread exit reason: %d,%d,%S\n"),exitType,exitReason,&exitCat);
114 TUint32 pos=EraseInfo.iFirstBlock*EbSz;
115 TUint32 endpos=pos+EraseInfo.iNumBlocks*EbSz;
116 test.Printf(_L("\nAsync erase completed; verifying...\n"));
117 for (; pos<endpos; pos+=KBufferSize)
119 TInt64 pos64 = MAKE_TINT64(0, pos);
120 TPtr8 ptr(Buffer,0,KBufferSize);
121 Mem::FillZ(Buffer,KBufferSize);
122 TInt r=Drive.Read(pos64,KBufferSize,ptr);
124 test(ptr.Length()==KBufferSize);
125 const TUint32* pB=(const TUint32*)Buffer;
126 const TUint32* pE=(const TUint32*)(Buffer+KBufferSize);
127 while (pB<pE && *pB==0xffffffff) ++pB;
130 test.Printf(_L("ERROR: pos %08x data %08x\n"),((TUint32)pB)-((TUint32)Buffer)+pos,*pB);
135 test.Printf(_L("\n"));
139 /******************************************************************************
140 * Extra thread for background write, for use in the read-while-write tests
141 ******************************************************************************/
144 TInt WriteThreadFn(TAny* aPtr)
146 // re-use the struct created for the erase thread
147 SEraseInfo& e=*(SEraseInfo*)aPtr;
150 TPtrC8 wptr(Buffer,KBufferSize);
151 TUint32* pB=(TUint32*)Buffer;
152 TUint32* pE=(TUint32*)(Buffer+KBufferSize);
156 for (Block=e.iFirstBlock; Block<e.iFirstBlock+e.iNumBlocks; ++Block)
158 TInt64 pos64 = MAKE_TINT64(0, Block*EbSz);
159 r=Drive.Write(pos64,wptr);
167 TRequestStatus WriteStatus;
169 _LIT(KWriteThreadName,"Writer");
170 TInt StartAsyncWrite(TInt aFirstBlock, TInt aNumBlocks)
172 // re-use the struct created for the erase thread
173 EraseInfo.iFirstBlock=aFirstBlock;
174 EraseInfo.iNumBlocks=aNumBlocks;
175 TInt r=WriteThread.Create(KWriteThreadName,WriteThreadFn,0x4000,KHeapSize,KHeapSize,&EraseInfo,EOwnerThread);
178 WriteThread.Logon(WriteStatus);
179 WriteThread.Resume();
183 TInt WaitForAsyncWrite()
185 User::WaitForRequest(WriteStatus);
186 TInt exitType=WriteThread.ExitType();
187 TInt exitReason=WriteThread.ExitReason();
188 TBuf<16> exitCat=WriteThread.ExitCategory();
189 if((exitType!= EExitKill)||(exitReason!=KErrNone))
191 test.Printf(_L("Async Write error: %d, block %d\n"),WriteStatus.Int(),Block);
192 test.Printf(_L("Thread exit reason: %d,%d,%S\n"),exitType,exitReason,&exitCat);
196 // No verification performed
197 test.Printf(_L("\n"));
201 /******************************************************************************
202 * Control mode and Object mode test functions
203 ******************************************************************************/
204 TInt DoControlModeWriteAndVerify(TUint32 aPattern, TUint32 aStartOffset)
206 // Writes 4K bytes of a given pattern to the "A" half of programming regions,
207 // starting at the specified offset, then reads the data back to verify it
209 TUint32* pB=(TUint32*)(Buffer);
210 TUint32* pE=(TUint32*)(Buffer + KBufferSize);
213 // Fill the entire buffer with an initial value
217 // In this mode, half the device is available for writing, the other half is reserved;
218 // the available half appears as the first DriveCaps.iControlModeSize bytes, the reserved
219 // half as the following DriveCaps.iControlModeSize, and this alternating continues.
220 // To perform this discrete-write test, therefore, the data held in Buffer that corresponds
221 // to the reserved area is overwritten with 0xFF; 'writing' this value to the reserved area
222 // has no detrimental effect.
226 for(i=0; i< KBufferSize; i+=(DriveCaps.iControlModeSize*2))
228 pB = (TUint32 *)((TUint32)pB + DriveCaps.iControlModeSize);
229 for (b=0; b < DriveCaps.iControlModeSize; b+=4)
236 for (i=0; i<KBufferSize; i+=(4*DriveCaps.iControlModeSize))
238 TInt64 pos64(i + aStartOffset);
239 TPtrC8 ptr(Buffer+i,(4*DriveCaps.iControlModeSize));
240 r=Drive.Write(pos64,ptr);
243 // Check what has been written
244 Mem::FillZ(Buffer,KBigBufferSize);
245 TPtr8 buf(Buffer,0,KBufferSize);
246 r=Drive.Read(aStartOffset,KBufferSize,buf);
249 for(i=0; i< KBufferSize; i+=(DriveCaps.iControlModeSize*2))
251 for (b=0; b< DriveCaps.iControlModeSize; b+=4)
253 if(*pB++ != aPattern)
255 test.Printf(_L("ERROR: addr %08x data %08x expected %08x\n"),pB,*pB,aPattern);
260 for (b=0; b< DriveCaps.iControlModeSize; b+=4)
262 if(*pB++ != 0xFFFFFFFF)
264 test.Printf(_L("ERROR: addr %08x data %08x expected 0xFFFFFFFF\n"),pB,*pB);
273 TInt DoObjectModeWriteAndVerify(TUint32 aOffset, TUint32 aSize)
275 // Writes 'aSize' bytes of a 'random' pattern to the specified offset
276 // then read back and verify
279 // Check that aSize is valid
280 if(aSize>DriveCaps.iObjectModeSize)
282 test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - aSize=%x is greater than max (%x)\n"),aSize,DriveCaps.iObjectModeSize);
289 TInt64 pos64 = MAKE_TINT64(0, aOffset);
290 TPtrC8 ptr(Buffer,aSize);
291 TUint32* pB=(TUint32*)Buffer;
292 TUint32* pE=(TUint32*)(Buffer+aSize);
295 r=Drive.Write(pos64,ptr);
301 // Read the data back
304 TPtr8 rptr(Buffer,0,aSize);
305 Mem::FillZ(Buffer,aSize);
306 r=Drive.Read(pos64,aSize,rptr);
309 test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - Read returned %d\n"),r);
312 test((TUint32)(rptr.Length())==aSize);
314 // Verify the content
316 pE=(TUint32*)(Buffer+aSize);
318 while (pB<pE && (ex=Random(seed),*pB==ex)) ++pB;
321 test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - addr %08x data %08x expected %08x\n"),pB,*pB,ex);
328 TInt DoControlModeBoundaryWriteAndVerify()
333 //test.Printf(_L("Entering: DoControlModeBoundaryWriteAndVerify - Start Test\n"));
335 r=Drive.Format(0,DriveCaps.iEraseBlockSize);
338 // Program into the last Control mode region in the programming region.
339 TInt64 pos64 = MAKE_TINT64(0, (DriveCaps.iObjectModeSize - (DriveCaps.iControlModeSize*2)));
340 TPtrC8 ptr(Buffer,DriveCaps.iControlModeSize);
341 TUint32* pB=(TUint32*)Buffer;
342 TUint32* pE=(TUint32*)(Buffer+DriveCaps.iControlModeSize);
345 r=Drive.Write(pos64,ptr);
348 test.Printf(_L("ERROR: DoControlModeBoundaryWriteAndVerify - Write 1\n"));
352 // Program into the next programming region starting at the first byte up to the size of the Control Mode Size.
353 pos64 = MAKE_TINT64(0, DriveCaps.iObjectModeSize);
354 r=Drive.Write(pos64,ptr);
357 test.Printf(_L("ERROR: DoControlModeBoundaryWriteAndVerify - Write 2\n"));
361 // Read the data back from the first program
362 pos64 = MAKE_TINT64(0, (DriveCaps.iObjectModeSize - (DriveCaps.iControlModeSize*2)));
363 TPtr8 rptr(Buffer,0,(TInt)DriveCaps.iControlModeSize);
364 Mem::FillZ(Buffer,DriveCaps.iControlModeSize);
365 r=Drive.Read(pos64,DriveCaps.iControlModeSize,rptr);
368 test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - Read returned %d\n"),r);
371 test((TUint32)(rptr.Length())==DriveCaps.iControlModeSize);
373 // Verify the content
375 pE=(TUint32*)(Buffer+DriveCaps.iControlModeSize);
376 TUint32 ex=0xb4b4a5a5;
377 while (pB<pE && (*pB==ex)) ++pB;
380 test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - addr %08x data %08x expected %08x\n"),pB,*pB,ex);
384 // Read the data back from the second program
385 pos64 = MAKE_TINT64(0, DriveCaps.iObjectModeSize);
386 TPtr8 rptr2(Buffer,0,((TInt)DriveCaps.iControlModeSize));
387 Mem::FillZ(Buffer,DriveCaps.iControlModeSize);
388 r=Drive.Read(pos64,DriveCaps.iControlModeSize,rptr2);
391 test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - Read returned %d\n"),r);
394 test((TUint32)(rptr2.Length())==DriveCaps.iControlModeSize);
396 // Verify the content
398 pE=(TUint32*)(Buffer+DriveCaps.iControlModeSize);
400 while (pB<pE && (*pB==ex)) ++pB;
403 test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - addr %08x data %08x expected %08x\n"),pB,*pB,ex);
407 // Bit Twiddle the last bit of the last Control Mode Region
408 // Then bit twiddle the first bit of the first control Mode region.
410 // Program into the last Control mode region in the programming region.
411 pos64 = MAKE_TINT64(0, (DriveCaps.iObjectModeSize - DriveCaps.iControlModeSize - 4));
412 TPtrC8 ptr2(Buffer,4);
413 TUint32* pC=(TUint32*)Buffer;
415 r=Drive.Write(pos64,ptr2);
418 test.Printf(_L("ERROR: DoControlModeBoundaryWriteAndVerify - Write 3\n"));
423 // Read the data back from the first program
424 pos64 = MAKE_TINT64(0, (DriveCaps.iObjectModeSize - DriveCaps.iControlModeSize - 4));
425 TPtr8 rptr3(Buffer,0,4);
426 Mem::FillZ(Buffer,4);
427 r=Drive.Read(pos64,4,rptr3);
430 test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - Read returned %d\n"),r);
433 test(rptr3.Length()==4);
435 // Verify the content
437 if (*pB != 0xb4b4a5a4)
439 test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - addr %08x data %08x expected 0xb4b4a5a4\n"),pB,*pB);
443 // Program into the last Control mode region in the programming region.
444 pos64 = MAKE_TINT64(0, DriveCaps.iObjectModeSize);
445 TPtrC8 ptr3(Buffer,4);
448 r=Drive.Write(pos64,ptr3);
451 test.Printf(_L("ERROR: DoControlModeBoundaryWriteAndVerify - Write 4\n"));
456 // Read the data back from the first program
457 pos64 = MAKE_TINT64(0, DriveCaps.iObjectModeSize);
458 TPtr8 rptr4(Buffer,0,4);
459 Mem::FillZ(Buffer,4);
460 r=Drive.Read(pos64,4,rptr4);
463 test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - Read returned %d\n"),r);
466 test(rptr4.Length()==4);
468 // Verify the content
470 if (*pB != 0x34b4a5a5)
472 test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - addr %08x data %08x expected 0x34b4a5a5\n"),pB,*pB);
482 /******************************************************************************
484 ******************************************************************************/
485 GLDEF_C TInt E32Main()
489 /******************************************************************************
491 ******************************************************************************/
492 TDriveInfoV1Buf diBuf;
493 UserHal::DriveInfo(diBuf);
494 TDriveInfoV1 &di=diBuf();
495 test.Start(_L("Test the LFFS media driver"));
496 test.Printf(_L("DRIVES PRESENT :%d\r\n"),di.iTotalSupportedDrives);
497 test.Printf(_L("C:(1ST) DRIVE NAME :%- 16S\r\n"),&di.iDriveName[0]);
498 test.Printf(_L("D:(2ND) DRIVE NAME :%- 16S\r\n"),&di.iDriveName[1]);
499 test.Printf(_L("E:(3RD) DRIVE NAME :%- 16S\r\n"),&di.iDriveName[2]);
500 test.Printf(_L("F:(4TH) DRIVE NAME :%- 16S\r\n"),&di.iDriveName[3]);
501 test.Printf(_L("G:(5TH) DRIVE NAME :%- 16S\r\n"),&di.iDriveName[4]);
502 test.Printf(_L("H:(6TH) DRIVE NAME :%- 16S\r\n"),&di.iDriveName[5]);
503 test.Printf(_L("I:(7TH) DRIVE NAME :%- 16S\r\n"),&di.iDriveName[6]);
504 test.Printf(_L("J:(8TH) DRIVE NAME :%- 16S\r\n"),&di.iDriveName[7]);
505 test.Printf(_L("K:(9TH) DRIVE NAME :%- 16S\r\n"),&di.iDriveName[8]);
507 test.Printf(_L("\r\nWarning - all data on LFFS drive will be lost.\r\n"));
508 test.Printf(_L("<<<Select drive to continue>>>\r\n"));
511 TChar c=(TUint)test.Getch();
513 DriveNumber=((TUint)c)-'C';
514 if (DriveNumber>=0&&DriveNumber<='C'+ 8)
518 test.Next(_L("Load media driver"));
519 TInt r=User::LoadPhysicalDevice(KMediaDriverName);
520 test(r==KErrNone || r==KErrAlreadyExists);
522 test.Next(_L("Connect to drive"));
523 r=Drive.Connect(DriveNumber,ChangedFlag);
525 test.Next(_L("Get capabilities"));
527 DriveCaps.iControlModeSize=0; // If test invoked for a chip other than Sibley then this element will not be updated
528 DriveCaps.iObjectModeSize=0; // If test invoked for a chip other than Sibley then this element will not be updated
529 TPckg<TLocalDriveCapsV7> capsPckg(DriveCaps);
530 r=Drive.Caps(capsPckg);
533 test.Printf(_L("Size : %08x\n"),I64LOW(DriveCaps.iSize));
534 test.Printf(_L("Type : %d\n"),DriveCaps.iType);
535 test.Printf(_L("Connection Bus : %d\n"),DriveCaps.iConnectionBusType);
536 test.Printf(_L("DriveAtt : %02x\n"),DriveCaps.iDriveAtt);
537 test.Printf(_L("MediaAtt : %02x\n"),DriveCaps.iMediaAtt);
538 test.Printf(_L("BaseAddress : %08x\n"),DriveCaps.iBaseAddress);
539 test.Printf(_L("FileSysID : %d\n"),DriveCaps.iFileSystemId);
540 test.Printf(_L("Hidden sectors : %d\n"),DriveCaps.iHiddenSectors);
541 test.Printf(_L("Erase block size: %d\n"),DriveCaps.iEraseBlockSize);
543 test.Printf(_L("Partition size: %d\n"),DriveCaps.iPartitionSize);
544 test.Printf(_L("Control Mode size: %d\n"),DriveCaps.iControlModeSize);
545 test.Printf(_L("Object Mode size: %d\n"),DriveCaps.iObjectModeSize);
546 test.Printf(_L("Press any key...\n\n"));
549 test(DriveCaps.iDriveAtt==(KDriveAttLocal|KDriveAttInternal));
550 test((DriveCaps.iMediaAtt&KMediaAttFormattable)==(KMediaAttFormattable)); // Apply mask since other flags may be set
552 #if defined(_DEBUG) && defined(_WINS)
553 /******************************************************************************
554 * Simulate device timeout
555 ******************************************************************************/
556 test.Next(_L("Timeout"));
557 EbSz=DriveCaps.iEraseBlockSize;
558 r=Drive.Format(0,EbSz);
560 r=Drive.ControlIO(ECtrlIoTimeout, NULL, NULL);
562 if(r!=KErrNotSupported)
566 // Test timeout behaviour for Write operation
567 TPtrC8 ptr(Buffer,1);
568 r=Drive.Write(0,ptr);
569 test(r==KErrNotReady);
570 // Test condition now cleared, ensure normal operation is OK
571 r=Drive.Write(0,ptr);
573 // Test timeout behaviour for Format operation
574 r=Drive.ControlIO(ECtrlIoTimeout, NULL, NULL);
576 r=Drive.Format(0,EbSz);
577 test(r==KErrNotReady);
579 r=Drive.Format(0,EbSz);
584 test.Printf(_L("Timeout ControlIO failed initialisation\n"));
585 test(0); // Cannot proceed with this test
590 test.Printf(_L("Timeout ControlIO not supported\n"));
593 test.Printf(_L("Press any key...\n"));
597 /******************************************************************************
599 ******************************************************************************/
600 test.Next(_L("Format"));
602 EbSz=DriveCaps.iEraseBlockSize;
603 Size=I64LOW(DriveCaps.iSize);
604 // Reduce size so test doesn't take forever
608 for (pos=0; pos<Size; pos+=EbSz)
610 TInt64 pos64 = MAKE_TINT64(0, pos);
611 r=Drive.Format(pos64,EbSz);
615 test.Next(_L("\nVerify"));
616 for (pos=0; pos<Size; pos+=KBufferSize)
618 TInt64 pos64 = MAKE_TINT64(0, pos);
619 TPtr8 ptr(Buffer,0,KBufferSize);
620 Mem::FillZ(Buffer,KBigBufferSize);
621 r=Drive.Read(pos64,KBufferSize,ptr);
623 test(ptr.Length()==KBufferSize);
624 const TUint32* pB=(const TUint32*)Buffer;
625 const TUint32* pE=(const TUint32*)(Buffer+KBufferSize);
626 while (pB<pE && *pB==0xffffffff) ++pB;
629 test.Printf(_L("ERROR: addr %08x data %08x\n"),pB,*pB);
634 test.Printf(_L("\nPress any key...\n\n"));
637 /******************************************************************************
639 ******************************************************************************/
640 test.Next(_L("Write"));
644 for (pos=0; pos<Size; pos+=KBufferSize)
646 TInt64 pos64 = MAKE_TINT64(0, pos);
647 TPtrC8 ptr(Buffer,KBufferSize);
648 TUint32* pB=(TUint32*)Buffer;
649 TUint32* pE=(TUint32*)(Buffer+KBufferSize);
652 r=Drive.Write(pos64,ptr);
656 test.Printf(_L("\n"));
657 test.Next(_L("Verify"));
660 for (pos=0; pos<Size; pos+=KBufferSize)
662 TInt64 pos64 = MAKE_TINT64(0, pos);
663 TPtr8 ptr(Buffer,0,KBufferSize);
664 Mem::FillZ(Buffer,KBigBufferSize);
665 r=Drive.Read(pos64,KBufferSize,ptr);
667 test(ptr.Length()==KBufferSize);
668 const TUint32* pB=(const TUint32*)Buffer;
669 const TUint32* pE=(const TUint32*)(Buffer+KBufferSize);
671 while (pB<pE && (ex=Random(seed),*pB==ex)) ++pB;
674 test.Printf(_L("ERROR: addr %08x data %08x expected %08x\n"),pB,*pB,ex);
680 test.Printf(_L("\nPress any key...\n\n"));
683 /******************************************************************************
685 ******************************************************************************/
686 test.Next(_L("Format first block"));
687 r=Drive.Format(0,EbSz);
689 test.Next(_L("Single byte writes"));
692 TUint32* pB=(TUint32*)Buffer;
693 TUint32* pE=(TUint32*)(Buffer+KBufferSize);
697 // For M18 devices, this test requires control mode operation.
698 // In this mode, half the device is available for writing, the other half is reserved;
699 // the available half appears as the first DriveCaps.iControlModeSize bytes, the reserved
700 // half as the following DriveCaps.iControlModeSize, and this alternating continues.
701 // To perform this discrete-write test, therefore, the data held in Buffer that corresponds
702 // to the reserved area is overwritten with 0xFF; 'writing' this value to the reserved area
703 // has no detrimental effect.
706 if (DriveCaps.iControlModeSize > 0)
709 for(i=0; i< KBufferSize; i+=(DriveCaps.iControlModeSize*2))
711 pB = (TUint32 *)((TUint32)pB + DriveCaps.iControlModeSize);
712 for (b=0; b < DriveCaps.iControlModeSize; b+=4)
721 // Debug - print content of buffer
722 test.Printf(_L("Content of buffer after inserting 0xFFFFFFFFs follows\n"));
724 TUint32* verifyPtr=(TUint32*)Buffer;
727 test.Printf(_L("%8x %8X %8X\n"),i+=8,*verifyPtr++,*verifyPtr++);
731 for (i=0; i<KBufferSize; ++i)
734 TPtrC8 ptr(Buffer+i,1);
735 r=Drive.Write(pos64,ptr);
740 test.Printf(_L("\n"));
741 test.Next(_L("Verify"));
742 Mem::FillZ(Buffer,KBigBufferSize);
743 TPtr8 buf(Buffer,0,KBufferSize);
744 r=Drive.Read(0,KBufferSize,buf);
750 if (DriveCaps.iControlModeSize > 0)
753 for(i=0; i< KBufferSize; i+=(DriveCaps.iControlModeSize*2))
755 for (b=0; b< DriveCaps.iControlModeSize; b+=4)
760 test.Printf(_L("ERROR: addr %08x data %08x expected %08x\n"),pB,*pB,ex);
764 for (b=0; b< DriveCaps.iControlModeSize; b+=4)
767 if(*pB++ != 0xFFFFFFFF)
769 test.Printf(_L("ERROR: addr %08x data %08x expected 0xFF\n"),pB,*pB);
780 while (pB<pE && (ex=Random(seed),*pB==ex)) ++pB;
784 test.Printf(_L("ERROR: addr %08x data %08x expected %08x\n"),pB,*pB,ex);
788 test.Printf(_L("Single byte writes OK\n"));
790 test.Printf(_L("Press any key...\n\n"));
793 /******************************************************************************
794 * Random length writes
795 ******************************************************************************/
796 test.Next(_L("Random length writes"));
797 // Prepare the device (required if control mode is used for M18 devices)
798 // assume that a maximum of 2 blocks is required
799 r=Drive.Format(0,EbSz);
800 r=Drive.Format(DriveCaps.iEraseBlockSize,EbSz);
805 pE=(TUint32*)(Buffer+KBigBufferSize);
808 TInt remain=KBigBufferSize;
809 TInt objectModeOffset=0;
810 TUint32 writeCount=0;
813 for(writeCount=0; remain && (writeCount<512); writeCount++)
815 TInt l=1+(Random(seed)&255); // random length between 1 and 256
819 if(DriveCaps.iObjectModeSize == 0)
821 pos=KBigBufferSize-remain;
824 TPtrC8 ptr(Buffer+(KBigBufferSize-remain),l);
825 TInt64 pos64(pos+objectModeOffset); // Start writes in a new programming region if object mode supported
826 r=Drive.Write(pos64,ptr);
828 objectModeOffset+=DriveCaps.iObjectModeSize;
832 test.Printf(_L("\n"));
833 test.Next(_L("Verify"));
834 Mem::FillZ(Buffer,KBigBufferSize);
835 new (&buf) TPtr8(Buffer,0,KBigBufferSize);
836 if(DriveCaps.iObjectModeSize==0)
838 r=Drive.Read(0,KBigBufferSize,buf);
844 remain=KBigBufferSize;
847 while(remain && writeCount)
850 TInt l=1+(Random(seed)&255); // random length between 1 and 256
853 TPtr8 ptr(Buffer+(totalLength),l);
854 r=Drive.Read(objectModeOffset,l,ptr);
867 if(DriveCaps.iObjectModeSize==0)
869 while (pB<pE && (ex=Random(seed),*pB==ex)) ++pB;
872 test.Printf(_L("ERROR: addr %08x data %08x expected %08x\n"),pB,*pB,ex);
878 r=Drive.Format(0,EbSz);
879 r=Drive.Format(DriveCaps.iEraseBlockSize,EbSz);
880 test.Printf(_L("\nPress any key...\n\n"));
883 /******************************************************************************
884 * Concurrent read/write/erase
885 ******************************************************************************/
886 test.Printf(_L("Foreground R/W\n"));
887 r=StartAsyncErase(1,Size/EbSz-1);
892 for (pos=KBufferSize+KBigBufferSize; pos<EbSz; pos+=KBufferSize)
894 TInt64 pos64 = MAKE_TINT64(0, pos);
895 TPtrC8 wptr(Buffer,KBufferSize);
896 TUint32* pB=(TUint32*)Buffer;
897 TUint32* pE=(TUint32*)(Buffer+KBufferSize);
900 r=Drive.Write(pos64,wptr);
903 Mem::FillZ(Buffer+KBufferSize,KBufferSize);
904 TPtr8 rptr(Buffer+KBufferSize,0,KBufferSize);
905 r=Drive.Read(pos64,KBufferSize,rptr);
907 test(rptr.Length()==KBufferSize);
908 //test(Mem::Compare(Buffer,KBufferSize,Buffer+KBufferSize,KBufferSize)==0);
909 r = Mem::Compare(Buffer,KBufferSize,Buffer+KBufferSize,KBufferSize);
914 pE=(TUint32*)(Buffer+KBufferSize);
915 for(TInt i=0; i < (KBufferSize>>2); i++)
917 test.Printf(_L("%d Buffer Content %08x %08x Flash Content\n"),i, pB[i], pE[i]);
922 test.Printf(KSemiColon);
925 r=WaitForAsyncErase();
928 r=Drive.Format(0,EbSz);
929 r=Drive.Format(DriveCaps.iEraseBlockSize,EbSz);
930 test.Printf(_L("Press any key...\n\n"));
933 // Perform the following tests for debug builds, only
937 /******************************************************************************
938 * Concurrent operations to exercise TYAX Read-While-Write capability
939 * First, show read while write denied when attempting to read from a partition
940 * that is being written to
941 * Second, show read while write proceeding when reading from a partition other
942 * than that which is being written to
943 ******************************************************************************/
945 // Do not perform these tests unless read-while-write is supported
946 if(DriveCaps.iMediaAtt&KMediaAttReadWhileWrite)
948 test.Next(_L("Denied read while write"));
949 r=Drive.ControlIO(ECtrlIoRww, NULL, NULL);
952 test.Printf(_L("ControlIO not ready, returned %d\n"), r);
953 test(0); // Cannot proceed with this test
955 test.Printf(_L("Press any key...\n"));
958 test.Printf(_L("Starting async write for the first RWE/RWW test"));
959 r=StartAsyncWrite(1,3); // Write to the first three blocks, only, to limit duration
962 // Allow the write thread to be created and ready to run
963 // This will ensure that the driver will have received a write request before the second of the read
964 // requests, below. Following the issue of the ControlIO command, above, the driver will not instigate
965 // the write request until the next (second) read request is received. This is done so that the high priority
966 // driver thread recognises the existence of a read request (from a lower priority test / user thread)
967 // before it executes a sequence of writes to the FLASH device. This is necessary because, although
968 // each write takes a finite amount of time, the poll timer expires so quickly that the driver thread
969 // would not be blocked for a sufficiently long period to allow the read request to be processed. Adopting
970 // the contrived, and artificial, approach of using ControlIO to 'stage' the write allows the read-while-write
971 // capability of the device to be execrised.
974 test.Printf(_L("Starting concurrent loop for background write\n"));
976 // First read - this will be performed before the write thread is run, so does
977 // not exercise read while write.
978 TInt64 pos64 = MAKE_TINT64(0,0);
979 TPtr8 rptr(Buffer+KBufferSize,0,KBufferSize);
980 test.Printf(_L("Issuing Drive.Read 1\n"));
981 r=Drive.Read(pos64,KBufferSize,rptr);
983 test.Printf(KSemiColon);
986 // Second read - to same partition (and block) as the active write
987 // This read should be deferred by the driver
988 TInt64 pos64 = MAKE_TINT64(0, 2*EbSz);
989 TPtr8 rptr(Buffer+KBufferSize,0,KBufferSize);
990 test.Printf(_L("Issuing Drive.Read 2\n"));
991 r=Drive.Read(pos64,KBufferSize,rptr); // Should collide with second write
993 test.Printf(KSemiColon);
996 // Third read - due to the tight poll timer period, this will not be scheduled
997 // until the write request has completed - so does not exercise read while write.
998 TInt64 pos64 = MAKE_TINT64(0, DriveCaps.iPartitionSize);
999 TPtr8 rptr(Buffer+KBufferSize,0,KBufferSize);
1000 test.Printf(_L("Issuing Drive.Read 3\n"));
1001 r=Drive.Read(pos64,KBufferSize,rptr);
1003 test.Printf(KSemiColon);
1006 r=WaitForAsyncWrite();
1009 ///////////////////////////////////////////////////////////////////////////////
1010 r=Drive.Format(0,EbSz);
1011 r=Drive.Format(DriveCaps.iEraseBlockSize,EbSz);
1012 r=Drive.Format((DriveCaps.iEraseBlockSize*2),EbSz);
1013 r=Drive.Format((DriveCaps.iEraseBlockSize*3),EbSz);
1014 test.Printf(_L("Press any key...\n"));
1016 test.Next(_L("Supported read while write"));
1017 r=Drive.ControlIO(ECtrlIoRww, NULL, NULL);
1020 test.Printf(_L("ControlIO not ready\n"));
1023 test.Printf(_L("Press any key...\n"));
1026 test.Printf(_L("Starting async write for the second RWE/RWW test"));
1027 r=StartAsyncWrite(1,3); // Write to the first three blocks, only, to limit duration
1030 // Allow the write thread to be created and ready to run
1033 test.Printf(_L("Starting concurrent loop for background write\n"));
1035 // First read - this will be performed before the write thread is run, so does
1036 // not exercise read while write.
1037 TInt64 pos64 = MAKE_TINT64(0, DriveCaps.iPartitionSize);
1038 TPtr8 rptr(Buffer+KBufferSize,0,KBufferSize);
1039 test.Printf(_L("Issuing Drive.Read 1\n"));
1040 r=Drive.Read(pos64,KBufferSize,rptr);
1042 test.Printf(KSemiColon);
1045 // Second read - to different partition than that targeted by the active write
1046 // This read should check the overlap and proceed without being deferred
1047 TInt64 pos64 = MAKE_TINT64(0, DriveCaps.iPartitionSize);
1048 TPtr8 rptr(Buffer+KBufferSize,0,KBufferSize);
1049 test.Printf(_L("Issuing Drive.Read 2\n"));
1050 r=Drive.Read(pos64,KBufferSize,rptr); // Should collide with second write
1052 test.Printf(KSemiColon);
1055 // Third read - due to the tight poll timer period, this will not be scheduled
1056 // until the write request has completed - so does not exercise read while write.
1057 TInt64 pos64 = MAKE_TINT64(0, DriveCaps.iPartitionSize);
1058 TPtr8 rptr(Buffer+KBufferSize,0,KBufferSize);
1059 test.Printf(_L("Issuing Drive.Read 3\n"));
1060 r=Drive.Read(pos64,KBufferSize,rptr);
1062 test.Printf(KSemiColon);
1065 test.Printf(_L("\nForeground Read OK\n"));
1066 r=WaitForAsyncWrite();
1072 r=Drive.Format(0,EbSz);
1073 r=Drive.Format(DriveCaps.iEraseBlockSize,EbSz);
1074 r=Drive.Format((DriveCaps.iEraseBlockSize*2),EbSz);
1075 r=Drive.Format((DriveCaps.iEraseBlockSize*3),EbSz);
1077 /*****************************************************************************************************
1078 Tests for M18 NOR Flash devices
1080 These tests assume that object mode and control mode is supported
1081 *****************************************************************************************************/
1082 if((DriveCaps.iControlModeSize !=0) && (DriveCaps.iObjectModeSize != 0))
1084 // Control mode writes
1085 // Prove that control mode writes are supported
1086 // This requires that data is formatted such that areas coinciding with the "B" Half of a
1087 // programming region are set to all 0xFFs
1088 // Write to programming region zero
1089 test.Next(_L("\nControl mode writes"));
1091 r=DoControlModeWriteAndVerify(0xa5a5a5a5, 0);
1093 // Now verify that data written in control mode can be further modified
1094 // Do this by ANDing the read-back pattern with a mask that clears particular bits
1095 // then write the resulting pattern back to the region
1096 r=DoControlModeWriteAndVerify(0x84848484, 0);
1098 // Now verify that data written in control mode can be further modified to all 0x00s
1099 // Do this by ANDing the read-back pattern with a mask that clears the remaining bits
1100 // then write the resulting pattern back to the region
1101 r=DoControlModeWriteAndVerify(0x00000000, 0);
1103 // Erase the block before attempting to re-use the programming region for object mode writing
1104 test.Printf(_L("\nErase block 0 before object mode write"));
1105 r=Drive.Format(0,EbSz);
1108 test.Next(_L("\n(Subsequent) Object mode writes"));
1110 // Control mode writes
1111 // Prove that object mode writes are allowd to an erased block that was previously
1112 // used in control mode
1113 // Use offset zero and length equal to one-quarter of the allowed object mode size (i.e. one-
1114 // quarter of the lengh of the programming region) (The write test, above, wrote an entire region
1116 test.Printf(_L("\nObject mode write, object mode size=%d"),DriveCaps.iObjectModeSize);
1117 r=DoObjectModeWriteAndVerify(0, (DriveCaps.iObjectModeSize>>2));
1119 // Prove that an attempt to append data to an object mode region fails
1120 test.Printf(_L("\nAttempt append to object mode region"));
1121 r=DoObjectModeWriteAndVerify((DriveCaps.iObjectModeSize>>2),(DriveCaps.iObjectModeSize>>2));
1122 test(r==KErrGeneral);
1123 // Erase the block after a failed write and before attempting to re-use for programming
1124 test.Printf(_L("\nErase block 0 after failed object mode write"));
1125 r=Drive.Format(0,EbSz);
1128 test.Next(_L("\n(Subsequent) Object mode writes following an error"));
1130 // write to a new object mode region after a failed write and before attempting to erase the block
1131 // Prove that erase block can be re-written to
1132 test.Printf(_L("\nObject mode write following failed write and erase"));
1133 r=DoObjectModeWriteAndVerify(0, (DriveCaps.iObjectModeSize>>2));
1135 // Cause a failed object mode write
1136 r=DoObjectModeWriteAndVerify(0, (DriveCaps.iObjectModeSize>>2));
1137 test(r==KErrGeneral);
1138 // the status register has an error. Attempt to write in a new region and ensure that it succeeds
1139 r=DoObjectModeWriteAndVerify(DriveCaps.iObjectModeSize, DriveCaps.iObjectModeSize);
1142 test.Next(_L("\n(Subsequent) Control mode writes following previous use in object mode"));
1144 // Re-use a former object mode region for control mode writes
1145 // Erase the block after a failed write and before attempting to re-use for programming
1146 r=Drive.Format(0,EbSz);
1148 r=DoControlModeWriteAndVerify(0xa5a5a5a5, 0);
1150 // Verify that data written in control mode can be further modified
1151 r=DoControlModeWriteAndVerify(0x84848484, 0);
1154 test.Next(_L("\n(Subsequent) Control mode writes following an error"));
1156 // Test that a control mode write can succeed after a previous error
1157 // Use a failed object mode write attempt to the "B" half of a control mode region
1158 // to cause the error
1159 r=DoObjectModeWriteAndVerify(DriveCaps.iControlModeSize,(DriveCaps.iObjectModeSize>>2));
1160 test(r==KErrGeneral);
1161 r=DoControlModeWriteAndVerify(0x00000000, 0);
1164 test.Next(_L("\nControl mode boundary write test"));
1166 r=DoControlModeBoundaryWriteAndVerify();
1171 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1173 test.Printf(_L("Press any key...\n"));