Update contrib.
1 // Copyright (c) 2005-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 // e32/drivers/paging/emulated/emulated_rom_paging.cpp
18 #include <kernel/kern_priv.h>
19 #include <kernel/kernel.h>
20 #include <memmodel/epoc/platform.h>
22 class DEmulatedDataPagingDevice : public DPagingDevice
25 static TInt Install();
28 TInt Read(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TInt);
29 TInt Write(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TBool aBackground);
31 static void ReadTimerCallback(TAny* aSem);
32 static void ReadDfcCallback(TAny* aReq);
35 static void WriteTimerCallback(TAny* aSem);
36 static void WriteDfcCallback(TAny* aReq);
48 NFastSemaphore* iSemaphore;
52 TDataRequest iReadRequest;
53 TInt iAccumulatedReadDelay;
55 TInt iReadPageCPUDelay;
57 TDataRequest iWriteRequest;
58 TInt iAccumulatedWriteDelay;
60 TInt iWritePageCPUDelay;
64 TInt DEmulatedDataPagingDevice::Install()
66 __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf(">DEmulatedDataPagingDevice::Install"));
68 DEmulatedDataPagingDevice* dataDevice = new DEmulatedDataPagingDevice;
73 r = dataDevice->Construct();
75 Kern::InstallPagingDevice(dataDevice);
79 __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("<DEmulatedDataPagingDevice::Install returns %d",r));
84 TInt DEmulatedDataPagingDevice::Construct()
86 __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf(">DEmulatedDataPagingDevice::Construct"));
88 // Initialise DPagingDevice base class
90 iReadUnitShift = 9; // 512 byte units
91 iName = "EmulatedDataPagingDevice";
93 // Calculate swap size
94 TInt free = Kern::FreeRamInBytes()>>20; // megabytes free
95 TInt swapSize = free/2;
99 iSwapSize = swapSize>>iReadUnitShift;
100 __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("DEmulatedDataPagingDevice::Construct swap size 0x%x",swapSize));
102 TInt r = Kern::MutexCreate(iMutex, _L("EmulDataPageDev"), KMutexOrdNone);
103 __NK_ASSERT_ALWAYS(r==KErrNone);
104 // Create a shared chunk to map the ROM pages
105 TChunkCreateInfo info;
106 info.iType = TChunkCreateInfo::ESharedKernelSingle;
107 info.iMaxSize = swapSize;
108 info.iMapAttr = EMapAttrFullyBlocking;
109 info.iOwnsMemory = ETrue;
112 r = Kern::ChunkCreate(info,chunk,iDataStore,mapAttr);
113 __NK_ASSERT_ALWAYS(r==KErrNone);
114 r = Kern::ChunkCommit(chunk,0,swapSize);
115 __NK_ASSERT_ALWAYS(r==KErrNone);
117 // create DFC thread for NAND read simulation
118 _LIT8(KDemandPagingDelay,"DataPagingDelay");
119 r = Kern::DfcQCreate(iDfcQue,24,&KDemandPagingDelay); // DFC thread of same priority as NAND driver
120 __NK_ASSERT_ALWAYS(r==KErrNone);
122 // setup delays used for simulation
123 SDemandPagingConfig config = Epoc::RomHeader().iDemandPagingConfig;
124 iReadPageDelay = config.iSpare[0];
125 iReadPageCPUDelay = config.iSpare[1];
126 iWritePageDelay = config.iSpare[0]*2;
127 iWritePageCPUDelay = config.iSpare[1];
128 __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("DEmulatedDataPagingDevice::Construct emulated delays=%d,%d",iReadPageDelay,iReadPageCPUDelay));
130 __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("<DEmulatedDataPagingDevice::Construct"));
135 TInt DEmulatedDataPagingDevice::Read(TThreadMessage* /*aReq*/,TLinAddr aBuffer,TUint aOffset,TUint aSize,TInt)
137 aOffset <<= iReadUnitShift;
138 aSize <<= iReadUnitShift;
140 if(iReadPageCPUDelay==0 || KDebugNum(KTESTFAST))
142 // don't do emulated NAND delay, just copy it immediately...
143 memcpy((TAny*)aBuffer,(TAny*)(iDataStore+aOffset),aSize);
147 // make sure we are single threaded when we use the DFC.
148 Kern::MutexWait(*iMutex);
150 // get a DFC to do the simulated read
152 NKern::FSSetOwner(&sem,NULL);
153 iReadRequest.iBuffer = aBuffer;
154 iReadRequest.iOffset = aOffset;
155 iReadRequest.iSize = aSize;
156 iReadRequest.iSemaphore = &sem;
157 TDfc dfc(ReadDfcCallback,this,iDfcQue,0);
160 TInt result = iReadRequest.iResult;
162 // let any other threads have a go.
163 Kern::MutexSignal(*iMutex);
168 void DEmulatedDataPagingDevice::ReadTimerCallback(TAny* aSem)
170 NKern::FSSignal((NFastSemaphore*)aSem);
174 void DEmulatedDataPagingDevice::ReadDfcCallback(TAny* aSelf)
176 ((DEmulatedDataPagingDevice*)aSelf)->ReadDfc();
180 void DEmulatedDataPagingDevice::ReadDfc()
182 // calculate number of ticks to stall to emulate elapsed time for page read request
183 iAccumulatedReadDelay += iReadPageDelay;
184 TInt tick = NKern::TickPeriod();
186 if(iAccumulatedReadDelay>tick)
188 delay = iAccumulatedReadDelay/tick;
189 iAccumulatedReadDelay -= delay*tick+(tick>>1);
192 NKern::FSSetOwner(&sem,NULL);
193 NTimer timer(ReadTimerCallback,&sem);
195 timer.OneShot(delay,ETrue);
197 // emulate CPU load for processing read
198 Kern::NanoWait(iReadPageCPUDelay*1000);
200 // get data using memcpy
201 memcpy((TAny*)iReadRequest.iBuffer,(TAny*)(iDataStore+iReadRequest.iOffset),iReadRequest.iSize);
203 // wait for delay timer
208 iReadRequest.iResult = KErrNone;
209 NKern::FSSignal(iReadRequest.iSemaphore);
213 TInt DEmulatedDataPagingDevice::Write(TThreadMessage* /*aReq*/,TLinAddr aBuffer,TUint aOffset,TUint aSize,TBool aBackground)
215 aOffset <<= iReadUnitShift;
216 aSize <<= iReadUnitShift;
218 if(iWritePageCPUDelay==0 || KDebugNum(KTESTFAST))
220 // don't do emulated NAND delay, just copy it immediately...
221 memcpy((TAny*)(iDataStore+aOffset),(TAny*)aBuffer,aSize);
225 // make sure we are single threaded when we use the DFC.
226 Kern::MutexWait(*iMutex);
228 // get a DFC to do the simulated write
230 NKern::FSSetOwner(&sem,NULL);
231 iWriteRequest.iBuffer = aBuffer;
232 iWriteRequest.iOffset = aOffset;
233 iWriteRequest.iSize = aSize;
234 iWriteRequest.iSemaphore = &sem;
235 TDfc dfc(WriteDfcCallback,this,iDfcQue,0);
238 TInt result = iWriteRequest.iResult;
240 // let any other threads have a go.
241 Kern::MutexSignal(*iMutex);
246 void DEmulatedDataPagingDevice::WriteTimerCallback(TAny* aSem)
248 NKern::FSSignal((NFastSemaphore*)aSem);
252 void DEmulatedDataPagingDevice::WriteDfcCallback(TAny* aSelf)
254 ((DEmulatedDataPagingDevice*)aSelf)->WriteDfc();
258 void DEmulatedDataPagingDevice::WriteDfc()
260 // calculate number of ticks to stall to emulate elapsed time for page read request
261 iAccumulatedWriteDelay += iWritePageDelay;
262 TInt tick = NKern::TickPeriod();
264 if(iAccumulatedWriteDelay>tick)
266 delay = iAccumulatedWriteDelay/tick;
267 iAccumulatedWriteDelay -= delay*tick+(tick>>1);
270 NKern::FSSetOwner(&sem,NULL);
271 NTimer timer(WriteTimerCallback,&sem);
273 timer.OneShot(delay,ETrue);
275 // emulate CPU load for processing read
276 Kern::NanoWait(iWritePageCPUDelay*1000);
278 // write data using memcpy
279 memcpy((TAny*)(iDataStore+iWriteRequest.iOffset),(TAny*)iWriteRequest.iBuffer,iWriteRequest.iSize);
281 // wait for delay timer
286 iWriteRequest.iResult = KErrNone;
287 NKern::FSSignal(iWriteRequest.iSemaphore);
291 DECLARE_STANDARD_EXTENSION()
293 return DEmulatedDataPagingDevice::Install();