kernel/eka/drivers/locmedia/dmasupport.cpp
changeset 13 46fffbe7b5a7
parent 9 96e5fb8b040d
child 28 5b5d147c7838
equal deleted inserted replaced
12:0bf4040442f9 13:46fffbe7b5a7
    19 #include <kernel/cache.h>
    19 #include <kernel/cache.h>
    20 #include "locmedia.h"
    20 #include "locmedia.h"
    21 #include "dmasupport.h"
    21 #include "dmasupport.h"
    22 #include "dmasupport.inl"
    22 #include "dmasupport.inl"
    23 
    23 
       
    24 #include "OstTraceDefinitions.h"
       
    25 #ifdef OST_TRACE_COMPILER_IN_USE
       
    26 #include "locmedia_ost.h"
       
    27 #ifdef __VC32__
       
    28 #pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
       
    29 #endif
       
    30 #include "dmasupportTraces.h"
       
    31 #endif
       
    32 
    24 #define PHYSADDR_FAULT()	Kern::Fault("TLOCDRV-PHYS-ADDR",__LINE__)
    33 #define PHYSADDR_FAULT()	Kern::Fault("TLOCDRV-PHYS-ADDR",__LINE__)
    25 
    34 
    26 //#define __DEBUG_DMASUP__
    35 //#define __DEBUG_DMASUP__
    27 #ifdef __DEBUG_DMASUP__
    36 #ifdef __DEBUG_DMASUP__
    28 #define __KTRACE_DMA(p) {p;}
    37 #define __KTRACE_DMA(p) {p;}
    68 	iFragLenRemaining = 0;
    77 	iFragLenRemaining = 0;
    69 	}
    78 	}
    70 
    79 
    71 DDmaHelper::DDmaHelper()
    80 DDmaHelper::DDmaHelper()
    72 	{
    81 	{
       
    82 	OstTraceFunctionEntry0( DDMAHELPER_DDMAHELPER_ENTRY );
    73 	iPageSize = Kern::RoundToPageSize(1);
    83 	iPageSize = Kern::RoundToPageSize(1);
    74 	__ASSERT_ALWAYS(IsPowerOfTwo(iPageSize), PHYSADDR_FAULT());
    84 	__ASSERT_ALWAYS(IsPowerOfTwo(iPageSize), PHYSADDR_FAULT());
    75 	iPageSizeLog2 = Log2(iPageSize);
    85 	iPageSizeLog2 = Log2(iPageSize);
    76 	iPageSizeMsk = iPageSize-1;
    86 	iPageSizeMsk = iPageSize-1;
       
    87 	OstTraceFunctionExit0( DDMAHELPER_DDMAHELPER_EXIT );
    77 	}
    88 	}
    78 
    89 
    79 DDmaHelper::~DDmaHelper()
    90 DDmaHelper::~DDmaHelper()
    80 	{
    91 	{
       
    92 	OstTraceFunctionEntry0( DESTRUCTOR_DDMAHELPER_ENTRY );
    81 	delete [] iPageArray;
    93 	delete [] iPageArray;
    82 	delete [] iPageList;
    94 	delete [] iPageList;
    83 	if (iPhysicalPinObject)
    95 	if (iPhysicalPinObject)
    84 		{
    96 		{
    85 		NKern::ThreadEnterCS();
    97 		NKern::ThreadEnterCS();
    86 		Kern::DestroyPhysicalPinObject(iPhysicalPinObject);
    98 		Kern::DestroyPhysicalPinObject(iPhysicalPinObject);
    87 		NKern::ThreadLeaveCS();
    99 		NKern::ThreadLeaveCS();
    88 		}
   100 		}
       
   101 	OstTraceFunctionExit0( DESTRUCTOR_DDMAHELPER_EXIT );
    89 	}
   102 	}
    90 
   103 
    91 /**
   104 /**
    92 Constructs the DDmaHelper object 
   105 Constructs the DDmaHelper object 
    93 
   106 
    99 @return KErrNone,if successful;
   112 @return KErrNone,if successful;
   100 		KErrNoMemory, if unable to create Page Array's.
   113 		KErrNoMemory, if unable to create Page Array's.
   101 */
   114 */
   102 TInt DDmaHelper::Construct(TInt aLength, TInt aMediaBlockSize, TInt aDmaAlignment)
   115 TInt DDmaHelper::Construct(TInt aLength, TInt aMediaBlockSize, TInt aDmaAlignment)
   103 	{
   116 	{
       
   117 	OstTraceFunctionEntry1( DDMAHELPER_CONSTRUCT_ENTRY, this );
   104 	__ASSERT_ALWAYS(aMediaBlockSize > 0, PHYSADDR_FAULT());
   118 	__ASSERT_ALWAYS(aMediaBlockSize > 0, PHYSADDR_FAULT());
   105 	__ASSERT_ALWAYS(IsPowerOfTwo(aMediaBlockSize), PHYSADDR_FAULT());
   119 	__ASSERT_ALWAYS(IsPowerOfTwo(aMediaBlockSize), PHYSADDR_FAULT());
   106 	__ASSERT_ALWAYS(aLength > 0, PHYSADDR_FAULT());
   120 	__ASSERT_ALWAYS(aLength > 0, PHYSADDR_FAULT());
   107 	__ASSERT_ALWAYS(aLength > iPageSize, PHYSADDR_FAULT());
   121 	__ASSERT_ALWAYS(aLength > iPageSize, PHYSADDR_FAULT());
   108 
   122 
   112 	// buffer & then calling Cache::SyncMemoryAfterDmaRead would invalidate an entire 1024 
   126 	// buffer & then calling Cache::SyncMemoryAfterDmaRead would invalidate an entire 1024 
   113 	// bytes in the user's address space.
   127 	// bytes in the user's address space.
   114 	TUint cacheLineSize = Cache::DmaBufferAlignment();
   128 	TUint cacheLineSize = Cache::DmaBufferAlignment();
   115 	__ASSERT_ALWAYS(IsPowerOfTwo(cacheLineSize), PHYSADDR_FAULT());
   129 	__ASSERT_ALWAYS(IsPowerOfTwo(cacheLineSize), PHYSADDR_FAULT());
   116 	if (cacheLineSize > (TUint) aMediaBlockSize)
   130 	if (cacheLineSize > (TUint) aMediaBlockSize)
       
   131 	    {
       
   132 		OstTraceFunctionExitExt( DDMAHELPER_CONSTRUCT_EXIT1, this, KErrNotSupported );
   117 		return KErrNotSupported;
   133 		return KErrNotSupported;
   118 
   134 	    }
       
   135 	
   119 	//Check whether Kernel supports physical memory pinning:
   136 	//Check whether Kernel supports physical memory pinning:
   120 	TInt mm = Kern::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, 0, 0) & EMemModelTypeMask;
   137 	TInt mm = Kern::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, 0, 0) & EMemModelTypeMask;
   121 	if (mm >= EMemModelTypeFlexible)
   138 	if (mm >= EMemModelTypeFlexible)
   122 		{
   139 		{
   123 		// Flexible memory model supports physical pinning for user (and Kernel) memory that
   140 		// Flexible memory model supports physical pinning for user (and Kernel) memory that
   130 		// Cache Sync of physically pinned memory on flexible memory model is done by:
   147 		// Cache Sync of physically pinned memory on flexible memory model is done by:
   131 		//  - Cache::SyncPhysicalMemoryBeforeDmaWrite
   148 		//  - Cache::SyncPhysicalMemoryBeforeDmaWrite
   132 		//  - Cache::SyncPhysicalMemoryBeforeDmaRead
   149 		//  - Cache::SyncPhysicalMemoryBeforeDmaRead
   133 		//  - Cache::SyncPhysicalMemoryAfterDmaRead
   150 		//  - Cache::SyncPhysicalMemoryAfterDmaRead
   134 		iPhysPinningAvailable = ETrue;
   151 		iPhysPinningAvailable = ETrue;
   135 		__KTRACE_DMA(Kern::Printf("Memory model (%d) supports physical pining\n",mm));
   152 		__KTRACE_DMA(Kern::Printf("Memory model (%d) supports physical pinning\n",mm));
   136 		NKern::ThreadEnterCS();
   153 		NKern::ThreadEnterCS();
   137 		TInt r=Kern::CreatePhysicalPinObject(iPhysicalPinObject);
   154 		TInt r=Kern::CreatePhysicalPinObject(iPhysicalPinObject);
       
   155 		OstTraceExt2(TRACE_DMASUPPORT, DDMAHELPER_CONSTRUCT1, "Memory model=%d supports physical pinning; created Physical Pin Object with return value=%d",mm, r);
   138 		NKern::ThreadLeaveCS();
   156 		NKern::ThreadLeaveCS();
   139 		if (r) return r;
   157 		if (r) return r;
   140 		}
   158 		}
   141 	else
   159 	else
   142 		{
   160 		{
   154 		//  - Cache::SyncMemoryBeforeDmaRead
   172 		//  - Cache::SyncMemoryBeforeDmaRead
   155 		//  - Cache::SyncMemoryAfterDmaRead
   173 		//  - Cache::SyncMemoryAfterDmaRead
   156 		// As they all require linear address as input, these methods also rely on File System buffers
   174 		// As they all require linear address as input, these methods also rely on File System buffers
   157 		// to be in valid state during sync calls.
   175 		// to be in valid state during sync calls.
   158 		iPhysPinningAvailable = EFalse;
   176 		iPhysPinningAvailable = EFalse;
   159 		__KTRACE_DMA(Kern::Printf("Memory model (%d) doesn't support physical pining\n",mm));
   177 		__KTRACE_DMA(Kern::Printf("Memory model (%d) doesn't support physical pining",mm));
       
   178 		OstTrace1(TRACE_DMASUPPORT, DDMAHELPER_CONSTRUCT2, "Memory model=%d doesn't support physical pinning",mm);
   160 		iPhysicalPinObject = NULL;
   179 		iPhysicalPinObject = NULL;
   161 		}
   180 		}
   162 	
   181 	
   163 	iMaxPages = (aLength >> iPageSizeLog2)-1;
   182 	iMaxPages = (aLength >> iPageSizeLog2)-1;
   164 	
   183 	
   172 			iMediaBlockSize = aMediaBlockSize;
   191 			iMediaBlockSize = aMediaBlockSize;
   173 			iMediaBlockSizeMask = TInt64(iMediaBlockSize - 1);
   192 			iMediaBlockSizeMask = TInt64(iMediaBlockSize - 1);
   174 
   193 
   175 			iDmaAlignment = aDmaAlignment;
   194 			iDmaAlignment = aDmaAlignment;
   176 			__KTRACE_DMA(Kern::Printf("-PHYSADDR: Construct iMaxPages(%d), MediaBlocks(%d), DMAalign(%d)",iMaxPages,iMediaBlockSize,iDmaAlignment));
   195 			__KTRACE_DMA(Kern::Printf("-PHYSADDR: Construct iMaxPages(%d), MediaBlocks(%d), DMAalign(%d)",iMaxPages,iMediaBlockSize,iDmaAlignment));
       
   196 			OstTraceExt3(TRACE_FLOW, DDMAHELPER_CONSTRUCT_EXIT2, "< KErrNone PHYSADDR: Construct iMaxPages %d MediaBlocks %d DMAalign %d", iMaxPages,iMediaBlockSize,iDmaAlignment );
   177 			return KErrNone;
   197 			return KErrNone;
   178 			}
   198 			}
   179 		delete [] iPageArray; iPageArray = NULL;
   199 		delete [] iPageArray; iPageArray = NULL;
   180 		}
   200 		}
   181 	
   201 	
   182 	iMaxPages = 0;
   202 	iMaxPages = 0;
       
   203 	OstTraceFunctionExitExt( DDMAHELPER_CONSTRUCT_EXIT3, this, KErrNoMemory );
   183 	return KErrNoMemory;
   204 	return KErrNoMemory;
   184 	}
   205 	}
   185 
   206 
   186 /**
   207 /**
   187  * Each Read/Write request is examined to determine if the descriptor that 
   208  * Each Read/Write request is examined to determine if the descriptor that 
   191  * If a request does not make use of physical memory or is not configured correctly the
   212  * If a request does not make use of physical memory or is not configured correctly the
   192  * request is passed through without modification.
   213  * request is passed through without modification.
   193  */
   214  */
   194 TInt DDmaHelper::SendReceive(TLocDrvRequest& aReq, TLinAddr aLinAddress)
   215 TInt DDmaHelper::SendReceive(TLocDrvRequest& aReq, TLinAddr aLinAddress)
   195 	{
   216 	{
       
   217 	OstTraceFunctionEntry0( DDMAHELPER_SENDRECEIVE_ENTRY );
   196 	DPrimaryMediaBase& primaryMedia = *aReq.Drive()->iPrimaryMedia;
   218 	DPrimaryMediaBase& primaryMedia = *aReq.Drive()->iPrimaryMedia;
   197 
   219 	
   198 	TInt reqId = aReq.Id();
   220 	TInt reqId = aReq.Id();
   199 	if (reqId != DLocalDrive::ERead && reqId != DLocalDrive::EWrite)
   221 	if (reqId != DLocalDrive::ERead && reqId != DLocalDrive::EWrite)
       
   222 	    {
       
   223 	    OstTrace0(TRACE_FLOW, DDMAHELPER_SENDRECEIVE_EXIT1, "< Request is not ERead or EWrite, cannot perform Direct Memory Access");
   200 		return aReq.SendReceive(&primaryMedia.iMsgQ);
   224 		return aReq.SendReceive(&primaryMedia.iMsgQ);
   201 
   225 	    }
       
   226 		
   202 	if ((I64HIGH(aReq.Length()) > 0) || (aReq.Length() < iMediaBlockSize))
   227 	if ((I64HIGH(aReq.Length()) > 0) || (aReq.Length() < iMediaBlockSize))
       
   228 	    {
       
   229 	    OstTrace0(TRACE_FLOW, DDMAHELPER_SENDRECEIVE_EXIT2, "< Invalid request length, cannot perform Direct Memory Access");
   203 		return aReq.SendReceive(&primaryMedia.iMsgQ);
   230 		return aReq.SendReceive(&primaryMedia.iMsgQ);
   204 
   231 	    }
       
   232 	
   205 	// If more than one user thread tries to access the drive, then bail out as there is 
   233 	// If more than one user thread tries to access the drive, then bail out as there is 
   206 	// only one DDmaHelper object per TLocDrv. Normally this shouldn't ever happen unless
   234 	// only one DDmaHelper object per TLocDrv. Normally this shouldn't ever happen unless
   207 	// a client app accesses the drive directly using TBusLOcalDrive or the file system is 
   235 	// a client app accesses the drive directly using TBusLOcalDrive or the file system is 
   208 	// asynchronous (i.e. there is a separate drive thread) but the file server message is 
   236 	// asynchronous (i.e. there is a separate drive thread) but the file server message is 
   209 	// flagged as synchronous - e.g. EFsDrive
   237 	// flagged as synchronous - e.g. EFsDrive
   210 	if (TInt(__e32_atomic_add_ord32(&iLockCount, 1)) > 0)	// busy ?
   238 	if (TInt(__e32_atomic_add_ord32(&iLockCount, 1)) > 0)	// busy ?
   211 		{
   239 		{
   212 		__KTRACE_DMA(Kern::Printf("-PHYSADDR: BUSY"));
   240 		__KTRACE_DMA(Kern::Printf("-PHYSADDR: BUSY"));
   213 		__e32_atomic_add_ord32(&iLockCount, TUint32(-1));
   241 		__e32_atomic_add_ord32(&iLockCount, TUint32(-1));
       
   242 		OstTrace0(TRACE_FLOW, DDMAHELPER_SENDRECEIVE_EXIT3, "< DMA Busy");
   214 		return aReq.SendReceive(&primaryMedia.iMsgQ);
   243 		return aReq.SendReceive(&primaryMedia.iMsgQ);
   215 		}
   244 		}
   216 
   245 
   217 	// make a copy of the request 
   246 	// make a copy of the request 
   218 	iMemoryType = EUnknown;
   247 	iMemoryType = EUnknown;
   248 	TInt fragments = 0;
   277 	TInt fragments = 0;
   249 	TInt r;
   278 	TInt r;
   250 	do
   279 	do
   251 		{
   280 		{
   252 		__KTRACE_DMA(Kern::Printf(">PHYSADDR:SendReceive() iReqLen %d; iLenConsumed %d; fragments %d",iReqLen, iLenConsumed, fragments));
   281 		__KTRACE_DMA(Kern::Printf(">PHYSADDR:SendReceive() iReqLen %d; iLenConsumed %d; fragments %d",iReqLen, iLenConsumed, fragments));
       
   282 		OstTraceExt2( TRACE_DMASUPPORT, DDMAHELPER_SENDRECEIVE1, "PHYSADDR:SendReceive() iLenConsumed=%d; fragments=%d", iLenConsumed, fragments);
   253 		r = RequestStart();
   283 		r = RequestStart();
   254 		if (r != KErrNone)
   284 		if (r != KErrNone)
   255 			{
   285 			{
   256 			if (iChunk)
   286 			if (iChunk)
   257 				{
   287 				{
   259 				Kern::ChunkClose(iChunk);
   289 				Kern::ChunkClose(iChunk);
   260 				iChunk = NULL;
   290 				iChunk = NULL;
   261 				NKern::ThreadLeaveCS();
   291 				NKern::ThreadLeaveCS();
   262 				}
   292 				}
   263 			__KTRACE_DMA(Kern::Printf("<PHYSADDR:SendReceive()- r:%d",r));
   293 			__KTRACE_DMA(Kern::Printf("<PHYSADDR:SendReceive()- r:%d",r));
       
   294 			OstTrace1( TRACE_FLOW, DDMAHELPER_SENDRECEIVE_EXIT4, "< PHYSADDR:SendReceive() Return code %d",r);
   264 			iMemoryType = EUnknown;
   295 			iMemoryType = EUnknown;
   265 			__e32_atomic_add_ord32(&iLockCount, TUint32(-1));
   296 			__e32_atomic_add_ord32(&iLockCount, TUint32(-1));
   266 			return fragments ? r : iReq->SendReceive(&primaryMedia.iMsgQ);
   297 			return fragments ? r : iReq->SendReceive(&primaryMedia.iMsgQ);
   267 			}
   298 			}
   268 		else
   299 		else
   270 			iReq->Flags() |= TLocDrvRequest::EPhysAddr;
   301 			iReq->Flags() |= TLocDrvRequest::EPhysAddr;
   271 			}
   302 			}
   272 
   303 
   273 		__KTRACE_DMA(Kern::Printf("-PHYSADDR:SendReceive() rThread %08X pos %08lX, len %d addr %08X off %08X", 
   304 		__KTRACE_DMA(Kern::Printf("-PHYSADDR:SendReceive() rThread %08X pos %08lX, len %d addr %08X off %08X", 
   274 				iRemoteThread, iReq->Pos(), I64LOW(iReq->Length()), iLinAddressUser, iReqRemoteDesOffset));
   305 				iRemoteThread, iReq->Pos(), I64LOW(iReq->Length()), iLinAddressUser, iReqRemoteDesOffset));
       
   306 		OstTraceExt4(TRACE_DMASUPPORT, DDMAHELPER_SENDRECEIVE2, "PHYSADDR:SendReceive() position=%Ld; length=%d; address=0x%x; offset=0x%x", iReq->Pos(), (TInt) I64LOW(iReq->Length()), (TUint) iLinAddressUser, (TUint) iReqRemoteDesOffset );
   275 		
   307 		
   276 		__ASSERT_DEBUG(iReq->Length() == FragLength(), PHYSADDR_FAULT());
   308 		__ASSERT_DEBUG(iReq->Length() == FragLength(), PHYSADDR_FAULT());
   277 		__ASSERT_DEBUG(iReq->Length() != 0, PHYSADDR_FAULT());
   309 		__ASSERT_DEBUG(iReq->Length() != 0, PHYSADDR_FAULT());
   278 
   310 
   279 		// reinstate iValue in case overwritten by DMediaPagingDevice::CompleteRequest()
   311 		// reinstate iValue in case overwritten by DMediaPagingDevice::CompleteRequest()
   280 		iReq->iValue = iReqId;
   312 		iReq->iValue = iReqId;
   281 
   313 		
       
   314 		OstTrace1(TRACE_DMASUPPORT, DDMAHELPER_SENDRECEIVE3, "Dma SendReceive Start iReq=%d", iReq);
   282 		r = iReq->SendReceive(&primaryMedia.iMsgQ);
   315 		r = iReq->SendReceive(&primaryMedia.iMsgQ);
       
   316 		OstTrace1(TRACE_DMASUPPORT, DDMAHELPER_SENDRECEIVE4, "Dma SendReceive Return iReq=%d", iReq);
   283 		
   317 		
   284 		// The media driver could potentially choose to deal with the request 
   318 		// The media driver could potentially choose to deal with the request 
   285 		// without accessing physical memory (e.g. if the data is already cached).
   319 		// without accessing physical memory (e.g. if the data is already cached).
   286 		iLenConsumed += iFragLenRemaining;
   320 		iLenConsumed += iFragLenRemaining;
   287 				
   321 				
   309 	__KTRACE_DMA(Kern::Printf("<PHYSADDR:SendReceive()"));
   343 	__KTRACE_DMA(Kern::Printf("<PHYSADDR:SendReceive()"));
   310 
   344 
   311 	iMemoryType = EUnknown;
   345 	iMemoryType = EUnknown;
   312 
   346 
   313 	__e32_atomic_add_ord32(&iLockCount, TUint32(-1));
   347 	__e32_atomic_add_ord32(&iLockCount, TUint32(-1));
       
   348 	OstTraceFunctionExit0( DDMAHELPER_SENDRECEIVE_EXIT5 );
   314 	return r;
   349 	return r;
   315 	}
   350 	}
   316 
   351 
   317 
   352 
   318 /**
   353 /**
   334  * then they are supplied to the media driver one contiguous 
   369  * then they are supplied to the media driver one contiguous 
   335  * sequent at a time by GetPhysicalAddress()
   370  * sequent at a time by GetPhysicalAddress()
   336  **/
   371  **/
   337 TInt DDmaHelper::RequestStart()
   372 TInt DDmaHelper::RequestStart()
   338 	{
   373 	{
       
   374 	OstTraceFunctionEntry1( DDMAHELPER_REQUESTSTART_ENTRY, this );
   339 	__KTRACE_DMA(Kern::Printf(">PHYSADDR:RequestStart()"));
   375 	__KTRACE_DMA(Kern::Printf(">PHYSADDR:RequestStart()"));
       
   376 
   340 	iIndex = 0;
   377 	iIndex = 0;
   341 
   378 
   342 	TLinAddr startAddr = LinAddress();
   379 	TLinAddr startAddr = LinAddress();
   343 	TInt64 startPos = iReqPosClient + iLenConsumed;
   380 	TInt64 startPos = iReqPosClient + iLenConsumed;
   344 	TInt mediaBlockOffset = BlockOffset(startPos);
   381 	TInt mediaBlockOffset = BlockOffset(startPos);
   364 		ofset = iMediaBlockSize - ofset;
   401 		ofset = iMediaBlockSize - ofset;
   365 
   402 
   366 		if (!IsDmaAligned(startAddr))
   403 		if (!IsDmaAligned(startAddr))
   367 			{			
   404 			{			
   368 			__KTRACE_DMA(Kern::Printf("<PHYSADDR:RequestStart() - not DMA Aligned pos 0x%x addr 0x%x)",I64LOW(startPos), startAddr));
   405 			__KTRACE_DMA(Kern::Printf("<PHYSADDR:RequestStart() - not DMA Aligned pos 0x%x addr 0x%x)",I64LOW(startPos), startAddr));
       
   406 			OstTraceExt2( TRACE_FLOW, DDMAHELPER_REQUESTSTART_EXIT1, "< KErrNotSupported Not DMA Aligned startPos %x startAddr %x", I64LOW(startPos), startAddr );
   369 			return KErrNotSupported;
   407 			return KErrNotSupported;
   370 			}
   408 			}
   371 		}
   409 		}
   372 	else 
   410 	else 
   373 		{ //block aligned!
   411 		{ //block aligned!
   374 		if (!IsDmaAligned(startAddr))
   412 		if (!IsDmaAligned(startAddr))
   375 			{
   413 			{
   376 			__KTRACE_DMA(Kern::Printf("<PHYSADDR:RequestStart() - not DMA Aligned (0x%x)",startAddr));
   414 			__KTRACE_DMA(Kern::Printf("<PHYSADDR:RequestStart() - not DMA Aligned (0x%x)",startAddr));
       
   415 			OstTrace1(TRACE_FLOW, DDMAHELPER_REQUESTSTART_EXIT2, "< KErrNotSupported Not DMA Aligned startAddr %x", startAddr);
   377 			return KErrNotSupported;
   416 			return KErrNotSupported;
   378 			}
   417 			}
   379 		}
   418 		}
   380 
   419 
   381 	//************************************************
   420 	//************************************************
   383 	// i.e. Media blocks which may straddle 2 non contiguous pages. 
   422 	// i.e. Media blocks which may straddle 2 non contiguous pages. 
   384 	//************************************************
   423 	//************************************************
   385 	if (mediaBlockOffset != addrBlockOffset)
   424 	if (mediaBlockOffset != addrBlockOffset)
   386 		{
   425 		{
   387 		__KTRACE_DMA(Kern::Printf("<PHYSADDR:RequestStart() - Frag / not block aligned: pos 0x%x addr 0x%x", I64LOW(startPos), startAddr));
   426 		__KTRACE_DMA(Kern::Printf("<PHYSADDR:RequestStart() - Frag / not block aligned: pos 0x%x addr 0x%x", I64LOW(startPos), startAddr));
       
   427 		OstTraceExt2(TRACE_FLOW, DDMAHELPER_REQUESTSTART_EXIT3, "< KErrNotSupported Frag / not block aligned: startPos 0x%x startAddr 0x%x", I64LOW(startPos), startAddr );
   388 		return KErrNotSupported;
   428 		return KErrNotSupported;
   389 		}
   429 		}
   390 
   430 
   391 	//************************************************
   431 	//************************************************
   392 	// Is it File Server Cache request ?
   432 	// Is it File Server Cache request ?
   411 			NKern::ThreadEnterCS();
   451 			NKern::ThreadEnterCS();
   412 			r = Kern::PrepareMemoryForDMA(iCurrentThread, (void*)firstPageAddr, iPageArrayCount << iPageSizeLog2, iPageArray);
   452 			r = Kern::PrepareMemoryForDMA(iCurrentThread, (void*)firstPageAddr, iPageArrayCount << iPageSizeLog2, iPageArray);
   413 			NKern::ThreadLeaveCS();
   453 			NKern::ThreadLeaveCS();
   414 			}
   454 			}
   415 		if (r != KErrNone) 
   455 		if (r != KErrNone) 
       
   456 		    {
       
   457 			OstTraceFunctionExitExt( DDMAHELPER_REQUESTSTART_EXIT4, this, r );
   416 			return r;
   458 			return r;
       
   459 		    }
   417 
   460 
   418 		iMemoryType = EFileServerChunk;
   461 		iMemoryType = EFileServerChunk;
   419 		
   462 		
   420 		__KTRACE_DMA(Kern::Printf("-PHYSADDR:RequestStart() - EFileServerChunk"));
   463 		__KTRACE_DMA(Kern::Printf("-PHYSADDR:RequestStart() - EFileServerChunk"));
       
   464 		OstTrace0( TRACE_DMASUPPORT, DDMAHELPER_REQUESTSTART1, "EFileServerChunk");
   421 		}
   465 		}
   422 	//****************************
   466 	//****************************
   423 	// Is it shared chunk ?
   467 	// Is it shared chunk ?
   424 	//****************************
   468 	//****************************
   425 	else if (iChunk)
   469 	else if (iChunk)
   427 		// calculate chunk offset of start of first page
   471 		// calculate chunk offset of start of first page
   428 		TInt offset = iChunkOffset + iReqRemoteDesOffset+ iLenConsumed;
   472 		TInt offset = iChunkOffset + iReqRemoteDesOffset+ iLenConsumed;
   429 				
   473 				
   430 		TInt r = Kern::ChunkPhysicalAddress(iChunk, offset, length, iLinAddressKernel, iMapAttr, iPhysAddr, iPageArray);
   474 		TInt r = Kern::ChunkPhysicalAddress(iChunk, offset, length, iLinAddressKernel, iMapAttr, iPhysAddr, iPageArray);
   431 		
   475 		
   432 		if (r < KErrNone) 
   476 		if (r < KErrNone)
       
   477 		    {
       
   478 			OstTraceFunctionExitExt( DDMAHELPER_REQUESTSTART_EXIT5, this, r );
   433 			return r;  // 0 = Contiguous Memory, 1 = Fragmented/Dis-Contiguous Memory
   479 			return r;  // 0 = Contiguous Memory, 1 = Fragmented/Dis-Contiguous Memory
   434 		
   480 		    }
       
   481 			
   435 		iMemoryType = ESharedChunk;
   482 		iMemoryType = ESharedChunk;
   436 		
   483 		
   437 		__KTRACE_DMA(Kern::Printf("-PHYSADDR:RequestStart() - ESharedChunk"));
   484 		__KTRACE_DMA(Kern::Printf("-PHYSADDR:RequestStart() - ESharedChunk"));
       
   485 		OstTrace0( TRACE_DMASUPPORT, DDMAHELPER_REQUESTSTART2, "ESharedChunk");
   438 		}
   486 		}
   439 	else
   487 	else
   440 		{
   488 		{
   441 		__KTRACE_DMA(Kern::Printf("<PHYSADDR:RequestStart() - EUnknown"));
   489 		__KTRACE_DMA(Kern::Printf("<PHYSADDR:RequestStart() - EUnknown"));
       
   490 		OstTraceFunctionExitExt( DDMAHELPER_REQUESTSTART_EXIT6, this, KErrNotFound );
   442 		return KErrNotFound;
   491 		return KErrNotFound;
   443 		}
   492 		}
   444 
   493 
   445 	SetFragLength(length);
   494 	SetFragLength(length);
   446 	
   495 	
   461 
   510 
   462 	//************************************************
   511 	//************************************************
   463 	// Sync memory
   512 	// Sync memory
   464 	//************************************************
   513 	//************************************************
   465 	__KTRACE_DMA(Kern::Printf(">SYNC-PHYSADDR:addr 0x%x len %d", startAddr, length));
   514 	__KTRACE_DMA(Kern::Printf(">SYNC-PHYSADDR:addr 0x%x len %d", startAddr, length));
       
   515 	OstTraceExt2(TRACE_DMASUPPORT, DDMAHELPER_REQUESTSTART3, "startAddr=0x%x length=%d", (TUint) startAddr, length );
   466 
   516 
   467 	// Only sync whole blocks: it is assumed that the media driver will transfer 
   517 	// Only sync whole blocks: it is assumed that the media driver will transfer 
   468 	// partial start and end blocks without DMA
   518 	// partial start and end blocks without DMA
   469 
   519 
   470 	TInt startBlockPartialLen = IsBlockAligned(startPos) ? 0 : iMediaBlockSize - BlockOffset(startPos);
   520 	TInt startBlockPartialLen = IsBlockAligned(startPos) ? 0 : iMediaBlockSize - BlockOffset(startPos);
   496 				Cache::SyncMemoryBeforeDmaRead(startAddr, length);
   546 				Cache::SyncMemoryBeforeDmaRead(startAddr, length);
   497 			}
   547 			}
   498 		}
   548 		}
   499 
   549 
   500 	__KTRACE_DMA(Kern::Printf("<PHYSADDR:RequestStart()"));
   550 	__KTRACE_DMA(Kern::Printf("<PHYSADDR:RequestStart()"));
       
   551 
       
   552 	OstTraceFunctionExitExt( DDMAHELPER_REQUESTSTART_EXIT7, this, KErrNone );
   501 	return KErrNone;
   553 	return KErrNone;
   502 	}
   554 	}
   503 
   555 
   504 /**
   556 /**
   505  * After read requests this method synchronous the current physical memory in use.
   557  * After read requests this method synchronous the current physical memory in use.
   506  */
   558  */
   507 void DDmaHelper::RequestEnd()
   559 void DDmaHelper::RequestEnd()
   508 	{
   560 	{
       
   561 	OstTraceFunctionEntry0( DDMAHELPER_REQUESTEND_ENTRY );
   509 	__KTRACE_DMA(Kern::Printf(">PHYSADDR:RequestEnd()"));
   562 	__KTRACE_DMA(Kern::Printf(">PHYSADDR:RequestEnd()"));
       
   563 
   510 
   564 
   511 	__ASSERT_DEBUG(iReqId == DLocalDrive::ERead || iReqId == DLocalDrive::EWrite, PHYSADDR_FAULT());
   565 	__ASSERT_DEBUG(iReqId == DLocalDrive::ERead || iReqId == DLocalDrive::EWrite, PHYSADDR_FAULT());
   512 	__ASSERT_DEBUG(iMemoryType == ESharedChunk || iMemoryType == EFileServerChunk, PHYSADDR_FAULT());
   566 	__ASSERT_DEBUG(iMemoryType == ESharedChunk || iMemoryType == EFileServerChunk, PHYSADDR_FAULT());
   513 
   567 
   514 	TInt length = FragLength();	// len of data just transferred
   568 	TInt length = FragLength();	// len of data just transferred
   535 				Cache::SyncMemoryAfterDmaRead(startAddr + startBlockPartialLen, blockLen);
   589 				Cache::SyncMemoryAfterDmaRead(startAddr + startBlockPartialLen, blockLen);
   536 			}
   590 			}
   537 
   591 
   538 		}
   592 		}
   539 	ReleasePages(PageAlign(startAddr));
   593 	ReleasePages(PageAlign(startAddr));
       
   594 	OstTraceFunctionExit0( DDMAHELPER_REQUESTEND_EXIT );
   540 	}
   595 	}
   541 
   596 
   542 /**
   597 /**
   543  * For File Server chunks this method releases the current physical memory in use.
   598  * For File Server chunks this method releases the current physical memory in use.
   544  * 
   599  * 
   545  * @see Kern::ReleaseMemoryFromDMA()
   600  * @see Kern::ReleaseMemoryFromDMA()
   546  */
   601  */
   547 void DDmaHelper::ReleasePages(TLinAddr aAddr)
   602 void DDmaHelper::ReleasePages(TLinAddr aAddr)
   548 	{
   603 	{
       
   604 	OstTraceFunctionEntry1( DDMAHELPER_RELEASEPAGES_ENTRY, this );
   549 	if (iMemoryType == EFileServerChunk)
   605 	if (iMemoryType == EFileServerChunk)
   550 		{
   606 		{
   551 		__KTRACE_DMA(Kern::Printf(">PHYSADDR():ReleasePages thread (0x%x) aAddr(0x%08x) size(%d) iPageArray(0x%x)",iCurrentThread, aAddr, (iPageArrayCount << iPageSizeLog2), iPageArray));
   607 		__KTRACE_DMA(Kern::Printf(">PHYSADDR():ReleasePages thread (0x%x) aAddr(0x%08x) size(%d) iPageArray(0x%x)",iCurrentThread, aAddr, (iPageArrayCount << iPageSizeLog2), iPageArray));
       
   608 		OstTraceExt3( TRACE_DMASUPPORT, DDMAHELPER_RELEASEPAGES, "ReleasePages aAddr=0x%x; size=%d; iPageArray-0x%x", (TUint) aAddr, (iPageArrayCount << iPageSizeLog2), (TUint) iPageArray);
   552 
   609 
   553 		TInt r;
   610 		TInt r;
   554 		if (iPhysPinningAvailable)
   611 		if (iPhysPinningAvailable)
   555 			{
   612 			{
   556 			r = Kern::UnpinPhysicalMemory(iPhysicalPinObject);
   613 			r = Kern::UnpinPhysicalMemory(iPhysicalPinObject);
   561 			r = Kern::ReleaseMemoryFromDMA(iCurrentThread, (void*) aAddr, iPageArrayCount << iPageSizeLog2, iPageArray);
   618 			r = Kern::ReleaseMemoryFromDMA(iCurrentThread, (void*) aAddr, iPageArrayCount << iPageSizeLog2, iPageArray);
   562 			NKern::ThreadLeaveCS();
   619 			NKern::ThreadLeaveCS();
   563 			}
   620 			}
   564 		__ASSERT_ALWAYS(r == KErrNone, PHYSADDR_FAULT());
   621 		__ASSERT_ALWAYS(r == KErrNone, PHYSADDR_FAULT());
   565 		}		
   622 		}		
       
   623 	OstTraceFunctionExit1( DDMAHELPER_RELEASEPAGES_EXIT, this );
   566 	}
   624 	}
   567 
   625 
   568 /**
   626 /**
   569  * Utility method which examines the page array, compiling adjacent pages into contiguous fragments
   627  * Utility method which examines the page array, compiling adjacent pages into contiguous fragments
   570  * and populating iPageList with said fragments.
   628  * and populating iPageList with said fragments.
   571  */
   629  */
   572 void DDmaHelper::BuildPageList()
   630 void DDmaHelper::BuildPageList()
   573 	{
   631 	{
       
   632 	OstTraceFunctionEntry1( DDMAHELPER_BUILDPAGELIST_ENTRY, this );
   574 	iPageListCount = 0;
   633 	iPageListCount = 0;
   575 	
   634 	
   576 	if (iPhysAddr != KPhysMemFragmented)
   635 	if (iPhysAddr != KPhysMemFragmented)
   577 		{
   636 		{
   578 		__KTRACE_DMA(Kern::Printf(">PHYSADDR:BuildPageList() - Contiguous Memory"));
   637 		__KTRACE_DMA(Kern::Printf(">PHYSADDR:BuildPageList() - Contiguous Memory"));
       
   638 		OstTrace0( TRACE_DMASUPPORT, DDMAHELPER_BUILDPAGELIST1, "Contiguous Memory");
   579 		// Only one entry required.
   639 		// Only one entry required.
   580 		iPageList[0].iAddress = iPhysAddr;
   640 		iPageList[0].iAddress = iPhysAddr;
   581 		iPageList[0].iLength = FragLength();
   641 		iPageList[0].iLength = FragLength();
   582 		iPageListCount = 1;
   642 		iPageListCount = 1;
   583 		}
   643 		}
   584 	else
   644 	else
   585 		{
   645 		{
   586 		__KTRACE_DMA(Kern::Printf(">PHYSADDR:BuildPageList() - Dis-Contiguous Memory"));
   646 		__KTRACE_DMA(Kern::Printf(">PHYSADDR:BuildPageList() - Dis-Contiguous Memory"));
       
   647 		OstTrace0( TRACE_DMASUPPORT, DDMAHELPER_BUILDPAGELIST2, "Dis-Contiguous Memory");
   587 		TInt offset;
   648 		TInt offset;
   588 		
   649 		
   589 		offset = PageOffset(iChunkOffset + iReqRemoteDesOffset+ iLenConsumed);
   650 		offset = PageOffset(iChunkOffset + iReqRemoteDesOffset+ iLenConsumed);
   590 		iPageList[0].iAddress = iPageArray[0]+offset;
   651 		iPageList[0].iAddress = iPageArray[0]+offset;
   591 		iPageList[0].iLength  = iPageSize-offset;
   652 		iPageList[0].iLength  = iPageSize-offset;
   623 
   684 
   624 //#ifdef __DEBUG_DMASUP__
   685 //#ifdef __DEBUG_DMASUP__
   625 //	for (TInt m=0; m<iPageListCount; m++)
   686 //	for (TInt m=0; m<iPageListCount; m++)
   626 //		__KTRACE_DMA(Kern::Printf("-PHYSADDR:BuildPageList() [%d]: %08X l:%d", m, iPageList[m].iAddress, iPageList[m].iLength));
   687 //		__KTRACE_DMA(Kern::Printf("-PHYSADDR:BuildPageList() [%d]: %08X l:%d", m, iPageList[m].iAddress, iPageList[m].iLength));
   627 //#endif
   688 //#endif
       
   689 	OstTraceFunctionExit1( DDMAHELPER_BUILDPAGELIST_EXIT, this );
   628 	}
   690 	}
   629 
   691 
   630 
   692 
   631 /**
   693 /**
   632  * Returns Address and Length of next contiguous Physical memory fragment
   694  * Returns Address and Length of next contiguous Physical memory fragment
   637  * @return KErrNone, if successful;
   699  * @return KErrNone, if successful;
   638  * 		   KErrNoMemory, if no more memory fragments left.
   700  * 		   KErrNoMemory, if no more memory fragments left.
   639  */
   701  */
   640 TInt DDmaHelper::GetPhysicalAddress(TPhysAddr& aAddr, TInt& aLen)
   702 TInt DDmaHelper::GetPhysicalAddress(TPhysAddr& aAddr, TInt& aLen)
   641 	{
   703 	{
       
   704 	OstTraceFunctionEntry1( DUP1_DDMAHELPER_GETPHYSICALADDRESS_ENTRY, this );
   642 	if (iIndex >= iPageListCount)
   705 	if (iIndex >= iPageListCount)
   643 		{
   706 		{
   644 		__KTRACE_DMA(Kern::Printf(">PHYSADDR:GetPhysD() [%d], PageListCount:%d", iIndex, iPageListCount));
   707 		__KTRACE_DMA(Kern::Printf(">PHYSADDR:GetPhysD() [%d], PageListCount:%d", iIndex, iPageListCount));
       
   708 		OstTraceExt2(TRACE_DMASUPPORT, DDMAHELPER_GETPHYSICALADDRESS1, "GetPhysD() [%d]; iPageCountList=%d", iIndex, iPageListCount );
   645 		aAddr = 0;
   709 		aAddr = 0;
   646 		aLen = 0;
   710 		aLen = 0;
       
   711 		OstTraceFunctionExitExt( DUP1_DDMAHELPER_GETPHYSICALADDRESS_EXIT1, this, KErrGeneral );
   647 		return KErrGeneral;
   712 		return KErrGeneral;
   648 		}
   713 		}
   649 	
   714 	
   650 	aAddr = iPageList[iIndex].iAddress;
   715 	aAddr = iPageList[iIndex].iAddress;
   651 	aLen = iPageList[iIndex].iLength;
   716 	aLen = iPageList[iIndex].iLength;
   652 	iLenConsumed+= aLen;
   717 	iLenConsumed+= aLen;
   653 	iFragLenRemaining-= aLen;
   718 	iFragLenRemaining-= aLen;
   654 	
   719 	
   655 	__KTRACE_DMA(Kern::Printf(">PHYSADDR:GetPhysD() [%d] addr:0x%08X, l:%d; Used:%d, Left:%d", iIndex, aAddr, aLen, iLenConsumed, iFragLenRemaining));
   720 	__KTRACE_DMA(Kern::Printf(">PHYSADDR:GetPhysD() [%d] addr:0x%08X, l:%d; Used:%d, Left:%d", iIndex, aAddr, aLen, iLenConsumed, iFragLenRemaining));
       
   721 	OstTraceExt5(TRACE_DMASUPPORT, DDMAHELPER_GETPHYSICALADDRESS2, "GetPhysD() [%d]; address=0x%x; length=%d; iLenConsumed=%d; iFragLenRemaining=%d", iIndex, (TUint) aAddr, aLen, iLenConsumed, iFragLenRemaining);
   656 	__ASSERT_DEBUG(aLen >= 0, PHYSADDR_FAULT());
   722 	__ASSERT_DEBUG(aLen >= 0, PHYSADDR_FAULT());
   657 
   723 
   658 	iIndex++;  //Move index to next page
   724 	iIndex++;  //Move index to next page
   659 
   725 
       
   726 	OstTraceFunctionExitExt( DDMAHELPER_GETPHYSICALADDRESS_EXIT2, this, KErrNone );
   660 	return KErrNone;
   727 	return KErrNone;
   661 	}
   728 	}
   662 
   729 
   663 
   730 
   664 #ifdef __DEMAND_PAGING__
   731 #ifdef __DEMAND_PAGING__
   672  * 
   739  * 
   673  * @return KErrNone 
   740  * @return KErrNone 
   674  */
   741  */
   675 TInt DDmaHelper::GetPhysicalAddress(TLocDrvRequest& aReq, TPhysAddr& aAddr, TInt& aLen)
   742 TInt DDmaHelper::GetPhysicalAddress(TLocDrvRequest& aReq, TPhysAddr& aAddr, TInt& aLen)
   676 	{
   743 	{
       
   744 	OstTraceFunctionEntry0( DDMAHELPER_GETPHYSICALADDRESS_ENTRY );
   677 	__ASSERT_DEBUG( (aReq.Flags() & TLocDrvRequest::ETClientBuffer) == 0,  PHYSADDR_FAULT());
   745 	__ASSERT_DEBUG( (aReq.Flags() & TLocDrvRequest::ETClientBuffer) == 0,  PHYSADDR_FAULT());
   678 	TLinAddr linAddr = (TLinAddr) aReq.RemoteDes();
   746 	TLinAddr linAddr = (TLinAddr) aReq.RemoteDes();
   679 	TInt& offset = aReq.RemoteDesOffset();
   747 	TInt& offset = aReq.RemoteDesOffset();
   680 	TLinAddr currLinAddr = linAddr + offset;
   748 	TLinAddr currLinAddr = linAddr + offset;
   681 	TInt reqLen = I64LOW(aReq.Length());
   749 	TInt reqLen = I64LOW(aReq.Length());
   709 		aLen+= len;
   777 		aLen+= len;
   710 		}
   778 		}
   711 
   779 
   712 
   780 
   713 	__KTRACE_DMA(Kern::Printf(">PHYSADDR:DP:GetPhysS(), linAddr %08X, physAddr %08X, len %x reqLen %x", linAddr + offset, aAddr, aLen, reqLen));
   781 	__KTRACE_DMA(Kern::Printf(">PHYSADDR:DP:GetPhysS(), linAddr %08X, physAddr %08X, len %x reqLen %x", linAddr + offset, aAddr, aLen, reqLen));
   714 
   782 	OstTraceExt4(TRACE_DEMANDPAGING, DDMAHELPER_GETPHYSICALADDRESS_DP, "linAddr=0x%x; physAddr=0x%x; length=0x%x; reqLen=0x%x", linAddr + offset, aAddr, aLen, reqLen);
       
   783 	OstTraceFunctionExit0( DDMAHELPER_GETPHYSICALADDRESS_EXIT );
   715 	return KErrNone;
   784 	return KErrNone;
   716 	}
   785 	}
   717 #endif	// (__DEMAND_PAGING__)
   786 #endif	// (__DEMAND_PAGING__)
   718 
   787 
   719 
   788 
   727  * 		   otherwise one of the other system wide error codes.
   796  * 		   otherwise one of the other system wide error codes.
   728  */
   797  */
   729 
   798 
   730 TInt DDmaHelper::UpdateRemoteDescriptorLength(TInt aLength)
   799 TInt DDmaHelper::UpdateRemoteDescriptorLength(TInt aLength)
   731 	{
   800 	{
       
   801 	OstTraceFunctionEntryExt( DDMAHELPER_UPDATEREMOTEDESCRIPTORLENGTH_ENTRY, this );
   732 	__KTRACE_DMA(Kern::Printf(">PHYSADDR:UpDesLen(%d)",aLength));
   802 	__KTRACE_DMA(Kern::Printf(">PHYSADDR:UpDesLen(%d)",aLength));
   733 
   803 
   734 	// Restore request Id (overwritten by KErrNone return code) to stop ASSERT in WriteRemote
   804 	// Restore request Id (overwritten by KErrNone return code) to stop ASSERT in WriteRemote
   735 	iReq->Id() = DLocalDrive::ERead;
   805 	iReq->Id() = DLocalDrive::ERead;
   736 
   806 
   742 	TInt r = iReq->WriteRemote(&zeroDes, aLength);
   812 	TInt r = iReq->WriteRemote(&zeroDes, aLength);
   743 
   813 
   744 	// restore return code	
   814 	// restore return code	
   745 	iReq->iValue = KErrNone;
   815 	iReq->iValue = KErrNone;
   746 
   816 
       
   817 	OstTraceFunctionExitExt( DDMAHELPER_UPDATEREMOTEDESCRIPTORLENGTH_EXIT, this, r );
   747 	return r;
   818 	return r;
   748 	}
   819 	}
   749 
   820