kernel/eka/drivers/locmedia/locmedia.cpp
branchRCL_3
changeset 28 5b5d147c7838
parent 26 c734af59ce98
child 36 bbf8bed59bcb
--- a/kernel/eka/drivers/locmedia/locmedia.cpp	Tue May 11 17:28:22 2010 +0300
+++ b/kernel/eka/drivers/locmedia/locmedia.cpp	Tue May 25 14:09:55 2010 +0300
@@ -76,6 +76,7 @@
 #ifdef __DEMAND_PAGING__
 	DMediaPagingDevice* iPagingDevice;
 	TInt iPageSizeMsk;			// Mask of page size (e.g. 4096-1 -> 4095)
+	TInt iPageSizeLog2;        // LOG2 of page size (i.e. 4096 -> 12)
 	TInt iMediaChanges;
 #endif
 	};
@@ -259,7 +260,6 @@
 
 #endif	// __DEMAND_PAGING__
 
-
 /********************************************
  * Local drive device base class
  ********************************************/
@@ -1377,6 +1377,10 @@
 	RemoteDes()=(TAny*)d.iPtr;
 	RemoteDesOffset()=d.iOffset;
 	DriverFlags()=d.iFlags;
+	
+	// EPhysAddrOnly should not be set for client requests
+	Flags() &= ~TLocDrvRequest::EPhysAddrOnly;
+	
 	if (Pos()<0 || Length()<0)
 	    {
 		OstTraceFunctionExitExt( TLOCDRVREQUEST_PROCESSMESSAGEDATA_EXIT2, this, KErrArgument );
@@ -1640,6 +1644,7 @@
 #ifdef __DEMAND_PAGING__
 	TInt pageSize = Kern::RoundToPageSize(1);
 	iBody->iPageSizeMsk = pageSize-1;
+	iBody->iPageSizeLog2 = __e32_find_ms1_32(pageSize);
 #endif
 
 	iLastMediaId=aLastMediaId;
@@ -3615,19 +3620,15 @@
 void DPrimaryMediaBase::RequestCountInc()
 	{
 	__ASSERT_DEBUG(iBody, LOCM_FAULT());
-	if (iBody->iPagingDevice)
+	TInt oldVal = (TInt) __e32_atomic_add_ord32(&iBody->iRequestCount, (TUint) 1);
+//Kern::Printf("RCINC: this %x cnt %d, old %d", this, iBody->iRequestCount, oldVal);
+	
+	OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_REQUESTCOUNTINC, "new count=%d; old count=%d", iBody->iRequestCount, oldVal );
+	
+	if (oldVal == 0 && iBody->iPagingDevice)
 		{
-		NFastMutex* lock = iBody->iPagingDevice->NotificationLock();
-		NKern::FMWait(lock);
-		TInt oldVal = iBody->iRequestCount++;
-		//Kern::Printf("RCINC: this %x cnt %d, old %d", this, iBody->iRequestCount, oldVal);
-		OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_REQUESTCOUNTINC, "new count=%d; old count=%d", iBody->iRequestCount, oldVal );
-		if (oldVal == 0)
-			{
-			//Kern::Printf("RCINC: NotifyBusy()");
-			iBody->iPagingDevice->NotifyBusy();
-			}
-		NKern::FMSignal(lock);
+//Kern::Printf("RCINC: NotifyBusy()");
+		iBody->iPagingDevice->NotifyBusy();
 		}
 	}
 
