1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/drivers/paging/emulated/emulated_rom_paging.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,202 @@
1.4 +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32/drivers/paging/emulated/emulated_rom_paging.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include <kernel/kern_priv.h>
1.22 +#include <kernel/kernel.h>
1.23 +#include <memmodel/epoc/platform.h>
1.24 +
1.25 +class DEmulatedRomPagingDevice : public DPagingDevice
1.26 + {
1.27 +public:
1.28 + static TInt Install();
1.29 +private:
1.30 + TInt Construct();
1.31 + TInt Read(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TInt);
1.32 + static void ReadTimerCallback(TAny* aSem);
1.33 + static void ReadDfcCallback(TAny* aReq);
1.34 + void ReadDfc();
1.35 +private:
1.36 + TLinAddr iRomStore;
1.37 +
1.38 + struct TReadRequest
1.39 + {
1.40 + TLinAddr iBuffer;
1.41 + TLinAddr iOffset;
1.42 + TUint iSize;
1.43 + NFastSemaphore* iSemaphore;
1.44 + TInt iResult;
1.45 + };
1.46 +
1.47 + TReadRequest iReadRequest;
1.48 + TDfcQue* iDfcQue;
1.49 + TInt iAccumulatedDelay;
1.50 + TInt iReadPageDelay;
1.51 + TInt iReadPageCPUDelay;
1.52 + DMutex* iMutex;
1.53 + };
1.54 +
1.55 +
1.56 +TInt DEmulatedRomPagingDevice::Install()
1.57 + {
1.58 + __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf(">DEmulatedRomPagingDevice::Install"));
1.59 + TInt r;
1.60 + DEmulatedRomPagingDevice* romDevice = new DEmulatedRomPagingDevice;
1.61 + if(!romDevice)
1.62 + r = KErrNoMemory;
1.63 + else
1.64 + {
1.65 + r = romDevice->Construct();
1.66 + if(r==KErrNone)
1.67 + Kern::InstallPagingDevice(romDevice);
1.68 + else
1.69 + delete romDevice;
1.70 + }
1.71 + __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("<DEmulatedRomPagingDevice::Install returns %d",r));
1.72 + return r;
1.73 + }
1.74 +
1.75 +
1.76 +TInt DEmulatedRomPagingDevice::Construct()
1.77 + {
1.78 + __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf(">DEmulatedRomPagingDevice::Construct"));
1.79 +
1.80 + // Initialise DPagingDevice base class
1.81 + iType = ERom;
1.82 + iReadUnitShift = 9; // 512 byte units
1.83 + iName = "EmulatedRomPagingDevice";
1.84 +
1.85 + // Get info about ROM
1.86 + TPhysAddr* romPages;
1.87 + TInt numRomPages;
1.88 + TInt r=Kern::HalFunction(EHalGroupVM,EVMHalGetOriginalRomPages,&romPages,&numRomPages);
1.89 + __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("DEmulatedRomPagingDevice::Construct numRomPages=%08x",numRomPages));
1.90 + __NK_ASSERT_ALWAYS(r==KErrNone);
1.91 +
1.92 + r = Kern::MutexCreate(iMutex, _L("EmulRomPageDev"), KMutexOrdNone);
1.93 + __NK_ASSERT_ALWAYS(r==KErrNone);
1.94 + // Create a shared chunk to map the ROM pages
1.95 + TInt pageSize = Kern::RoundToPageSize(1);
1.96 + TChunkCreateInfo info;
1.97 + info.iType = TChunkCreateInfo::ESharedKernelSingle;
1.98 + info.iMaxSize = numRomPages*pageSize;
1.99 + info.iMapAttr = EMapAttrFullyBlocking;
1.100 + info.iOwnsMemory = EFalse;
1.101 + DChunk* chunk;
1.102 + TUint32 mapAttr;
1.103 + r = Kern::ChunkCreate(info,chunk,iRomStore,mapAttr);
1.104 + __NK_ASSERT_ALWAYS(r==KErrNone);
1.105 + r = Kern::ChunkCommitPhysical(chunk,0,numRomPages*pageSize,romPages);
1.106 + __NK_ASSERT_ALWAYS(r==KErrNone);
1.107 +
1.108 + // create DFC thread for NAND read simulation
1.109 + _LIT8(KDemandPagingDelay,"DemandPagingDelay");
1.110 + r = Kern::DfcQCreate(iDfcQue,24,&KDemandPagingDelay); // DFC thread of same priority as NAND driver
1.111 + __NK_ASSERT_ALWAYS(r==KErrNone);
1.112 +
1.113 + // setup delays used for simulation
1.114 + SDemandPagingConfig config = Epoc::RomHeader().iDemandPagingConfig;
1.115 + iReadPageDelay = config.iSpare[0];
1.116 + iReadPageCPUDelay = config.iSpare[1];
1.117 + __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("DEmulatedRomPagingDevice::Construct emulated delays=%d,%d",iReadPageDelay,iReadPageCPUDelay));
1.118 +
1.119 + __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("<DEmulatedRomPagingDevice::Construct"));
1.120 + return KErrNone;
1.121 + }
1.122 +
1.123 +
1.124 +TInt DEmulatedRomPagingDevice::Read(TThreadMessage* /*aReq*/,TLinAddr aBuffer,TUint aOffset,TUint aSize,TInt)
1.125 + {
1.126 + aOffset <<= iReadUnitShift;
1.127 + aSize <<= iReadUnitShift;
1.128 +
1.129 + if(iReadPageCPUDelay==0 || KDebugNum(KTESTFAST))
1.130 + {
1.131 + // don't do emulated NAND delay, just copy it immediately...
1.132 + memcpy((TAny*)aBuffer,(TAny*)(iRomStore+aOffset),aSize);
1.133 + return KErrNone;
1.134 + }
1.135 +
1.136 + // make sure we are single threaded when we use the DFC.
1.137 + Kern::MutexWait(*iMutex);
1.138 +
1.139 + // get a DFC to do the simulated read
1.140 + NFastSemaphore sem;
1.141 + NKern::FSSetOwner(&sem,NULL);
1.142 + iReadRequest.iBuffer = aBuffer;
1.143 + iReadRequest.iOffset = aOffset;
1.144 + iReadRequest.iSize = aSize;
1.145 + iReadRequest.iSemaphore = &sem;
1.146 + TDfc dfc(ReadDfcCallback,this,iDfcQue,0);
1.147 + dfc.Enque();
1.148 + NKern::FSWait(&sem);
1.149 + TInt result = iReadRequest.iResult;
1.150 +
1.151 + // let any other threads have a go.
1.152 + Kern::MutexSignal(*iMutex);
1.153 + return result;
1.154 + }
1.155 +
1.156 +
1.157 +void DEmulatedRomPagingDevice::ReadTimerCallback(TAny* aSem)
1.158 + {
1.159 + NKern::FSSignal((NFastSemaphore*)aSem);
1.160 + }
1.161 +
1.162 +
1.163 +void DEmulatedRomPagingDevice::ReadDfcCallback(TAny* aSelf)
1.164 + {
1.165 + ((DEmulatedRomPagingDevice*)aSelf)->ReadDfc();
1.166 + }
1.167 +
1.168 +
1.169 +void DEmulatedRomPagingDevice::ReadDfc()
1.170 + {
1.171 + // calculate number of ticks to stall to emulate elapsed time for page read request
1.172 + iAccumulatedDelay += iReadPageDelay;
1.173 + TInt tick = NKern::TickPeriod();
1.174 + TInt delay = 0;
1.175 + if(iAccumulatedDelay>tick)
1.176 + {
1.177 + delay = iAccumulatedDelay/tick;
1.178 + iAccumulatedDelay -= delay*tick+(tick>>1);
1.179 + }
1.180 + NFastSemaphore sem;
1.181 + NKern::FSSetOwner(&sem,NULL);
1.182 + NTimer timer(ReadTimerCallback,&sem);
1.183 + if(delay)
1.184 + timer.OneShot(delay,ETrue);
1.185 +
1.186 + // emulate CPU load for processing read
1.187 + Kern::NanoWait(iReadPageCPUDelay*1000);
1.188 +
1.189 + // get data using memcpy
1.190 + memcpy((TAny*)iReadRequest.iBuffer,(TAny*)(iRomStore+iReadRequest.iOffset),iReadRequest.iSize);
1.191 +
1.192 + // wait for delay timer
1.193 + if(delay)
1.194 + NKern::FSWait(&sem);
1.195 +
1.196 + // signal done
1.197 + iReadRequest.iResult = KErrNone;
1.198 + NKern::FSSignal(iReadRequest.iSemaphore);
1.199 + }
1.200 +
1.201 +
1.202 +DECLARE_STANDARD_EXTENSION()
1.203 + {
1.204 + return DEmulatedRomPagingDevice::Install();
1.205 + }