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 "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.
19 #include <nand_media.h>
23 /********************************************
25 ********************************************/
26 const TInt KSimulatedDeviceId = 0xEC73;
27 const CHAR KNandFileName[] = "NANDDRV.BIN";
30 // Platform dependent media driver class
32 class DMediaDriverNandWin32 : public DMediaDriverNand
35 DMediaDriverNandWin32(TMediaDevice aDevice);
37 // replacing pure virtual - NAND device specific stuff
38 virtual TInt Initialise();
39 virtual TInt GetDeviceId(TUint8& aDeviceId, TUint8& aManufacturerId);
40 virtual TInt DeviceRead(const TUint aPageAddress, TAny* aBuf, const TUint aLength);
41 virtual TInt DeviceWrite(const TUint aPageAddress, TAny* aBuf, const TUint aLength);
42 virtual TInt DeviceErase(const TUint aBlockAddress);
43 virtual TInt DeviceClose();
51 LOCAL_C TInt MapLastError()
53 // Map an NT error to an Epoc/32 error.
56 __PATH_NOT_YET_TESTED;
57 DWORD r=GetLastError();
61 case ERROR_SHARING_VIOLATION : res=KErrAccessDenied; break;
62 case ERROR_LOCK_VIOLATION : res=KErrLocked; break;
63 case ERROR_FILE_NOT_FOUND: res=KErrNotFound; break;
64 case ERROR_PATH_NOT_FOUND: res=KErrPathNotFound; break;
65 case ERROR_ALREADY_EXISTS:
66 case ERROR_FILE_EXISTS:
67 res=KErrAlreadyExists;
69 case ERROR_NOT_READY: res=KErrNotReady; break;
70 case ERROR_UNRECOGNIZED_VOLUME:
71 case ERROR_NOT_DOS_DISK:
74 case ERROR_UNRECOGNIZED_MEDIA: res=KErrCorrupt; break;
75 case ERROR_INVALID_NAME: res=KErrBadName; break;
76 case ERROR_NO_MORE_FILES: res=KErrEof; break;
77 case ERROR_DISK_FULL: res=KErrDiskFull; break;
78 default: res=KErrGeneral;
83 TInt DMediaDriverNandWin32::Initialise()
85 // Create the simulated NAND file if necessary and
86 // map it into memory.
91 // locate/open the file that models the flash
92 CHAR filename[MAX_PATH];
93 strcpy(filename, Property::GetString("EmulatorMediaPath"));
94 if (!Emulator::CreateAllDirectories(filename))
96 __PATH_NOT_YET_TESTED;
97 return Emulator::LastError();
99 strcat(filename, KNandFileName);
100 iFile = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
102 if (iFile == INVALID_HANDLE_VALUE)
104 __PATH_NOT_YET_TESTED;
105 return Emulator::LastError();
108 const TUint32 flashSizeInBytes = iNumBlocks * iNumPagesPerBlock * (iNumBytesMain + iNumBytesSpare);
110 SetFilePointer(iFile, flashSizeInBytes, NULL, FILE_BEGIN);
113 iMapping = CreateFileMappingA(iFile, NULL, PAGE_READWRITE, 0, flashSizeInBytes, NULL);
114 if (iMapping == NULL)
116 __PATH_NOT_YET_TESTED;
117 return Emulator::LastError();
120 iBase = (TUint8*)MapViewOfFile(iMapping, FILE_MAP_WRITE, 0, 0, flashSizeInBytes);
123 __PATH_NOT_YET_TESTED;
124 return Emulator::LastError();
130 TInt DMediaDriverNandWin32::GetDeviceId(TUint8& aDeviceId, TUint8& aManufacturerId)
134 aManufacturerId = (KSimulatedDeviceId & 0xFF00) >> 8;
135 aDeviceId = (KSimulatedDeviceId & 0xFF);
139 TInt DMediaDriverNandWin32::DeviceRead(const TUint aPageAddress, TAny* aBuf, const TUint aLength)
143 __NAND_ASSERT(aPageAddress < (iNumBlocks * iNumPagesPerBlock));
144 __NAND_ASSERT( (aLength == iNumBytesMain)
145 || (aLength == iNumBytesMain + iNumBytesSpare)
146 || (aLength == iNumBytesSpare) );
148 #ifdef __TEST_MEDIA_DRIVER__
149 extern TBool gNoPower;
155 if (aLength == iNumBytesMain)
158 readPoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare));
160 else if (aLength == iNumBytesSpare)
163 readPoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare)) + iNumBytesMain;
165 else if (aLength == (iNumBytesMain + iNumBytesSpare))
168 readPoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare));
172 __PATH_NOT_YET_TESTED;
176 for (TUint i = 0; i < aLength; i++)
178 ((TUint8*)aBuf)[i] = readPoint[i];
181 #ifdef __TEST_MEDIA_DRIVER__
182 extern TBool gECCFail;
185 //introduce a random one bit error
186 TUint8* p=(TUint8*)aBuf;
187 TUint32 key=Kern::Random() % aLength;
188 TUint32 shift=1<<(Kern::Random() % 8);
189 p[key]=(TUint8)(p[key]&shift?p[key]-shift:p[key]+shift);
197 #ifdef __TEST_MEDIA_DRIVER__
198 extern "C" TUint32 gbbm_get_sphy_blknum(TUint32, TUint32);
200 TInt DMediaDriverNandWin32::DeviceWrite(const TUint aPageAddress, TAny* aBuf, const TUint aLength)
204 __NAND_ASSERT(aPageAddress < (iNumBlocks * iNumPagesPerBlock));
205 __NAND_ASSERT( (aLength == iNumBytesMain)
206 || (aLength == iNumBytesMain + iNumBytesSpare)
207 || (aLength == iNumBytesSpare) );
209 #ifdef __TEST_MEDIA_DRIVER__
210 extern TBool gNoPower;
211 extern TBool gPowerFail;
212 extern TUint32 gPowerFailAfter;
223 extern TUint32 gNotificationType;
224 extern TUint32 KNandDbgNotifyPowerDown;
225 extern TInt NotifyThread();
226 if(gNotificationType==KNandDbgNotifyPowerDown)
235 if (aLength == iNumBytesMain)
238 writePoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare));
240 else if (aLength == iNumBytesSpare)
243 writePoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare)) + iNumBytesMain;
245 else if (aLength == (iNumBytesMain + iNumBytesSpare))
248 writePoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare));
252 __PATH_NOT_YET_TESTED;
256 for (TUint i = 0; i < aLength; i++)
258 writePoint[i] &= ((TUint8*)aBuf)[i];
261 #ifdef __TEST_MEDIA_DRIVER__
262 extern TUint32 gFailAfter;
263 extern TUint32 gFailAfterCnt;
264 extern TBool gFailureType; //true-WriteFail, false-EraseFail
265 extern TBool gFailON;
266 if(gFailON && gFailureType)
272 extern TUint32 FirstReadPUN;
273 extern DMediaDriverNand* gMediaDriverPtr;
274 if(gbbm_get_sphy_blknum(0,aPageAddress/gMediaDriverPtr->iNumPagesPerBlock)==FirstReadPUN)
276 gFailAfterCnt=gFailAfter;
278 extern TUint32 gNotificationType;
279 extern TUint32 KNandDbgNotifyWriteFail;
280 extern TInt NotifyThread();
281 if(gNotificationType==KNandDbgNotifyWriteFail)
293 TInt DMediaDriverNandWin32::DeviceErase(const TUint aBlockAddress)
297 __NAND_ASSERT(aBlockAddress < iNumBlocks);
298 #ifdef __TEST_MEDIA_DRIVER__
299 extern TBool gNoPower;
300 extern TBool gPowerFail;
301 extern TUint32 gPowerFailAfter;
312 extern TUint32 gNotificationType;
313 extern TUint32 KNandDbgNotifyPowerDown;
314 extern TInt NotifyThread();
315 if(gNotificationType==KNandDbgNotifyPowerDown)
322 const TUint bytesPerEraseBlock = iNumPagesPerBlock * (iNumBytesMain + iNumBytesSpare);
323 const TUint erasePos = aBlockAddress * bytesPerEraseBlock;
325 TUint8* temp = iBase + erasePos;
326 for (TUint i=0; i < bytesPerEraseBlock; i++)
333 TInt DMediaDriverNandWin32::DeviceClose()
335 __PATH_NOT_YET_TESTED;
336 TBool bRtn=UnmapViewOfFile(iBase);
339 __PATH_NOT_YET_TESTED;
340 return(MapLastError());
343 bRtn=CloseHandle(iMapping);
346 __PATH_NOT_YET_TESTED;
347 return(MapLastError());
350 bRtn=CloseHandle(iFile);
353 __PATH_NOT_YET_TESTED;
354 return(MapLastError());
360 DMediaDriverNandWin32::DMediaDriverNandWin32(TMediaDevice aDevice)
361 : DMediaDriverNand(aDevice)
366 DMediaDriverNand* DMediaDriverNand::New(TMediaDevice aDevice)
369 return new DMediaDriverNandWin32(aDevice);
372 #ifdef __USE_CUSTOM_ALLOCATOR
374 Concrete implementation of the NAND buffer allocator class
375 - Uses Kern::Alloc based allocation
379 class TNandAllocatorWins : public TNandAllocatorBase
382 virtual TInt AllocateBuffers(SBufferInfo& aBufferInfo); // Initialise the allocator
385 /** Concrete implementation of the NAND buffer allocator class
386 Creates a customallocator (using Kern::Alloc)
388 @param aBufferInfo A reference to a SBufferInfo containing the details of the PSL allocated buffer
389 @return Standard Symbian OS error code
390 @see TNandAllocatorBase::SCellInfo
392 TInt TNandAllocatorWins::AllocateBuffers(SBufferInfo& aBufferInfo)
394 const TUint32 KNumBuffers = 4;
395 const TUint32 KMaxNumBytesSpare = 16;
396 const TUint32 KMaxNumBytesMain = 512;
397 const TUint32 KMaxNumBytesPage = KMaxNumBytesSpare + KMaxNumBytesMain;
399 aBufferInfo.iBytesPerSpareArray = KMaxNumBytesSpare;
400 aBufferInfo.iBytesPerMainArray = KMaxNumBytesMain;
401 aBufferInfo.iBufferCount = KNumBuffers;
403 aBufferInfo.iBufferP = reinterpret_cast<TUint8*>(Kern::Alloc(KMaxNumBytesPage * KNumBuffers));
405 return(aBufferInfo.iBufferP ? KErrNone : KErrNoMemory);
409 Create an allocator suitable for use on this target
412 TNandAllocatorBase* DMediaDriverNand::ExtensionInitAllocator()
414 return new TNandAllocatorWins;