kernel/eka/include/drivers/dma_hai.h
branchRCL_3
changeset 257 3e88ff8f41d5
parent 256 c1f20ce4abcf
child 258 880ff05ad710
child 263 9e2d4f7f5028
equal deleted inserted replaced
256:c1f20ce4abcf 257:3e88ff8f41d5
     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_hai.h
       
    15 // DMA Framework - Symbian Hardware Abstraction Interface (SHAI).
       
    16 //
       
    17 //
       
    18 
       
    19 /** @file
       
    20 	@publishedPartner
       
    21 	@released
       
    22 */
       
    23 
       
    24 #ifndef __DMA_HAI_H__
       
    25 #define __DMA_HAI_H__
       
    26 
       
    27 
       
    28 #include <kernel/kern_priv.h>
       
    29 
       
    30 
       
    31 //////////////////////////////////////////////////////////////////////////////
       
    32 
       
    33 
       
    34 /** Interface used by PIL to open and close DMA channels.
       
    35 
       
    36 	Must be implemented by the PSL.
       
    37 */
       
    38 class DmaChannelMgr
       
    39 	{
       
    40 
       
    41 public:
       
    42 	/** Opens a channel using a client-provided identifier.
       
    43 
       
    44 		This function must be implemented by the PSL.
       
    45 
       
    46 		@param aOpenId PSL-specific magic cookie passed by client. This could
       
    47 		identify the channel exactly (by being just the channel number), or at
       
    48 		least sufficiently (for example for use with a certain peripheral), or
       
    49 		it may indicate some properties which the channel must possess. It may
       
    50 		be set to zero always if all channels are equivalent.
       
    51 
       
    52 		@param aDynChannel ETrue if the Open call is for a dynamic channel. A
       
    53 		dynamic channel is not exclusively reserved for just one client, and
       
    54 		further Open calls for more dynamic channels should succeed as long as
       
    55 		certain resources (but not including the number of available physical
       
    56 		channels) are not exceeded. Different transfer requests on this dynamic
       
    57 		channel may be serviced using different actual channels.
       
    58 
       
    59 		@param aPriority The desired channel priority as requested by the
       
    60 		client. This may be an actual hardware priority or a
       
    61 		platform-independent value. Not being able to satisfy the requested
       
    62 		value is not a reason for the PSL to return NULL. This parameter may be
       
    63 		ignored if aDynChannel is passed as ETrue. An overriding per-transfer
       
    64 		priority may be requested by a client later via
       
    65 		TDmaTransferArgs::iChannelPriority.
       
    66 		@see SDmacCaps::iChannelPriorities
       
    67 		@see TDmaPriority
       
    68 
       
    69 		@return Pointer to channel if available, NULL otherwise. It should not
       
    70 		be NULL if the Open call was for a dynamic channel unless a processing
       
    71 		error occurred.
       
    72 
       
    73 		@pre The PIL calls this function with a global fast mutex held to avoid
       
    74 		race conditions.
       
    75 
       
    76 		@post If a non-NULL pointer is returned, the object pointed to has its
       
    77 		iController, iDmacCaps, iPslId, iDynChannel and iPriority members set
       
    78 		to valid states.
       
    79 
       
    80 		iController should point to the controller handling the
       
    81 		channel.
       
    82 
       
    83 		iDmacCaps should point to a SDmacCaps structure containing values
       
    84 		relating to this particular channel.
       
    85 
       
    86 		iPslId should contain a value uniquely identifying the channel - the
       
    87 		PIL assigns this value later during request fragmentation to
       
    88 		TDmaTransferArgs::iChannelCookie. It can be given any convenient value
       
    89 		by the PSL (channel index, I/O port address, etc.).
       
    90 
       
    91 		iDynChannel should be set to ETrue by the PSL if a dynamic channel was
       
    92 		requested and has been opened.
       
    93 
       
    94 		If applicable, iPriority should contain the actual hardware priority
       
    95 		that has been configured or reserved. Otherwise it may be left at its
       
    96 		default value TDmaPriority::KDmaPriorityNone.
       
    97 	*/
       
    98 	static TDmaChannel* Open(TUint32 aOpenId, TBool aDynChannel, TUint aPriority);
       
    99 
       
   100 
       
   101 	/** Performs platform-specific operations when a channel is closed.
       
   102 
       
   103 		If aChannel was opened as a dynamic channel then this call is a sign
       
   104 		that there is a client which does not intend to queue any further
       
   105 		transfer requests via this channel.
       
   106 
       
   107 		This function must be implemented by the PSL but the implementation can
       
   108 		be a no-op.
       
   109 
       
   110 		@param aChannel The channel to close
       
   111 
       
   112 		@pre The PIL calls this function with a global fast mutex held to avoid
       
   113 		race conditions.
       
   114 	*/
       
   115 	static void Close(TDmaChannel* aChannel);
       
   116 
       
   117 
       
   118 	/** Function allowing PSL to extend DMA API with new channel-independent
       
   119 		operations.
       
   120 
       
   121 		This function must be implemented by the PSL.
       
   122 
       
   123 		@param aCmd Command identifier. Negative values are reserved for FW
       
   124 		internal use.
       
   125 
       
   126 		@param aArg PSL-specific
       
   127 
       
   128 		@return KErrNotSupported if aCmd is not supported. PSL-specific value
       
   129 		otherwise.
       
   130 	*/
       
   131 	static TInt StaticExtension(TInt aCmd, TAny* aArg);
       
   132 
       
   133 
       
   134 	/** Acquires the channel manager lock. Called by the PIL before opening and
       
   135 		closing a channel.
       
   136 	*/
       
   137 	static void Wait();
       
   138 
       
   139 
       
   140 	/** Releases the channel manager lock. Called by the PIL after opening and
       
   141 		closing a channel.
       
   142 	*/
       
   143 	static void Signal();
       
   144 
       
   145 private:
       
   146 	/** Declared, defined, and called by PSL's DECLARE_STANDARD_EXTENSION(). */
       
   147 	friend TInt InitExtension();
       
   148 
       
   149 	/** Must be called in the PSL's DECLARE_STANDARD_EXTENSION(). */
       
   150 	static TInt Initialise();
       
   151 
       
   152 	static NFastMutex Lock;
       
   153 	};
       
   154 
       
   155 
       
   156 //////////////////////////////////////////////////////////////////////////////
       
   157 
       
   158 
       
   159 /** Abstract base class representing a DMA controller.
       
   160 
       
   161 	The class has two purposes.
       
   162 
       
   163 	First, it is a container for channels, descriptors and descriptor headers.
       
   164 
       
   165 	Second, it exposes a set of virtual functions implemented by the PSL
       
   166 	(platform-specific layer).
       
   167 
       
   168 	These functions are the main interfaces between the PIL
       
   169 	(platform-independent layer) and PSL.
       
   170 */
       
   171 class TDmac
       
   172 	{
       
   173 friend class DmaChannelMgr;
       
   174 
       
   175 // The following friend declaration will become obsolete once header
       
   176 // pool manipulation functionality is owned and provided by the controller
       
   177 // class instead of the request class.
       
   178 // (TDmac::iFreeHdr could then also be made private.)
       
   179 friend class DDmaRequest;
       
   180 
       
   181 friend class TSkelDmac;
       
   182 
       
   183 protected:
       
   184 	/** Data required for creating a new instance. */
       
   185 	struct SCreateInfo
       
   186 		{
       
   187 		/** True if DMAC uses hardware descriptors (i.e. supports
       
   188 			scatter/gather mode).
       
   189 		*/
       
   190 		TBool iCapsHwDes;
       
   191 
       
   192 		/** Initial maximum number of descriptors and headers (shared by all
       
   193 			channels) to be allocated by the PIL. If at run time more
       
   194 			descriptors are needed then they will be dynamically allocated and
       
   195 			added to the available pool.
       
   196 
       
   197 			The PSL may consider a number of factors when providing this
       
   198 			initial value, such as the number of channels on this controller,
       
   199 			the maximum transfer size per descriptor and also likely usage
       
   200 			scenarios for the platform or device (number of drivers using DMA,
       
   201 			their traffic patterns, simultaneity of operations, etc.).
       
   202 
       
   203 			(NB: Dynamic growing of the descriptor pool is not yet implemented
       
   204 			in the PIL, so this value is currently also the final maximum
       
   205 			number of descriptors.)
       
   206 		*/
       
   207 		TInt iDesCount;
       
   208 
       
   209 		/** Size of an individual descriptor.
       
   210 
       
   211 			Use sizeof(TDmaTransferArgs) for single-buffer and double-buffer
       
   212 		 	(i.e. non-s/g) controllers.
       
   213 		*/
       
   214 		TInt iDesSize;
       
   215 
       
   216 		/** Bitmask used when creating the memory chunk storing the descriptor
       
   217 			pool in the PIL. Used only for hardware descriptors.
       
   218 
       
   219 			The access part must be EMapAttrSupRw. If the chunk is cached
       
   220 			and/or buffered, the PSL must flush the data cache and/or drain the
       
   221 			write buffer in InitHwDes() and related functions.
       
   222 
       
   223 			The physical start address of the chunk will always be MMU page
       
   224 		 	size aligned.
       
   225 
       
   226 		 	@see TMappingAttributes
       
   227 		 */
       
   228 		TUint iDesChunkAttribs;
       
   229 		};
       
   230 
       
   231 	/** Base class constructor.
       
   232 	 */
       
   233 	TDmac(const SCreateInfo& aInfo);
       
   234 
       
   235 	/** Base class 2nd-phase constructor.
       
   236 	 */
       
   237 	TInt Create(const SCreateInfo& aInfo);
       
   238 
       
   239 public:
       
   240 	/** Base class virtual destructor.
       
   241 	 */
       
   242 	virtual ~TDmac();
       
   243 
       
   244 
       
   245 	/** Allocates a number of headers (and hence also descriptors) from the
       
   246 		header/descriptor pools. Called by the PIL but may also be used by the
       
   247 		PSL.
       
   248 	*/
       
   249 	TInt ReserveSetOfDes(TInt aCount);
       
   250 
       
   251 
       
   252 	/** Returns previously allocated headers (and hence also descriptors) to
       
   253 		the header/descriptor pools. Called by the PIL but may also be used by
       
   254 		the PSL.
       
   255 	*/
       
   256 	void ReleaseSetOfDes(TInt aCount);
       
   257 
       
   258 
       
   259 	/** Called by the PIL during request fragmentation to fill a descriptor or
       
   260 		pseudo descriptor with transfer arguments.
       
   261 	*/
       
   262 	TInt InitDes(const SDmaDesHdr& aHdr, const TDmaTransferArgs& aTransferArgs);
       
   263 
       
   264 
       
   265 	/** Called by the PIL in TDmaChannel::IsrRedoRequest() if any of the
       
   266 		latter's arguments is non-zero.
       
   267 	*/
       
   268 	TInt UpdateDes(const SDmaDesHdr& aHdr, TUint32 aSrcAddr, TUint32 aDstAddr,
       
   269 				   TUint aTransferCount, TUint32 aPslRequestInfo);
       
   270 
       
   271 
       
   272 	/** Returns a reference to the associated pseudo descriptor for a given
       
   273 		descriptor header. For use by PIL and PSL.
       
   274 	*/
       
   275 	inline TDmaTransferArgs& HdrToDes(const SDmaDesHdr& aHdr) const;
       
   276 
       
   277 
       
   278 	/** Returns a reference to the associated hardware descriptor for a given
       
   279 		descriptor header. For use by PIL and PSL.
       
   280 	*/
       
   281 	inline TAny* HdrToHwDes(const SDmaDesHdr& aHdr) const;
       
   282 
       
   283 
       
   284 	/** Returns the physical address of the hardware descriptor
       
   285 		pointed to by aDes. For use by PIL and PSL.
       
   286 	*/
       
   287 	inline TUint32 HwDesLinToPhys(TAny* aDes) const;
       
   288 
       
   289 
       
   290 	/** Called by PIL when one fragment (single-buffer and double-buffer DMACs)
       
   291 		or list of fragments (scatter/gather DMAC) is to be transferred.
       
   292 
       
   293 		Called when initiating a new transfer and also, for double-buffer
       
   294 		DMACs, for configuring the next fragment to transfer while the current
       
   295 		one is ongoing.
       
   296 
       
   297 		The function must be implemented by the PSL if
       
   298 		SCreateInfo::iCaps::iAsymHwDescriptors is reported as false.
       
   299 
       
   300 		@note This function may be called in thread or ISR context by the PIL
       
   301 
       
   302 		@param aChannel The channel to use.
       
   303 		@param aHdr Header associated with fragment to transfer.
       
   304 	*/
       
   305 	virtual void Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aHdr);
       
   306 
       
   307 
       
   308 	/** Called by PIL when two lists of fragments (scatter/gather DMAC with
       
   309 		asymmetrical linked-list capability) are to be transferred.
       
   310 
       
   311 		Called when initiating a new transfer.
       
   312 
       
   313 		The function must be implemented by the PSL if
       
   314 		SDmaCaps::iAsymHwDescriptors is reported as true.
       
   315 
       
   316 		@note This function may be called in thread or ISR context by the PIL
       
   317 
       
   318 		@param aChannel The channel to use.
       
   319 		@param aSrcHdr Header associated with descriptor to transfer on the
       
   320 		source side.
       
   321 		@param aDstHdr Header associated with descriptor to transfer on the
       
   322 		destination side.
       
   323 	*/
       
   324 	virtual void Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aSrcHdr,
       
   325 						  const SDmaDesHdr& aDstHdr);
       
   326 
       
   327 
       
   328 	/** Called by PIL to stop a transfer on a given channel.
       
   329 
       
   330 		The stopping must occur synchronously as the PIL assumes the channel
       
   331 		is halted after calling this function. A channel stopped via this
       
   332 		function is not intended to be resumed. Function must always be
       
   333 		implemented by the PSL.
       
   334 
       
   335 		@param aChannel The channel to stop
       
   336 		@post The channel will be idle
       
   337 		@post No interrupt will occur from this channel until a new
       
   338 		request is queued.
       
   339 	*/
       
   340 	virtual void StopTransfer(const TDmaChannel& aChannel) = 0;
       
   341 
       
   342 
       
   343 	/** Called by PIL to pause (suspend) a transfer on a given channel.
       
   344 
       
   345 		A paused channel transfer must be able to be resumed by calling
       
   346 		ResumeTransfer().
       
   347 
       
   348 		The function must be implemented by the PSL if
       
   349 		SDmacCaps::iChannelPauseAndResume is reported as true.
       
   350 
       
   351 		@return KErrNone if the transfer has been paused successfully,
       
   352 		KErrCompletion if the transfer was already paused, KErrGeneral
       
   353 		if a general error occurred preventing a successful outcome.
       
   354 
       
   355 		@post No interrupt will occur from this channel until it is
       
   356 		resumed.
       
   357 	*/
       
   358 	virtual TInt PauseTransfer(const TDmaChannel& aChannel);
       
   359 
       
   360 
       
   361 	/** Called by PIL to resume a paused (suspended) transfer on a given
       
   362 		channel.
       
   363 
       
   364 		Resume() can be called when the transfer is paused as a result of a
       
   365 		previous call to PauseTransfer() or because the DMAC has encountered a
       
   366 		Pause bit in a H/W descriptor.
       
   367 
       
   368 		The function must be implemented by the PSL if
       
   369 		SDmacCaps::iChannelPauseAndResume or
       
   370 		SDmacCaps::iLinkedListPausedInterrupt is reported as true.
       
   371 
       
   372 		@return KErrNone if the transfer has been resumed successfully,
       
   373 		KErrCompletion if there was no paused transfer, KErrGeneral
       
   374 		if a general error occurred preventing a successful outcome.
       
   375 	*/
       
   376 	virtual TInt ResumeTransfer(const TDmaChannel& aChannel);
       
   377 
       
   378 
       
   379 	/** Called by PIL to check whether a DMA channel is idle.
       
   380 
       
   381 		'Idle' here means that the channel is ultimately stopped, for example
       
   382 		because the transfer has finished, or an error was encountered, or it
       
   383 		was manually stopped, but not because it was manually suspended (aka
       
   384 		'paused'), or it is waiting for a request line assertion to start the
       
   385 		transfer.
       
   386 
       
   387 		@param aChannel The channel to test
       
   388 
       
   389 		@return ETrue if channel idle, EFalse if transferring.
       
   390 	*/
       
   391 	virtual TBool IsIdle(const TDmaChannel& aChannel) = 0;
       
   392 
       
   393 
       
   394 	/** Called by PIL to retrieve from the PSL the maximum transfer length
       
   395 		based on the parameters passed.
       
   396 
       
   397 		@param aChannel Channel to be used for the transfer
       
   398 		@param aSrcFlags Bitmask characterising transfer source
       
   399 		@see TDmaTransferArgs::iSrcConfig::iFlags
       
   400 		@param aDstFlags Bitmask characterising transfer destination
       
   401 		@see TDmaTransferArgs::iDstConfig::iFlags
       
   402 		@param aPslInfo Cookie passed by client and used by the PSL
       
   403 		@see TDmaTransferArgs::iPslRequestInfo
       
   404 
       
   405 		@return 0 if transfer length is not limited, the maximum transfer
       
   406 		length in bytes otherwise.
       
   407 	*/
       
   408 	virtual TUint MaxTransferLength(TDmaChannel& aChannel, TUint aSrcFlags,
       
   409 									TUint aDstFlags, TUint32 aPslInfo) = 0;
       
   410 
       
   411 
       
   412 	/** Called by PIL to retrieve from the PSL the memory alignment mask based
       
   413 		on the parameters passed. Some DMA controllers impose alignment
       
   414 		constraints on the base address of memory buffers. This mask is AND'ed
       
   415 		against memory addresses computed during fragmentation.
       
   416 
       
   417 		The PIL will call this function separately for source and destination.
       
   418 
       
   419 		An assumption is that the PSL doesn't need to know if a call to this
       
   420 		function is for the source or the destination side, i.e. both ports
       
   421 		are, as far as the alignment is concerned, equivalent. All that matters
       
   422 		are the values of the relevant configuration parameters.
       
   423 
       
   424 		Another assumption is that the alignment requirement for a port on a
       
   425 		DMAC with potentially different values for source and destination does
       
   426 		not depend on the configuration of the respective other port.
       
   427 
       
   428 		@param aChannel Channel used for the transfer
       
   429 		@param aTargetFlags Bitmask characterising transfer source or
       
   430 		destination
       
   431 		@see TDmaTransferArgs::iSrcConfig::iFlags
       
   432 		@see TDmaTransferArgs::iDstConfig::iFlags
       
   433 		@param aElementSize Element size used for the transfer. May be zero if
       
   434 		not known or 'don't care'.
       
   435 		@param aPslInfo Cookie passed by client and used by the PSL
       
   436 		@see TDmaTransferArgs::iPslRequestInfo
       
   437 
       
   438 		@return A value representing the alignment mask (e.g. 3 if buffer must
       
   439 		be 4-byte aligned)
       
   440 	*/
       
   441 	virtual TUint AddressAlignMask(TDmaChannel& aChannel, TUint aTargetFlags,
       
   442 								   TUint aElementSize, TUint32 aPslInfo) = 0;
       
   443 
       
   444 
       
   445 	/** Called by PIL during fragmentation to initialise a hardware descriptor.
       
   446 
       
   447 		The PSL must assume the descriptor is the last in the chain and so set
       
   448 		the interrupt bit and set the next descriptor field to an end of chain
       
   449 		marker.
       
   450 
       
   451 		The function must be implemented by the PSL if and only if the DMAC
       
   452 		supports hardware descriptors and SDmaCaps::iAsymHwDescriptors is
       
   453 		reported as false.
       
   454 
       
   455 		@param aHdr Header associated with the hardware descriptor to
       
   456 		initialise
       
   457 		@param aTransferArgs The transfer parameters for this descriptor
       
   458 
       
   459 		@return KErrNone if the descriptor was successfully initialized,
       
   460 		KErrArgument if any of the transfer arguments were detected to be
       
   461 		invalid, KErrGeneral if a general error occurred preventing a
       
   462 		successful outcome.
       
   463 	*/
       
   464 	virtual TInt InitHwDes(const SDmaDesHdr& aHdr, const TDmaTransferArgs& aTransferArgs);
       
   465 
       
   466 
       
   467 	/** Called by PIL during fragmentation to initialise a hardware descriptor
       
   468 		on the source side of an asymmetric linked list.
       
   469 
       
   470 		The function must be implemented by the PSL if
       
   471 		SDmaCaps::iAsymHwDescriptors is reported as true.
       
   472 
       
   473 		@param aHdr Header associated with the hardware descriptor to
       
   474 		initialise
       
   475 		@param aTransferArgs The transfer parameters for this descriptor. Only
       
   476 		the elements relating to the source side should be relevant to the
       
   477 		implementation.
       
   478 
       
   479 		@return KErrNone if the descriptor was successfully initialized,
       
   480 		KErrArgument if any of the transfer arguments were detected to be
       
   481 		invalid, KErrGeneral if a general error occurred preventing a
       
   482 		successful outcome.
       
   483 	*/
       
   484 	virtual TInt InitSrcHwDes(const SDmaDesHdr& aHdr, const TDmaTransferArgs& aTransferArgs);
       
   485 
       
   486 
       
   487 	/** Called by PIL during fragmentation to initialise a hardware descriptor
       
   488 		on the destination side of an asymmetric linked list.
       
   489 
       
   490 		The function must be implemented by the PSL if
       
   491 		SDmaCaps::iAsymHwDescriptors is reported as true.
       
   492 
       
   493 		@param aHdr Header associated with the hardware descriptor to
       
   494 		initialise
       
   495 		@param aTransferArgs The transfer parameters for this descriptor. Only
       
   496 		the elements relating to the destination side should be relevant to the
       
   497 		implementation.
       
   498 
       
   499 		@return KErrNone if the descriptor was successfully initialized,
       
   500 		KErrArgument if any of the transfer arguments were detected to be
       
   501 		invalid, KErrGeneral if a general error occurred preventing a
       
   502 		successful outcome.
       
   503 	*/
       
   504 	virtual TInt InitDstHwDes(const SDmaDesHdr& aHdr, const TDmaTransferArgs& aTransferArgs);
       
   505 
       
   506 
       
   507 	/** Called by the PIL in ISR context to change specific fields in a
       
   508 		hardware descriptor.
       
   509 
       
   510 		The function must be implemented by the PSL if and only if the DMAC
       
   511 		supports hardware descriptors and SDmaCaps::iAsymHwDescriptors is
       
   512 		reported as false.
       
   513 
       
   514 		@param aHdr Header associated with the hardware descriptor to be
       
   515 		updated
       
   516 		@param aSrcAddr @see TDmaTransferArgs::iSrcConfig::iAddr
       
   517 		@param aDstAddr @see TDmaTransferArgs::iDstConfig::iAddr
       
   518 		@param aTransferCount @see TDmaTransferArgs::iTransferCount
       
   519 		@param aPslRequestInfo @see TDmaTransferArgs::iPslRequestInfo
       
   520 
       
   521 		Since Epoc::LinearToPhysical() cannot be called in ISR context the
       
   522 		addresses passed into this function are always physical ones, i.e.
       
   523 		TDmaTransferFlags::KDmaPhysAddr is implied.
       
   524 
       
   525 		@return KErrNone if the descriptor was successfully modified,
       
   526 		KErrArgument if any of the transfer arguments were detected to be
       
   527 		invalid, KErrGeneral if a general error occurred preventing a
       
   528 		successful outcome.
       
   529 	*/
       
   530 	virtual TInt UpdateHwDes(const SDmaDesHdr& aHdr, TUint32 aSrcAddr, TUint32 aDstAddr,
       
   531 							 TUint aTransferCount, TUint32 aPslRequestInfo);
       
   532 
       
   533 
       
   534 	/** Called by the PIL in ISR context to change specific fields in a
       
   535 		hardware descriptor.
       
   536 
       
   537 		The function must be implemented by the PSL if
       
   538 		SDmaCaps::iAsymHwDescriptors is reported as true.
       
   539 
       
   540 		@param aHdr Header associated with the hardware descriptor to be
       
   541 		updated
       
   542 		@param aSrcAddr @see TDmaTransferArgs::iSrcConfig::iAddr
       
   543 		@param aTransferCount @see TDmaTransferArgs::iTransferCount
       
   544 		@param aPslRequestInfo @see TDmaTransferArgs::iPslRequestInfo
       
   545 
       
   546 		Since Epoc::LinearToPhysical() cannot be called in ISR context the
       
   547 		address passed into this function is always a physical ones, i.e.
       
   548 		TDmaTransferFlags::KDmaPhysAddr is implied.
       
   549 
       
   550 		@return KErrNone if the descriptor was successfully modified,
       
   551 		KErrArgument if any of the transfer arguments were detected to be
       
   552 		invalid, KErrGeneral if a general error occurred preventing a
       
   553 		successful outcome.
       
   554 	*/
       
   555 	virtual TInt UpdateSrcHwDes(const SDmaDesHdr& aHdr, TUint32 aSrcAddr,
       
   556 								TUint aTransferCount, TUint32 aPslRequestInfo);
       
   557 
       
   558 
       
   559 	/** Called by the PIL in ISR context to change specific fields in a
       
   560 		hardware descriptor.
       
   561 
       
   562 		The function must be implemented by the PSL if
       
   563 		SDmaCaps::iAsymHwDescriptors is reported as true.
       
   564 
       
   565 		@param aHdr Header associated with the hardware descriptor to be
       
   566 		updated
       
   567 		@param aDstAddr @see TDmaTransferArgs::iDstConfig::iAddr
       
   568 		@param aTransferCount @see TDmaTransferArgs::iTransferCount
       
   569 		@param aPslRequestInfo @see TDmaTransferArgs::iPslRequestInfo
       
   570 
       
   571 		Since Epoc::LinearToPhysical() cannot be called in ISR context the
       
   572 		address passed into this function is always a physical ones, i.e.
       
   573 		TDmaTransferFlags::KDmaPhysAddr is implied.
       
   574 
       
   575 		@return KErrNone if the descriptor was successfully modified,
       
   576 		KErrArgument if any of the transfer arguments were detected to be
       
   577 		invalid, KErrGeneral if a general error occurred preventing a
       
   578 		successful outcome.
       
   579 	*/
       
   580 	virtual TInt UpdateDstHwDes(const SDmaDesHdr& aHdr, TUint32 aDstAddr,
       
   581 								TUint aTransferCount, TUint32 aPslRequestInfo);
       
   582 
       
   583 
       
   584 	/** Called by PIL, when fragmenting a request, to append a new hardware
       
   585 		descriptor to an existing descriptor chain. May also be called by
       
   586 		clients who wish to create their own descriptor chains.
       
   587 
       
   588 		Must clear the interrupt bit of the descriptor associated with aHdr.
       
   589 
       
   590 		The function must be implemented by the PSL if and only if the DMAC
       
   591 		supports hardware descriptors.
       
   592 
       
   593 		@param aHdr Header associated with last fragment in chain
       
   594 		@param aNextHdr Header associated with fragment to append
       
   595 	*/
       
   596 	virtual void ChainHwDes(const SDmaDesHdr& aHdr, const SDmaDesHdr& aNextHdr);
       
   597 
       
   598 
       
   599 	/** Called by PIL when queuing a new request while the channel is running.
       
   600 
       
   601 		Must append the first hardware descriptor of the new request to the
       
   602 		last descriptor in the existing chain.
       
   603 
       
   604 		The function must be implemented by the PSL if and only if the DMAC
       
   605 		supports hardware descriptors.
       
   606 
       
   607 		@param aChannel The channel where the transfer takes place
       
   608 		@param aLastHdr Header associated with last hardware descriptor in
       
   609 		chain
       
   610 		@param aNewHdr Header associated with first hardware descriptor in new
       
   611 		request
       
   612 	*/
       
   613 	virtual void AppendHwDes(const TDmaChannel& aChannel, const SDmaDesHdr& aLastHdr,
       
   614 							 const SDmaDesHdr& aNewHdr);
       
   615 
       
   616 
       
   617 	/** Called by PIL when queuing a new request while the channel is running.
       
   618 
       
   619 		Must append the first hardware descriptor of the new request to the
       
   620 		last descriptor in the existing chain.
       
   621 
       
   622 		The function must be implemented by the PSL if
       
   623 		SDmaCaps::iAsymHwDescriptors is reported as true.
       
   624 
       
   625 		@param aChannel The channel where the transfer takes place
       
   626 		@param aSrcLastHdr Header associated with the last descriptor in the
       
   627 		source side chain
       
   628 		@param aSrcNewHdr Header associated with the first source side
       
   629 		descriptor of the new request
       
   630 		@param aDstLastHdr Header associated with the last descriptor in the
       
   631 		destination side chain
       
   632 		@param aDstNewHdr Header associated with the first destination side
       
   633 		descriptor of the new request
       
   634 	*/
       
   635 	virtual void AppendHwDes(const TDmaChannel& aChannel,
       
   636 							 const SDmaDesHdr& aSrcLastHdr, const SDmaDesHdr& aSrcNewHdr,
       
   637 							 const SDmaDesHdr& aDstLastHdr, const SDmaDesHdr& aDstNewHdr);
       
   638 
       
   639 
       
   640 	/** Called by PIL when completing or cancelling a request to cause the PSL
       
   641 		to unlink the last item in the h/w descriptor chain from a subsequent
       
   642 		chain that it was possibly linked to.
       
   643 
       
   644 		The function must be implemented by the PSL if and only if the DMAC
       
   645 		supports hardware descriptors.
       
   646 
       
   647 		@param aChannel The channel where the request (and thus the descriptor)
       
   648 		was queued
       
   649 		@param aHdr Header associated with last h/w descriptor in
       
   650 		completed / cancelled chain
       
   651 	*/
       
   652 	virtual void UnlinkHwDes(const TDmaChannel& aChannel, SDmaDesHdr& aHdr);
       
   653 
       
   654 
       
   655 	/** Called by PIL when freeing descriptors back to the shared pool in
       
   656 		FreeDesList(). The PSL inside ClearHwDes() can clear the contents of
       
   657 		the h/w descriptor.
       
   658 
       
   659 		This may be necessary if the PSL implementation uses the h/w descriptor
       
   660 		as another header which in turn points to the actual DMA h/w descriptor
       
   661 		(aka LLI).
       
   662 
       
   663 		The function may be implemented by the PSL if the DMAC supports
       
   664 		hardware descriptors.
       
   665 
       
   666 		@param aHdr Header associated with the h/w descriptor being freed.
       
   667 	*/
       
   668 	virtual void ClearHwDes(const SDmaDesHdr& aHdr);
       
   669 
       
   670 
       
   671 	/** Called by PIL to logically link two physical channels.
       
   672 
       
   673 		The function must be implemented by the PSL if the DMAC supports
       
   674 		logical channel linking.
       
   675 
       
   676 		@see SDmacCaps::iChannelLinking
       
   677 
       
   678 		@param a1stChannel The channel which is to be linked to another channel
       
   679 		@param a2ndChannel The channel the first one is to be linked to
       
   680 
       
   681 		@return KErrNone if the two channels have been linked successfully,
       
   682 		KErrCompletion if a1stChannel was already linked to a2ndChannel,
       
   683 		KErrArgument if a1stChannel was already linked to a different channel,
       
   684 		KErrGeneral if a general error occurred preventing a successful
       
   685 		outcome. The default PIL implementation returns KErrNotSupported.
       
   686 	*/
       
   687 	virtual TInt LinkChannels(TDmaChannel& a1stChannel, TDmaChannel& a2ndChannel);
       
   688 
       
   689 
       
   690 	/** Called by PIL to logically unlink a physical channel from its linked-to
       
   691 		successor.
       
   692 
       
   693 		The function must be implemented by the PSL if the DMAC supports
       
   694 		logical channel linking.
       
   695 
       
   696 		@see SDmacCaps::iChannelLinking
       
   697 
       
   698 		@param aChannel The channel which is to be unlinked from its successor
       
   699 
       
   700 		@return KErrNone if the channel has been unlinked successfully,
       
   701 		KErrCompletion if the channel was not linked to another channel,
       
   702 		KErrGeneral if a general error occurred preventing a successful
       
   703 		outcome. The default PIL implementation returns KErrNotSupported.
       
   704 	*/
       
   705 	virtual TInt UnlinkChannel(TDmaChannel& aChannel);
       
   706 
       
   707 
       
   708 	/** Called by a test harness to force an error when the next fragment is
       
   709 		transferred.
       
   710 
       
   711 		Must be implemented by the PSL only if possible.
       
   712 
       
   713 		@param aChannel The channel where the error is to occur.
       
   714 
       
   715 		@return KErrNone if implemented. The default PIL implementation
       
   716 		returns KErrNotSupported.
       
   717 	*/
       
   718 	virtual TInt FailNext(const TDmaChannel& aChannel);
       
   719 
       
   720 
       
   721 	/** Called by a test harness to force the DMA controller to miss one or
       
   722 		more interrupts.
       
   723 
       
   724 		The function must be implemented by the PSL only if possible.
       
   725 
       
   726 		@param aChannel The channel where the error is to occur
       
   727 		@param aInterruptCount The number of interrupt to miss.
       
   728 
       
   729 		@return KErrNone if implemented. The default PIL implementation
       
   730 		returns KErrNotSupported.
       
   731 	*/
       
   732 	virtual TInt MissNextInterrupts(const TDmaChannel& aChannel, TInt aInterruptCount);
       
   733 
       
   734 
       
   735 	/** Function allowing platform-specific layer to extend channel API with
       
   736 		new channel-specific operations.
       
   737 
       
   738 		@see TDmaChannel::ChannelExtension
       
   739 
       
   740 		@param aChannel Channel to operate on
       
   741 		@param aCmd Command identifier. Negative values are reserved for use by
       
   742 		Nokia.
       
   743 		@param aArg PSL-specific argument
       
   744 
       
   745 		@return KErrNotSupported if aCmd is not supported. PSL-specific value
       
   746 		otherwise.
       
   747 	*/
       
   748 	virtual TInt Extension(TDmaChannel& aChannel, TInt aCmd, TAny* aArg);
       
   749 
       
   750 
       
   751 	/** Called by the PIL to query the number of elements that have so far been
       
   752 		transferred by the hardware descriptor associated with aHdr at the
       
   753 		source port.
       
   754 
       
   755 		If SDmacCaps::iAsymHwDescriptors is true then the PIL will call this
       
   756 		function only for source-side descriptors, and the PSL should fault the
       
   757 		kernel if this is not the case.
       
   758 
       
   759 		The function must be implemented (i.e. overridden) by the PSL if and
       
   760 		only if the DMAC supports hardware descriptors.
       
   761 
       
   762 		@param aHdr Descriptor header associated with the hardware descriptor
       
   763 		to be queried
       
   764 
       
   765 		@return The number of elements that have been transferred by the
       
   766 		hardware descriptor associated with aHdr at the source port
       
   767 	*/
       
   768 	virtual TUint32 HwDesNumSrcElementsTransferred(const SDmaDesHdr& aHdr);
       
   769 
       
   770 
       
   771 	/** Called by the PIL to query the number of elements that have so far been
       
   772 		transferred by the hardware descriptor associated with aHdr at the
       
   773 		destination port.
       
   774 
       
   775 		If SDmacCaps::iAsymHwDescriptors is true then the PIL will call this
       
   776 		function only for destination-side descriptors, and the PSL should
       
   777 		panic if this is not the case.
       
   778 
       
   779 		The function must be implemented (i.e. overridden) by the PSL if and
       
   780 		only if the DMAC supports hardware descriptors.
       
   781 
       
   782 		@param aHdr Descriptor header associated with the hardware descriptor
       
   783 		to be queried
       
   784 
       
   785 		@return The number of elements that have been transferred by the
       
   786 		hardware descriptor associated with aHdr at the destination port
       
   787 	*/
       
   788 	virtual TUint32 HwDesNumDstElementsTransferred(const SDmaDesHdr& aHdr);
       
   789 
       
   790 protected:
       
   791 	/** Called by the PSL in interrupt context upon a channel interrupt event.
       
   792 
       
   793 		@param aChannel The channel the ISR relates to
       
   794 		@param aEventMask Bitmask of one or more TDmaCallbackType values
       
   795 		@param aIsComplete Set to ETrue if no error was encountered
       
   796 	*/
       
   797 	static void HandleIsr(TDmaChannel& aChannel, TUint aEventMask, TBool aIsComplete);
       
   798 
       
   799 private:
       
   800 	/** Called in Create() */
       
   801 	TInt AllocDesPool(TUint aAttribs);
       
   802 
       
   803 	/** Called in ~TDmac() */
       
   804 	void FreeDesPool();
       
   805 
       
   806 	/** Called by the PIL to acquire the controller lock which protects the
       
   807 		header and descriptor pools.
       
   808 	*/
       
   809 	inline void Wait();
       
   810 
       
   811 	/** Called by the PIL to release the controller lock which protects the
       
   812 		header and descriptor pools.
       
   813 	*/
       
   814 	inline void Signal();
       
   815 
       
   816 private:
       
   817 	NFastMutex iLock;			 // protect descriptor reservation and allocation
       
   818 	const TInt iMaxDesCount;	 // initial number of descriptors and headers
       
   819 	TInt iAvailDesCount;		 // current available number of descriptors and headers
       
   820 	SDmaDesHdr* iHdrPool;		 // descriptor header dynamic array
       
   821 #ifndef __WINS__
       
   822 	DPlatChunkHw* iHwDesChunk;	 // chunk for hardware descriptor pool
       
   823 #endif
       
   824 	TAny* iDesPool;				 // hardware or pseudo descriptor dynamic array
       
   825 	const TInt iDesSize;		 // descriptor size in bytes
       
   826 
       
   827 public:
       
   828 	const TBool iCapsHwDes;		 /*< True if DMAC uses h/w descriptors */
       
   829 	SDmaDesHdr* iFreeHdr;		 /*< head of unallocated descriptors linked list */
       
   830 
       
   831 #ifdef _DEBUG
       
   832 	/** Tests whether aHdr points into the descriptor header array. */
       
   833 	TBool IsValidHdr(const SDmaDesHdr* aHdr);
       
   834 #endif
       
   835 	__DMA_DECLARE_INVARIANT
       
   836 	};
       
   837 
       
   838 
       
   839 //////////////////////////////////////////////////////////////////////////////
       
   840 
       
   841 
       
   842 /** Single-buffer DMA channel.
       
   843 
       
   844 	Can be instantiated or further derived by the PSL.
       
   845 */
       
   846 class TDmaSbChannel : public TDmaChannel
       
   847 	{
       
   848 private:
       
   849 	virtual void DoQueue(const DDmaRequest& aReq);
       
   850 	virtual void DoCancelAll();
       
   851 	virtual void DoDfc(const DDmaRequest& aCurReq, SDmaDesHdr*& aCompletedHdr);
       
   852 
       
   853 protected:
       
   854 	enum {EIdle = 0, ETransferring} iState;
       
   855 	};
       
   856 
       
   857 
       
   858 /** Double-buffer DMA channel.
       
   859 
       
   860 	Can be instantiated or further derived by the PSL.
       
   861 */
       
   862 class TDmaDbChannel : public TDmaChannel
       
   863 	{
       
   864 private:
       
   865 	virtual void DoQueue(const DDmaRequest& aReq);
       
   866 	virtual void DoCancelAll();
       
   867 	virtual void DoDfc(const DDmaRequest& aCurReq, SDmaDesHdr*& aCompletedHdr);
       
   868 
       
   869 protected:
       
   870 	enum {EIdle = 0, ETransferring, ETransferringLast} iState;
       
   871 	};
       
   872 
       
   873 
       
   874 /** Scatter-gather DMA channel.
       
   875 
       
   876 	Can be instantiated or further derived by the PSL.
       
   877 */
       
   878 class TDmaSgChannel : public TDmaChannel
       
   879 	{
       
   880 private:
       
   881 	virtual void DoQueue(const DDmaRequest& aReq);
       
   882 	virtual void DoCancelAll();
       
   883 	virtual void DoUnlink(SDmaDesHdr& aHdr);
       
   884 	virtual void DoDfc(const DDmaRequest& aCurReq, SDmaDesHdr*& aCompletedHdr);
       
   885 
       
   886 protected:
       
   887 	enum {EIdle = 0, ETransferring} iState;
       
   888 	};
       
   889 
       
   890 
       
   891 /** Scatter-gather DMA channel with asymmetric linked-lists.
       
   892 
       
   893 	Can be instantiated or further derived by the PSL.
       
   894 
       
   895 	@prototype
       
   896 */
       
   897 class TDmaAsymSgChannel : public TDmaChannel
       
   898 	{
       
   899 public:
       
   900 	TDmaAsymSgChannel();
       
   901 
       
   902 private:
       
   903 	virtual void DoQueue(const DDmaRequest& aReq);
       
   904 	virtual void DoCancelAll();
       
   905 	virtual void DoUnlink(SDmaDesHdr& aHdr);
       
   906 	virtual void DoDfc(const DDmaRequest& aCurReq, SDmaDesHdr*& aSrcCompletedHdr,
       
   907 					   SDmaDesHdr*& aDstCompletedHdr);
       
   908 	virtual void SetNullPtr(const DDmaRequest& aReq);
       
   909 	virtual void ResetNullPtr();
       
   910 
       
   911 protected:
       
   912 	SDmaDesHdr* iSrcCurHdr;	  // source fragment being transferred or NULL
       
   913 	SDmaDesHdr** iSrcNullPtr; // Pointer to NULL pointer following last source fragment
       
   914 	SDmaDesHdr* iDstCurHdr;	  // destination fragment being transferred or NULL
       
   915 	SDmaDesHdr** iDstNullPtr; // Pointer to NULL pointer following last destination fragment
       
   916 	enum {EIdle = 0, ETransferring} iState;
       
   917 
       
   918 	__DMA_DECLARE_VIRTUAL_INVARIANT
       
   919 	};
       
   920 
       
   921 
       
   922 //////////////////////////////////////////////////////////////////////////////
       
   923 
       
   924 // Trace macros intended for use by the DMA PSL
       
   925 #define DMA_PRINTF(MSG) __KTRACE_OPT(KDMA, Kern::Printf((MSG)))
       
   926 #define DMA_PRINTF1(MSG, ARG1) __KTRACE_OPT(KDMA, Kern::Printf((MSG), (ARG1)))
       
   927 #define DMA_PRINTF2(MSG, ARG1, ARG2) __KTRACE_OPT(KDMA, Kern::Printf((MSG), (ARG1), (ARG2)))
       
   928 
       
   929 #define DMA_PSL_MESG "DMA PSL: "
       
   930 
       
   931 // General PSL tracing
       
   932 #define DMA_PSL_TRACE(MSG) DMA_PRINTF(DMA_PSL_MESG MSG)
       
   933 #define DMA_PSL_TRACE1(MSG, ARG1) DMA_PRINTF1(DMA_PSL_MESG MSG, (ARG1))
       
   934 #define DMA_PSL_TRACE2(MSG, ARG1, ARG2) DMA_PRINTF2(DMA_PSL_MESG MSG, (ARG1), (ARG2))
       
   935 
       
   936 
       
   937 #define DMA_PSL_CHAN_MESG DMA_PSL_MESG "ChanId %d: "
       
   938 #define DMA_PSL_CHAN_ARGS(CHAN) ((CHAN).PslId())
       
   939 
       
   940 // For channel specific tracing (where CHAN is a TDmaChannel)
       
   941 #define DMA_PSL_CHAN_TRACE_STATIC(CHAN, MSG) DMA_PRINTF1(DMA_PSL_CHAN_MESG MSG, DMA_PSL_CHAN_ARGS(CHAN))
       
   942 #define DMA_PSL_CHAN_TRACE_STATIC1(CHAN, MSG, ARG1) DMA_PRINTF2(DMA_PSL_CHAN_MESG MSG, DMA_PSL_CHAN_ARGS(CHAN), (ARG1))
       
   943 
       
   944 // For channel specific tracing, for use within methods of TDmaChannel derived
       
   945 // class
       
   946 #define DMA_PSL_CHAN_TRACE(MSG) DMA_PSL_CHAN_TRACE_STATIC(*this, MSG)
       
   947 #define DMA_PSL_CHAN_TRACE1(MSG, ARG1) DMA_PSL_CHAN_TRACE_STATIC1(*this, MSG, (ARG1))
       
   948 
       
   949 
       
   950 
       
   951 #include <drivers/dma_hai.inl>
       
   952 
       
   953 
       
   954 #endif	// #ifndef __DMA_HAI_H__