--- 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 <drivers/dma.h>.
-//
-
-#ifndef __DMA_H__
-#error "dma_v2.h must'n be included directly - use <drivers/dma.h> instead"
-#endif // #ifndef __DMA_H__
-
-#ifndef __DMA_V2_H__
-#define __DMA_V2_H__
-
-
-#include <kernel/kernel.h>
-#include <drivers/dmadefs.h>
-
-
-//////////////////////////////////////////////////////////////////////////////
-// 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 <drivers/dma_compat.inl>
-#include <drivers/dma_v2.inl>
-
-
-#endif // #ifndef __DMA_V2_H__