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