os/kernelhwsrv/kernel/eka/include/drivers/dma_hai.h
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/include/drivers/dma_hai.h	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,870 @@
     1.4 +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// include/drivers/dma_hai.h
    1.18 +// DMA Framework - Symbian Hardware Abstraction Interface (SHAI).
    1.19 +//
    1.20 +//
    1.21 +
    1.22 +#ifndef __DMA_HAI_H__
    1.23 +#define __DMA_HAI_H__
    1.24 +
    1.25 +
    1.26 +#include <kernel/kern_priv.h>
    1.27 +
    1.28 +
    1.29 +//////////////////////////////////////////////////////////////////////////////
    1.30 +
    1.31 +
    1.32 +/** Interface used by PIL to open and close DMA channels.
    1.33 +
    1.34 +	Must be implemented by the PSL.
    1.35 +
    1.36 +	@publishedPartner
    1.37 +	@released
    1.38 +*/
    1.39 +class DmaChannelMgr
    1.40 +	{
    1.41 +public:
    1.42 +	/** Opens a channel using a client-provided identifier.
    1.43 +
    1.44 +		This function must be implemented by the PSL.
    1.45 +
    1.46 +		@param aOpenId PSL-specific magic cookie passed by client. This could
    1.47 +		identify the channel exactly (by being just the channel number), or at
    1.48 +		least sufficiently (for example for use with a certain peripheral), or
    1.49 +		it may indicate some properties which the channel must possess. It may
    1.50 +		be set to zero always if all channels are equivalent.
    1.51 +
    1.52 +		@param aDynChannel ETrue if the Open call is for a dynamic channel. A
    1.53 +		dynamic channel is not exclusively reserved for just one client, and
    1.54 +		further Open calls for more dynamic channels should succeed as long as
    1.55 +		certain resources (but not including the number of available physical
    1.56 +		channels) are not exceeded. Different transfer requests on this dynamic
    1.57 +		channel may be serviced using different actual channels.
    1.58 +
    1.59 +		@param aPriority The desired channel priority as requested by the
    1.60 +		client. This may be an actual hardware priority or a
    1.61 +		platform-independent value. Not being able to satisfy the requested
    1.62 +		value is not a reason for the PSL to return NULL. This parameter may be
    1.63 +		ignored if aDynChannel is passed as ETrue. An overriding per-transfer
    1.64 +		priority may be requested by a client later via
    1.65 +		TDmaTransferArgs::iChannelPriority.
    1.66 +		@see SDmacCaps::iChannelPriorities
    1.67 +		@see TDmaPriority
    1.68 +
    1.69 +		@return Pointer to channel if available, NULL otherwise. It should not
    1.70 +		be NULL if the Open call was for a dynamic channel unless a processing
    1.71 +		error occurred.
    1.72 +
    1.73 +		@pre The PIL calls this function with a global fast mutex held to avoid
    1.74 +		race conditions.
    1.75 +
    1.76 +		@post If a non-NULL pointer is returned, the object pointed to has its
    1.77 +		iController, iDmacCaps, iPslId, iDynChannel and iPriority members set
    1.78 +		to valid states.
    1.79 +
    1.80 +		iController should point to the controller handling the
    1.81 +		channel.
    1.82 +
    1.83 +		iDmacCaps should point to a SDmacCaps structure containing values
    1.84 +		relating to this particular channel.
    1.85 +
    1.86 +		iPslId should contain a value uniquely identifying the channel - the
    1.87 +		PIL assigns this value later during request fragmentation to
    1.88 +		TDmaTransferArgs::iChannelCookie. It can be given any convenient value
    1.89 +		by the PSL (channel index, I/O port address, etc.).
    1.90 +
    1.91 +		iDynChannel should be set to ETrue by the PSL if a dynamic channel was
    1.92 +		requested and has been opened.
    1.93 +
    1.94 +		If applicable, iPriority should contain the actual hardware priority
    1.95 +		that has been configured or reserved. Otherwise it may be left at its
    1.96 +		default value TDmaPriority::KDmaPriorityNone.
    1.97 +	*/
    1.98 +	static TDmaChannel* Open(TUint32 aOpenId, TBool aDynChannel, TUint aPriority);
    1.99 +
   1.100 +	/** Performs platform-specific operations when a channel is closed.
   1.101 +
   1.102 +		If aChannel was opened as a dynamic channel then this call is a sign
   1.103 +		that there is a client which does not intend to queue any further
   1.104 +		transfer requests via this channel.
   1.105 +
   1.106 +		This function must be implemented by the PSL but the implementation can
   1.107 +		be a no-op.
   1.108 +
   1.109 +		@param aChannel The channel to close
   1.110 +
   1.111 +		@pre The PIL calls this function with a global fast mutex held to avoid
   1.112 +		race conditions.
   1.113 +	*/
   1.114 +	static void Close(TDmaChannel* aChannel);
   1.115 +
   1.116 +	/** Function allowing PSL to extend DMA API with new channel-independent
   1.117 +		operations.
   1.118 +
   1.119 +		This function must be implemented by the PSL.
   1.120 +
   1.121 +		@param aCmd Command identifier. Negative values are reserved for FW
   1.122 +		internal use.
   1.123 +
   1.124 +		@param aArg PSL-specific
   1.125 +
   1.126 +		@return KErrNotSupported if aCmd is not supported. PSL-specific value
   1.127 +		otherwise.
   1.128 +	 */
   1.129 +	static TInt StaticExtension(TInt aCmd, TAny* aArg);
   1.130 +
   1.131 +	/** Acquires the channel manager lock. Called by the PIL before opening and
   1.132 +		closing a channel.
   1.133 +	*/
   1.134 +	static void Wait();
   1.135 +
   1.136 +	/** Releases the channel manager lock. Called by the PIL after opening and
   1.137 +		closing a channel.
   1.138 +	*/
   1.139 +	static void Signal();
   1.140 +
   1.141 +private:
   1.142 +	/** Declared, defined, and called by PSL's DECLARE_STANDARD_EXTENSION(). */
   1.143 +	friend TInt InitExtension();
   1.144 +
   1.145 +	/** Must be called in the DMA DLL entry point. */
   1.146 +	static TInt Initialise();
   1.147 +
   1.148 +	static NFastMutex Lock;
   1.149 +	};
   1.150 +
   1.151 +
   1.152 +//////////////////////////////////////////////////////////////////////////////
   1.153 +
   1.154 +
   1.155 +/** Abstract base class representing a DMA controller.
   1.156 +
   1.157 +	The class has two purposes.
   1.158 +
   1.159 +	First, it is a container for channels, descriptors and descriptor headers.
   1.160 +
   1.161 +	Second, it exposes a set of virtual functions implemented by the PSL
   1.162 +	(platform-specific layer).
   1.163 +
   1.164 +	These functions are the main interfaces between the PIL
   1.165 +	(platform-independent layer) and PSL.
   1.166 +
   1.167 +	@publishedPartner
   1.168 +	@released
   1.169 +*/
   1.170 +class TDmac
   1.171 +	{
   1.172 +	friend class DmaChannelMgr;
   1.173 +
   1.174 +protected:
   1.175 +	/** Data required for creating a new instance */
   1.176 +	struct SCreateInfo
   1.177 +		{
   1.178 +		/** True if DMAC uses hardware descriptors (i.e. supports
   1.179 +			scatter/gather mode).
   1.180 +		*/
   1.181 +		TBool iCapsHwDes;
   1.182 +		/** Initial maximum number of descriptors and headers (shared by all
   1.183 +			channels) to be allocated by the PIL. If at run time more
   1.184 +			descriptors are needed then they will be dynamically allocated and
   1.185 +			added to the available pool.
   1.186 +
   1.187 +			The PSL may consider a number of factors when providing this
   1.188 +			initial value, such as the number of channels on this controller,
   1.189 +			the maximum transfer size per descriptor and also likely usage
   1.190 +			scenarios for the platform or device (number of drivers using DMA,
   1.191 +			their traffic patterns, simultaneity of operations, etc.).
   1.192 +		*/
   1.193 +		TInt iDesCount;
   1.194 +		/** Size of individual descriptors. Use sizeof(TDmaTransferArgs) for
   1.195 +		 	single-buffer and double-buffer (i.e. non-s/g) controllers.
   1.196 +		*/
   1.197 +		TInt iDesSize;
   1.198 +		/** Bitmask used when creating the memory chunk storing the descriptor
   1.199 +			pool. Used only for hardware descriptors.
   1.200 +
   1.201 +			The access part must be EMapAttrSupRw. If the chunk is cached
   1.202 +			and/or buffered, the PSL must flush the data cache and/or drain the
   1.203 +			write buffer in InitHwDes() and related functions.
   1.204 +
   1.205 +			The physical start address of the chunk will always be MMU page
   1.206 +		 	size aligned.
   1.207 +
   1.208 +		 	@see TMappingAttributes
   1.209 +		 */
   1.210 +		TUint iDesChunkAttribs;
   1.211 +		};
   1.212 +
   1.213 +	/** Base class constructor. */
   1.214 +	TDmac(const SCreateInfo& aInfo);
   1.215 +
   1.216 +	/** Base class 2nd-phase constructor. */
   1.217 +	TInt Create(const SCreateInfo& aInfo);
   1.218 +
   1.219 +public:
   1.220 +	/** Base class virtual destructor. */
   1.221 +	virtual ~TDmac();
   1.222 +
   1.223 +	/** Allocates a number of headers (and hence also descriptors) from the
   1.224 +		header/descriptor pools. Called by the PIL but may also be used by the
   1.225 +		PSL.
   1.226 +	*/
   1.227 +	TInt ReserveSetOfDes(TInt aCount);
   1.228 +
   1.229 +	/** Returns previously allocated headers (and hence also descriptors) to
   1.230 +		the header/descriptor pools. Called by the PIL but may also be used by
   1.231 +		the PSL.
   1.232 +	*/
   1.233 +	void ReleaseSetOfDes(TInt aCount);
   1.234 +
   1.235 +	/** Called by the PIL during request fragmentation to fill a descriptor or
   1.236 +		pseudo descriptor with transfer arguments.
   1.237 +	*/
   1.238 +	TInt InitDes(const SDmaDesHdr& aHdr, const TDmaTransferArgs& aTransferArgs);
   1.239 +
   1.240 +	/** Called by the PIL in TDmaChannel::IsrRedoRequest() if any of the
   1.241 +		latter's arguments is non-zero.
   1.242 +	*/
   1.243 +	TInt UpdateDes(const SDmaDesHdr& aHdr, TUint32 aSrcAddr, TUint32 aDstAddr,
   1.244 +				   TUint aTransferCount, TUint32 aPslRequestInfo);
   1.245 +
   1.246 +	/** Returns a reference to the associated pseudo descriptor for a given
   1.247 +		descriptor header. For use by PIL and PSL.
   1.248 +	*/
   1.249 +	inline TDmaTransferArgs& HdrToDes(const SDmaDesHdr& aHdr) const;
   1.250 +
   1.251 +	/** Returns a reference to the associated hardware descriptor for a given
   1.252 +		descriptor header. For use by PIL and PSL.
   1.253 +	*/
   1.254 +	inline TAny* HdrToHwDes(const SDmaDesHdr& aHdr) const;
   1.255 +
   1.256 +	/** Returns the physical address of the hardware descriptor
   1.257 +		pointed to by aDes. For use by PIL and PSL.
   1.258 +	*/
   1.259 +	inline TUint32 HwDesLinToPhys(TAny* aDes) const;
   1.260 +
   1.261 +	/** Called by the PIL to acquire the controller lock which protects the
   1.262 +		header and descriptor pools.
   1.263 +	*/
   1.264 +	inline void Wait();
   1.265 +
   1.266 +	/** Called by the PIL to release the controller lock which protects the
   1.267 +		header and descriptor pools.
   1.268 +	*/
   1.269 +	inline void Signal();
   1.270 +
   1.271 +public:
   1.272 +	/** Called by PIL when one fragment (single-buffer and double-buffer DMACs)
   1.273 +		or list of fragments (scatter/gather DMAC) is to be transferred.
   1.274 +
   1.275 +		Called when initiating a new transfer and also, for double-buffer
   1.276 +		DMACs, for configuring the next fragment to transfer while the current
   1.277 +		one is ongoing.
   1.278 +
   1.279 +		The function must be implemented by the PSL if
   1.280 +		SCreateInfo::iCaps::iAsymHwDescriptors is reported as false.
   1.281 +
   1.282 +		@note This function may be called in thread or ISR context by the PIL
   1.283 +
   1.284 +		@param aChannel The channel to use.
   1.285 +		@param aHdr Header associated with fragment to transfer.
   1.286 +	*/
   1.287 +	virtual void Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aHdr);
   1.288 +
   1.289 +	/** Called by PIL when two lists of fragments (scatter/gather DMAC with
   1.290 +		asymmetrical linked-list capability) are to be transferred.
   1.291 +
   1.292 +		Called when initiating a new transfer.
   1.293 +
   1.294 +		The function must be implemented by the PSL if
   1.295 +		SDmaCaps::iAsymHwDescriptors is reported as true.
   1.296 +
   1.297 +		@note This function may be called in thread or ISR context by the PIL
   1.298 +
   1.299 +		@param aChannel The channel to use.
   1.300 +		@param aSrcHdr Header associated with descriptor to transfer on the
   1.301 +		source side.
   1.302 +		@param aDstHdr Header associated with descriptor to transfer on the
   1.303 +		destination side.
   1.304 +	*/
   1.305 +	virtual void Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aSrcHdr,
   1.306 +						  const SDmaDesHdr& aDstHdr);
   1.307 +
   1.308 +	/** Called by PIL to stop a transfer on a given channel.
   1.309 +
   1.310 +		The stopping must occur synchronously as the PIL assumes the channel
   1.311 +		is halted after calling this function. A channel stopped via this
   1.312 +		function is not intended to be resumed. Function must always be
   1.313 +		implemented by the PSL.
   1.314 +
   1.315 +		@param aChannel The channel to stop
   1.316 +		@post The channel will be idle
   1.317 +		@post No interrupt will occur from this channel until a new
   1.318 +		request is queued.
   1.319 +	*/
   1.320 +	virtual void StopTransfer(const TDmaChannel& aChannel) = 0;
   1.321 +
   1.322 +	/** Called by PIL to pause (suspend) a transfer on a given channel.
   1.323 +
   1.324 +		A paused channel transfer must be able to be resumed by calling
   1.325 +		ResumeTransfer().
   1.326 +
   1.327 +		The function must be implemented by the PSL if
   1.328 +		SDmacCaps::iChannelPauseAndResume is reported as true.
   1.329 +
   1.330 +		@return KErrNone if the transfer has been paused successfully,
   1.331 +		KErrCompletion if the transfer was already paused, KErrGeneral
   1.332 +		if a general error occurred preventing a successful outcome.
   1.333 +
   1.334 +		@post No interrupt will occur from this channel until it is
   1.335 +		resumed.
   1.336 +	 */
   1.337 +	virtual TInt PauseTransfer(const TDmaChannel& aChannel);
   1.338 +
   1.339 +	/** Called by PIL to resume a paused (suspended) transfer on a given
   1.340 +		channel.
   1.341 +
   1.342 +		Resume() can be called when the transfer is paused as a result of a
   1.343 +		previous call to PauseTransfer() or because the DMAC has encountered a
   1.344 +		Pause bit in a H/W descriptor.
   1.345 +
   1.346 +		The function must be implemented by the PSL if
   1.347 +		SDmacCaps::iChannelPauseAndResume is reported as true.
   1.348 +
   1.349 +		@return KErrNone if the transfer has been resumed successfully,
   1.350 +		KErrCompletion if there was no paused transfer, KErrGeneral
   1.351 +		if a general error occurred preventing a successful outcome.
   1.352 +	 */
   1.353 +	virtual TInt ResumeTransfer(const TDmaChannel& aChannel);
   1.354 +
   1.355 +	/** Called by PIL to check whether a DMA channel is idle.
   1.356 +
   1.357 +		'Idle' here means that the channel is ultimately stopped, for example
   1.358 +		because the transfer has finished, or an error was encountered, or it
   1.359 +		was manually stopped, but not because it was manually suspended (aka
   1.360 +		'paused'), or it is waiting for a request line assertion to start the
   1.361 +		transfer.
   1.362 +
   1.363 +		@param aChannel The channel to test
   1.364 +
   1.365 +		@return ETrue if channel idle, EFalse if transferring.
   1.366 +	*/
   1.367 +	virtual TBool IsIdle(const TDmaChannel& aChannel) = 0;
   1.368 +
   1.369 +	/** Called by PIL to retrieve from the PSL the maximum transfer length
   1.370 +		based on the parameters passed.
   1.371 +
   1.372 +		@param aChannel Channel to be used for the transfer
   1.373 +		@param aSrcFlags Bitmask characterising transfer source
   1.374 +		@see TDmaTransferArgs::iSrcConfig::iFlags
   1.375 +		@param aDstFlags Bitmask characterising transfer destination
   1.376 +		@see TDmaTransferArgs::iDstConfig::iFlags
   1.377 +		@param aPslInfo Cookie passed by client and used by the PSL
   1.378 +		@see TDmaTransferArgs::iPslRequestInfo
   1.379 +
   1.380 +		@return 0 if transfer length is not limited, the maximum transfer
   1.381 +		length in bytes otherwise.
   1.382 +	*/
   1.383 +	virtual TUint MaxTransferLength(TDmaChannel& aChannel, TUint aSrcFlags,
   1.384 +									TUint aDstFlags, TUint32 aPslInfo) = 0;
   1.385 +
   1.386 +	/** Called by PIL to retrieve from the PSL the memory alignment mask based
   1.387 +		on the parameters passed. Some DMA controllers impose alignment
   1.388 +		constraints on the base address of memory buffers. This mask is AND'ed
   1.389 +		against memory addresses computed during fragmentation.
   1.390 +
   1.391 +		The PIL will call this function separately for source and destination.
   1.392 +
   1.393 +		An assumption is that the PSL doesn't need to know if a call to this
   1.394 +		function is for the source or the destination side, i.e. both ports
   1.395 +		are, as far as the alignment is concerned, equivalent. All that matters
   1.396 +		are the values of the relevant configuration parameters.
   1.397 +
   1.398 +		Another assumption is that the alignment requirement for a port on a
   1.399 +		DMAC with potentially different values for source and destination does
   1.400 +		not depend on the configuration of the respective other port.
   1.401 +
   1.402 +		@param aChannel Channel used for the transfer
   1.403 +		@param aTargetFlags Bitmask characterising transfer source or
   1.404 +		destination
   1.405 +		@see TDmaTransferArgs::iSrcConfig::iFlags
   1.406 +		@see TDmaTransferArgs::iDstConfig::iFlags
   1.407 +		@param aElementSize Element size used for the transfer. May be zero if
   1.408 +		not known or 'don't care'.
   1.409 +		@param aPslInfo Cookie passed by client and used by the PSL
   1.410 +		@see TDmaTransferArgs::iPslRequestInfo
   1.411 +
   1.412 +		@return A value representing the alignment mask (e.g. 3 if buffer must
   1.413 +		be 4-byte aligned)
   1.414 +	*/
   1.415 +	virtual TUint AddressAlignMask(TDmaChannel& aChannel, TUint aTargetFlags,
   1.416 +								   TUint aElementSize, TUint32 aPslInfo) = 0;
   1.417 +
   1.418 +	/** Called by PIL during fragmentation to initialise a hardware descriptor.
   1.419 +
   1.420 +		The PSL must assume the descriptor is the last in the chain and so set
   1.421 +		the interrupt bit and set the next descriptor field to an end of chain
   1.422 +		marker.
   1.423 +
   1.424 +		The function must be implemented by the PSL if and only if the DMAC
   1.425 +		supports hardware descriptors and SDmaCaps::iAsymHwDescriptors is
   1.426 +		reported as false.
   1.427 +
   1.428 +		@param aHdr Header associated with the hardware descriptor to
   1.429 +		initialise
   1.430 +		@param aTransferArgs The transfer parameters for this descriptor
   1.431 +
   1.432 +		@return KErrNone if the descriptor was successfully initialized,
   1.433 +		KErrArgument if any of the transfer arguments were detected to be
   1.434 +		invalid, KErrGeneral if a general error occurred preventing a
   1.435 +		successful outcome.
   1.436 +	*/
   1.437 +	virtual TInt InitHwDes(const SDmaDesHdr& aHdr, const TDmaTransferArgs& aTransferArgs);
   1.438 +
   1.439 +	/** Called by PIL during fragmentation to initialise a hardware descriptor
   1.440 +		on the source side of an asymmetric linked list.
   1.441 +
   1.442 +		The function must be implemented by the PSL if
   1.443 +		SDmaCaps::iAsymHwDescriptors is reported as true.
   1.444 +
   1.445 +		@param aHdr Header associated with the hardware descriptor to
   1.446 +		initialise
   1.447 +		@param aTransferArgs The transfer parameters for this descriptor. Only
   1.448 +		the elements relating to the source side should be relevant to the
   1.449 +		implementation.
   1.450 +
   1.451 +		@return KErrNone if the descriptor was successfully initialized,
   1.452 +		KErrArgument if any of the transfer arguments were detected to be
   1.453 +		invalid, KErrGeneral if a general error occurred preventing a
   1.454 +		successful outcome.
   1.455 +	*/
   1.456 +	virtual TInt InitSrcHwDes(const SDmaDesHdr& aHdr, const TDmaTransferArgs& aTransferArgs);
   1.457 +
   1.458 +	/** Called by PIL during fragmentation to initialise a hardware descriptor
   1.459 +		on the destination side of an asymmetric linked list.
   1.460 +
   1.461 +		The function must be implemented by the PSL if
   1.462 +		SDmaCaps::iAsymHwDescriptors is reported as true.
   1.463 +
   1.464 +		@param aHdr Header associated with the hardware descriptor to
   1.465 +		initialise
   1.466 +		@param aTransferArgs The transfer parameters for this descriptor. Only
   1.467 +		the elements relating to the destination side should be relevant to the
   1.468 +		implementation.
   1.469 +
   1.470 +		@return KErrNone if the descriptor was successfully initialized,
   1.471 +		KErrArgument if any of the transfer arguments were detected to be
   1.472 +		invalid, KErrGeneral if a general error occurred preventing a
   1.473 +		successful outcome.
   1.474 +	*/
   1.475 +	virtual TInt InitDstHwDes(const SDmaDesHdr& aHdr, const TDmaTransferArgs& aTransferArgs);
   1.476 +
   1.477 +	/** Called by the PIL in ISR context to change specific fields in a
   1.478 +		hardware descriptor.
   1.479 +
   1.480 +		The function must be implemented by the PSL if and only if the DMAC
   1.481 +		supports hardware descriptors and SDmaCaps::iAsymHwDescriptors is
   1.482 +		reported as false.
   1.483 +
   1.484 +		@param aHdr Header associated with the hardware descriptor to be
   1.485 +		updated
   1.486 +		@param aSrcAddr @see TDmaTransferArgs::iSrcConfig::iAddr
   1.487 +		@param aDstAddr @see TDmaTransferArgs::iDstConfig::iAddr
   1.488 +		@param aTransferCount @see TDmaTransferArgs::iTransferCount
   1.489 +		@param aPslRequestInfo @see TDmaTransferArgs::iPslRequestInfo
   1.490 +
   1.491 +		Since Epoc::LinearToPhysical() cannot be called in ISR context the
   1.492 +		addresses passed into this function are always physical ones, i.e.
   1.493 +		TDmaTransferFlags::KDmaPhysAddr is implied.
   1.494 +
   1.495 +		@return KErrNone if the descriptor was successfully modified,
   1.496 +		KErrArgument if any of the transfer arguments were detected to be
   1.497 +		invalid, KErrGeneral if a general error occurred preventing a
   1.498 +		successful outcome.
   1.499 +	*/
   1.500 +	virtual TInt UpdateHwDes(const SDmaDesHdr& aHdr, TUint32 aSrcAddr, TUint32 aDstAddr,
   1.501 +							 TUint aTransferCount, TUint32 aPslRequestInfo);
   1.502 +
   1.503 +	/** Called by the PIL in ISR context to change specific fields in a
   1.504 +		hardware descriptor.
   1.505 +
   1.506 +		The function must be implemented by the PSL if
   1.507 +		SDmaCaps::iAsymHwDescriptors is reported as true.
   1.508 +
   1.509 +		@param aHdr Header associated with the hardware descriptor to be
   1.510 +		updated
   1.511 +		@param aSrcAddr @see TDmaTransferArgs::iSrcConfig::iAddr
   1.512 +		@param aTransferCount @see TDmaTransferArgs::iTransferCount
   1.513 +		@param aPslRequestInfo @see TDmaTransferArgs::iPslRequestInfo
   1.514 +
   1.515 +		Since Epoc::LinearToPhysical() cannot be called in ISR context the
   1.516 +		address passed into this function is always a physical ones, i.e.
   1.517 +		TDmaTransferFlags::KDmaPhysAddr is implied.
   1.518 +
   1.519 +		@return KErrNone if the descriptor was successfully modified,
   1.520 +		KErrArgument if any of the transfer arguments were detected to be
   1.521 +		invalid, KErrGeneral if a general error occurred preventing a
   1.522 +		successful outcome.
   1.523 +	*/
   1.524 +	virtual TInt UpdateSrcHwDes(const SDmaDesHdr& aHdr, TUint32 aSrcAddr,
   1.525 +								TUint aTransferCount, TUint32 aPslRequestInfo);
   1.526 +
   1.527 +	/** Called by the PIL in ISR context to change specific fields in a
   1.528 +		hardware descriptor.
   1.529 +
   1.530 +		The function must be implemented by the PSL if
   1.531 +		SDmaCaps::iAsymHwDescriptors is reported as true.
   1.532 +
   1.533 +		@param aHdr Header associated with the hardware descriptor to be
   1.534 +		updated
   1.535 +		@param aDstAddr @see TDmaTransferArgs::iDstConfig::iAddr
   1.536 +		@param aTransferCount @see TDmaTransferArgs::iTransferCount
   1.537 +		@param aPslRequestInfo @see TDmaTransferArgs::iPslRequestInfo
   1.538 +
   1.539 +		Since Epoc::LinearToPhysical() cannot be called in ISR context the
   1.540 +		address passed into this function is always a physical ones, i.e.
   1.541 +		TDmaTransferFlags::KDmaPhysAddr is implied.
   1.542 +
   1.543 +		@return KErrNone if the descriptor was successfully modified,
   1.544 +		KErrArgument if any of the transfer arguments were detected to be
   1.545 +		invalid, KErrGeneral if a general error occurred preventing a
   1.546 +		successful outcome.
   1.547 +	*/
   1.548 +	virtual TInt UpdateDstHwDes(const SDmaDesHdr& aHdr, TUint32 aDstAddr,
   1.549 +								TUint aTransferCount, TUint32 aPslRequestInfo);
   1.550 +
   1.551 +	/** Called by PIL, when fragmenting a request, to append a new hardware
   1.552 +		descriptor to an existing descriptor chain. May also be called by
   1.553 +		clients who wish to create their own descriptor chains.
   1.554 +
   1.555 +		Must clear the interrupt bit of the descriptor associated with aHdr.
   1.556 +
   1.557 +		The function must be implemented by the PSL if and only if the DMAC
   1.558 +		supports hardware descriptors.
   1.559 +
   1.560 +		@param aHdr Header associated with last fragment in chain
   1.561 +		@param aNextHdr Header associated with fragment to append
   1.562 +	*/
   1.563 +	virtual void ChainHwDes(const SDmaDesHdr& aHdr, const SDmaDesHdr& aNextHdr);
   1.564 +
   1.565 +	/** Called by PIL when queuing a new request while the channel is running.
   1.566 +
   1.567 +		Must append the first hardware descriptor of the new request to the
   1.568 +		last descriptor in the existing chain.
   1.569 +
   1.570 +		The function must be implemented by the PSL if and only if the DMAC
   1.571 +		supports hardware descriptors.
   1.572 +
   1.573 +		@param aChannel The channel where the transfer takes place
   1.574 +		@param aLastHdr Header associated with last hardware descriptor in
   1.575 +		chain
   1.576 +		@param aNewHdr Header associated with first hardware descriptor in new
   1.577 +		request
   1.578 +	*/
   1.579 +	virtual void AppendHwDes(const TDmaChannel& aChannel, const SDmaDesHdr& aLastHdr,
   1.580 +							 const SDmaDesHdr& aNewHdr);
   1.581 +
   1.582 +	/** Called by PIL when queuing a new request while the channel is running.
   1.583 +
   1.584 +		Must append the first hardware descriptor of the new request to the
   1.585 +		last descriptor in the existing chain.
   1.586 +
   1.587 +		The function must be implemented by the PSL if
   1.588 +		SDmaCaps::iAsymHwDescriptors is reported as true.
   1.589 +
   1.590 +		@param aChannel The channel where the transfer takes place
   1.591 +		@param aSrcLastHdr Header associated with the last descriptor in the
   1.592 +		source side chain
   1.593 +		@param aSrcNewHdr Header associated with the first source side
   1.594 +		descriptor of the new request
   1.595 +		@param aDstLastHdr Header associated with the last descriptor in the
   1.596 +		destination side chain
   1.597 +		@param aDstNewHdr Header associated with the first destination side
   1.598 +		descriptor of the new request
   1.599 +	*/
   1.600 +	virtual void AppendHwDes(const TDmaChannel& aChannel,
   1.601 +							 const SDmaDesHdr& aSrcLastHdr, const SDmaDesHdr& aSrcNewHdr,
   1.602 +							 const SDmaDesHdr& aDstLastHdr, const SDmaDesHdr& aDstNewHdr);
   1.603 +
   1.604 +	/** Called by PIL when completing or cancelling a request to cause the PSL
   1.605 +		to unlink the last item in the h/w descriptor chain from a subsequent
   1.606 +		chain that it was possibly linked to.
   1.607 +
   1.608 +		The function must be implemented by the PSL if and only if the DMAC
   1.609 +		supports hardware descriptors.
   1.610 +
   1.611 +		@param aChannel The channel where the request (and thus the descriptor)
   1.612 +		was queued
   1.613 +		@param aHdr Header associated with last h/w descriptor in
   1.614 +		completed / cancelled chain
   1.615 +	*/
   1.616 +	virtual void UnlinkHwDes(const TDmaChannel& aChannel, SDmaDesHdr& aHdr);
   1.617 +
   1.618 +	/** Called by PIL when freeing descriptors back to the shared pool in
   1.619 +		FreeDesList(). The PSL inside ClearHwDes() can clear the contents of
   1.620 +		the h/w descriptor.
   1.621 +
   1.622 +		This may be necessary if the PSL implementation uses the h/w descriptor
   1.623 +		as another header which in turn points to the actual DMA h/w descriptor
   1.624 +		(aka LLI).
   1.625 +
   1.626 +		The function may be implemented by the PSL if the DMAC supports
   1.627 +		hardware descriptors.
   1.628 +
   1.629 +		@param aHdr Header associated with the h/w descriptor being freed.
   1.630 +	 */
   1.631 +	virtual void ClearHwDes(const SDmaDesHdr& aHdr);
   1.632 +
   1.633 +	/** Called by PIL to logically link two physical channels.
   1.634 +
   1.635 +		The function must be implemented by the PSL if the DMAC supports
   1.636 +		logical channel linking.
   1.637 +
   1.638 +		@see SDmacCaps::iChannelLinking
   1.639 +
   1.640 +		@param a1stChannel The channel which is to be linked to another channel
   1.641 +		@param a2ndChannel The channel the first one is to be linked to
   1.642 +
   1.643 +		@return KErrNone if the two channels have been linked successfully,
   1.644 +		KErrCompletion if a1stChannel was already linked to a2ndChannel,
   1.645 +		KErrArgument if a1stChannel was already linked to a different channel,
   1.646 +		KErrGeneral if a general error occurred preventing a successful
   1.647 +		outcome. The default PIL implementation returns KErrNotSupported.
   1.648 +	 */
   1.649 +	virtual TInt LinkChannels(TDmaChannel& a1stChannel, TDmaChannel& a2ndChannel);
   1.650 +
   1.651 +	/** Called by PIL to logically unlink a physical channel from its linked-to
   1.652 +		successor.
   1.653 +
   1.654 +		The function must be implemented by the PSL if the DMAC supports
   1.655 +		logical channel linking.
   1.656 +
   1.657 +		@see SDmacCaps::iChannelLinking
   1.658 +
   1.659 +		@param aChannel The channel which is to be unlinked from its successor
   1.660 +
   1.661 +		@return KErrNone if the channel has been unlinked successfully,
   1.662 +		KErrCompletion if the channel was not linked to another channel,
   1.663 +		KErrGeneral if a general error occurred preventing a successful
   1.664 +		outcome. The default PIL implementation returns KErrNotSupported.
   1.665 +	 */
   1.666 +	virtual TInt UnlinkChannel(TDmaChannel& aChannel);
   1.667 +
   1.668 +	/** Called by a test harness to force an error when the next fragment is
   1.669 +		transferred.
   1.670 +
   1.671 +		Must be implemented by the PSL only if possible.
   1.672 +
   1.673 +		@param aChannel The channel where the error is to occur.
   1.674 +
   1.675 +		@return KErrNone if implemented. The default PIL implementation
   1.676 +		returns KErrNotSupported.
   1.677 +	*/
   1.678 +	virtual TInt FailNext(const TDmaChannel& aChannel);
   1.679 +
   1.680 +	/** Called by a test harness to force the DMA controller to miss one or
   1.681 +		more interrupts.
   1.682 +
   1.683 +		The function must be implemented by the PSL only if possible.
   1.684 +
   1.685 +		@param aChannel The channel where the error is to occur
   1.686 +		@param aInterruptCount The number of interrupt to miss.
   1.687 +
   1.688 +		@return KErrNone if implemented. The default PIL implementation
   1.689 +		returns KErrNotSupported.
   1.690 +	*/
   1.691 +	virtual TInt MissNextInterrupts(const TDmaChannel& aChannel, TInt aInterruptCount);
   1.692 +
   1.693 +	/** Function allowing platform-specific layer to extend channel API with
   1.694 +		new channel-specific operations.
   1.695 +
   1.696 +		@see TDmaChannel::ChannelExtension
   1.697 +
   1.698 +		@param aChannel Channel to operate on
   1.699 +		@param aCmd Command identifier. Negative values are reserved for use by
   1.700 +		Nokia.
   1.701 +		@param aArg PSL-specific argument
   1.702 +
   1.703 +		@return KErrNotSupported if aCmd is not supported. PSL-specific value
   1.704 +		otherwise.
   1.705 +	*/
   1.706 +	virtual TInt Extension(TDmaChannel& aChannel, TInt aCmd, TAny* aArg);
   1.707 +
   1.708 +	/** Called by the PIL to query the number of elements that have so far been
   1.709 +		transferred by the hardware descriptor associated with aHdr at the
   1.710 +		source port.
   1.711 +
   1.712 +		If SDmacCaps::iAsymHwDescriptors is true then the PIL will call this
   1.713 +		function only for source-side descriptors, and the PSL should fault the
   1.714 +		kernel if this is not the case.
   1.715 +
   1.716 +		The function must be implemented (i.e. overridden) by the PSL if and
   1.717 +		only if the DMAC supports hardware descriptors.
   1.718 +
   1.719 +		@param aHdr Descriptor header associated with the hardware descriptor
   1.720 +		to be queried
   1.721 +
   1.722 +		@return The number of elements that have been transferred by the
   1.723 +		hardware descriptor associated with aHdr at the source port
   1.724 +	*/
   1.725 +	virtual TUint32 HwDesNumSrcElementsTransferred(const SDmaDesHdr& aHdr);
   1.726 +
   1.727 +	/** Called by the PIL to query the number of elements that have so far been
   1.728 +		transferred by the hardware descriptor associated with aHdr at the
   1.729 +		destination port.
   1.730 +
   1.731 +		If SDmacCaps::iAsymHwDescriptors is true then the PIL will call this
   1.732 +		function only for destination-side descriptors, and the PSL should
   1.733 +		panic if this is not the case.
   1.734 +
   1.735 +		The function must be implemented (i.e. overridden) by the PSL if and
   1.736 +		only if the DMAC supports hardware descriptors.
   1.737 +
   1.738 +		@param aHdr Descriptor header associated with the hardware descriptor
   1.739 +		to be queried
   1.740 +
   1.741 +		@return The number of elements that have been transferred by the
   1.742 +		hardware descriptor associated with aHdr at the destination port
   1.743 +	*/
   1.744 +	virtual TUint32 HwDesNumDstElementsTransferred(const SDmaDesHdr& aHdr);
   1.745 +
   1.746 +protected:
   1.747 +	/** Called by the PSL in interrupt context upon a channel interrupt event.
   1.748 +
   1.749 +		@param aChannel The channel the ISR relates to
   1.750 +		@param aEventMask Bitmask of one or more TDmaCallbackType values
   1.751 +		@param aIsComplete Set to ETrue if no error was encountered
   1.752 +	 */
   1.753 +	static void HandleIsr(TDmaChannel& aChannel, TUint aEventMask, TBool aIsComplete);
   1.754 +
   1.755 +private:
   1.756 +	/** Called in Create() */
   1.757 +	TInt AllocDesPool(TUint aAttribs);
   1.758 +
   1.759 +	/** Called in ~TDmac() */
   1.760 +	void FreeDesPool();
   1.761 +
   1.762 +private:
   1.763 +	NFastMutex iLock;			 // protect descriptor reservation and allocation
   1.764 +	const TInt iMaxDesCount;	 // initial number of descriptors and headers
   1.765 +	TInt iAvailDesCount;		 // current available number of descriptors and headers
   1.766 +	SDmaDesHdr* iHdrPool;		 // descriptor header dynamic array
   1.767 +#ifndef __WINS__
   1.768 +	DPlatChunkHw* iHwDesChunk;	 // chunk for hardware descriptor pool
   1.769 +#endif
   1.770 +	TAny* iDesPool;				 // hardware or pseudo descriptor dynamic array
   1.771 +	const TInt iDesSize;		 // descriptor size in bytes
   1.772 +
   1.773 +public:
   1.774 +	const TBool iCapsHwDes;		 /*< True if DMAC uses h/w descriptors */
   1.775 +	SDmaDesHdr* iFreeHdr;		 /*< head of unallocated descriptors linked list */
   1.776 +
   1.777 +#ifdef _DEBUG
   1.778 +	/** Tests whether aHdr points into the descriptor header array. */
   1.779 +	TBool IsValidHdr(const SDmaDesHdr* aHdr);
   1.780 +#endif
   1.781 +	__DMA_DECLARE_INVARIANT
   1.782 +	};
   1.783 +
   1.784 +
   1.785 +//////////////////////////////////////////////////////////////////////////////
   1.786 +
   1.787 +
   1.788 +/** Single-buffer DMA channel.
   1.789 +
   1.790 +	Can be instantiated or further derived by the PSL.
   1.791 +
   1.792 +	@publishedPartner
   1.793 +	@released
   1.794 +*/
   1.795 +class TDmaSbChannel : public TDmaChannel
   1.796 +	{
   1.797 +private:
   1.798 +	virtual void DoQueue(const DDmaRequest& aReq);
   1.799 +	virtual void DoCancelAll();
   1.800 +	virtual void DoDfc(const DDmaRequest& aCurReq, SDmaDesHdr*& aCompletedHdr);
   1.801 +private:
   1.802 +	enum {EIdle = 0, ETransferring} iState;
   1.803 +	};
   1.804 +
   1.805 +
   1.806 +/** Double-buffer DMA channel.
   1.807 +
   1.808 +	Can be instantiated or further derived by the PSL.
   1.809 +
   1.810 +	@publishedPartner
   1.811 +	@released
   1.812 +*/
   1.813 +class TDmaDbChannel : public TDmaChannel
   1.814 +	{
   1.815 +private:
   1.816 +	virtual void DoQueue(const DDmaRequest& aReq);
   1.817 +	virtual void DoCancelAll();
   1.818 +	virtual void DoDfc(const DDmaRequest& aCurReq, SDmaDesHdr*& aCompletedHdr);
   1.819 +private:
   1.820 +	enum {EIdle = 0, ETransferring, ETransferringLast} iState;
   1.821 +	};
   1.822 +
   1.823 +
   1.824 +/** Scatter-gather DMA channel.
   1.825 +
   1.826 +	Can be instantiated or further derived by the PSL.
   1.827 +
   1.828 +	@publishedPartner
   1.829 +	@released
   1.830 +*/
   1.831 +class TDmaSgChannel : public TDmaChannel
   1.832 +	{
   1.833 +private:
   1.834 +	virtual void DoQueue(const DDmaRequest& aReq);
   1.835 +	virtual void DoCancelAll();
   1.836 +	virtual void DoUnlink(SDmaDesHdr& aHdr);
   1.837 +	virtual void DoDfc(const DDmaRequest& aCurReq, SDmaDesHdr*& aCompletedHdr);
   1.838 +private:
   1.839 +	enum {EIdle = 0, ETransferring} iState;
   1.840 +	};
   1.841 +
   1.842 +
   1.843 +/** Scatter-gather DMA channel with asymmetric linked-lists.
   1.844 +
   1.845 +	Can be instantiated or further derived by the PSL.
   1.846 +
   1.847 +	@publishedPartner
   1.848 +	@released
   1.849 +*/
   1.850 +class TDmaAsymSgChannel : public TDmaChannel
   1.851 +	{
   1.852 +private:
   1.853 +	virtual void DoQueue(const DDmaRequest& aReq);
   1.854 +	virtual void DoCancelAll();
   1.855 +	virtual void DoUnlink(SDmaDesHdr& aHdr);
   1.856 +	virtual void DoDfc(const DDmaRequest& aCurReq, SDmaDesHdr*& aSrcCompletedHdr,
   1.857 +					   SDmaDesHdr*& aDstCompletedHdr);
   1.858 +private:
   1.859 +	SDmaDesHdr* iSrcCurHdr;		   // source fragment being transferred or NULL
   1.860 +	SDmaDesHdr** iSrcNullPtr; // Pointer to NULL pointer following last source fragment
   1.861 +	SDmaDesHdr* iDstCurHdr;	  // destination fragment being transferred or NULL
   1.862 +	SDmaDesHdr** iDstNullPtr; // Pointer to NULL pointer following last destination fragment
   1.863 +	enum {EIdle = 0, ETransferring} iState;
   1.864 +	};
   1.865 +
   1.866 +
   1.867 +//////////////////////////////////////////////////////////////////////////////
   1.868 +
   1.869 +
   1.870 +#include <drivers/dma_hai.inl>
   1.871 +
   1.872 +
   1.873 +#endif	// #ifndef __DMA_HAI_H__