sl@0: // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32/drivers/paging/emulated/emulated_rom_paging.cpp sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: class DEmulatedRomPagingDevice : public DPagingDevice sl@0: { sl@0: public: sl@0: static TInt Install(); sl@0: private: sl@0: TInt Construct(); sl@0: TInt Read(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TInt); sl@0: static void ReadTimerCallback(TAny* aSem); sl@0: static void ReadDfcCallback(TAny* aReq); sl@0: void ReadDfc(); sl@0: private: sl@0: TLinAddr iRomStore; sl@0: sl@0: struct TReadRequest sl@0: { sl@0: TLinAddr iBuffer; sl@0: TLinAddr iOffset; sl@0: TUint iSize; sl@0: NFastSemaphore* iSemaphore; sl@0: TInt iResult; sl@0: }; sl@0: sl@0: TReadRequest iReadRequest; sl@0: TDfcQue* iDfcQue; sl@0: TInt iAccumulatedDelay; sl@0: TInt iReadPageDelay; sl@0: TInt iReadPageCPUDelay; sl@0: DMutex* iMutex; sl@0: }; sl@0: sl@0: sl@0: TInt DEmulatedRomPagingDevice::Install() sl@0: { sl@0: __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf(">DEmulatedRomPagingDevice::Install")); sl@0: TInt r; sl@0: DEmulatedRomPagingDevice* romDevice = new DEmulatedRomPagingDevice; sl@0: if(!romDevice) sl@0: r = KErrNoMemory; sl@0: else sl@0: { sl@0: r = romDevice->Construct(); sl@0: if(r==KErrNone) sl@0: Kern::InstallPagingDevice(romDevice); sl@0: else sl@0: delete romDevice; sl@0: } sl@0: __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("DEmulatedRomPagingDevice::Construct")); sl@0: sl@0: // Initialise DPagingDevice base class sl@0: iType = ERom; sl@0: iReadUnitShift = 9; // 512 byte units sl@0: iName = "EmulatedRomPagingDevice"; sl@0: sl@0: // Get info about ROM sl@0: TPhysAddr* romPages; sl@0: TInt numRomPages; sl@0: TInt r=Kern::HalFunction(EHalGroupVM,EVMHalGetOriginalRomPages,&romPages,&numRomPages); sl@0: __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("DEmulatedRomPagingDevice::Construct numRomPages=%08x",numRomPages)); sl@0: __NK_ASSERT_ALWAYS(r==KErrNone); sl@0: sl@0: r = Kern::MutexCreate(iMutex, _L("EmulRomPageDev"), KMutexOrdNone); sl@0: __NK_ASSERT_ALWAYS(r==KErrNone); sl@0: // Create a shared chunk to map the ROM pages sl@0: TInt pageSize = Kern::RoundToPageSize(1); sl@0: TChunkCreateInfo info; sl@0: info.iType = TChunkCreateInfo::ESharedKernelSingle; sl@0: info.iMaxSize = numRomPages*pageSize; sl@0: info.iMapAttr = EMapAttrFullyBlocking; sl@0: info.iOwnsMemory = EFalse; sl@0: DChunk* chunk; sl@0: TUint32 mapAttr; sl@0: r = Kern::ChunkCreate(info,chunk,iRomStore,mapAttr); sl@0: __NK_ASSERT_ALWAYS(r==KErrNone); sl@0: r = Kern::ChunkCommitPhysical(chunk,0,numRomPages*pageSize,romPages); sl@0: __NK_ASSERT_ALWAYS(r==KErrNone); sl@0: sl@0: // create DFC thread for NAND read simulation sl@0: _LIT8(KDemandPagingDelay,"DemandPagingDelay"); sl@0: r = Kern::DfcQCreate(iDfcQue,24,&KDemandPagingDelay); // DFC thread of same priority as NAND driver sl@0: __NK_ASSERT_ALWAYS(r==KErrNone); sl@0: sl@0: // setup delays used for simulation sl@0: SDemandPagingConfig config = Epoc::RomHeader().iDemandPagingConfig; sl@0: iReadPageDelay = config.iSpare[0]; sl@0: iReadPageCPUDelay = config.iSpare[1]; sl@0: __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("DEmulatedRomPagingDevice::Construct emulated delays=%d,%d",iReadPageDelay,iReadPageCPUDelay)); sl@0: sl@0: __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("ReadDfc(); sl@0: } sl@0: sl@0: sl@0: void DEmulatedRomPagingDevice::ReadDfc() sl@0: { sl@0: // calculate number of ticks to stall to emulate elapsed time for page read request sl@0: iAccumulatedDelay += iReadPageDelay; sl@0: TInt tick = NKern::TickPeriod(); sl@0: TInt delay = 0; sl@0: if(iAccumulatedDelay>tick) sl@0: { sl@0: delay = iAccumulatedDelay/tick; sl@0: iAccumulatedDelay -= delay*tick+(tick>>1); sl@0: } sl@0: NFastSemaphore sem; sl@0: NKern::FSSetOwner(&sem,NULL); sl@0: NTimer timer(ReadTimerCallback,&sem); sl@0: if(delay) sl@0: timer.OneShot(delay,ETrue); sl@0: sl@0: // emulate CPU load for processing read sl@0: Kern::NanoWait(iReadPageCPUDelay*1000); sl@0: sl@0: // get data using memcpy sl@0: memcpy((TAny*)iReadRequest.iBuffer,(TAny*)(iRomStore+iReadRequest.iOffset),iReadRequest.iSize); sl@0: sl@0: // wait for delay timer sl@0: if(delay) sl@0: NKern::FSWait(&sem); sl@0: sl@0: // signal done sl@0: iReadRequest.iResult = KErrNone; sl@0: NKern::FSSignal(iReadRequest.iSemaphore); sl@0: } sl@0: sl@0: sl@0: DECLARE_STANDARD_EXTENSION() sl@0: { sl@0: return DEmulatedRomPagingDevice::Install(); sl@0: }