kernel/eka/include/drivers/dma_v1.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_v1.h
       
    15 // DMA Framework API v1
       
    16 //
       
    17 // NB: DMA clients should never include this file directly, but only ever the
       
    18 // generic header file <drivers/dma.h>.
       
    19 //
       
    20 
       
    21 #ifndef __DMA_H__
       
    22 #error "dma_v1.h must'n be included directly - use <drivers/dma.h> instead"
       
    23 #endif	// #ifndef __DMA_H__
       
    24 
       
    25 #ifndef __DMA_V1_H__
       
    26 #define __DMA_V1_H__
       
    27 
       
    28 #include <kernel/kern_priv.h>
       
    29 
       
    30 
       
    31 //////////////////////////////////////////////////////////////////////////////
       
    32 // Debug Support - KDmaPanicCat is defined in each source file
       
    33 
       
    34 #define __DMA_ASSERTD(e) __ASSERT_DEBUG(e, Kern::Fault(KDmaPanicCat, __LINE__))
       
    35 #define __DMA_ASSERTA(e) __ASSERT_ALWAYS(e, Kern::Fault(KDmaPanicCat, __LINE__))
       
    36 #ifdef _DEBUG
       
    37 #define __DMA_CANT_HAPPEN() Kern::Fault(KDmaPanicCat, __LINE__)
       
    38 #define __DMA_DECLARE_INVARIANT public: void Invariant();
       
    39 #define __DMA_INVARIANT() Invariant()
       
    40 #else
       
    41 #define __DMA_CANT_HAPPEN()
       
    42 #define __DMA_DECLARE_INVARIANT
       
    43 #define __DMA_INVARIANT()
       
    44 #endif
       
    45 
       
    46 
       
    47 //////////////////////////////////////////////////////////////////////////////
       
    48 // INTERFACE EXPOSED TO DEVICE-DRIVERS
       
    49 //////////////////////////////////////////////////////////////////////////////
       
    50 
       
    51 /**
       
    52 Bitmasks used for configuring a DMA request.
       
    53 
       
    54 In general, specify KDmaMemSrc|KDmaIncSrc (resp. KDmaMemDest|KDmaIncDest) if
       
    55 the source (resp. destination) is a memory buffer and clear
       
    56 KDmaMemSrc|KDmaIncSrc (resp. KDmaMemDest|KDmaIncDest) if the source
       
    57 (resp. destination) is a peripheral.
       
    58 
       
    59 If the location is given as a physical address (rather than a linear one)
       
    60 then also specify KDmaPhysAddrSrc and/or KDmaPhysAddrDest.
       
    61 
       
    62 The EKA1 "Fill Mode" can be implemented by omitting KDmaIncSrc.
       
    63 
       
    64 Some peripherals may require a post-increment address mode.
       
    65 
       
    66 @see DDmaRequest::Fragment
       
    67 @publishedPartner
       
    68 @released
       
    69 */
       
    70 
       
    71 enum TDmaRequestFlags
       
    72 	{
       
    73 	/** Source is address of memory buffer */
       
    74 	KDmaMemSrc       = 0x01,
       
    75 	/** Destination is address of memory buffer */
       
    76 	KDmaMemDest      = 0x02,
       
    77 	/** Source address must be post-incremented during transfer */
       
    78 	KDmaIncSrc       = 0x04,
       
    79 	/** Destination address must be post-incremented during transfer */
       
    80 	KDmaIncDest      = 0x08,
       
    81 	/** Source address is a physical address (as opposed to a linear one) */
       
    82 	KDmaPhysAddrSrc  = 0x10,
       
    83 	/** Destination address is a physical address (as opposed to a linear one) */
       
    84 	KDmaPhysAddrDest = 0x20,
       
    85 	/** Request a different max transfer size (for instance for test purposes) */
       
    86 	KDmaAltTransferLen = 0x40
       
    87 	};
       
    88 
       
    89 
       
    90 //////////////////////////////////////////////////////////////////////////////
       
    91 
       
    92 class TDmaChannel;
       
    93 struct SDmaDesHdr;
       
    94 
       
    95 /** A DMA request is a list of fragments small enough to be transferred in one go
       
    96 	by the DMAC.
       
    97 
       
    98 	In general, fragmentation is done in the framework by calling Fragment() but
       
    99 	clients with special needs can allocate a blank descriptor list with
       
   100 	ExpandDesList() and customise it to fit their needs.
       
   101 
       
   102 	Clients should not set attributes directly, but should use the various functions
       
   103 	instead.
       
   104 
       
   105 	This class has not been designed to be called from several concurrent threads.
       
   106 	Multithreaded clients must implement their own locking scheme (via DMutex).
       
   107 
       
   108 	Fast mutexes are used internally to protect data structures accessed both
       
   109 	by the client thread and the DFC thread.  Therefore no fast mutex can be held
       
   110 	when calling a request function.
       
   111 
       
   112 	@publishedPartner
       
   113 	@released
       
   114  */
       
   115 class DDmaRequest : public DBase
       
   116 	{
       
   117 	friend class TDmaChannel;
       
   118 public:
       
   119 	/** The outcome of the transfer */
       
   120 	enum TResult {EBadResult=0, EOk, EError};
       
   121 	/** The signature of the completion/failure callback function */
       
   122 	typedef void (*TCallback)(TResult, TAny*);
       
   123 public:
       
   124    
       
   125     /**
       
   126     Create a new transfer request. 
       
   127 
       
   128     @param aChannel The channel this request is bound to.
       
   129     @param aCb      Callback function called on transfer completion or failure (in channel
       
   130                     DFC context).  Can be NULL.
       
   131     @param aCbArg   Argument passed to callback function.
       
   132     @param aMaxTransferSize Maximum fragment size.  If not specified, defaults to the maximum size
       
   133            supported by the DMA controller for the type of transfer that is later scheduled.
       
   134     */
       
   135 	IMPORT_C DDmaRequest(TDmaChannel& aChannel, TCallback aCb=NULL, TAny* aCbArg=NULL, TInt aMaxTransferSize=0);
       
   136 	
       
   137 	
       
   138 	/**
       
   139     Destructor.
       
   140 
       
   141     Assume the request is not being transferred or pending.
       
   142     */
       
   143 	IMPORT_C ~DDmaRequest();
       
   144 	
       
   145 	
       
   146 	/**
       
   147     Split request into a list of fragments small enough to be fed to the DMAC.
       
   148 
       
   149     The size of each fragment is smaller than or equal to the maximum transfer size
       
   150     supported by the DMAC.  If the source and/or destination is memory, each
       
   151     fragment points to memory which is physically contiguous.
       
   152 
       
   153     The kind of transfer to perform is specified via a set of flags used by a PIL
       
   154     and a magic cookie passed to the PSL.  If the source (resp. destination) is a
       
   155     peripheral, aSrc (resp. aDest) is treated as a magic cookie by the PIL and
       
   156     passed straight to the PSL.
       
   157 
       
   158     The request can be uninitialised or may have been fragmented previously.  The
       
   159     previous configuration if any is lost whether or not the function succeeds.
       
   160 
       
   161     @param aSrc     Source memory buffer linear address or peripheral magic cookie.
       
   162     @param aDest    Destination memory buffer linear address or peripheral magic cookie.
       
   163     @param aCount   Number of bytes to transfer.
       
   164     @param aFlags   Bitmask characterising the transfer.
       
   165     @param aPslInfo Hardware-specific information passed to PSL.
       
   166 
       
   167     @return KErrNone if success. KErrArgument if aFlags and/or aPslInfo are invalid when finding
       
   168     the maximum transfer size. May also fail if running out of descriptors.
       
   169 
       
   170     @pre The request is not being transferred or pending.
       
   171     @pre The various parameters must be valid.  The PIL or PSL will fault the
       
   172     kernel if not.
       
   173 
       
   174     @see TDmaRequestFlags
       
   175     */
       
   176 	IMPORT_C TInt Fragment(TUint32 aSrc, TUint32 aDest, TInt aCount, TUint aFlags, TUint32 aPslInfo);
       
   177 	
       
   178 	
       
   179 	/**
       
   180     Transfer asynchronously this request.
       
   181 
       
   182     If this request's channel is idle, the request is transferred immediately.
       
   183     Otherwise, it is queued and transferred later.
       
   184 
       
   185     The client is responsible for ensuring cache consistency before and/or after the
       
   186     transfer if necessary.
       
   187     */
       
   188 	IMPORT_C void Queue();
       
   189 	
       
   190 
       
   191     /**
       
   192     Append new descriptor(s) to existing list.
       
   193 
       
   194     Clients needing to build a custom descriptor list should call this function to
       
   195     allocate the list and access the resulting list through iFirstHdr and iLastHdr.
       
   196 
       
   197     Clients should not change the value of iFirstHdr, iLastHdr and the iNext field
       
   198     of the descriptor headers to ensure descriptors can be deallocated. Clients
       
   199     are free to change hardware descriptors, including chaining, in whatever way
       
   200     suit them.
       
   201 
       
   202     Assume the request is not being transferred or pending.
       
   203 
       
   204     @param aCount Number of descriptors to append.
       
   205 
       
   206     @return KErrNone or KErrTooBig if not enough descriptors available.
       
   207     */
       
   208 	IMPORT_C TInt ExpandDesList(TInt aCount=1);
       
   209 	
       
   210 	
       
   211 	/**
       
   212     Free resources associated with this request.
       
   213 
       
   214     Assume the request is not being transferred or pending.
       
   215     */
       
   216 	IMPORT_C void FreeDesList();
       
   217 private:
       
   218 	inline void OnDeque();
       
   219 public:
       
   220 	// WARNING: The following attributes are accessed both in client and DFC
       
   221 	// context and so accesses must be protected with the channel lock.
       
   222 	TDmaChannel& iChannel;		/**< The channel this request is bound to */
       
   223 	volatile TCallback iCb;		/**< Called on completion/failure (can be NULL) */
       
   224 	TAny* volatile iCbArg;		/**< Callback argument */
       
   225 	TInt iDesCount;				/**< The number of fragments in list */
       
   226 	SDmaDesHdr* iFirstHdr;		/**< The first fragment in the list (or NULL) */
       
   227 	SDmaDesHdr* iLastHdr;		/**< The last fragment in the list (or NULL) */
       
   228 	SDblQueLink iLink;			/**< The link on channel queue of pending requests */
       
   229 	TBool iQueued;				/**< Indicates whether request is pending or being transferred */
       
   230 	TInt iMaxTransferSize;		/**< Defaults to DMA controller max. transfer size */
       
   231 	__DMA_DECLARE_INVARIANT
       
   232 	};
       
   233 
       
   234 
       
   235 //////////////////////////////////////////////////////////////////////////////
       
   236 
       
   237 class TDmac;
       
   238 class DmaChannelMgr;
       
   239 
       
   240 /** DMA channel base class.
       
   241 
       
   242 	This class has not been designed to be called from several concurrent
       
   243 	client threads.  Multithreaded clients must implement their own locking
       
   244 	scheme (via DMutex).
       
   245 
       
   246 	Fast mutexes are used internally to protect data structures accessed both
       
   247 	by the client thread and the DFC one.  Therefore no fast mutex can be held
       
   248 	when calling a channel function.
       
   249 
       
   250 	Must be allocated in BSS because it relies on being zeroed at
       
   251 	creation-time.  If the PSL really needs to allocate channels on the kernel
       
   252 	heap, it must manually zero-initialises the instances.  This can be
       
   253 	achieved either by allocating raw memory and using placement new, or by
       
   254 	wrapping channels into a DBase-derived wrapper.
       
   255 
       
   256 	@publishedPartner
       
   257 	@released
       
   258  */
       
   259 class TDmaCancelInfo;
       
   260 class TDmaChannel
       
   261 	{
       
   262 	friend class DDmaRequest;
       
   263 	friend class TDmac;
       
   264 	friend class DmaChannelMgr;
       
   265 public:
       
   266 	/**  Information passed by client when opening channel */
       
   267 	struct SCreateInfo
       
   268 		{
       
   269 		/** Identifier used by PSL to select channel to open */
       
   270 		TUint32 iCookie;
       
   271 		/** Number of descriptors this channel can use */
       
   272 		TInt iDesCount;
       
   273 		/** DFC queue used to service DMA interrupts.  The DFC thread
       
   274 			priority must be higher than any client thread priority to
       
   275 			avoid a situation where a transfer completes while being
       
   276 			cancelled and another transfer is started before the DFC
       
   277 			thread gets a chance to run.  This would lead to a stray
       
   278 			DFC.
       
   279 		*/
       
   280 		TDfcQue* iDfcQ;
       
   281 		/** DFC priority */
       
   282 		TUint8 iDfcPriority;
       
   283 		};
       
   284 public:
       
   285     /**
       
   286  	Opens the DMA channel.
       
   287 
       
   288  	Channel selection is done by the hardware-specific layer using a cookie passed in
       
   289  	via aInfo.
       
   290 
       
   291  	The client should not delete the returned pointer as the framework owns
       
   292  	channel objects.  However, the client should explicitly close the channel when
       
   293  	finished with it.
       
   294 
       
   295 	@param aInfo    Information passed by caller to select and configure channel.
       
   296  	@param aChannel Point to open channel on successful return.  NULL otherwise.
       
   297 
       
   298  	@return KErrNone or standard error code.
       
   299  	*/
       
   300 	IMPORT_C static TInt Open(const SCreateInfo& aInfo, TDmaChannel*& aChannel);
       
   301 	
       
   302 	
       
   303 	/**
       
   304  	Closes a previously opened DMA channel.
       
   305 
       
   306  	Assume the channel is idle and all requests have been deleted.
       
   307  	*/
       
   308 	IMPORT_C void Close();
       
   309 	
       
   310 	
       
   311 	/**
       
   312  	Cancels the current request and all the pending ones.
       
   313  	*/
       
   314 	IMPORT_C void CancelAll();
       
   315 	inline TBool IsOpened() const;
       
   316 	inline TBool IsQueueEmpty() const;
       
   317 	inline TUint32 PslId() const;
       
   318 	inline TInt FailNext(TInt aFragmentCount);
       
   319 	inline TInt MissNextInterrupts(TInt aInterruptCount);
       
   320 	inline TInt Extension(TInt aCmd, TAny* aArg);
       
   321 	
       
   322 	/**
       
   323 	This is a function that allows the Platform Specific Layer (PSL) to extend the DMA API
       
   324 	with new channel-independent operations.
       
   325 
       
   326 	@param aCmd Command identifier.  Negative values are reserved for Symbian use.
       
   327 	@param aArg PSL-specific.
       
   328 	
       
   329 	@return KErrNotSupported if aCmd is not supported; a  PSL specific value otherwise.
       
   330  	*/
       
   331 	IMPORT_C TInt StaticExtension(TInt aCmd, TAny* aArg);
       
   332 	inline const TDmac* Controller() const;
       
   333 	inline TInt MaxTransferSize(TUint aFlags, TUint32 aPslInfo);
       
   334 	inline TUint MemAlignMask(TUint aFlags, TUint32 aPslInfo);
       
   335 protected:
       
   336 	// Interface with state machines
       
   337 	TDmaChannel();
       
   338 	virtual void DoQueue(DDmaRequest& aReq) = 0;
       
   339 	virtual void DoCancelAll() = 0;
       
   340 	virtual void DoUnlink(SDmaDesHdr& aHdr);
       
   341 	virtual void DoDfc(DDmaRequest& aCurReq, SDmaDesHdr*& aCompletedHdr) = 0;
       
   342 	/**
       
   343 	   This function allows the Platform Specific Layer (PSL) to control the
       
   344 	   power management of the channel or its controller by overriding the
       
   345 	   PIL's default implementation (which does nothing) and making appropriate
       
   346 	   use of the Power Resource Manager (PRM).
       
   347 
       
   348 	   The function gets called by the PIL whenever the channel's queued
       
   349 	   requests count has changed in a significant way, either before the
       
   350 	   channel's Transfer() method is invoked for a request on a previously
       
   351 	   empty request queue, or immediately after the request count has become
       
   352 	   zero because of request cancellation or completion.
       
   353 
       
   354 	   Depending on the current value of iQueuedRequests, the PSL may power
       
   355 	   down or power up the channel. Note that iQueuedRequests gets accessed
       
   356 	   and changed by different threads, so the PSL needs to take the usual
       
   357 	   precautions when evaluating the variable's value.
       
   358 
       
   359 	   None of the internal DMA framework mutexes is being held by the PIL when
       
   360 	   calling this function.
       
   361 
       
   362 	   @see iQueuedRequests
       
   363 	 */
       
   364 	virtual void QueuedRequestCountChanged();
       
   365 #if defined(__CPU_ARM) && !defined(__EABI__)
       
   366 	inline virtual ~TDmaChannel() {}	// kill really annoying warning
       
   367 #endif
       
   368 private:
       
   369 	static void Dfc(TAny*);
       
   370 	void DoDfc();
       
   371 	inline void Wait();
       
   372 	inline void Signal();
       
   373 	inline TBool Flash();
       
   374 	void ResetStateMachine();
       
   375 protected:
       
   376 	TDmac* iController;										// DMAC this channel belongs to (NULL when closed)
       
   377 	TUint32 iPslId;											// unique identifier provided by PSL
       
   378 	NFastMutex iLock;										// for data accessed in both client & DFC context
       
   379 	SDmaDesHdr* iCurHdr;									// fragment being transferred or NULL
       
   380 	SDmaDesHdr** iNullPtr;									// Pointer to NULL pointer following last fragment
       
   381 	TDfc iDfc;												// transfer completion/failure DFC
       
   382 	TInt iMaxDesCount;										// maximum number of allocable descriptors
       
   383 	TInt iAvailDesCount;									// available number of descriptors
       
   384 	volatile TUint32 iIsrDfc;								// Interface between ISR and DFC:
       
   385 	enum { KErrorFlagMask = 0x80000000 };					// bit 31 - error flag
       
   386 	enum { KCancelFlagMask = 0x40000000 };					// bit 30 - cancel flag
       
   387 	enum { KDfcCountMask = 0x3FFFFFFF };					// bits 0-29 - number of queued DFCs
       
   388 	SDblQue iReqQ;											// being/about to be transferred request queue
       
   389 	TInt iReqCount;											// number of requests attached to this channel
       
   390 	TInt iQueuedRequests; 									// number of requests currently queued on this channel
       
   391 private:
       
   392 	TDmaCancelInfo* iCancelInfo;
       
   393 	__DMA_DECLARE_INVARIANT
       
   394 	};
       
   395 
       
   396 
       
   397 //////////////////////////////////////////////////////////////////////////////
       
   398 // PIL-PSL INTERFACE
       
   399 //////////////////////////////////////////////////////////////////////////////
       
   400 
       
   401 /**
       
   402 Generic DMA descriptor used if the DMAC does not have support for hardware
       
   403 descriptor.
       
   404 @see DDmaRequest::Fragment
       
   405 @publishedPartner
       
   406 @released
       
   407 */
       
   408 
       
   409 struct SDmaPseudoDes
       
   410 	{
       
   411 	/** Source linear address or peripheral cookie */
       
   412 	TUint32 iSrc;
       
   413 	/** Destination linear address or peripheral cookie */
       
   414 	TUint32 iDest;
       
   415 	/** Number of bytes to transfer */
       
   416 	TInt iCount;
       
   417 	/** @see TDmaRequestFlags */
       
   418 	TUint iFlags;
       
   419 	/** PSL-specific information provided by client */
       
   420 	TUint32 iPslInfo;
       
   421 	/** The same as TDmaChannel::SCreateInfo.iCookie */
       
   422 	TUint32 iCookie;
       
   423 	};
       
   424 
       
   425 
       
   426 /**
       
   427 Each hardware or pseudo descriptor is associated with a header.  Headers are
       
   428 needed because hardware descriptors can not easily be extended to store
       
   429 additional information.
       
   430 @publishedPartner
       
   431 @released
       
   432 */
       
   433 
       
   434 struct SDmaDesHdr
       
   435 	{
       
   436 	SDmaDesHdr* iNext;
       
   437 	};
       
   438 
       
   439 
       
   440 /**
       
   441 Interface used by PIL to open and close DMA channels.
       
   442 
       
   443 Must be implemented by PSL.
       
   444 @publishedPartner
       
   445 @released
       
   446 */
       
   447 
       
   448 class DmaChannelMgr
       
   449 	{
       
   450 public:
       
   451 	/** Opens a channel using a client-provided identifier.
       
   452 		This function must be implemented by the PSL.
       
   453 		@param	aOpenId Magic cookie passed by client
       
   454 				This may identify the channel (if a static channel
       
   455 				allocation scheme is used) or may indicate some
       
   456 				properties which the channel must possess (if a dynamic
       
   457 				channel allocation scheme is used). It may be set to
       
   458 				zero always if dynamic allocation is used and all
       
   459 				channels are equivalent.
       
   460 		@return	Pointer to channel if available, NULL otherwise.
       
   461 		@pre	The PIL calls this function with a global fast mutex held to
       
   462 				avoid race conditions.
       
   463 		@post	If a non-NULL pointer is returned, the object pointed to has its
       
   464 				iController and iPslId members set to valid states.
       
   465 				iController should point to the controller handling that channel.
       
   466 				iPslId should contain a value uniquely identifying the channel -
       
   467 				it is used only for debug tracing by PIL. It can be given any
       
   468 				convenient value by PSL	(channel index, I/O port address, ...).
       
   469 	*/
       
   470 	static TDmaChannel* Open(TUint32 aOpenId);
       
   471 
       
   472 	/** Performs platform-specific operations when a channel is closed.
       
   473 		This function must be implemented by the PSL but the implementation can be
       
   474 		a no-op.
       
   475 		@param aChannel The channel to close
       
   476 		@pre The PIL calls this function with a global fast mutex held to
       
   477 			avoid race conditions.
       
   478 	*/
       
   479 	static void Close(TDmaChannel* aChannel);
       
   480 
       
   481 	/** Function allowing PSL to extend DMA API with new channel-independent operations.
       
   482 		This function must be implemented by the PSL.
       
   483 		@param aCmd Command identifier.  Negative values are reserved for Symbian use.
       
   484 		@param aArg PSL-specific
       
   485 		@return KErrNotSupported if aCmd is not supported.  PSL-specific value otherwise.
       
   486 	 */
       
   487 	static TInt StaticExtension(TInt aCmd, TAny* aArg);
       
   488 
       
   489 	static inline void Wait();
       
   490 	static inline void Signal();
       
   491 private:
       
   492 	static NFastMutex Lock;
       
   493 	};
       
   494 
       
   495 
       
   496 //////////////////////////////////////////////////////////////////////////////
       
   497 
       
   498 /**
       
   499  Abstract base class representing a DMA controller.
       
   500 
       
   501  The class has two purposes.
       
   502 
       
   503  First, it is a container for channels, descriptors and descriptor headers.
       
   504 
       
   505  Second, it exposes a set of virtual functions implemented by
       
   506  the PSL (platform-specific layer).
       
   507  These functions are the main interfaces between
       
   508  the PIL (platform-independent layer) and PSL.
       
   509 
       
   510  Must be allocated in BSS because it relies on being zeroed at creation-time.
       
   511 
       
   512  @publishedPartner
       
   513  @released
       
   514  */
       
   515 
       
   516 class TDmac
       
   517 	{
       
   518 	friend class DmaChannelMgr;
       
   519 // protected: VC++ complains when building PSL if following decl is protected
       
   520 public:
       
   521 	/** Data required for creating a new instance */
       
   522 	struct SCreateInfo
       
   523 		{
       
   524 		/** Number of channels in controller */
       
   525 		TInt iChannelCount;
       
   526         /** Maximum number of descriptors (shared by all channels) */
       
   527 		TInt iDesCount;
       
   528 		/** Bitmask.  The only supported value is KCapsBitHwDes (hardware
       
   529 			descriptors used). */
       
   530 		TUint32 iCaps;
       
   531 		/** Size of individual descriptors.  Use sizeof(SDmaPseudoDes) for
       
   532 		 	single-buffer and double-buffer controllers. */
       
   533 		TInt iDesSize;
       
   534 		/** Bitmask used when creating the hardware chunk storing the descriptor
       
   535 			pool. Used only for hardware descriptors. The access part must be
       
   536 			EMapAttrSupRw.  If the chunk is cached and/or buffered, the PSL must
       
   537 			flush the data cache and/or drain the write buffer in InitHwDes()
       
   538 			and related functions.
       
   539 		 	@see TMappingAttributes
       
   540 		 */
       
   541 		TUint iDesChunkAttribs;
       
   542 		};
       
   543 public:
       
   544 	TInt Create(const SCreateInfo& aInfo);
       
   545 	virtual ~TDmac();
       
   546 	TInt ReserveSetOfDes(TInt aCount);
       
   547 	void ReleaseSetOfDes(TInt aCount);
       
   548 	void InitDes(const SDmaDesHdr& aHdr, TUint32 aSrc, TUint32 aDest, TInt aCount,
       
   549 				 TUint aFlags, TUint32 aPslInfo, TUint32 aCookie);
       
   550 	inline SDmaPseudoDes& HdrToDes(const SDmaDesHdr& aHdr) const;
       
   551 	inline TAny* HdrToHwDes(const SDmaDesHdr& aHdr) const;
       
   552 	inline TUint32 DesLinToPhys(TAny* aDes) const;
       
   553 	inline void Wait();
       
   554 	inline void Signal();
       
   555 protected:
       
   556 	TDmac(const SCreateInfo& aInfo);
       
   557 
       
   558 public:
       
   559 	/**
       
   560 	Called by PIL when one fragment (single-buffer and double-buffer DMACs) or
       
   561 	list of fragments (scatter/gather DMAC) is to be transferred.
       
   562 
       
   563 	Called when	initiating a new transfer and also, for double-buffer DMACs, for
       
   564 	configuring the next fragment to transfer while the current one is
       
   565 	ongoing. Must always be implemented by PSL.
       
   566 	@param aChannel The channel to use
       
   567 	@param aHdr Header associated with fragment to transfer
       
   568 	*/
       
   569 	virtual void Transfer(const TDmaChannel& aChannel, const SDmaDesHdr& aHdr) = 0;
       
   570 
       
   571 	/**
       
   572     Called by PIL to suspend transfer on a given channel.
       
   573 
       
   574     The suspension must occur synchronously as the PSL assumes the channel
       
   575     is suspended after calling this function. Must always be implemented by PSL.
       
   576 	@param aChannel The channel to suspend
       
   577 	*/
       
   578 	virtual void StopTransfer(const TDmaChannel& aChannel) = 0;
       
   579 
       
   580 	/**
       
   581 	Called by PIL to check whether a DMA channel is idle.
       
   582 	@param aChannel The channel to test
       
   583 	@return ETrue if channel idle, EFalse if transferring.
       
   584 	 */
       
   585 	virtual TBool IsIdle(const TDmaChannel& aChannel) = 0;
       
   586 
       
   587 	/**
       
   588 	Called by PIL to retrieve from the PSL the maximum transfer size based on the
       
   589 	parameters passed.
       
   590 	@param aChannel Channel to be used for the transfer
       
   591 	@param aFlags Bitmask characterising transfer
       
   592 	@param aPslInfo Cookie passed by client and used by PSL
       
   593 	@return 0 if invalid argument(s), -1 if transfer size not limited, the maximum
       
   594 	transfer size otherwise.
       
   595 	*/
       
   596 	virtual TInt MaxTransferSize(TDmaChannel& aChannel, TUint aFlags, TUint32 aPslInfo) = 0;
       
   597 
       
   598 	/**
       
   599 	Called by PIL to retrieve from the PSL the memory alignment mask based on the
       
   600 	parameters passed. Some DMA controllers impose alignment constraints on the base
       
   601 	address of memory buffers. This mask is AND'ed against memory addresses computed
       
   602 	during fragmentation.
       
   603 	@param aChannel Channel to be used for the transfer
       
   604 	@param aFlags Bitmask characterising transfer
       
   605 	@param aPslInfo Cookie passed by client and used by PSL
       
   606 	@return A value representing the alignment mask (e.g. 3 if buffer must be 4-byte aligned)
       
   607 	*/
       
   608 	virtual TUint MemAlignMask(TDmaChannel& aChannel, TUint aFlags, TUint32 aPslInfo) = 0;
       
   609 
       
   610 	/**
       
   611     Called by PIL during fragmentation to initialise a hardware descriptor.
       
   612 
       
   613     The PSL must assume the descriptor is the last in the chain and so set the
       
   614 	interrupt bit and set the next descriptor field to an end of chain marker.
       
   615 	Must be implemented by PSL if and only if the DMAC supports hardware
       
   616 	descriptors.
       
   617 	@param aHdr Header associated with hardware descriptor to initialise
       
   618 	@param aSrc Transfer source
       
   619 	@param aDest Transfer destination
       
   620 	@param aCount Number of bytes to transfer (<= max. size supported by DMAC)
       
   621 	@param aFlags Bitmask characterising transfer
       
   622 	@param aPslInfo Cookie passed by client and used by PSL
       
   623 	@param aCookie the channel selection cookie
       
   624 	@see DDmaRequest::Fragment
       
   625 	*/
       
   626 	virtual void InitHwDes(const SDmaDesHdr& aHdr, TUint32 aSrc, TUint32 aDest, TInt aCount,
       
   627 						   TUint aFlags, TUint32 aPslInfo, TUint32 aCookie);
       
   628 
       
   629 	/**
       
   630 	Called by PIL, when fragmenting a request, to append a new hardware
       
   631 	descriptor to an existing descriptor chain.
       
   632 
       
   633 	Must clear the interrupt bit of	the descriptor associated with aHdr.
       
   634 	Must be implemented by PSL if and only if the DMAC supports hardware descriptors.
       
   635 	@param aHdr Header associated with last fragment in chain
       
   636 	@param aNextHdr Header associated with fragment to append
       
   637 	*/
       
   638 	virtual void ChainHwDes(const SDmaDesHdr& aHdr, const SDmaDesHdr& aNextHdr);
       
   639 
       
   640 	/**
       
   641 	Called by PIL when queuing a new request while the channel is running.
       
   642 
       
   643 	Must append the first hardware descriptor of the new request to the last
       
   644 	descriptor in the existing chain. Must be implemented by PSL if and only if
       
   645 	the DMAC supports hardware descriptors.
       
   646 	@param aChannel The channel where the transfer takes place
       
   647 	@param aLastHdr Header associated with last hardware descriptor in chain
       
   648 	@param aNewHdr Header associated with first hardware descriptor in new request
       
   649 	*/
       
   650 	virtual void AppendHwDes(const TDmaChannel& aChannel, const SDmaDesHdr& aLastHdr,
       
   651 							 const SDmaDesHdr& aNewHdr);
       
   652 
       
   653 	/**
       
   654 	Called by PIL when completing or cancelling a request to cause the PSL to unlink
       
   655 	the last item in the h/w descriptor chain from a subsequent chain that it was
       
   656 	possibly linked to. Must be implemented by the PSL if and only if the DMAC supports
       
   657 	hardware descriptors.
       
   658 
       
   659 	@param aChannel The channel where the request (and thus the descriptor) was queued
       
   660 	@param aHdr Header associated with last h/w descriptor in completed/cancelled chain
       
   661 	*/
       
   662 	virtual void UnlinkHwDes(const TDmaChannel& aChannel, SDmaDesHdr& aHdr);
       
   663 
       
   664 	/**
       
   665 	Called by 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 	@param aChannel The channel where the error is to occur.
       
   670 	@return KErrNone if implemented.  The default PIL implementation returns
       
   671 	KErrNotSupported and the test harness knows how to deal with that.
       
   672 	*/
       
   673 	virtual TInt FailNext(const TDmaChannel& aChannel);
       
   674 
       
   675 	/**
       
   676 	Called by test harness to force the DMA controller to miss one or
       
   677 	more interrupts.
       
   678 
       
   679 	Must be implemented by the PSL only if possible.
       
   680 	@param aChannel The channel where the error is to occur
       
   681 	@param aInterruptCount The number of interrupt to miss.
       
   682 	@return KErrNone if implemented.  The default PIL implementation returns
       
   683 	KErrNotSupported and the test harness knows how to deal with that.
       
   684 	*/
       
   685 	virtual TInt MissNextInterrupts(const TDmaChannel& aChannel, TInt aInterruptCount);
       
   686 
       
   687 	/** Function allowing platform-specific layer to extend channel API with
       
   688 		new channel-specific operations.
       
   689 		@param aChannel Channel to operate on
       
   690 		@param aCmd Command identifier.  Negative values are reserved for Symbian use.
       
   691 		@param aArg PSL-specific
       
   692 		@return KErrNotSupported if aCmd is not supported.  PSL-specific value otherwise.
       
   693 		@see TDmaChannel::Extension
       
   694 	*/
       
   695 	virtual TInt Extension(TDmaChannel& aChannel, TInt aCmd, TAny* aArg);
       
   696 
       
   697 protected:
       
   698 	static void HandleIsr(TDmaChannel& aChannel, TBool aIsComplete);
       
   699 private:
       
   700 	TInt AllocDesPool(TUint aAttribs);
       
   701 	void FreeDesPool();
       
   702 private:
       
   703 	NFastMutex iLock;			 // protect descriptor reservation and allocation
       
   704 	const TInt iMaxDesCount;	 // initial number of descriptors and headers
       
   705 	TInt iAvailDesCount;		 // current available number of descriptors and headers
       
   706 	SDmaDesHdr* iHdrPool;		 // descriptor header dynamic array
       
   707 #ifndef __WINS__
       
   708 	DPlatChunkHw* iHwDesChunk;	 // chunk for hardware descriptor pool
       
   709 #endif
       
   710 	TAny* iDesPool;				 // hardware or pseudo descriptor dynamic array
       
   711 	const TInt iDesSize;		 // descriptor size in bytes
       
   712 public:
       
   713 	const TUint iCaps;  		 /*< what is supported by DMA controller */
       
   714 	enum {KCapsBitHwDes = 1};	 /*< hardware descriptors supported */
       
   715 	SDmaDesHdr* iFreeHdr;		 /*< head of unallocated descriptors linked list */
       
   716 #ifdef _DEBUG
       
   717 	TBool IsValidHdr(const SDmaDesHdr* aHdr);
       
   718 #endif
       
   719 	__DMA_DECLARE_INVARIANT
       
   720 	};
       
   721 
       
   722 
       
   723 //////////////////////////////////////////////////////////////////////////////
       
   724 
       
   725 /**
       
   726 Single-buffer DMA channel.
       
   727 
       
   728 Can be instantiated or further derived by PSL.  Not
       
   729 intended to be instantiated by client device drivers.
       
   730 @publishedPartner
       
   731 @released
       
   732 */
       
   733 
       
   734 class TDmaSbChannel : public TDmaChannel
       
   735 	{
       
   736 private:
       
   737 	virtual void DoQueue(DDmaRequest& aReq);
       
   738 	virtual void DoCancelAll();
       
   739 	virtual void DoDfc(DDmaRequest& aCurReq, SDmaDesHdr*& aCompletedHdr);
       
   740 private:
       
   741 	TBool iTransferring;
       
   742 	};
       
   743 
       
   744 
       
   745 /**
       
   746 Double-buffer DMA channel.
       
   747 
       
   748 Can be instantiated or further derived by PSL.  Not
       
   749 intended to be instantiated by client device drivers.
       
   750 @publishedPartner
       
   751 @released
       
   752 */
       
   753 
       
   754 class TDmaDbChannel : public TDmaChannel
       
   755 	{
       
   756 private:
       
   757 	virtual void DoQueue(DDmaRequest& aReq);
       
   758 	virtual void DoCancelAll();
       
   759 	virtual void DoDfc(DDmaRequest& aCurReq, SDmaDesHdr*& aCompletedHdr);
       
   760 private:
       
   761 	enum { EIdle = 0, ETransferring, ETransferringLast } iState;
       
   762 	};
       
   763 
       
   764 
       
   765 /**
       
   766 Scatter-gather DMA channel.
       
   767 
       
   768 Can be instantiated or further derived by PSL.
       
   769 Not intended to be instantiated by client device drivers.
       
   770 @publishedPartner
       
   771 @released
       
   772 */
       
   773 
       
   774 class TDmaSgChannel : public TDmaChannel
       
   775 	{
       
   776 private:
       
   777 	virtual void DoQueue(DDmaRequest& aReq);
       
   778 	virtual void DoCancelAll();
       
   779 	virtual void DoUnlink(SDmaDesHdr& aHdr);
       
   780 	virtual void DoDfc(DDmaRequest& aCurReq, SDmaDesHdr*& aCompletedHdr);
       
   781 private:
       
   782 	TBool iTransferring;
       
   783 	};
       
   784 
       
   785 
       
   786 //////////////////////////////////////////////////////////////////////////////
       
   787 // INTERFACE WITH TEST HARNESS
       
   788 //////////////////////////////////////////////////////////////////////////////
       
   789 
       
   790 /**
       
   791 Set of information used by test harness.
       
   792 @publishedPartner
       
   793 @released
       
   794 */
       
   795 
       
   796 struct TDmaTestInfo
       
   797 	{
       
   798 	/** Maximum transfer size in bytes for all channels (ie. the minimum of all channels' maximum size)*/
       
   799 	TInt iMaxTransferSize;
       
   800 	/** 3->Memory buffers must be 4-byte aligned, 7->8-byte aligned, ... */
       
   801 	TUint iMemAlignMask;
       
   802 	/** Cookie to pass to DDmaRequest::Fragment for memory-memory transfer*/
       
   803 	TUint32 iMemMemPslInfo;
       
   804 	/** Number of test single-buffer channels */
       
   805 	TInt iMaxSbChannels;
       
   806 	/** Pointer to array containing single-buffer test channel ids */
       
   807 	TUint32* iSbChannels;
       
   808 	/** Number of test double-buffer channels */
       
   809 	TInt iMaxDbChannels;
       
   810 	/** Pointer to array containing double-buffer test channel ids */
       
   811 	TUint32* iDbChannels;
       
   812 	/** Number of test scatter-gather channels */
       
   813 	TInt iMaxSgChannels;
       
   814 	/** Pointer to array containing scatter-gather test channel ids */
       
   815 	TUint32* iSgChannels;
       
   816 	};
       
   817 
       
   818 
       
   819 /**
       
   820 Provides access to test information structure stored in the PSL.
       
   821 
       
   822 Must be implemented by the PSL.
       
   823 @publishedPartner
       
   824 @released
       
   825 */
       
   826 
       
   827 IMPORT_C const TDmaTestInfo& DmaTestInfo();
       
   828 
       
   829 
       
   830 //////////////////////////////////////////////////////////////////////////////
       
   831 
       
   832 #include <drivers/dma_v1.inl>
       
   833 
       
   834 #endif