@@ -3639,21 +3640,17 @@
 void DPrimaryMediaBase::RequestCountDec()
 	{
 	__ASSERT_DEBUG(iBody, LOCM_FAULT());
-	if (iBody->iPagingDevice)
+	TInt oldVal = (TInt) __e32_atomic_add_ord32(&iBody->iRequestCount, (TUint) -1);
+//Kern::Printf("RCDEC: this %x cnt %d, old %d", this, iBody->iRequestCount, oldVal);
+	
+	OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_REQUESTCOUNTDEC, "new count=%d; old count=%d", iBody->iRequestCount, oldVal );
+	
+	if (oldVal == 1 && iBody->iPagingDevice)
 		{
-		NFastMutex* lock = iBody->iPagingDevice->NotificationLock();
-		NKern::FMWait(lock);
-		TInt oldVal = iBody->iRequestCount--;
-		//Kern::Printf("RCDEC: this %x cnt %d, old %d", this, iBody->iRequestCount, oldVal);
-		OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_REQUESTCOUNTDEC, "new count=%d; old count=%d", iBody->iRequestCount, oldVal );
-		if (oldVal == 1)
-			{
-			//Kern::Printf("RCDEC: NotifyIdle()");
-			iBody->iPagingDevice->NotifyIdle();
-			}		
-		NKern::FMSignal(lock);
-		__ASSERT_DEBUG(iBody->iRequestCount >= 0, LOCM_FAULT());
+//Kern::Printf("RCDEC: NotifyIdle()");
+		iBody->iPagingDevice->NotifyIdle();
 		}
+	__ASSERT_DEBUG(iBody->iRequestCount >= 0, LOCM_FAULT());
 	}
 #endif	// __DEMAND_PAGING__
 
@@ -3776,19 +3773,23 @@
 	TInt len = I64LOW(m.Length());
 
 	TBool needSyncAfterRead = EFalse;
-	if (m.Drive()->iDmaHelper)
-		{
-		m.Flags() |= TLocDrvRequest::EPhysAddr;
-		if (m.Id() == DLocalDrive::EWrite)
-			{
-			Cache::SyncMemoryBeforeDmaWrite(addr, len);
-			}
-		else
-			{
-			Cache::SyncMemoryBeforeDmaRead(addr, len);
-			needSyncAfterRead = ETrue;
-			}
-		}
+    if (m.Drive()->iDmaHelper)
+        {        
+        m.Flags() |= TLocDrvRequest::EPhysAddr;
+        // don't cache sync for zero mapping...
+        if (!(m.Flags() & TLocDrvRequest::EPhysAddrOnly))
+            {
+            if (m.Id() == DLocalDrive::EWrite)
+                {
+                Cache::SyncMemoryBeforeDmaWrite(addr, len);
+                }
+            else
+                {
+                Cache::SyncMemoryBeforeDmaRead(addr, len);
+                needSyncAfterRead = ETrue;
+                }
+            }
+	    }
 
 	// Count the number of outstanding requests if this is the data-paging media, so that
 	// we can call DPagingDevice::NotifyBusy() / DPagingDevice::NotifyIdle()
@@ -3845,6 +3846,17 @@
 	}
 
 TInt DMediaPagingDevice::Read(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TInt aDrvNumber)
+    {
+    return BaseRead(aReq,(TUint32)aBuffer,aOffset,aSize,aDrvNumber,EFalse);
+    }
+
+TInt DMediaPagingDevice::ReadPhysical(TThreadMessage* aReq, TPhysAddr* aPageArray, TUint aPageCount, TUint aOffset, TInt aDrvNumber)
+    {    
+    TUint adjSize = (aPageCount << iPrimaryMedia->iBody->iPageSizeLog2) >> iReadUnitShift; // translate to Read Units
+    return BaseRead(aReq,(TUint32)aPageArray,aOffset,adjSize,aDrvNumber,ETrue);
+    }
+
+TInt DMediaPagingDevice::BaseRead(TThreadMessage* aReq,TUint32 aBuffer,TUint aOffset,TUint aSize,TInt aDrvNumber, TBool aPhysAddr)
 	{
 	OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_READ_ENTRY, this );
 	__ASSERT_ALWAYS(NKern::CurrentThread()!=iPrimaryMedia->iDfcQ->iThread,LOCM_FAULT());	// that would lock up the system, thus better die now
