|
1 // Copyright (c) 2002-2010 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 "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 // include/drivers/dma_v2.h |
|
15 // DMA Framework - Client API v2 definition. |
|
16 // |
|
17 // NB: DMA clients should never include this file directly, but only ever the |
|
18 // generic header file <drivers/dma.h>. |
|
19 // |
|
20 |
|
21 /** @file |
|
22 @publishedPartner |
|
23 */ |
|
24 |
|
25 #ifndef __DMA_H__ |
|
26 #error "dma_v2.h must'n be included directly - use <drivers/dma.h> instead" |
|
27 #endif // #ifndef __DMA_H__ |
|
28 |
|
29 #ifndef __DMA_V2_H__ |
|
30 #define __DMA_V2_H__ |
|
31 |
|
32 |
|
33 #include <kernel/kernel.h> |
|
34 #include <drivers/dmadefs.h> |
|
35 |
|
36 |
|
37 ////////////////////////////////////////////////////////////////////////////// |
|
38 // Debug Support - KDmaPanicCat is defined in each source file |
|
39 |
|
40 #define __DMA_ASSERTD(e) __ASSERT_DEBUG(e, Kern::Fault(KDmaPanicCat, __LINE__)) |
|
41 #define __DMA_ASSERTA(e) __ASSERT_ALWAYS(e, Kern::Fault(KDmaPanicCat, __LINE__)) |
|
42 #ifdef _DEBUG |
|
43 #define __DMA_CANT_HAPPEN() Kern::Fault(KDmaPanicCat, __LINE__) |
|
44 #define __DMA_DECLARE_INVARIANT public: void Invariant(); |
|
45 #define __DMA_DECLARE_VIRTUAL_INVARIANT public: virtual void Invariant(); |
|
46 #define __DMA_INVARIANT() Invariant() |
|
47 #else |
|
48 #define __DMA_CANT_HAPPEN() |
|
49 #define __DMA_DECLARE_INVARIANT |
|
50 #define __DMA_DECLARE_VIRTUAL_INVARIANT |
|
51 #define __DMA_INVARIANT() |
|
52 #endif |
|
53 |
|
54 #ifdef __DMASIM__ |
|
55 #ifdef __PRETTY_FUNCTION__ |
|
56 #define __DMA_UNREACHABLE_DEFAULT() DMA_PSL_TRACE1("Calling default virtual: %s", __PRETTY_FUNCTION__) |
|
57 #else |
|
58 #define __DMA_UNREACHABLE_DEFAULT() DMA_PSL_TRACE("Calling default virtual function") |
|
59 #endif |
|
60 #else |
|
61 #define __DMA_UNREACHABLE_DEFAULT() __DMA_CANT_HAPPEN() |
|
62 #endif |
|
63 |
|
64 ////////////////////////////////////////////////////////////////////////////// |
|
65 // INTERFACE EXPOSED TO DEVICE-DRIVERS |
|
66 ////////////////////////////////////////////////////////////////////////////// |
|
67 |
|
68 ////////////////////////////////////////////////////////////////////////////// |
|
69 |
|
70 /** Bitmasks used for configuring a DMA request. |
|
71 |
|
72 In general, specify KDmaMemSrc|KDmaIncSrc (resp. KDmaMemDest|KDmaIncDest) |
|
73 if the source (resp. destination) is a memory buffer and clear |
|
74 KDmaMemSrc|KDmaIncSrc (resp. KDmaMemDest|KDmaIncDest) if the source |
|
75 (resp. destination) is a peripheral. |
|
76 |
|
77 If the location is given as a physical address (rather than a linear one) |
|
78 then also specify KDmaPhysAddrSrc and/or KDmaPhysAddrDest. |
|
79 |
|
80 The EKA1 "Fill Mode" can be implemented by omitting KDmaIncSrc. |
|
81 |
|
82 Some peripherals may require a post-increment address mode. |
|
83 |
|
84 @see DDmaRequest::Fragment() |
|
85 |
|
86 Note: This enum is only required for backwards compatibility with the old |
|
87 DMA framework, it can be removed once this is no longer needed. |
|
88 |
|
89 @deprecated |
|
90 */ |
|
91 enum TDmaRequestFlags |
|
92 { |
|
93 /** Source is address of memory buffer */ |
|
94 KDmaMemSrc = 0x01, |
|
95 /** Destination is address of memory buffer */ |
|
96 KDmaMemDest = 0x02, |
|
97 /** Source address must be post-incremented during transfer */ |
|
98 KDmaIncSrc = 0x04, |
|
99 /** Destination address must be post-incremented during transfer */ |
|
100 KDmaIncDest = 0x08, |
|
101 /** Source address is a physical address (as opposed to a linear one) */ |
|
102 KDmaPhysAddrSrc = 0x10, |
|
103 /** Destination address is a physical address (as opposed to a linear one) */ |
|
104 KDmaPhysAddrDest = 0x20, |
|
105 /** Request a different max transfer size (for instance for test purposes) */ |
|
106 KDmaAltTransferLen = 0x40 |
|
107 }; |
|
108 |
|
109 |
|
110 /** Each hardware or pseudo descriptor is associated with a header. Headers |
|
111 are needed because hardware descriptors can not easily be extended to store |
|
112 additional information. |
|
113 |
|
114 @released |
|
115 */ |
|
116 struct SDmaDesHdr |
|
117 { |
|
118 SDmaDesHdr* iNext; |
|
119 }; |
|
120 |
|
121 |
|
122 /** Pointer to signature of the new extended callback function. |
|
123 |
|
124 TUint - bitmask of one or more TDmaCallbackType values |
|
125 TDmaResult - just that |
|
126 TAny* - was provided by client in DDmaRequest constructor |
|
127 SDmaDesHdr* - points to header (and thus descriptor) which caused a |
|
128 'descriptor completed' or 'descriptor paused' event |
|
129 |
|
130 @released |
|
131 */ |
|
132 typedef void (*TDmaCallback)(TUint, TDmaResult, TAny*, SDmaDesHdr*); |
|
133 |
|
134 |
|
135 class TDmaChannel; |
|
136 |
|
137 |
|
138 /** A DMA request is a list of fragments small enough to be transferred in one go |
|
139 by the DMAC. |
|
140 |
|
141 In general, fragmentation is done in the framework by calling Fragment() but |
|
142 clients with special needs can allocate a blank descriptor list with |
|
143 ExpandDesList() and customise it to fit their needs. |
|
144 |
|
145 Clients should not set attributes directly, but should use the various functions |
|
146 instead. |
|
147 |
|
148 This class has not been designed to be called from several concurrent threads. |
|
149 Multithreaded clients must implement their own locking scheme (via DMutex). |
|
150 |
|
151 Mutexes are used internally to protect data structures accessed both by the |
|
152 client thread and the DFC thread. Therefore no fast mutex can be held when |
|
153 calling a request function. |
|
154 */ |
|
155 class DDmaRequest : public DBase |
|
156 { |
|
157 friend class TDmaChannel; |
|
158 |
|
159 public: |
|
160 /** The outcome of the transfer |
|
161 |
|
162 @see TDmaResult |
|
163 |
|
164 @deprecated |
|
165 */ |
|
166 enum TResult {EBadResult=0, EOk, EError}; |
|
167 |
|
168 /** The signature of the completion/failure callback function |
|
169 |
|
170 @see TDmaCallback |
|
171 |
|
172 @deprecated |
|
173 */ |
|
174 typedef void (*TCallback)(TResult, TAny*); |
|
175 |
|
176 public: |
|
177 /** Constructor. |
|
178 |
|
179 Create a new transfer request. |
|
180 |
|
181 @param aChannel The channel this request is bound to. |
|
182 @param aCb Callback function called on transfer completion or failure |
|
183 (in channel DFC context). Can be NULL. |
|
184 @param aCbArg Argument passed to callback function. |
|
185 @param aMaxTransferSize Maximum fragment size. If not specified, defaults to the maximum size |
|
186 supported by the DMA controller for the type of transfer that is later scheduled. |
|
187 |
|
188 @deprecated |
|
189 */ |
|
190 IMPORT_C DDmaRequest(TDmaChannel& aChannel, TCallback aCb=NULL, TAny* aCbArg=NULL, |
|
191 TInt aMaxTransferSize=0); |
|
192 |
|
193 |
|
194 /** Constructor. |
|
195 |
|
196 Create a new transfer request. |
|
197 |
|
198 @param aChannel The channel this request is bound to. |
|
199 @param aDmaCb Callback function called on transfer completion or |
|
200 failure (in channel DFC or ISR context). Can be NULL. |
|
201 @param aCbArg Argument passed to callback function. |
|
202 @param aMaxTransferSize Maximum fragment size. If not specified, |
|
203 defaults to the maximum size supported by the DMA controller for the |
|
204 type of transfer that is later scheduled. |
|
205 |
|
206 @released |
|
207 */ |
|
208 IMPORT_C DDmaRequest(TDmaChannel& aChannel, TDmaCallback aDmaCb, |
|
209 TAny* aCbArg=NULL, TUint aMaxTransferSize=0); |
|
210 |
|
211 |
|
212 /** Destructor. |
|
213 |
|
214 Assume the request is not being transferred or pending. |
|
215 |
|
216 @released |
|
217 */ |
|
218 IMPORT_C ~DDmaRequest(); |
|
219 |
|
220 |
|
221 /** Split request into a list of fragments small enough to be fed to the |
|
222 DMAC. |
|
223 |
|
224 The size of each fragment is smaller than or equal to the maximum |
|
225 transfer size supported by the DMAC. If the source and/or destination |
|
226 is memory, each fragment points to memory which is physically |
|
227 contiguous. |
|
228 |
|
229 The kind of transfer to perform is specified via a set of flags used by |
|
230 a PIL and a magic cookie passed to the PSL. If the source |
|
231 (resp. destination) is a peripheral, aSrc (resp. aDest) is treated as a |
|
232 magic cookie by the PIL and passed straight to the PSL. |
|
233 |
|
234 The request can be uninitialised or may have been fragmented |
|
235 previously. The previous configuration if any is lost whether or not |
|
236 the function succeeds. |
|
237 |
|
238 The client must ensure that any memory buffers involved in the transfer |
|
239 have been suitably prepared for DMA. For memory allocated on the kernel |
|
240 side or in a shared chunk this amounts to ensuring cache consistency |
|
241 before Queue() is called. However for memory that was allocated on the |
|
242 user side the client must also ensure that the memory is protected from |
|
243 both data paging and RAM defragmentation before Fragment() is called |
|
244 @see Kern::MapAndPinMemory(). Note however, that this function is only |
|
245 available if the flexible memory model (FMM) is in use. |
|
246 |
|
247 @param aSrc Source memory buffer linear address or peripheral magic |
|
248 cookie. |
|
249 @param aDest Destination memory buffer linear address or peripheral |
|
250 magic cookie. |
|
251 @param aCount Number of bytes to transfer. |
|
252 @param aFlags Bitmask characterising the transfer. |
|
253 @param aPslInfo Hardware-specific information passed to PSL. |
|
254 |
|
255 @return KErrNone if success. KErrArgument if aFlags and/or aPslInfo are |
|
256 invalid when finding the maximum transfer size. May also fail if |
|
257 running out of descriptors. |
|
258 |
|
259 @pre The request is not being transferred or pending. |
|
260 @pre The various parameters must be valid. The PIL or PSL will fault the |
|
261 kernel if not. |
|
262 |
|
263 @see TDmaRequestFlags |
|
264 |
|
265 @deprecated |
|
266 */ |
|
267 IMPORT_C TInt Fragment(TUint32 aSrc, TUint32 aDest, TInt aCount, TUint aFlags, TUint32 aPslInfo); |
|
268 |
|
269 |
|
270 /** New version of the DMA request fragment function, to be used with the |
|
271 TDmaTransferArgs structure. |
|
272 |
|
273 Split request into a list of fragments small enough to be fed to the |
|
274 DMAC. |
|
275 |
|
276 The size of each fragment is smaller than or equal to the maximum |
|
277 transfer size supported by the DMAC. If the source and/or destination |
|
278 is memory, each fragment points to memory which is physically |
|
279 contiguous. |
|
280 |
|
281 The request can be uninitialised or may have been fragmented |
|
282 previously. Any previous configuration is lost whether or not the |
|
283 function succeeds. |
|
284 |
|
285 The client must ensure that any memory buffers involved in the transfer |
|
286 have been suitably prepared for DMA. For memory allocated on the kernel |
|
287 side or in a shared chunk this amounts to ensuring cache consistency |
|
288 before Queue() is called. However for memory that was allocated on the |
|
289 user side the client must also ensure that the memory is protected from |
|
290 both data paging and RAM defragmentation before Fragment() is called |
|
291 @see Kern::MapAndPinMemory(). Note however, that this function is only |
|
292 available if the flexible memory model (FMM) is in use. |
|
293 |
|
294 @param aTransferArgs Describes the transfer to be performed. |
|
295 |
|
296 @return KErrNone if success. KErrArgument if certain arguments are |
|
297 invalid. May also fail if running out of descriptors. |
|
298 |
|
299 @pre The request is not being transferred or pending. |
|
300 @pre The various parameters must be valid. The PIL or PSL will fault |
|
301 the kernel if not. |
|
302 |
|
303 @released |
|
304 */ |
|
305 IMPORT_C TInt Fragment(const TDmaTransferArgs& aTransferArgs); |
|
306 |
|
307 |
|
308 /** Transfer asynchronously this request. |
|
309 |
|
310 If this request's channel is idle, the request is transferred |
|
311 immediately. Otherwise, it is queued and transferred later. |
|
312 |
|
313 The client is responsible for ensuring cache consistency before and/or |
|
314 after the transfer if necessary. |
|
315 |
|
316 @return KErrNone if success, KErrGeneral otherwise. |
|
317 |
|
318 @released |
|
319 */ |
|
320 IMPORT_C TInt Queue(); |
|
321 |
|
322 |
|
323 /** Append new descriptor(s) to existing list. |
|
324 |
|
325 Clients needing to build a custom descriptor list should call this |
|
326 function to allocate the list and access the resulting list through |
|
327 iFirstHdr and iLastHdr. |
|
328 |
|
329 Clients should not change the value of iFirstHdr, iLastHdr and the |
|
330 iNext field of the descriptor headers to ensure descriptors can be |
|
331 deallocated. Clients are free to change hardware descriptors, including |
|
332 chaining, in whatever way suit them. |
|
333 |
|
334 Assume the request is not being transferred or pending. |
|
335 |
|
336 @param aCount Number of descriptors to append. |
|
337 |
|
338 @return KErrNone or standard error code. |
|
339 |
|
340 @released |
|
341 */ |
|
342 IMPORT_C TInt ExpandDesList(TInt aCount=1); |
|
343 |
|
344 |
|
345 /** Append new descriptor(s) to existing list. This function variant |
|
346 operates on the source port descriptor chain. |
|
347 |
|
348 Works like ExpandDesList except that it uses the iSrcFirstHdr and |
|
349 iSrcLastHdr fields. |
|
350 |
|
351 @see ExpandDesList() |
|
352 |
|
353 This function should only be used if SDmacCaps::iAsymHwDescriptors is |
|
354 reported as true, as only then the framework will actually use the |
|
355 allocated descriptors. |
|
356 |
|
357 @param aCount Number of descriptors to append. |
|
358 |
|
359 @return KErrNone or standard error code. |
|
360 |
|
361 @prototype |
|
362 */ |
|
363 IMPORT_C TInt ExpandSrcDesList(TInt aCount=1); |
|
364 |
|
365 |
|
366 /** Append new descriptor(s) to existing list. This function variant |
|
367 operates on the destination port descriptor chain. |
|
368 |
|
369 Works like ExpandDesList except that it uses the iDstFirstHdr and |
|
370 iDstLastHdr fields. |
|
371 |
|
372 @see ExpandDesList() |
|
373 |
|
374 This function should only be used if SDmacCaps::iAsymHwDescriptors is |
|
375 reported as true, as only then the framework will actually use the |
|
376 allocated descriptors. |
|
377 |
|
378 @param aCount Number of descriptors to append. |
|
379 |
|
380 @return KErrNone or standard error code. |
|
381 |
|
382 @prototype |
|
383 */ |
|
384 IMPORT_C TInt ExpandDstDesList(TInt aCount=1); |
|
385 |
|
386 |
|
387 /** Free resources associated with this request. |
|
388 |
|
389 Assumes the request is not being transferred or pending. |
|
390 |
|
391 @see ExpandDesList() |
|
392 |
|
393 @released |
|
394 */ |
|
395 IMPORT_C void FreeDesList(); |
|
396 |
|
397 |
|
398 /** Free resources associated with this request. This function variant |
|
399 operates on the source port descriptor chain. |
|
400 |
|
401 Assumes the request is not being transferred or pending. |
|
402 |
|
403 @see ExpandSrcDesList() |
|
404 |
|
405 @prototype |
|
406 */ |
|
407 IMPORT_C void FreeSrcDesList(); |
|
408 |
|
409 |
|
410 /** Free resources associated with this request. This function variant |
|
411 operates on the destination port descriptor chain. |
|
412 |
|
413 Assumes the request is not being transferred or pending. |
|
414 |
|
415 @see ExpandDstDesList() |
|
416 |
|
417 @prototype |
|
418 */ |
|
419 IMPORT_C void FreeDstDesList(); |
|
420 |
|
421 |
|
422 /** Enables the functionality for counting the transferred source |
|
423 elements. |
|
424 |
|
425 This function can be called at any time, but the enabled/disabled |
|
426 status is checked by the framework only at two points in time. |
|
427 |
|
428 The first one is after a request has been queued, and if it is enabled |
|
429 then the counting will commence as soon as the transfer starts. |
|
430 |
|
431 The second point is when Resume() is called for a paused transfer, and |
|
432 in this case the following applies. If counting was enabled when the |
|
433 transfer was paused and it is now disabled then the counting is stopped |
|
434 at that point and the count value frozen. If counting was disabled when |
|
435 the transfer was paused and it is now enabled then the counting will |
|
436 commence when the transfer resumes. (The starting value will depend on |
|
437 the argument of the enable function.) Otherwise nothing will change, |
|
438 i.e. counting will either continue normally (enabled/enabled) or |
|
439 neither stop nor continue (disabled/disabled). |
|
440 |
|
441 Once a status has been set, it remains valid for the entire duration of |
|
442 the transfer (and beyond, if it is not changed again). |
|
443 |
|
444 @param aResetElementCount If ETrue (the default) then the count |
|
445 variable will be reset to zero, otherwise it will retain its current |
|
446 value. |
|
447 |
|
448 @see Queue() |
|
449 @see TotalNumSrcElementsTransferred() |
|
450 |
|
451 @prototype |
|
452 */ |
|
453 IMPORT_C void EnableSrcElementCounting(TBool aResetElementCount=ETrue); |
|
454 |
|
455 |
|
456 /** Enables the functionality for counting the transferred destination |
|
457 elements. |
|
458 |
|
459 This function can be called at any time, but the enabled/disabled |
|
460 status is checked by the framework only at two points in time. |
|
461 |
|
462 The first one is after a request has been queued, and if it is enabled |
|
463 then the counting will commence as soon as the transfer starts. |
|
464 |
|
465 The second point is when Resume() is called for a paused transfer, and |
|
466 in this case the following applies. If counting was enabled when the |
|
467 transfer was paused and it is now disabled then the counting is stopped |
|
468 at that point and the count value frozen. If counting was disabled when |
|
469 the transfer was paused and it is now enabled then the counting will |
|
470 commence when the transfer resumes. (The starting value will depend on |
|
471 the argument of the enable function.) Otherwise nothing will change, |
|
472 i.e. counting will either continue normally (enabled/enabled) or |
|
473 neither stop nor continue (disabled/disabled). |
|
474 |
|
475 Once a status has been set, it remains valid for the entire duration of |
|
476 the transfer (and beyond, if it is not changed again). |
|
477 |
|
478 @param aResetElementCount If ETrue (the default) then the count |
|
479 variable will be reset to zero, otherwise it will retain its current |
|
480 value. |
|
481 |
|
482 @see Queue() |
|
483 @see TotalNumDstElementsTransferred() |
|
484 |
|
485 @prototype |
|
486 */ |
|
487 IMPORT_C void EnableDstElementCounting(TBool aResetElementCount=ETrue); |
|
488 |
|
489 |
|
490 /** Disables the functionality for counting the transferred source |
|
491 elements. |
|
492 |
|
493 This function can be called at any time, but the enabled/disabled |
|
494 status is checked by the framework only at two points in time. |
|
495 |
|
496 The first one is after a request has been queued, and if it is enabled |
|
497 then the counting will commence as soon as the transfer starts. |
|
498 |
|
499 The second point is when Resume() is called for a paused transfer, and |
|
500 in this case the following applies. If counting was enabled when the |
|
501 transfer was paused and it is now disabled then the counting is stopped |
|
502 at that point and the count value frozen. If counting was disabled when |
|
503 the transfer was paused and it is now enabled then the counting will |
|
504 commence when the transfer resumes. (The starting value will depend on |
|
505 the argument of the enable function.) Otherwise nothing will change, |
|
506 i.e. counting will either continue normally (enabled/enabled) or |
|
507 neither stop nor continue (disabled/disabled). |
|
508 |
|
509 Once a status has been set, it remains valid for the entire duration of |
|
510 the transfer (and beyond, if it is not changed again). |
|
511 |
|
512 @see Queue() |
|
513 @see TotalNumSrcElementsTransferred() |
|
514 |
|
515 @prototype |
|
516 */ |
|
517 IMPORT_C void DisableSrcElementCounting(); |
|
518 |
|
519 |
|
520 /** Disables the functionality for counting the transferred destination |
|
521 elements. |
|
522 |
|
523 This function can be called at any time, but the enabled/disabled |
|
524 status is checked by the framework only at two points in time. |
|
525 |
|
526 The first one is after a request has been queued, and if it is enabled |
|
527 then the counting will commence as soon as the transfer starts. |
|
528 |
|
529 The second point is when Resume() is called for a paused transfer, and |
|
530 in this case the following applies. If counting was enabled when the |
|
531 transfer was paused and it is now disabled then the counting is stopped |
|
532 at that point and the count value frozen. If counting was disabled when |
|
533 the transfer was paused and it is now enabled then the counting will |
|
534 commence when the transfer resumes. (The starting value will depend on |
|
535 the argument of the enable function.) Otherwise nothing will change, |
|
536 i.e. counting will either continue normally (enabled/enabled) or |
|
537 neither stop nor continue (disabled/disabled). |
|
538 |
|
539 Once a status has been set, it remains valid for the entire duration of |
|
540 the transfer (and beyond, if it is not changed again). |
|
541 |
|
542 @see Queue() |
|
543 @see TotalNumDstElementsTransferred() |
|
544 |
|
545 @prototype |
|
546 */ |
|
547 IMPORT_C void DisableDstElementCounting(); |
|
548 |
|
549 |
|
550 /** Returns the number of elements that have been transferred by this |
|
551 transfer request at the source port. |
|
552 |
|
553 To use this method, the counting functionality has to be explicitly |
|
554 enabled, either before the transfer request is queued or while it is |
|
555 paused. |
|
556 |
|
557 @see EnableSrcElementCounting() |
|
558 @see DisableSrcElementCounting() |
|
559 |
|
560 This function should only be called after the transfer has finished |
|
561 (completed with or without error, or because it was cancelled) or while |
|
562 it is paused. Otherwise it may just return 0. |
|
563 |
|
564 @return The number of elements that have been transferred by this |
|
565 transfer request at the source port. |
|
566 |
|
567 @prototype |
|
568 */ |
|
569 IMPORT_C TUint32 TotalNumSrcElementsTransferred(); |
|
570 |
|
571 |
|
572 /** Returns the number of elements that have been transferred by this |
|
573 transfer request at the destination port. |
|
574 |
|
575 To use this method, the counting functionality has to be explicitly |
|
576 enabled, either before the transfer request is queued or while it is |
|
577 paused. |
|
578 |
|
579 @see EnableDstElementCounting() |
|
580 @see DisableDstElementCounting() |
|
581 |
|
582 This function should only be called after the transfer has finished |
|
583 (completed with or without error, or because it was cancelled) or while |
|
584 it is paused. Otherwise it may just return 0. |
|
585 |
|
586 @return The number of elements that have been transferred by this |
|
587 transfer request at the destination port. |
|
588 |
|
589 @prototype |
|
590 */ |
|
591 IMPORT_C TUint32 TotalNumDstElementsTransferred(); |
|
592 |
|
593 |
|
594 /** Returns the number of fragments that this transfer request has been |
|
595 split into. |
|
596 |
|
597 This number will only be different from 0 once Fragment() has been |
|
598 called or after descriptors have been manually allocated by the client |
|
599 using ExpandDesList(). |
|
600 |
|
601 If SDmacCaps::iAsymHwDescriptors is true then this function will always |
|
602 return 0, and SrcFragmentCount() / DstFragmentCount() should be used |
|
603 instead. |
|
604 |
|
605 @return The number of fragments (descriptors / pseudo descriptors) that |
|
606 this transfer request has been split into. |
|
607 |
|
608 @released |
|
609 */ |
|
610 IMPORT_C TInt FragmentCount(); |
|
611 |
|
612 |
|
613 /** Returns the number of source port fragments that this transfer request |
|
614 has been split into. |
|
615 |
|
616 This number will only be different from 0 once Fragment() has been |
|
617 called or after descriptors have been manually allocated by the client |
|
618 using ExpandSrcDesList(). |
|
619 |
|
620 This function can only be used if SDmacCaps::iAsymHwDescriptors is |
|
621 true, otherwise it will always return 0. |
|
622 |
|
623 @return The number of source port fragments (descriptors) that this |
|
624 transfer request has been split into. |
|
625 |
|
626 @prototype |
|
627 */ |
|
628 IMPORT_C TInt SrcFragmentCount(); |
|
629 |
|
630 |
|
631 /** Returns the number of destination port fragments that this transfer |
|
632 request has been split into. |
|
633 |
|
634 This number will only be different from 0 once Fragment() has been |
|
635 called or after descriptors have been manually allocated by the client |
|
636 using ExpandDstDesList(). |
|
637 |
|
638 This function can only be used if SDmacCaps::iAsymHwDescriptors is |
|
639 true, otherwise it will always return 0. |
|
640 |
|
641 @return The number of destination port fragments (descriptors) that |
|
642 this transfer request has been split into. |
|
643 |
|
644 @prototype |
|
645 */ |
|
646 IMPORT_C TInt DstFragmentCount(); |
|
647 |
|
648 private: |
|
649 inline void OnDeque(); |
|
650 TInt CheckTransferConfig(const TDmaTransferConfig& aTarget, TUint aCount) const; |
|
651 TInt CheckMemFlags(const TDmaTransferConfig& aTarget) const; |
|
652 TInt AdjustFragmentSize(TUint& aFragSize, TUint aElementSize, TUint aFrameSize); |
|
653 TUint GetTransferCount(const TDmaTransferArgs& aTransferArgs) const; |
|
654 TUint GetMaxTransferlength(const TDmaTransferArgs& aTransferArgs, TUint aCount) const; |
|
655 TInt Frag(TDmaTransferArgs& aTransferArgs); |
|
656 TInt FragSym(TDmaTransferArgs& aTransferArgs, TUint aCount, TUint aMaxTransferLen); |
|
657 TInt FragAsym(TDmaTransferArgs& aTransferArgs, TUint aCount, TUint aMaxTransferLen); |
|
658 TInt FragAsymSrc(TDmaTransferArgs& aTransferArgs, TUint aCount, TUint aMaxTransferLen); |
|
659 TInt FragAsymDst(TDmaTransferArgs& aTransferArgs, TUint aCount, TUint aMaxTransferLen); |
|
660 TInt FragBalancedAsym(TDmaTransferArgs& aTransferArgs, TUint aCount, TUint aMaxTransferLen); |
|
661 TInt ExpandDesList(TInt aCount, TInt& aDesCount, SDmaDesHdr*& aFirstHdr, |
|
662 SDmaDesHdr*& aLastHdr); |
|
663 void FreeDesList(TInt& aDesCount, SDmaDesHdr*& aFirstHdr, SDmaDesHdr*& aLastHdr); |
|
664 TInt FragmentCount(const SDmaDesHdr* aHdr); |
|
665 |
|
666 public: |
|
667 // WARNING: The following attributes are accessed both in client and DFC |
|
668 // thread context, so accesses must be protected with the channel lock. |
|
669 TDmaChannel& iChannel; /**< The channel this request is bound to */ |
|
670 TCallback iCb; /**< Called on completion/failure (can be NULL) */ |
|
671 TAny* iCbArg; /**< Callback argument */ |
|
672 TDmaCallback iDmaCb; // the new-style callback function |
|
673 TAny* iDmaCbArg; // the new-style callback arg |
|
674 TBool iIsrCb; // client wants callback in ISR context |
|
675 TInt iDesCount; /**< The number of fragments in list */ |
|
676 SDmaDesHdr* iFirstHdr; /**< The first fragment in the list (or NULL) */ |
|
677 SDmaDesHdr* iLastHdr; /**< The last fragment in the list (or NULL) */ |
|
678 TInt iSrcDesCount; /**< The number of fragments in list */ |
|
679 SDmaDesHdr* iSrcFirstHdr; /**< The first fragment in the list (or NULL) */ |
|
680 SDmaDesHdr* iSrcLastHdr; /**< The last fragment in the list (or NULL) */ |
|
681 TInt iDstDesCount; /**< The number of fragments in list */ |
|
682 SDmaDesHdr* iDstFirstHdr; /**< The first fragment in the list (or NULL) */ |
|
683 SDmaDesHdr* iDstLastHdr; /**< The last fragment in the list (or NULL) */ |
|
684 SDblQueLink iLink; /**< The link on channel queue of pending requests */ |
|
685 TBool iQueued; /**< Indicates whether request is pending or being transferred */ |
|
686 TUint iMaxTransferSize; /**< Defaults to DMA controller max. transfer size */ |
|
687 |
|
688 TUint32 iTotalNumSrcElementsTransferred; |
|
689 TUint32 iTotalNumDstElementsTransferred; |
|
690 |
|
691 __DMA_DECLARE_INVARIANT |
|
692 }; |
|
693 |
|
694 |
|
695 ////////////////////////////////////////////////////////////////////////////// |
|
696 |
|
697 class TDmac; |
|
698 class DmaChannelMgr; |
|
699 class TDmaCancelInfo; |
|
700 |
|
701 /** DMA channel base class. |
|
702 |
|
703 Standard derived classes are provided for this channel (see |
|
704 TDmaSbChannel, TDmaDbChannel, TDmaSgChannel, and TDmaAsymSgChannel). |
|
705 The base-port implementor will only need to write their own derived |
|
706 class if one of the standard classes is unsuitable. |
|
707 |
|
708 This class has not been designed to be called from several concurrent |
|
709 client threads. Multithreaded clients must implement their own locking |
|
710 scheme (via DMutex). |
|
711 |
|
712 Mutexes are used internally to protect data structures accessed both by the |
|
713 client thread and the DFC one. Therefore no fast mutex can be held when |
|
714 calling a channel function. |
|
715 */ |
|
716 class TDmaChannel |
|
717 { |
|
718 friend class DDmaRequest; |
|
719 friend class TDmac; |
|
720 friend class DmaChannelMgr; |
|
721 |
|
722 public: |
|
723 /** Information passed by client when opening a channel. */ |
|
724 struct SCreateInfo |
|
725 { |
|
726 /** Default constructor. Initializes all fields with meaningful default |
|
727 values. |
|
728 |
|
729 Must be inline (for now) because exporting it would break existing |
|
730 custom DMA libs as their clients would need the export which would |
|
731 be missing from the custom .def files. |
|
732 |
|
733 @released |
|
734 */ |
|
735 SCreateInfo() : iPriority(KDmaPriorityNone), iDynChannel(EFalse) {}; |
|
736 |
|
737 /** Identifier used by PSL to select channel to open. |
|
738 |
|
739 @released |
|
740 */ |
|
741 TUint32 iCookie; |
|
742 /** Number of descriptors this channel can maximally use. |
|
743 |
|
744 This value will not be used in the fully implemented new version of |
|
745 the DMA framework. Until then it is still required. |
|
746 |
|
747 @released |
|
748 */ |
|
749 TInt iDesCount; |
|
750 /** DFC queue used to service DMA interrupts. |
|
751 |
|
752 @released |
|
753 */ |
|
754 TDfcQue* iDfcQ; |
|
755 /** DFC priority. |
|
756 |
|
757 @released |
|
758 */ |
|
759 TUint8 iDfcPriority; |
|
760 /** Used by PSL to configure a channel priority (if possible). |
|
761 |
|
762 The default is KDmaPriorityNone (the don't care value). |
|
763 |
|
764 @see TDmaPriority |
|
765 |
|
766 @prototype |
|
767 */ |
|
768 TUint iPriority; |
|
769 /** Request a dynamic DMA channel. |
|
770 |
|
771 If this is set to ETrue then the Open call is for a 'dynamic' as |
|
772 opposed to a static and solely owned DMA channel. A number of |
|
773 properties of the opened TDmaChannel object will be different in |
|
774 that case. |
|
775 |
|
776 The default value is EFalse. |
|
777 |
|
778 @prototype |
|
779 */ |
|
780 TBool iDynChannel; |
|
781 }; |
|
782 |
|
783 public: |
|
784 /** Opens the DMA channel. |
|
785 |
|
786 Channel selection is done by the hardware-specific layer using a cookie |
|
787 passed in via aInfo. |
|
788 |
|
789 The client should not delete the returned pointer as the framework owns |
|
790 channel objects. However, the client should explicitly close the |
|
791 channel when finished with it. |
|
792 |
|
793 @param aInfo Information passed by caller to select and configure |
|
794 channel. |
|
795 |
|
796 @param aChannel Points to open channel on successful return. NULL |
|
797 otherwise. |
|
798 |
|
799 @return KErrNone or standard error code. |
|
800 |
|
801 @released |
|
802 */ |
|
803 IMPORT_C static TInt Open(const SCreateInfo& aInfo, TDmaChannel*& aChannel); |
|
804 |
|
805 |
|
806 /** Closes a previously opened DMA channel. |
|
807 |
|
808 Assumes the channel is idle and all requests have been deleted. |
|
809 |
|
810 The call will cause the resources associated with this channel to be |
|
811 released, and the pointer/reference to it mustn't therefore be accessed |
|
812 any longer after the function has returned. The channel pointer should |
|
813 be set to NULL by the client. |
|
814 |
|
815 @released |
|
816 */ |
|
817 IMPORT_C void Close(); |
|
818 |
|
819 |
|
820 /** Logically links this channel to the one specified as an argument, or, |
|
821 if the argument is NULL, unlinks this channel. |
|
822 |
|
823 The effect of channel linking is that once a transfer on this channel |
|
824 has finished, instead of causing the associated client callback to be |
|
825 called, 'aChannel' will be enabled by hardware and a preconfigured |
|
826 transfer on that channel will start. |
|
827 |
|
828 Note that conceptually 'linking' here always refers to the end of a |
|
829 channel transfer, not the beginning, i.e. a channel can only be linked |
|
830 once and always to a successor, never twice or to a predecessor. (This |
|
831 does not preclude the possibility that two channels are linked in a |
|
832 circular fashion.) |
|
833 |
|
834 This function can only be used if the DMAC supports logical channel |
|
835 linking. |
|
836 |
|
837 @see SDmacCaps::iChannelLinking |
|
838 |
|
839 @param aChannel Points to the channel this one should be linked to, or |
|
840 NULL if this channel is to be unlinked from any other one. |
|
841 |
|
842 @return KErrNone if the channel has been linked or unlinked |
|
843 successfully, KErrCompletion if this channel was already linked to |
|
844 aChannel or already unlinked, KErrNotSupported if the DMAC doesn't |
|
845 support channel linking, KErrArgument if this channel was already |
|
846 linked to a different channel, KErrGeneral if a general error occurred |
|
847 preventing a successful outcome. |
|
848 |
|
849 @prototype |
|
850 */ |
|
851 IMPORT_C TInt LinkToChannel(TDmaChannel* aChannel); |
|
852 |
|
853 |
|
854 /** Pauses an active transfer on this channel. |
|
855 |
|
856 A paused channel transfer can be resumed by calling Resume() or it can |
|
857 be stopped altogether by calling CancelAll(). |
|
858 |
|
859 @see TDmaChannel::Resume() |
|
860 |
|
861 Function can only be used if the DMAC supports this functionality. |
|
862 |
|
863 @see SDmacCaps::iChannelPauseAndResume |
|
864 |
|
865 @return KErrNone if a transfer has been paused successfully, |
|
866 KErrCompletion if a transfer was already paused, KErrNotSupported if |
|
867 the DMAC doesn't support channel transfer pausing/resuming, KErrGeneral |
|
868 if a general error occurred preventing a successful outcome. |
|
869 |
|
870 @released |
|
871 */ |
|
872 IMPORT_C TInt Pause(); |
|
873 |
|
874 |
|
875 /** Resumes a transfer on this channel that is paused. |
|
876 |
|
877 Resume() can be called to resume channel operation when the transfer is |
|
878 paused as a result of a previous call to Pause() or because the DMAC |
|
879 has encountered a Pause bit in a H/W descriptor. |
|
880 |
|
881 @see TDmaChannel::Pause() |
|
882 @see TDmaCallbackType::EDmaCallbackLinkedListPaused |
|
883 |
|
884 Function can only be used if the DMAC supports this functionality. |
|
885 |
|
886 @see SDmacCaps::iChannelPauseAndResume |
|
887 @see SDmacCaps::iLinkedListPausedInterrupt |
|
888 |
|
889 @return KErrNone if a paused transfer has been resumed successfully, |
|
890 KErrCompletion if there was no paused transfer, KErrNotSupported if the |
|
891 DMAC doesn't support channel transfer pausing/resuming, KErrGeneral if |
|
892 a general error occurred preventing a successful outcome. |
|
893 |
|
894 @released |
|
895 */ |
|
896 IMPORT_C TInt Resume(); |
|
897 |
|
898 |
|
899 /** Cancels the current request and all the pending ones. |
|
900 |
|
901 @released |
|
902 */ |
|
903 IMPORT_C void CancelAll(); |
|
904 |
|
905 |
|
906 /** Returns the channel's maximum transfer length based on the passed |
|
907 arguments. |
|
908 |
|
909 @param aSrcFlags Bitmask characterising transfer source |
|
910 @see TDmaTransferArgs::iSrcConfig::iFlags |
|
911 |
|
912 @param aDstFlags Bitmask characterising transfer destination |
|
913 @see TDmaTransferArgs::iDstConfig::iFlags |
|
914 |
|
915 @param aPslInfo Cookie passed to the PSL |
|
916 @see TDmaTransferArgs::iPslRequestInfo |
|
917 |
|
918 @return 0 if transfer length is not limited, the maximum transfer |
|
919 length in bytes otherwise. |
|
920 |
|
921 @released |
|
922 */ |
|
923 IMPORT_C TUint MaxTransferLength(TUint aSrcFlags, TUint aDstFlags, TUint32 aPslInfo); |
|
924 |
|
925 |
|
926 /** Retrieves from the PSL the address / memory alignment mask based on the |
|
927 parameters passed. Some DMA controllers impose alignment constraints on |
|
928 the base address of memory buffers. This mask is AND'ed against memory |
|
929 addresses computed during fragmentation. |
|
930 |
|
931 This function needs to be called separately for source and destination. |
|
932 |
|
933 @param aTargetFlags Bitmask characterising transfer source or |
|
934 destination |
|
935 @see TDmaTransferArgs::iSrcConfig::iFlags |
|
936 @see TDmaTransferArgs::iDstConfig::iFlags |
|
937 |
|
938 @param aElementSize Element size used for the transfer. Can be zero if |
|
939 not known or 'don't care'. |
|
940 |
|
941 @param aPslInfo Cookie passed to the PSL |
|
942 @see TDmaTransferArgs::iPslRequestInfo |
|
943 |
|
944 @return A value representing the alignment mask (e.g. 3 if buffer must |
|
945 be 4-byte aligned) |
|
946 |
|
947 @released |
|
948 */ |
|
949 IMPORT_C TUint AddressAlignMask(TUint aTargetFlags, TUint aElementSize, |
|
950 TUint32 aPslInfo); |
|
951 |
|
952 |
|
953 /** Returns a reference to a structure containing the capabilities and |
|
954 features of the DMA controller associated with this channel. |
|
955 |
|
956 @return A reference to a structure containing the capabilities and |
|
957 features of the DMA controller associated with this channel. |
|
958 |
|
959 @released |
|
960 */ |
|
961 IMPORT_C const SDmacCaps& DmacCaps(); |
|
962 |
|
963 |
|
964 /** Sets up once more the transfer request that has just completed, after |
|
965 optionally having adjusted the transfer parameters as specified. |
|
966 |
|
967 This function is meant to be called exclusively from a client-supplied |
|
968 callback that is executed in ISR context, and only in response to a |
|
969 transfer completion notification. |
|
970 |
|
971 If this call returns to the caller with KErrNone then the framework's |
|
972 ISR handler will subsequently not queue the channel DFC for this |
|
973 completed request. |
|
974 |
|
975 The parameters specify which changes the framework should apply to the |
|
976 descriptors of the transfer request before rescheduling it. Arguments |
|
977 for which no change is required should be passed as their default |
|
978 values. The parameters correspond to those in the TDmaTransferArgs |
|
979 struct as follows. |
|
980 |
|
981 @param aSrcAddr @see TDmaTransferArgs::iSrcConfig::iAddr |
|
982 @param aDstAddr @see TDmaTransferArgs::iDstConfig::iAddr |
|
983 @param aTransferCount @see TDmaTransferArgs::iTransferCount |
|
984 @param aPslRequestInfo @see TDmaTransferArgs::iPslRequestInfo |
|
985 @param aIsrCb If set to ETrue (the default) then the callback of the |
|
986 rescheduled request will again be called in ISR context |
|
987 |
|
988 Since Epoc::LinearToPhysical() cannot be called in ISR context the |
|
989 addresses passed into this function must be physical ones, i.e. |
|
990 TDmaTransferFlags::KDmaPhysAddr is implied. |
|
991 |
|
992 If an address refers to a memory target then |
|
993 TDmaTransferFlags::KDmaMemIsContiguous is implied as well as no |
|
994 fragmentation is possible at this point. |
|
995 |
|
996 @pre Must only be called from a 'transfer complete' client callback in |
|
997 ISR context. |
|
998 |
|
999 @post Framework won't queue the channel DFC for the completed request |
|
1000 in success case. |
|
1001 |
|
1002 @see DDmaRequest::DDmaRequest(TDmaChannel&, TDmaCallback, TAny*, TUint) |
|
1003 @see TDmaCallbackType::EDmaCallbackRequestCompletion |
|
1004 @see TDmaPILFlags::KDmaRequestCallbackFromIsr |
|
1005 |
|
1006 @return KErrGeneral if there was an error, KErrNone otherwise. |
|
1007 |
|
1008 @released |
|
1009 */ |
|
1010 IMPORT_C TInt IsrRedoRequest(TUint32 aSrcAddr=KPhysAddrInvalid, |
|
1011 TUint32 aDstAddr=KPhysAddrInvalid, |
|
1012 TUint aTransferCount=0, |
|
1013 TUint32 aPslRequestInfo=0, |
|
1014 TBool aIsrCb=ETrue); |
|
1015 |
|
1016 |
|
1017 /** Tests whether the channel is currently opened. |
|
1018 |
|
1019 @return ETrue if channel is currently opened, EFalse otherwise. |
|
1020 |
|
1021 NB: This API should not be used any longer. |
|
1022 |
|
1023 After calling TDmaChannel::Open() successfully the channel is |
|
1024 guaranteed to be open, hence there seems no good reason for this API to |
|
1025 exist. |
|
1026 |
|
1027 @deprecated |
|
1028 */ |
|
1029 inline TBool IsOpened() const; |
|
1030 |
|
1031 |
|
1032 /** Tests whether the channel's request queue is currently empty. |
|
1033 |
|
1034 @return ETrue if request queue is currently empty, EFalse otherwise. |
|
1035 |
|
1036 @released |
|
1037 */ |
|
1038 inline TBool IsQueueEmpty() const; |
|
1039 |
|
1040 |
|
1041 /** Returns a PSL-specific value which uniquely identifies this channel - |
|
1042 it is used for debug tracing by the PIL. |
|
1043 |
|
1044 @return PSL-specific value which uniquely identifies this channel. |
|
1045 |
|
1046 @released |
|
1047 */ |
|
1048 inline TUint32 PslId() const; |
|
1049 |
|
1050 |
|
1051 /** Called by a test harness to force an error when the next fragment is |
|
1052 transferred. |
|
1053 |
|
1054 @param aFragmentCount The number of consecutive fragments to fail |
|
1055 |
|
1056 @released |
|
1057 */ |
|
1058 IMPORT_C TInt FailNext(TInt aFragmentCount); |
|
1059 |
|
1060 |
|
1061 /** Called by a test harness to force the DMA controller to miss one or |
|
1062 more interrupts. |
|
1063 |
|
1064 @param aInterruptCount The number of consecutive interrupts to miss |
|
1065 |
|
1066 @released |
|
1067 */ |
|
1068 IMPORT_C TInt MissNextInterrupts(TInt aInterruptCount); |
|
1069 |
|
1070 |
|
1071 /** Function allowing platform-specific layer to extend channel API with |
|
1072 new channel-specific operations. |
|
1073 |
|
1074 @param aCmd Command identifier. |
|
1075 @param aArg PSL-specific argument |
|
1076 |
|
1077 @return KErrNotSupported if aCmd is not supported. PSL-specific value |
|
1078 otherwise. |
|
1079 |
|
1080 @released |
|
1081 */ |
|
1082 IMPORT_C TInt Extension(TInt aCmd, TAny* aArg); |
|
1083 |
|
1084 |
|
1085 /** This is a function that allows the Platform Specific Layer (PSL) to |
|
1086 extend the DMA API with new channel-independent operations. |
|
1087 |
|
1088 @param aCmd Command identifier. |
|
1089 @param aArg PSL-specific. |
|
1090 |
|
1091 @return KErrNotSupported if aCmd is not supported; a PSL specific value |
|
1092 otherwise. |
|
1093 |
|
1094 @released |
|
1095 */ |
|
1096 IMPORT_C TInt StaticExtension(TInt aCmd, TAny* aArg); |
|
1097 |
|
1098 |
|
1099 /** @see DmacCaps() |
|
1100 |
|
1101 @deprecated |
|
1102 */ |
|
1103 inline const TDmac* Controller() const; |
|
1104 |
|
1105 /** @see MaxTransferLength() |
|
1106 |
|
1107 @deprecated |
|
1108 */ |
|
1109 inline TInt MaxTransferSize(TUint aFlags, TUint32 aPslInfo); |
|
1110 |
|
1111 /** @see AddressAlignMask() |
|
1112 |
|
1113 @deprecated |
|
1114 */ |
|
1115 inline TUint MemAlignMask(TUint aFlags, TUint32 aPslInfo); |
|
1116 |
|
1117 protected: |
|
1118 // Interface with state machines |
|
1119 |
|
1120 /** Constructor. |
|
1121 |
|
1122 @released |
|
1123 */ |
|
1124 TDmaChannel(); |
|
1125 |
|
1126 /** Called by the PIL when adding a new request to the channel's queue. |
|
1127 The implementation should update the channel's state as appropriate |
|
1128 and begin transfer of aReq if possible. |
|
1129 |
|
1130 @param aReq The request which has been added to the queue |
|
1131 |
|
1132 @released |
|
1133 */ |
|
1134 virtual void DoQueue(const DDmaRequest& aReq); |
|
1135 |
|
1136 /** Called by the PIL in response to a CancelAll call. It should update |
|
1137 the channel state appropriately. |
|
1138 |
|
1139 @released |
|
1140 */ |
|
1141 virtual void DoCancelAll() = 0; |
|
1142 |
|
1143 /** This is called by the PIL when a DDmaRequest is removed from the |
|
1144 channel's queue. In general the implementation simply needs to unlink |
|
1145 the hardware descriptor corresponding to aHdr from the next. |
|
1146 |
|
1147 Since the PIL links the hardware descriptor chains of adjacent queued |
|
1148 requests (for speed) it is necessary to break the chain when a request |
|
1149 is completed so that the request may be requeued by the client without |
|
1150 having called DDmaRequest::Fragment again. |
|
1151 |
|
1152 @param aHdr The header for a descriptor, which must be unlinked |
|
1153 from its next descriptor (if there is one) |
|
1154 |
|
1155 @released |
|
1156 */ |
|
1157 virtual void DoUnlink(SDmaDesHdr& aHdr); |
|
1158 |
|
1159 /** Called by the PIL whenever a transfer associated with aCurReq is |
|
1160 done. The implementation must advance the channel's state and |
|
1161 may transfer the next header if necessary (the provided |
|
1162 scatter-gather channel does not do this). It must also report |
|
1163 back which header was associated with the last transfer to |
|
1164 complete. |
|
1165 |
|
1166 @param aCurReq The current request. |
|
1167 @param aCompletedHdr Must be set by the implementation to the header |
|
1168 of the last transfer to complete. |
|
1169 |
|
1170 @released |
|
1171 */ |
|
1172 virtual void DoDfc(const DDmaRequest& aCurReq, SDmaDesHdr*& aCompletedHdr); |
|
1173 |
|
1174 /** Called by the PIL whenever a transfer associated with aCurReq is |
|
1175 done. The implementation must advance the channel's state and |
|
1176 may start the transfer for the next headers if necessary (the |
|
1177 provided scatter-gather channels do not do this). If one |
|
1178 header has a successor but the other is the last in the chain it |
|
1179 is an error. |
|
1180 |
|
1181 @note Must be implemented by PSL if channel uses asymmetric hardware |
|
1182 descriptors and is not derived from TDmaAsymSgChannel. |
|
1183 |
|
1184 @param aCurReq The current request. |
|
1185 |
|
1186 @param aSrcCompletedHdr Must be set by the implementation to |
|
1187 the header of the last source descriptor to complete. |
|
1188 |
|
1189 @param aDstCompletedHdr Must be set by the implementation to |
|
1190 the header of the last destination descriptor to complete. |
|
1191 |
|
1192 @prototype |
|
1193 */ |
|
1194 virtual void DoDfc(const DDmaRequest& aCurReq, SDmaDesHdr*& aSrcCompletedHdr, |
|
1195 SDmaDesHdr*& aDstCompletedHdr); |
|
1196 |
|
1197 /** This function allows the Platform Specific Layer (PSL) to control the |
|
1198 power management of the channel or its controller by overriding the |
|
1199 PIL's default implementation (which does nothing) and making |
|
1200 appropriate use of the Power Resource Manager (PRM). |
|
1201 |
|
1202 The function gets called by the PIL whenever the channel's queued |
|
1203 requests count has changed in a significant way, either before the |
|
1204 channel's Transfer() method is invoked for a request on a previously |
|
1205 empty request queue, or immediately after the request count has become |
|
1206 zero because of request cancellation or completion. |
|
1207 |
|
1208 Depending on the current and previous observed values of |
|
1209 iQueuedRequests, the PSL may power down or power up the channel. |
|
1210 |
|
1211 Note that iQueuedRequests gets accessed and changed by different |
|
1212 threads, so the PSL needs to take the usual precautions when evaluating |
|
1213 the variable's value. Also, due to the multithreaded framework |
|
1214 architecture, there is no guarantee that the function calls always |
|
1215 arrive at the PSL level in the strict chronological order of |
|
1216 iQueuedRequests being incremented/decremented in the PIL, i.e. it might |
|
1217 happen that the PSL finds iQueuedRequests to have the same value in two |
|
1218 or more consecutive calls (that's why the previous observed value needs |
|
1219 to be locally available and taken into account). It is however promised |
|
1220 that before any actual transfer commences the PSL will find the request |
|
1221 count to be greater than zero and that after the last request has |
|
1222 finished it will be found to be zero. |
|
1223 |
|
1224 None of the internal DMA framework mutexes is being held by the PIL |
|
1225 when calling this function. |
|
1226 |
|
1227 Here is an example implementation for a derived channel class: |
|
1228 |
|
1229 @code |
|
1230 |
|
1231 class TFooDmaChannel : public TDmaSgChannel |
|
1232 { |
|
1233 DMutex* iDmaMutex; |
|
1234 TInt iPrevQueuedRequests; |
|
1235 virtual void QueuedRequestCountChanged(); |
|
1236 }; |
|
1237 |
|
1238 void TFooDmaChannel::QueuedRequestCountChanged() |
|
1239 { |
|
1240 Kern::MutexWait(*iDmaMutex); |
|
1241 const TInt queued_now = __e32_atomic_load_acq32(&iQueuedRequests); |
|
1242 if ((queued_now > 0) && (iPrevQueuedRequests == 0)) |
|
1243 { |
|
1244 IncreasePowerCount(); // Base port specific |
|
1245 } |
|
1246 else if ((queued_now == 0) && (iPrevQueuedRequests > 0)) |
|
1247 { |
|
1248 DecreasePowerCount(); // Base port specific |
|
1249 } |
|
1250 iPrevQueuedRequests = queued_now; |
|
1251 Kern::MutexSignal(*iDmaMutex); |
|
1252 } |
|
1253 |
|
1254 @endcode |
|
1255 |
|
1256 @see iQueuedRequests |
|
1257 */ |
|
1258 virtual void QueuedRequestCountChanged(); |
|
1259 |
|
1260 virtual void SetNullPtr(const DDmaRequest& aReq); |
|
1261 virtual void ResetNullPtr(); |
|
1262 |
|
1263 inline virtual ~TDmaChannel() {} |
|
1264 |
|
1265 inline void Wait(); |
|
1266 inline void Signal(); |
|
1267 inline TBool Flash(); |
|
1268 |
|
1269 private: |
|
1270 static void Dfc(TAny*); |
|
1271 void DoDfc(); |
|
1272 |
|
1273 protected: |
|
1274 TDmac* iController; // DMAC this channel belongs to (NULL when closed) |
|
1275 const SDmacCaps* iDmacCaps; // what is supported by DMAC on this channel |
|
1276 TUint32 iPslId; // unique identifier provided by PSL |
|
1277 TBool iDynChannel; // this is a dynamically allocated channel |
|
1278 TUint iPriority; // hardware priority of this channel |
|
1279 NFastMutex iLock; // for data accessed in both client & DFC context |
|
1280 SDmaDesHdr* iCurHdr; // fragment being transferred or NULL |
|
1281 SDmaDesHdr** iNullPtr; // Pointer to NULL pointer following last fragment |
|
1282 TDfc iDfc; // transfer completion/failure DFC |
|
1283 TInt iMaxDesCount; // maximum number of allocable descriptors |
|
1284 TInt iAvailDesCount; // available number of descriptors |
|
1285 volatile TUint32 iIsrDfc; // Interface between ISR and DFC: |
|
1286 enum {KErrorFlagMask = 0x80000000}; // bit 31 - error flag |
|
1287 enum {KCancelFlagMask = 0x40000000}; // bit 30 - cancel flag |
|
1288 enum {KDfcCountMask = 0x3FFFFFFF}; // bits 0-29 - number of queued DFCs |
|
1289 SDblQue iReqQ; // being/about to be transferred request queue |
|
1290 TInt iReqCount; // number of requests attached to this channel |
|
1291 TInt iQueuedRequests; // number of requests currently queued on this channel |
|
1292 TBool iCallQueuedRequestFn; // call QueuedRequestCountChanged? (default: true) |
|
1293 |
|
1294 private: |
|
1295 TDmaCancelInfo* iCancelInfo; // ... |
|
1296 TBool iRedoRequest; // client ISR callback wants a redo of request |
|
1297 TBool iIsrCbRequest; // request on queue using ISR callback |
|
1298 |
|
1299 __DMA_DECLARE_VIRTUAL_INVARIANT |
|
1300 }; |
|
1301 |
|
1302 |
|
1303 ////////////////////////////////////////////////////////////////////////////// |
|
1304 // INTERFACE WITH TEST HARNESS |
|
1305 ////////////////////////////////////////////////////////////////////////////// |
|
1306 |
|
1307 /** Provides access to test information structure stored in the PSL. |
|
1308 |
|
1309 Must be implemented by the PSL (v1). |
|
1310 |
|
1311 @deprecated |
|
1312 */ |
|
1313 IMPORT_C const TDmaTestInfo& DmaTestInfo(); |
|
1314 |
|
1315 |
|
1316 /** Provides access to test information structure stored in the PSL. |
|
1317 |
|
1318 Must be implemented by the PSL (v2). |
|
1319 |
|
1320 @released |
|
1321 */ |
|
1322 IMPORT_C const TDmaV2TestInfo& DmaTestInfoV2(); |
|
1323 |
|
1324 |
|
1325 ////////////////////////////////////////////////////////////////////////////// |
|
1326 |
|
1327 |
|
1328 #include <drivers/dma_compat.inl> |
|
1329 #include <drivers/dma_v2.inl> |
|
1330 |
|
1331 |
|
1332 #endif // #ifndef __DMA_V2_H__ |