os/kernelhwsrv/kernel/eka/drivers/paging/emulated/emulated_rom_paging.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32/drivers/paging/emulated/emulated_rom_paging.cpp
    15 // 
    16 //
    17 
    18 #include <kernel/kern_priv.h>
    19 #include <kernel/kernel.h>
    20 #include <memmodel/epoc/platform.h>
    21 
    22 class DEmulatedRomPagingDevice : public DPagingDevice
    23 	{
    24 public:
    25 	static TInt Install();
    26 private:
    27 	TInt Construct();
    28 	TInt Read(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TInt);
    29 	static void ReadTimerCallback(TAny* aSem);
    30 	static void ReadDfcCallback(TAny* aReq);
    31 	void ReadDfc();
    32 private:
    33 	TLinAddr iRomStore;
    34 
    35 	struct TReadRequest
    36 		{
    37 		TLinAddr iBuffer;
    38 		TLinAddr iOffset;
    39 		TUint	 iSize;
    40 		NFastSemaphore* iSemaphore;
    41 		TInt iResult;
    42 		};
    43 
    44 	TReadRequest iReadRequest;
    45 	TDfcQue* iDfcQue;
    46 	TInt iAccumulatedDelay;
    47 	TInt iReadPageDelay;
    48 	TInt iReadPageCPUDelay;
    49 	DMutex* iMutex;
    50 	};
    51 
    52 
    53 TInt DEmulatedRomPagingDevice::Install()
    54 	{
    55 	__KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf(">DEmulatedRomPagingDevice::Install"));
    56 	TInt r;
    57 	DEmulatedRomPagingDevice* romDevice = new DEmulatedRomPagingDevice;
    58 	if(!romDevice)
    59 		r = KErrNoMemory;
    60 	else
    61 		{
    62 		r = romDevice->Construct();
    63 		if(r==KErrNone)
    64 			Kern::InstallPagingDevice(romDevice);
    65 		else
    66 			delete romDevice;
    67 		}
    68 	__KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("<DEmulatedRomPagingDevice::Install returns %d",r));
    69 	return r;
    70 	}
    71 
    72 
    73 TInt DEmulatedRomPagingDevice::Construct()
    74 	{
    75 	__KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf(">DEmulatedRomPagingDevice::Construct"));
    76 
    77 	// Initialise DPagingDevice base class
    78 	iType = ERom;
    79 	iReadUnitShift = 9; // 512 byte units
    80 	iName = "EmulatedRomPagingDevice";
    81 
    82 	// Get info about ROM
    83 	TPhysAddr* romPages;
    84 	TInt numRomPages;
    85 	TInt r=Kern::HalFunction(EHalGroupVM,EVMHalGetOriginalRomPages,&romPages,&numRomPages);
    86 	__KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("DEmulatedRomPagingDevice::Construct numRomPages=%08x",numRomPages));
    87 	__NK_ASSERT_ALWAYS(r==KErrNone);
    88 
    89 	r = Kern::MutexCreate(iMutex, _L("EmulRomPageDev"), KMutexOrdNone);
    90 	__NK_ASSERT_ALWAYS(r==KErrNone);
    91 	// Create a shared chunk to map the ROM pages
    92 	TInt pageSize = Kern::RoundToPageSize(1);
    93 	TChunkCreateInfo info;
    94 	info.iType = TChunkCreateInfo::ESharedKernelSingle;
    95 	info.iMaxSize = numRomPages*pageSize;
    96 	info.iMapAttr = EMapAttrFullyBlocking;
    97 	info.iOwnsMemory = EFalse;
    98 	DChunk* chunk;
    99 	TUint32 mapAttr;
   100 	r = Kern::ChunkCreate(info,chunk,iRomStore,mapAttr);
   101 	__NK_ASSERT_ALWAYS(r==KErrNone);
   102 	r = Kern::ChunkCommitPhysical(chunk,0,numRomPages*pageSize,romPages);
   103 	__NK_ASSERT_ALWAYS(r==KErrNone);
   104 
   105 	// create DFC thread for NAND read simulation
   106 	_LIT8(KDemandPagingDelay,"DemandPagingDelay");
   107 	r = Kern::DfcQCreate(iDfcQue,24,&KDemandPagingDelay); // DFC thread of same priority as NAND driver
   108 	__NK_ASSERT_ALWAYS(r==KErrNone);
   109 
   110 	// setup delays used for simulation
   111 	SDemandPagingConfig config = Epoc::RomHeader().iDemandPagingConfig;
   112 	iReadPageDelay = config.iSpare[0];
   113 	iReadPageCPUDelay = config.iSpare[1];
   114 	__KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("DEmulatedRomPagingDevice::Construct emulated delays=%d,%d",iReadPageDelay,iReadPageCPUDelay));
   115 
   116 	__KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("<DEmulatedRomPagingDevice::Construct"));
   117 	return KErrNone;
   118 	}
   119 
   120 
   121 TInt DEmulatedRomPagingDevice::Read(TThreadMessage* /*aReq*/,TLinAddr aBuffer,TUint aOffset,TUint aSize,TInt)
   122 	{
   123 	aOffset <<= iReadUnitShift;
   124 	aSize <<= iReadUnitShift;
   125 
   126 	if(iReadPageCPUDelay==0 || KDebugNum(KTESTFAST))
   127 		{
   128 		// don't do emulated NAND delay, just copy it immediately...
   129 		memcpy((TAny*)aBuffer,(TAny*)(iRomStore+aOffset),aSize);
   130 		return KErrNone;
   131 		}
   132 	
   133 	// make sure we are single threaded when we use the DFC.
   134 	Kern::MutexWait(*iMutex);
   135 	
   136 	// get a DFC to do the simulated read
   137 	NFastSemaphore sem;
   138 	NKern::FSSetOwner(&sem,NULL);
   139 	iReadRequest.iBuffer = aBuffer;
   140 	iReadRequest.iOffset = aOffset;
   141 	iReadRequest.iSize = aSize;
   142 	iReadRequest.iSemaphore = &sem;
   143 	TDfc dfc(ReadDfcCallback,this,iDfcQue,0);
   144 	dfc.Enque();
   145 	NKern::FSWait(&sem);
   146 	TInt result = iReadRequest.iResult;
   147 	
   148 	// let any other threads have a go.
   149 	Kern::MutexSignal(*iMutex);
   150 	return result;
   151 	}
   152 
   153 
   154 void DEmulatedRomPagingDevice::ReadTimerCallback(TAny* aSem)
   155 	{
   156 	NKern::FSSignal((NFastSemaphore*)aSem);
   157 	}
   158 
   159 
   160 void DEmulatedRomPagingDevice::ReadDfcCallback(TAny* aSelf)
   161 	{
   162 	((DEmulatedRomPagingDevice*)aSelf)->ReadDfc();
   163 	}
   164 
   165 
   166 void DEmulatedRomPagingDevice::ReadDfc()
   167 	{
   168 	// calculate number of ticks to stall to emulate elapsed time for page read request
   169 	iAccumulatedDelay += iReadPageDelay;
   170 	TInt tick = NKern::TickPeriod();
   171 	TInt delay = 0;
   172 	if(iAccumulatedDelay>tick)
   173 		{
   174 		delay = iAccumulatedDelay/tick;
   175 		iAccumulatedDelay -= delay*tick+(tick>>1);
   176 		}
   177 	NFastSemaphore sem;
   178 	NKern::FSSetOwner(&sem,NULL);
   179 	NTimer timer(ReadTimerCallback,&sem);
   180 	if(delay)
   181 		timer.OneShot(delay,ETrue);
   182 
   183 	// emulate CPU load for processing read
   184 	Kern::NanoWait(iReadPageCPUDelay*1000);
   185 
   186 	// get data using memcpy
   187 	memcpy((TAny*)iReadRequest.iBuffer,(TAny*)(iRomStore+iReadRequest.iOffset),iReadRequest.iSize);
   188 
   189 	// wait for delay timer
   190 	if(delay)
   191 		NKern::FSWait(&sem);
   192 
   193 	// signal done
   194 	iReadRequest.iResult = KErrNone;
   195 	NKern::FSSignal(iReadRequest.iSemaphore);
   196 	}
   197 
   198 
   199 DECLARE_STANDARD_EXTENSION()
   200 	{
   201 	return DEmulatedRomPagingDevice::Install();
   202 	}