@@ -3993,7 +4005,10 @@
 		m.Length()=Int64(size);
 		m.RemoteDes()=(TAny*)aBuffer;
 		m.RemoteDesOffset()=0;		// pre-aligned
-		m.DriverFlags()=0;
+		m.DriverFlags() = 0;
+		if (aPhysAddr)
+		    m.Flags() |= TLocDrvRequest::EPhysAddrOnly;
+
 		__KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("ReqId=%d, Pos=0x%lx, Len=0x%lx, remote Des 0x%x",m.Id(),m.Pos(),m.Length(),m.RemoteDes()));
 		OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_READ2, "reqId=%d; position=0x%lx; length=0x%x; remote Des=0x%x", (TInt) m.Id(), (TUint) m.Pos(), (TUint) m.Length(), (TUint) m.RemoteDes());
 		
@@ -4041,7 +4056,18 @@
 	}
 
 TInt DMediaPagingDevice::Write(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TBool aBackground)
+    {
+    return BaseWrite(aReq,(TUint32)aBuffer,aOffset,aSize,aBackground,EFalse);
+    }
+
+TInt DMediaPagingDevice::WritePhysical(TThreadMessage* aReq, TPhysAddr* aPageArray, TUint aPageCount, TUint aOffset, TBool aBackground)
 	{
+    TUint adjSize = (aPageCount << iPrimaryMedia->iBody->iPageSizeLog2) >> iReadUnitShift; // translate to Read Units
+    return BaseWrite(aReq,(TUint32)aPageArray,aOffset,adjSize,aBackground,ETrue);
+	}
+
+TInt DMediaPagingDevice::BaseWrite(TThreadMessage* aReq,TUint32 aBuffer,TUint aOffset,TUint aSize,TBool aBackground, TBool aPhysAddr)
+    {
 	OstTraceFunctionEntry1( DMEDIAPAGINGDEVICE_WRITE_ENTRY, this );
 	__ASSERT_ALWAYS(NKern::CurrentThread()!=iPrimaryMedia->iDfcQ->iThread,LOCM_FAULT());	// that would lock up the system, thus better die now
 	__ASSERT_ALWAYS(aReq,LOCM_FAULT());
@@ -4101,7 +4127,10 @@
 	TInt retVal = KErrGeneral;
 	for (TInt i=0; retVal != KErrNone && i < KPageOutRetries; i++)
 		{
-		m.Flags() = TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging | (aBackground ? TLocDrvRequest::EBackgroundPaging : 0);
+		m.Flags() = TLocDrvRequest::EPaging | 
+                    TLocDrvRequest::EDataPaging | 
+                    (aBackground ? TLocDrvRequest::EBackgroundPaging : 0) |
+                    (aPhysAddr ? TLocDrvRequest::EPhysAddrOnly : 0);
 
 		m.Id() = DLocalDrive::EWrite;
 		m.Drive() = TheDrives[iDataPagingDriveNumber];
@@ -4111,7 +4140,8 @@
 		m.Length()=Int64(size);
 		m.RemoteDes()=(TAny*)aBuffer;
 		m.RemoteDesOffset()=0;		// pre-aligned
-		m.DriverFlags()=0;
+		m.DriverFlags() = 0;        
+
 		__KTRACE_OPT2(KLOCDRV,KLOCDPAGING,Kern::Printf("ReqId=%d, Pos=0x%lx, Len=0x%lx, remote Des 0x%x",m.Id(),m.Pos(),m.Length(),m.RemoteDes()));
 		OstTraceDefExt4(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DMEDIAPAGINGDEVICE_WRITE2, "reqId=%d; position=0x%lx; length=0x%lx; remote Des=0x%x", (TInt) m.Id(), (TUint) m.Pos(), (TUint) m.Length(), (TUint) m.RemoteDes());
 		
@@ -4820,8 +4850,6 @@
 		return KErrArgument;
 		}
 
-
-
 	for(i=0; i<KMaxLocalDrives; i++)
 		{
 		if (ThePagingDevices[i] == NULL)
@@ -4899,6 +4927,8 @@
 
 	TInt dataPagingDriveNumber = KErrNotFound;
 	TInt swapSize = 0;
+	TInt blockSize = 0;
+	TUint16 flags = 0;
 
 	// find the local drive assocated with the primary media
 	for (i=0; i<KMaxLocalDrives; ++i)
@@ -4929,9 +4959,10 @@
 
 
 		TLocDrvRequest m;
+        TBuf8<KMaxLocalDriveCapsLength> capsBuf;
+        
 		memclr(&m, sizeof(m));
 		
-
 		// Get the Caps from the device. NB for MMC/SD we may need to retry as some PSLs start up
 		// in "door open" or "media not present" state which can result in the cancellation of requests
 		TInt i;
@@ -4939,7 +4970,6 @@
 		TInt r = KErrNotReady;
 		for (i=0; r == KErrNotReady && i < KRetries; i++)
 			{
-			TBuf8<KMaxLocalDriveCapsLength> capsBuf;
 			capsBuf.SetMax();
 			capsBuf.FillZ();
 			m.Drive() = TheDrives[firstLocalDriveNumber];
@@ -4961,6 +4991,9 @@
 			return KErrNotSupported;
 		    }
 
+		TLocalDriveCapsV6& caps = *(TLocalDriveCapsV6*)capsBuf.Ptr();
+		blockSize = caps.iBlockSize;
+		
 		TLocDrv* drive;
 		for (i=0; i<KMaxLocalDrives; ++i)
 			{
@@ -4982,6 +5015,10 @@
 					OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE6, "Found SWAP partition on local drive=%d; size=0x%x", (TInt) i, (TUint) I64LOW(drive->iPartitionLen) );			
 					dataPagingDriveNumber = i;
 					swapSize = drive->iPartitionLen >> aReadShift;
+					
+			        // Mark Paging Device capable of utilising physical addresss only accesses
+			        if (drive->iDmaHelper)
+			            flags |= DPagingDevice::ESupportsPhysicalAccess;  
 					}
 				}
 			}
