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; |
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 |
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 |