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