kernel/eka/include/drivers/dma_v2.h
branchRCL_3
changeset 256 c1f20ce4abcf
equal deleted inserted replaced
249:a179b74831c9 256:c1f20ce4abcf
       
     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__