@@ -5006,6 +5043,7 @@
 		}
 
 	pagingDevice->iType = aPagingType;
+	pagingDevice->iFlags = flags;
 	pagingDevice->iReadUnitShift = aReadShift;
 
 	pagingDevice->iFirstLocalDriveNumber = firstLocalDriveNumber;
@@ -5013,15 +5051,19 @@
 
 	pagingDevice->iDataPagingDriveNumber = dataPagingDriveNumber;
 	pagingDevice->iSwapSize = swapSize;
+		
+	pagingDevice->iPreferredWriteShift = (blockSize) ? __e32_find_ms1_32(blockSize) : 0;
 
 #ifdef __DEBUG_DEMAND_PAGING__
 	Kern::Printf("PagingDevice :");
 	Kern::Printf("iType 0x%x\n", pagingDevice->iType);
+	Kern::Printf("iFlags 0x%x\n", pagingDevice->iFlags);
 	Kern::Printf("iReadUnitShift 0x%x\n", pagingDevice->iReadUnitShift);
 	Kern::Printf("iFirstLocalDriveNumber 0x%x\n", pagingDevice->iFirstLocalDriveNumber);
 	Kern::Printf("iRomPagingDriveNumber 0x%x\n", pagingDevice->iRomPagingDriveNumber);
 	Kern::Printf("iDataPagingDriveNumber 0x%x\n", pagingDevice->iDataPagingDriveNumber);
 	Kern::Printf("iSwapSize 0x%x\n", pagingDevice->iSwapSize);
+	Kern::Printf("iPreferredWriteShift 0x%x\n", pagingDevice->iPreferredWriteShift);
 #endif