diff -r c734af59ce98 -r 5b5d147c7838 kernel/eka/include/drivers/dma_v2.h --- a/kernel/eka/include/drivers/dma_v2.h Tue May 11 17:28:22 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1135 +0,0 @@ -// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). -// All rights reserved. -// This component and the accompanying materials are made available -// under the terms of "Eclipse Public License v1.0"" -// which accompanies this distribution, and is available -// at the URL "http://www.eclipse.org/legal/epl-v10.html". -// -// Initial Contributors: -// Nokia Corporation - initial contribution. -// -// Contributors: -// -// Description: -// include/drivers/dma_v2.h -// DMA Framework - Client API v2 definition. -// -// NB: DMA clients should never include this file directly, but only ever the -// generic header file . -// - -#ifndef __DMA_H__ -#error "dma_v2.h must'n be included directly - use instead" -#endif // #ifndef __DMA_H__ - -#ifndef __DMA_V2_H__ -#define __DMA_V2_H__ - - -#include -#include - - -////////////////////////////////////////////////////////////////////////////// -// Debug Support - KDmaPanicCat is defined in each source file - -#define __DMA_ASSERTD(e) __ASSERT_DEBUG(e, Kern::Fault(KDmaPanicCat, __LINE__)) -#define __DMA_ASSERTA(e) __ASSERT_ALWAYS(e, Kern::Fault(KDmaPanicCat, __LINE__)) -#ifdef _DEBUG -#define __DMA_CANT_HAPPEN() Kern::Fault(KDmaPanicCat, __LINE__) -#define __DMA_DECLARE_INVARIANT public: void Invariant(); -#define __DMA_INVARIANT() Invariant() -#else -#define __DMA_CANT_HAPPEN() -#define __DMA_DECLARE_INVARIANT -#define __DMA_INVARIANT() -#endif - - -////////////////////////////////////////////////////////////////////////////// -// INTERFACE EXPOSED TO DEVICE-DRIVERS -////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////// - -/** Bitmasks used for configuring a DMA request. - - In general, specify KDmaMemSrc|KDmaIncSrc (resp. KDmaMemDest|KDmaIncDest) - if the source (resp. destination) is a memory buffer and clear - KDmaMemSrc|KDmaIncSrc (resp. KDmaMemDest|KDmaIncDest) if the source - (resp. destination) is a peripheral. - - If the location is given as a physical address (rather than a linear one) - then also specify KDmaPhysAddrSrc and/or KDmaPhysAddrDest. - - The EKA1 "Fill Mode" can be implemented by omitting KDmaIncSrc. - - Some peripherals may require a post-increment address mode. - - @see DDmaRequest::Fragment - @publishedPartner - @released -*/ -enum TDmaRequestFlags - { - // Note: This enum is only required for backwards compatibility with the - // old DMA framework, it can be removed once this is no longer needed. - - /** Source is address of memory buffer */ - KDmaMemSrc = 0x01, - /** Destination is address of memory buffer */ - KDmaMemDest = 0x02, - /** Source address must be post-incremented during transfer */ - KDmaIncSrc = 0x04, - /** Destination address must be post-incremented during transfer */ - KDmaIncDest = 0x08, - /** Source address is a physical address (as opposed to a linear one) */ - KDmaPhysAddrSrc = 0x10, - /** Destination address is a physical address (as opposed to a linear one) */ - KDmaPhysAddrDest = 0x20, - /** Request a different max transfer size (for instance for test purposes) */ - KDmaAltTransferLen = 0x40 - }; - - -/** Each hardware or pseudo descriptor is associated with a header. Headers - are needed because hardware descriptors can not easily be extended to store - additional information. - - @publishedPartner - @released -*/ -struct SDmaDesHdr - { - SDmaDesHdr* iNext; - }; - -/** Pointer to signature of the new extended callback function. - - TUint - bitmask of one or more TDmaCallbackType values - TDmaResult - just that - TAny* - was provided by client in DDmaRequest constructor - SDmaDesHdr* - points to header (and thus descriptor) which caused a - 'descriptor completed' or 'descriptor paused' event. - */ -typedef void (*TDmaCallback)(TUint, TDmaResult, TAny*, SDmaDesHdr*); - -class TDmaChannel; - -/** A DMA request is a list of fragments small enough to be transferred in one go - by the DMAC. - - In general, fragmentation is done in the framework by calling Fragment() but - clients with special needs can allocate a blank descriptor list with - ExpandDesList() and customise it to fit their needs. - - Clients should not set attributes directly, but should use the various functions - instead. - - This class has not been designed to be called from several concurrent threads. - Multithreaded clients must implement their own locking scheme (via DMutex). - - Mutexes are used internally to protect data structures accessed both by the - client thread and the DFC thread. Therefore no fast mutex can be held when - calling a request function. - - @publishedPartner - @released - */ -class DDmaRequest : public DBase - { - friend class TDmaChannel; - -public: - /** The outcome of the transfer - - @deprecated - @see TDmaResult - */ - enum TResult {EBadResult=0, EOk, EError}; - /** The signature of the completion/failure callback function - - @deprecated - @see TDmaCallback - */ - typedef void (*TCallback)(TResult, TAny*); - -public: - /** Constructor. - - Create a new transfer request. - - @param aChannel The channel this request is bound to. - @param aCb Callback function called on transfer completion or failure - (in channel DFC context). Can be NULL. - @param aCbArg Argument passed to callback function. - @param aMaxTransferSize Maximum fragment size. If not specified, defaults to the maximum size - supported by the DMA controller for the type of transfer that is later scheduled. - - @deprecated - */ - IMPORT_C DDmaRequest(TDmaChannel& aChannel, TCallback aCb=NULL, TAny* aCbArg=NULL, - TInt aMaxTransferSize=0); - - - /** Constructor. - - Create a new transfer request. - - @param aChannel The channel this request is bound to. - @param aDmaCb Callback function called on transfer completion or - failure (in channel DFC or ISR context). Can be NULL. - @param aCbArg Argument passed to callback function. - @param aMaxTransferSize Maximum fragment size. If not specified, - defaults to the maximum size supported by the DMA controller for the - type of transfer that is later scheduled. - */ - IMPORT_C DDmaRequest(TDmaChannel& aChannel, TDmaCallback aDmaCb, TAny* aCbArg=NULL, - TUint aMaxTransferSize=0); - - - /** Destructor. - - Assume the request is not being transferred or pending. - */ - IMPORT_C ~DDmaRequest(); - - - /** Split request into a list of fragments small enough to be fed to the - DMAC. - - The size of each fragment is smaller than or equal to the maximum - transfer size supported by the DMAC. If the source and/or destination - is memory, each fragment points to memory which is physically - contiguous. - - The kind of transfer to perform is specified via a set of flags used by - a PIL and a magic cookie passed to the PSL. If the source - (resp. destination) is a peripheral, aSrc (resp. aDest) is treated as a - magic cookie by the PIL and passed straight to the PSL. - - The request can be uninitialised or may have been fragmented - previously. The previous configuration if any is lost whether or not - the function succeeds. - - @param aSrc Source memory buffer linear address or peripheral magic - cookie. - @param aDest Destination memory buffer linear address or peripheral - magic cookie. - @param aCount Number of bytes to transfer. - @param aFlags Bitmask characterising the transfer. - @param aPslInfo Hardware-specific information passed to PSL. - - @return KErrNone if success. KErrArgument if aFlags and/or aPslInfo are - invalid when finding the maximum transfer size. May also fail if - running out of descriptors. - - @pre The request is not being transferred or pending. - @pre The various parameters must be valid. The PIL or PSL will fault the - kernel if not. - - @see TDmaRequestFlags - - @deprecated - */ - IMPORT_C TInt Fragment(TUint32 aSrc, TUint32 aDest, TInt aCount, TUint aFlags, TUint32 aPslInfo); - - - /** New version of the DMA request fragment function, to be used with the - TDmaTransferArgs structure. - */ - IMPORT_C TInt Fragment(const TDmaTransferArgs& aTransferArgs); - - - /** Transfer asynchronously this request. - - If this request's channel is idle, the request is transferred - immediately. Otherwise, it is queued and transferred later. - - The client is responsible for ensuring cache consistency before and/or - after the transfer if necessary. - - @return KErrNone if success, KErrGeneral otherwise. - */ - IMPORT_C TInt Queue(); - - - /** Append new descriptor(s) to existing list. - - Clients needing to build a custom descriptor list should call this - function to allocate the list and access the resulting list through - iFirstHdr and iLastHdr. - - Clients should not change the value of iFirstHdr, iLastHdr and the - iNext field of the descriptor headers to ensure descriptors can be - deallocated. Clients are free to change hardware descriptors, including - chaining, in whatever way suit them. - - Assume the request is not being transferred or pending. - - @param aCount Number of descriptors to append. - - @return KErrNone or standard error code. - */ - IMPORT_C TInt ExpandDesList(TInt aCount=1); - - - /** Append new descriptor(s) to existing list. This function variant - operates on the source port descriptor chain. - - Works like ExpandDesList except that it uses the iSrcFirstHdr and - iSrcLastHdr fields. - - @see ExpandDesList - - This function can only be used if SDmacCaps::iAsymHwDescriptors is - true, otherwise it will just return KErrGeneral. - - @param aCount Number of descriptors to append. - - @return KErrNone or standard error code. - */ - IMPORT_C TInt ExpandSrcDesList(TInt aCount=1); - - - /** Append new descriptor(s) to existing list. This function variant - operates on the destination port descriptor chain. - - Works like ExpandDesList except that it uses the iDstFirstHdr and - iDstLastHdr fields. - - @see ExpandDesList - - This function can only be used if SDmacCaps::iAsymHwDescriptors is - true, otherwise it will just return KErrGeneral. - - @param aCount Number of descriptors to append. - - @return KErrNone or standard error code. - */ - IMPORT_C TInt ExpandDstDesList(TInt aCount=1); - - - /** Free resources associated with this request. - - Assume the request is not being transferred or pending. - */ - IMPORT_C void FreeDesList(); - - - /** Free resources associated with this request. This function variant - operates on the source port descriptor chain. - - @see FreeDesList - - This function can only be used if SDmacCaps::iAsymHwDescriptors is - true, otherwise it will do nothing. - */ - IMPORT_C void FreeSrcDesList(); - - - /** Free resources associated with this request. This function variant - operates on the destination port descriptor chain. - - @see FreeDesList - - This function can only be used if SDmacCaps::iAsymHwDescriptors is - true, otherwise it will do nothing. - */ - IMPORT_C void FreeDstDesList(); - - - /** Enables the functionality for counting the transferred source - elements. - - This function can be called at any time, but the enabled/disabled - status is checked by the framework only at two points in time. - - The first one is after a request has been queued, and if it is enabled - then the counting will commence as soon as the transfer starts. - - The second point is when Resume() is called for a paused transfer, and - in this case the following applies. If counting was enabled when the - transfer was paused and it is now disabled then the counting is stopped - at that point and the count value frozen. If counting was disabled when - the transfer was paused and it is now enabled then the counting will - commence when the transfer resumes. (The starting value will depend on - the argument of the enable function.) Otherwise nothing will change, - i.e. counting will either continue normally (enabled/enabled) or - neither stop nor continue (disabled/disabled). - - Once a status has been set, it remains valid for the entire duration of - the transfer (and beyond, if it is not changed again). - - @param aResetElementCount If ETrue (the default) then the count - variable will be reset to zero, otherwise it will retain its current - value. - - @see Queue() - @see TotalNumSrcElementsTransferred() - */ - IMPORT_C void EnableSrcElementCounting(TBool aResetElementCount=ETrue); - - - /** Enables the functionality for counting the transferred destination - elements. - - This function can be called at any time, but the enabled/disabled - status is checked by the framework only at two points in time. - - The first one is after a request has been queued, and if it is enabled - then the counting will commence as soon as the transfer starts. - - The second point is when Resume() is called for a paused transfer, and - in this case the following applies. If counting was enabled when the - transfer was paused and it is now disabled then the counting is stopped - at that point and the count value frozen. If counting was disabled when - the transfer was paused and it is now enabled then the counting will - commence when the transfer resumes. (The starting value will depend on - the argument of the enable function.) Otherwise nothing will change, - i.e. counting will either continue normally (enabled/enabled) or - neither stop nor continue (disabled/disabled). - - Once a status has been set, it remains valid for the entire duration of - the transfer (and beyond, if it is not changed again). - - @param aResetElementCount If ETrue (the default) then the count - variable will be reset to zero, otherwise it will retain its current - value. - - @see Queue() - @see TotalNumDstElementsTransferred() - */ - IMPORT_C void EnableDstElementCounting(TBool aResetElementCount=ETrue); - - - /** Disables the functionality for counting the transferred source - elements. - - This function can be called at any time, but the enabled/disabled - status is checked by the framework only at two points in time. - - The first one is after a request has been queued, and if it is enabled - then the counting will commence as soon as the transfer starts. - - The second point is when Resume() is called for a paused transfer, and - in this case the following applies. If counting was enabled when the - transfer was paused and it is now disabled then the counting is stopped - at that point and the count value frozen. If counting was disabled when - the transfer was paused and it is now enabled then the counting will - commence when the transfer resumes. (The starting value will depend on - the argument of the enable function.) Otherwise nothing will change, - i.e. counting will either continue normally (enabled/enabled) or - neither stop nor continue (disabled/disabled). - - Once a status has been set, it remains valid for the entire duration of - the transfer (and beyond, if it is not changed again). - - @see Queue() - @see TotalNumSrcElementsTransferred() - */ - IMPORT_C void DisableSrcElementCounting(); - - - /** Disables the functionality for counting the transferred destination - elements. - - This function can be called at any time, but the enabled/disabled - status is checked by the framework only at two points in time. - - The first one is after a request has been queued, and if it is enabled - then the counting will commence as soon as the transfer starts. - - The second point is when Resume() is called for a paused transfer, and - in this case the following applies. If counting was enabled when the - transfer was paused and it is now disabled then the counting is stopped - at that point and the count value frozen. If counting was disabled when - the transfer was paused and it is now enabled then the counting will - commence when the transfer resumes. (The starting value will depend on - the argument of the enable function.) Otherwise nothing will change, - i.e. counting will either continue normally (enabled/enabled) or - neither stop nor continue (disabled/disabled). - - Once a status has been set, it remains valid for the entire duration of - the transfer (and beyond, if it is not changed again). - - @see Queue() - @see TotalNumDstElementsTransferred() - */ - IMPORT_C void DisableDstElementCounting(); - - - /** Returns the number of elements that have been transferred by this - transfer request at the source port. - - To use this method, the counting functionality has to be explicitly - enabled, either before the transfer request is queued or while it is - paused. - - @see EnableSrcElementCounting() - @see DisableSrcElementCounting() - - This function should only be called after the transfer has finished - (completed with or without error, or because it was cancelled) or while - it is paused. Otherwise it may just return 0. - - @return The number of elements that have been transferred by this - transfer request at the source port. - */ - IMPORT_C TUint32 TotalNumSrcElementsTransferred(); - - - /** Returns the number of elements that have been transferred by this - transfer request at the destination port. - - To use this method, the counting functionality has to be explicitly - enabled, either before the transfer request is queued or while it is - paused. - - @see EnableDstElementCounting() - @see DisableDstElementCounting() - - This function should only be called after the transfer has finished - (completed with or without error, or because it was cancelled) or while - it is paused. Otherwise it may just return 0. - - @return The number of elements that have been transferred by this - transfer request at the destination port. - */ - IMPORT_C TUint32 TotalNumDstElementsTransferred(); - - - /** Returns the number of fragments that this transfer request has been - split into. - - This number will only be different from 0 once Fragment() has been - called or after descriptors have been manually allocated by the client - using ExpandDesList(). - - If SDmacCaps::iAsymHwDescriptors is true then this function will always - return 0, and SrcFragmentCount() / DstFragmentCount() should be used - instead. - - @return The number of fragments (descriptors / pseudo descriptors) that - this transfer request has been split into. - */ - IMPORT_C TInt FragmentCount(); - - /** Returns the number of source port fragments that this transfer request - has been split into. - - This number will only be different from 0 once Fragment() has been - called or after descriptors have been manually allocated by the client - using ExpandSrcDesList(). - - This function can only be used if SDmacCaps::iAsymHwDescriptors is - true, otherwise it will always return 0. - - @return The number of source port fragments (descriptors) that this - transfer request has been split into. - */ - IMPORT_C TInt SrcFragmentCount(); - - - /** Returns the number of destination port fragments that this transfer - request has been split into. - - This number will only be different from 0 once Fragment() has been - called or after descriptors have been manually allocated by the client - using ExpandDstDesList(). - - This function can only be used if SDmacCaps::iAsymHwDescriptors is - true, otherwise it will always return 0. - - @return The number of destination port fragments (descriptors) that - this transfer request has been split into. - */ - IMPORT_C TInt DstFragmentCount(); - -private: - inline void OnDeque(); - TUint GetTransferCount(const TDmaTransferArgs& aTransferArgs); - TInt Frag(TDmaTransferArgs& aTransferArgs); - TInt FragSym(TDmaTransferArgs& aTransferArgs, TUint aCount, TUint aMaxTransferLen); - TInt FragAsym(TDmaTransferArgs& aTransferArgs, TUint aCount, TUint aMaxTransferLen); - TInt FragAsymSrc(TDmaTransferArgs& aTransferArgs, TUint aCount, TUint aMaxTransferLen); - TInt FragAsymDst(TDmaTransferArgs& aTransferArgs, TUint aCount, TUint aMaxTransferLen); - TInt ExpandDesList(TInt aCount, TInt& aDesCount, SDmaDesHdr*& aFirstHdr, - SDmaDesHdr*& aLastHdr); - void FreeDesList(TInt& aDesCount, SDmaDesHdr*& aFirstHdr, SDmaDesHdr*& aLastHdr); - TInt FragmentCount(const SDmaDesHdr* aHdr); - -public: - // WARNING: The following attributes are accessed both in client and DFC - // context and so accesses must be protected with the channel lock. - TDmaChannel& iChannel; /**< The channel this request is bound to */ - TCallback iCb; /**< Called on completion/failure (can be NULL) */ - TAny* iCbArg; /**< Callback argument */ - TDmaCallback iDmaCb; // the new-style callback function - TAny* iDmaCbArg; // the new-style callback arg - TBool iIsrCb; // client wants callback in ISR context - TInt iDesCount; /**< The number of fragments in list */ - SDmaDesHdr* iFirstHdr; /**< The first fragment in the list (or NULL) */ - SDmaDesHdr* iLastHdr; /**< The last fragment in the list (or NULL) */ - TInt iSrcDesCount; /**< The number of fragments in list */ - SDmaDesHdr* iSrcFirstHdr; /**< The first fragment in the list (or NULL) */ - SDmaDesHdr* iSrcLastHdr; /**< The last fragment in the list (or NULL) */ - TInt iDstDesCount; /**< The number of fragments in list */ - SDmaDesHdr* iDstFirstHdr; /**< The first fragment in the list (or NULL) */ - SDmaDesHdr* iDstLastHdr; /**< The last fragment in the list (or NULL) */ - SDblQueLink iLink; /**< The link on channel queue of pending requests */ - TBool iQueued; /**< Indicates whether request is pending or being transferred */ - TUint iMaxTransferSize; /**< Defaults to DMA controller max. transfer size */ - - TUint32 iTotalNumSrcElementsTransferred; - TUint32 iTotalNumDstElementsTransferred; - - __DMA_DECLARE_INVARIANT - }; - - -////////////////////////////////////////////////////////////////////////////// - -class TDmac; -class DmaChannelMgr; -class TDmaCancelInfo; - -/** DMA channel base class. - - Standard derived classes are provided for this channel (see - TDmaSbChannel, TDmaDbChannel, TDmaSgChannel, and TDmaAsymSgChannel). - The base-port implementor will only need to write their own derived - class if one of the standard classes is unsuitable. - - This class has not been designed to be called from several concurrent - client threads. Multithreaded clients must implement their own locking - scheme (via DMutex). - - Mutexes are used internally to protect data structures accessed both by the - client thread and the DFC one. Therefore no fast mutex can be held when - calling a channel function. - - @publishedPartner - @released - */ -class TDmaChannel - { - friend class DDmaRequest; - friend class TDmac; - friend class DmaChannelMgr; -public: - - /** Information passed by client when opening a channel */ - struct SCreateInfo - { - /** Default constructor. Initializes all fields with meaningful default - values. - - Must be inline (for now) because exporting it would break existing - custom DMA libs as their clients would need the export which would - be missing from the custom .def files. - */ - SCreateInfo() : iPriority(KDmaPriorityNone), iDynChannel(EFalse) {}; - - /** Identifier used by PSL to select channel to open */ - TUint32 iCookie; - /** Number of descriptors this channel can use. - - This number is not used in the upgraded version of the DMA - framework and is kept there only for source compatibility. If the - client is certain that it will only ever use that version, then the - value passed here doesn't matter - the framework will ignore it. - - @deprecated - */ - TInt iDesCount; - /** DFC queue used to service DMA interrupts. - - The DFC thread priority must be higher than any client thread - priority to avoid a situation where a transfer completes while - being cancelled and another transfer is started before the DFC - thread gets a chance to run. This would lead to a stray DFC. - */ - TDfcQue* iDfcQ; - /** DFC priority */ - TUint8 iDfcPriority; - /** Used by PSL to configure a channel priority (if possible). - - The default is KDmaPriorityNone (the don't care value). - - @see TDmaPriority - */ - TUint iPriority; - /** Request a dynamic DMA channel. - - If this is set to ETrue then the Open call is for a 'dynamic' as - opposed to a static and solely owned DMA channel. A number of - properties of the opened TDmaChannel object will be different in - that case. - - The default value is EFalse. - */ - TBool iDynChannel; - }; - -public: - /** Opens the DMA channel. - - Channel selection is done by the hardware-specific layer using a cookie - passed in via aInfo. - - The client should not delete the returned pointer as the framework owns - channel objects. However, the client should explicitly close the - channel when finished with it. - - @param aInfo Information passed by caller to select and configure - channel. - - @param aChannel Points to open channel on successful return. NULL - otherwise. - - @return KErrNone or standard error code. - */ - IMPORT_C static TInt Open(const SCreateInfo& aInfo, TDmaChannel*& aChannel); - - - /** Closes a previously opened DMA channel. - - Assumes the channel is idle and all requests have been deleted. - - The call will cause the resources associated with this channel to be - released, and the pointer/reference to it mustn't therefore be accessed - any longer after the function has returned. The channel pointer should - be set to NULL by the client. - */ - IMPORT_C void Close(); - - - /** Logically links this channel to the one specified as an argument, or, - if the argument is NULL, unlinks this channel. - - The effect of channel linking is that once a transfer on this channel - has finished, instead of causing the associated client callback to be - called, 'aChannel' will be enabled by hardware and a preconfigured - transfer on that channel will start. - - Note that conceptually 'linking' here always refers to the end of a - channel transfer, not the beginning, i.e. a channel can only be linked - once and always to a successor, never twice or to a predecessor. (This - does not preclude the possibility that two channels are linked in a - circular fashion.) - - This function can only be used if the DMAC supports logical channel - linking. - - @see SDmacCaps::iChannelLinking - - @param aChannel Points to the channel this one should be linked to, or - NULL if this channel is to be unlinked from any other one. - - @return KErrNone if the channel has been linked or unlinked - successfully, KErrCompletion if this channel was already linked to - aChannel or already unlinked, KErrNotSupported if the DMAC doesn't - support channel linking, KErrArgument if this channel was already - linked to a different channel, KErrGeneral if a general error occurred - preventing a successful outcome. - */ - IMPORT_C TInt LinkToChannel(TDmaChannel* aChannel); - - /** Pauses an active transfer on this channel. - - A paused channel transfer can be resumed by calling Resume() or it can - be stopped altogether by calling CancelAll(). - - @see TDmaChannel::Resume() - - Function can only be used if the DMAC supports this functionality. - - @see SDmacCaps::iChannelPauseAndResume - - @return KErrNone if a transfer has been paused successfully, - KErrCompletion if a transfer was already paused, KErrNotSupported if - the DMAC doesn't support channel transfer pausing/resuming, KErrGeneral - if a general error occurred preventing a successful outcome. - */ - IMPORT_C TInt Pause(); - - - /** Resumes a transfer on this channel that is paused. - - Resume() can be called to resume channel operation when the transfer is - paused as a result of a previous call to Pause() or because the DMAC - has encountered a Pause bit in a H/W descriptor. - - @see TDmaChannel::Pause() - @see TDmaCallbackType::EDmaCallbackLinkedListPaused - - Function can only be used if the DMAC supports this functionality. - - @see SDmacCaps::iChannelPauseAndResume - - @return KErrNone if a paused transfer has been resumed successfully, - KErrCompletion if there was no paused transfer, KErrNotSupported if the - DMAC doesn't support channel transfer pausing/resuming, KErrGeneral if - a general error occurred preventing a successful outcome. - */ - IMPORT_C TInt Resume(); - - - /** Cancels the current request and all the pending ones. - */ - IMPORT_C void CancelAll(); - - - /** Returns the channel's maximum transfer length based on the passed - arguments. - - @param aSrcFlags Bitmask characterising transfer source - @see TDmaTransferArgs::iSrcConfig::iFlags - - @param aDstFlags Bitmask characterising transfer destination - @see TDmaTransferArgs::iDstConfig::iFlags - - @param aPslInfo Cookie passed to the PSL - @see TDmaTransferArgs::iPslRequestInfo - - @return 0 if transfer length is not limited, the maximum transfer - length in bytes otherwise. - */ - IMPORT_C TUint MaxTransferLength(TUint aSrcFlags, TUint aDstFlags, TUint32 aPslInfo); - - - /** Retrieves from the PSL the address / memory alignment mask based on the - parameters passed. Some DMA controllers impose alignment constraints on - the base address of memory buffers. This mask is AND'ed against memory - addresses computed during fragmentation. - - This function needs to be called separately for source and destination. - - @param aTargetFlags Bitmask characterising transfer source or - destination - @see TDmaTransferArgs::iSrcConfig::iFlags - @see TDmaTransferArgs::iDstConfig::iFlags - - @param aElementSize Element size used for the transfer. Can be zero if - not known or 'don't care'. - - @param aPslInfo Cookie passed to the PSL - @see TDmaTransferArgs::iPslRequestInfo - - @return A value representing the alignment mask (e.g. 3 if buffer must - be 4-byte aligned) - */ - IMPORT_C TUint AddressAlignMask(TUint aTargetFlags, TUint aElementSize, - TUint32 aPslInfo); - - - /** Returns a reference to a structure containing the capabilities and - features of the DMA controller associated with this channel. - - @return A reference to a structure containing the capabilities and - features of the DMA controller associated with this channel. - */ - IMPORT_C const SDmacCaps& DmacCaps(); - - - /** Sets up once more the transfer request that has just completed, after - optionally having adjusted the transfer parameters as specified. - - This function is meant to be called exclusively from a client-supplied - callback that is executed in ISR context, and only in response to a - transfer completion notification. - - If this call returns to the caller with KErrNone then the framework's - ISR handler will subsequently not queue the channel DFC for this - completed request. - - The parameters specify which changes the framework should apply to the - descriptors of the transfer request before rescheduling it. Arguments - for which no change is required should be passed as their default - values. The parameters correspond to those in the TDmaTransferArgs - struct as follows. - - @param aSrcAddr @see TDmaTransferArgs::iSrcConfig::iAddr - @param aDstAddr @see TDmaTransferArgs::iDstConfig::iAddr - @param aTransferCount @see TDmaTransferArgs::iTransferCount - @param aPslRequestInfo @see TDmaTransferArgs::iPslRequestInfo - @param aIsrCb If set to ETrue (the default) then the callback of the - rescheduled request will again be called in ISR context - - Since Epoc::LinearToPhysical() cannot be called in ISR context the - addresses passed into this function must be physical ones, i.e. - TDmaTransferFlags::KDmaPhysAddr is implied. - - If an address refers to a memory target then - TDmaTransferFlags::KDmaMemIsContiguous is implied as well as no - fragmentation is possible at this point. - - @pre Must only be called from a 'transfer complete' client callback in - ISR context. - - @post Framework won't queue the channel DFC for the completed request - in success case. - - @see DDmaRequest::DDmaRequest(TDmaChannel&, TDmaCallback, TAny*, TUint) - @see TDmaCallbackType::EDmaCallbackRequestCompletion - @see TDmaPILFlags::KDmaRequestCallbackFromIsr - - @return KErrGeneral if there was an error, KErrNone otherwise. - */ - IMPORT_C TInt IsrRedoRequest(TUint32 aSrcAddr=KPhysAddrInvalid, - TUint32 aDstAddr=KPhysAddrInvalid, - TUint aTransferCount=0, - TUint32 aPslRequestInfo=0, - TBool aIsrCb=ETrue); - - - /** Tests whether the channel is currently opened. - - @return ETrue if channel is currently opened, EFalse otherwise. - - NB: This API should not be used any longer. - - After calling TDmaChannel::Open() successfully the channel is - guaranteed to be open. Therefore there seems no good reason for this - API to exist. - - @deprecated - */ - inline TBool IsOpened() const; - - - /** Tests whether the channel's request queue is currently empty. - - @return ETrue if request queue is currently empty, EFalse otherwise. - */ - inline TBool IsQueueEmpty() const; - - - /** Returns a PSL-specific value which uniquely identifies this channel - - it is used for debug tracing by the PIL. - - @return PSL-specific value which uniquely identifies this channel. - */ - inline TUint32 PslId() const; - - - /** Called by a test harness to force an error when the next fragment is - transferred. - - @param aFragmentCount The number of consecutive fragments to fail - */ - IMPORT_C TInt FailNext(TInt aFragmentCount); - - - /** Called by a test harness to force the DMA controller to miss one or - more interrupts. - - @param aInterruptCount The number of consecutive interrupts to miss - */ - IMPORT_C TInt MissNextInterrupts(TInt aInterruptCount); - - - /** Function allowing platform-specific layer to extend channel API with - new channel-specific operations. - - @param aCmd Command identifier. Negative values are reserved for use by - Nokia. - @param aArg PSL-specific argument - - @return KErrNotSupported if aCmd is not supported. PSL-specific value - otherwise. - */ - IMPORT_C TInt Extension(TInt aCmd, TAny* aArg); - - - /** This is a function that allows the Platform Specific Layer (PSL) to - extend the DMA API with new channel-independent operations. - - @param aCmd Command identifier. Negative values are reserved for - Symbian use. - @param aArg PSL-specific. - - @return KErrNotSupported if aCmd is not supported; a PSL specific value - otherwise. - */ - IMPORT_C TInt StaticExtension(TInt aCmd, TAny* aArg); - - - /** @deprecated - @see DmacCaps() - */ - inline const TDmac* Controller() const; - - /** @deprecated - @see MaxTransferLength() - */ - inline TInt MaxTransferSize(TUint aFlags, TUint32 aPslInfo); - - /** @deprecated - @see AddressAlignMask() - */ - inline TUint MemAlignMask(TUint aFlags, TUint32 aPslInfo); - -protected: - // Interface with state machines - TDmaChannel(); - - /** Called by the PIL when adding a new request to the channel's queue. - The implementation should update the channel's state as appropriate - and begin transfer of aReq if possible. - - @param aReq The request which has been added to the queue - */ - virtual void DoQueue(const DDmaRequest& aReq); - - /** Called by the PIL in response to a CancelAll call. It should update - the channel state appropriately. - */ - virtual void DoCancelAll() = 0; - - /** This is called by the PIL when a DDmaRequest is removed from the - channel's queue. In general the implementation simply needs to unlink - the hardware descriptor corresponding to aHdr from the next. - - Since the PIL links the hardware descriptor chains of adjacent queued - requests (for speed) it is necessary to break the chain when a request - is completed so that the request may be requeued by the client without - having called DDmaRequest::Fragment again. - - @param aHdr The header for a descriptor, which must be unlinked - from its next descriptor (if there is one) - */ - virtual void DoUnlink(SDmaDesHdr& aHdr); - - /** Called by the PIL whenever a transfer associated with aCurReq is - done. The implementation must advance the channel's state and - may transfer the next header if necessary (the provided - scatter-gather channel does not do this). It must also report - back which header was associated with the last transfer to - complete. - - @param aCurReq The current request. - @param aCompletedHdr Must be set by the implementation to the header - of the last transfer to complete. - */ - virtual void DoDfc(const DDmaRequest& aCurReq, SDmaDesHdr*& aCompletedHdr); - - /** Called by the PIL whenever a transfer associated with aCurReq is - done. The implementation must advance the channel's state and - may start the transfer for the next headers if necessary (the - provided scatter-gather channels do not do this). If one - header has a successor but the other is the last in the chain it - is an error. - - @note Must be implemented by PSL if channel uses asymmetric hardware - descriptors and is not derived from TDmaAsymSgChannel. - - @param aCurReq The current request. - - @param aSrcCompletedHdr Must be set by the implementation to - the header of the last source descriptor to complete. - - @param aDstCompletedHdr Must be set by the implementation to - the header of the last destination descriptor to complete. - */ - virtual void DoDfc(const DDmaRequest& aCurReq, SDmaDesHdr*& aSrcCompletedHdr, - SDmaDesHdr*& aDstCompletedHdr); - - virtual ~TDmaChannel(); - -private: - static void Dfc(TAny*); - void DoDfc(); - inline void Wait(); - inline void Signal(); - inline void Flash(); - void ResetStateMachine(); - -protected: - TDmac* iController; // DMAC this channel belongs to (NULL when closed) - const SDmacCaps* iDmacCaps; // what is supported by DMAC on this channel - TUint32 iPslId; // unique identifier provided by PSL - TBool iDynChannel; // this is a dynamically allocated channel - TUint iPriority; // hardware priority of this channel - DMutex* iMutex; // for data accessed in both client & DFC context - SDmaDesHdr* iCurHdr; // fragment being transferred or NULL - SDmaDesHdr** iNullPtr; // Pointer to NULL pointer following last fragment - TDfc iDfc; // transfer completion/failure DFC - TInt iMaxDesCount; // maximum number of allocable descriptors - TInt iAvailDesCount; // available number of descriptors - volatile TUint32 iIsrDfc; // Interface between ISR and DFC: - enum {KErrorFlagMask = 0x80000000}; // bit 31 - error flag - enum {KCancelFlagMask = 0x40000000}; // bit 30 - cancel flag - enum {KDfcCountMask = 0x3FFFFFFF}; // bits 0-29 - number of queued DFCs - SDblQue iReqQ; // being/about to be transferred request queue - TInt iReqCount; // number of requests attached to this channel -private: - TDmaCancelInfo* iCancelInfo; // ... - TBool iRedoRequest; // client ISR callback wants a redo of request - TBool iIsrCbRequest; // request on queue using ISR callback - - __DMA_DECLARE_INVARIANT - }; - - -////////////////////////////////////////////////////////////////////////////// -// INTERFACE WITH TEST HARNESS -////////////////////////////////////////////////////////////////////////////// - -/** Set of information used by test harness. - - @publishedPartner - @released -*/ -struct TDmaTestInfo - { - /** Maximum transfer size in bytes for all channels (ie. the minimum of all channels' maximum size)*/ - TUint iMaxTransferSize; - /** 3->Memory buffers must be 4-byte aligned, 7->8-byte aligned, ... */ - TUint iMemAlignMask; - /** Cookie to pass to DDmaRequest::Fragment for memory-memory transfer*/ - TUint32 iMemMemPslInfo; - /** Number of test single-buffer channels */ - TInt iMaxSbChannels; - /** Pointer to array containing single-buffer test channel ids */ - TUint32* iSbChannels; - /** Number of test double-buffer channels */ - TInt iMaxDbChannels; - /** Pointer to array containing double-buffer test channel ids */ - TUint32* iDbChannels; - /** Number of test scatter-gather channels */ - TInt iMaxSgChannels; - /** Pointer to array containing scatter-gather test channel ids */ - TUint32* iSgChannels; - }; - - -/** Provides access to test information structure stored in the PSL. - - Must be implemented by the PSL. - - @publishedPartner - @released -*/ -IMPORT_C const TDmaTestInfo& DmaTestInfo(); - -/** Provides access to test information structure stored in the PSL. - - Must be implemented by the PSL. - - @publishedPartner - @released -*/ -IMPORT_C const TDmaV2TestInfo& DmaTestInfoV2(); - - - -////////////////////////////////////////////////////////////////////////////// - - -#include -#include - - -#endif // #ifndef __DMA_V2_H__