Adaptation/GUID-0D2F811C-81C3-526F-8EA4-98E50261BF4B.dita
changeset 15 307f4279f433
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Adaptation/GUID-0D2F811C-81C3-526F-8EA4-98E50261BF4B.dita	Fri Oct 15 14:32:18 2010 +0100
@@ -0,0 +1,282 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
+<!-- This component and the accompanying materials are made available under the terms of the License 
+"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: 
+-->
+<!DOCTYPE concept
+  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
+<concept id="GUID-0D2F811C-81C3-526F-8EA4-98E50261BF4B" xml:lang="en"><title>DMA
+Framework Technology</title><shortdesc>Describes the classes that the DMA Framework provides to transfer
+data using DMA. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
+<p>The following diagram shows the general relationship between the various
+classes and structs that form the DMA Framework. The individual items are
+described in more detail below. </p>
+<fig id="GUID-C6B032F0-7E05-5E29-8024-B713C42A2434">
+<image href="GUID-D43AB2F5-32AE-540C-80D8-DE8B2072F1E6_d0e10612_href.png" placement="inline"/>
+</fig>
+<section id="GUID-D9855D5F-3D4D-5A65-A1BB-B7CB94E60316"><title>The DMA Software
+Controller</title> <p>This is the <xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita"><apiname>TDmac</apiname></xref> object. It has
+two purposes: </p> <ul>
+<li id="GUID-E4C8A5C5-192B-5E3E-A2F1-D884BF7FE641"><p>It defines the main
+interface between the platform independent and platform specific layers. </p> </li>
+<li id="GUID-98888CE1-5AA6-5D91-A5C5-E60F1200465A"><p>it is a container for
+channels, descriptors and descriptor headers </p> </li>
+</ul> </section>
+<section id="GUID-37DF82BE-5F8E-5497-90E8-C48F44C2A7F1"><title>The Channel
+Manager</title> <p>The channel manager is a <xref href="GUID-176B8E0D-0422-341B-A134-7C85432E1303.dita"><apiname>DmaChannelMgr</apiname></xref> object. </p> <p> <codeph> DmaChannelMgr</codeph> is
+a static class defined by the platform independent layer but implemented in
+the platform specific layer. The functionality is used by the platform independent
+layer. It contains: </p> <ul>
+<li id="GUID-B5626DA4-1465-5469-BE3D-36F31996C75A"><p>a function to open a
+DMA channel: <xref href="GUID-176B8E0D-0422-341B-A134-7C85432E1303.dita#GUID-176B8E0D-0422-341B-A134-7C85432E1303/GUID-934F46B3-1DF9-3870-87EE-A8E2DEF82810"><apiname>DmaChannelMgr::Open()</apiname></xref>  </p> </li>
+<li id="GUID-67C7DE2F-196E-5919-BA80-99898DF6837D"><p>a function that is called
+when a channel is closed: <xref href="GUID-176B8E0D-0422-341B-A134-7C85432E1303.dita#GUID-176B8E0D-0422-341B-A134-7C85432E1303/GUID-909D795A-7303-3A76-9C8E-3B07A97DD716"><apiname>DmaChannelMgr::Close()</apiname></xref>  </p> </li>
+<li id="GUID-F044E05A-A307-51B0-BDD5-8A29A950BE5F"><p>a function that can
+be used to extend the framework with platform specific functionality on a
+channel independent basis: <xref href="GUID-176B8E0D-0422-341B-A134-7C85432E1303.dita#GUID-176B8E0D-0422-341B-A134-7C85432E1303/GUID-C733B302-4269-3391-8ADE-617CFF198B56"><apiname>DmaChannelMgr::StaticExtension()</apiname></xref>  </p> </li>
+</ul> </section>
+<section id="GUID-34B8E965-9C5C-533E-BFE6-EB9B486A81BB"><title>Descriptors</title> <p>DMA
+controllers operating in scatter/gather mode are configured via a linked list
+of small data structures describing the data to be transferred. These data
+structures are called descriptors. (Note that the use of the term descriptor
+in the context of DMA should not be confused with the same term widely used
+in Symbian platform to refer to the family of <xref href="GUID-52D07F46-2162-380C-A775-C3BB335C42F5.dita"><apiname>TDesC</apiname></xref> derived
+classes). </p> <p>The Symbian platform DMA Framework always uses descriptor
+data structures to store transfer-configuration-information, even if the underlying
+DMA controller does not support scatter/gather mode. </p> <p>The following
+example illustrates the idea: assume that a device driver needs to transfer
+two disjoint blocks of memory, A and B, into another block C. Block A starts
+at address 1000 and is 300 bytes long. Block B starts at address 2000 and
+is 700 bytes long. The destination buffer C starts at address 5000 and is
+1000 bytes long. Assume that the DMA descriptors are allocated in a pool starting
+at address 600. The following diagram shows the scatter/gather list that the
+device driver might create: </p> <fig id="GUID-966DC875-FA9E-59E5-A1CA-842F4A82592D">
+<image href="GUID-EA0C5715-7CE8-5415-A915-D5701E3C957A_d0e10709_href.png" placement="inline"/>
+</fig> <p>If the DMA controller supports the scatter/gather arrangement, then
+the framework uses a structure that will be specific to the hardware. This
+structure is defined in the platform specific layer. </p> <p>If the DMA controller
+does not support scatter/gather, then the framework uses the generic structure <xref href="GUID-D7934AD9-38F6-325A-A734-F867D886D7C2.dita"><apiname>SDmaPseudoDes</apiname></xref> containing
+the following information: </p> <ul>
+<li id="GUID-D5EA7DC2-FC49-5FF3-95FE-6E5426D25BFF"><p>a set of generic flags
+that characterise the transfer. For example, is the source of the data memory
+or a peripheral; is the destination memory or peripheral; what addressing
+mode is to be used? </p> </li>
+<li id="GUID-4D54D3E6-0252-5F15-9966-E7F09A10020E"><p>the source and destination
+location. This is in the form of the base virtual address for a memory buffer,
+and a 32-bit value (or cookie) for peripherals. The meaning of the 32-bit
+value is interpreted by the platform specific layer. </p> </li>
+<li id="GUID-416CB113-5973-50AD-9FF3-F3AF78B47D0C"><p>The number of bytes
+to be transferred. </p> </li>
+<li id="GUID-D76CE2CE-5005-5C2F-B17D-F882D6BD7EB8"><p>A word that only has
+meaning for the platform specific layer, and passed by the client at request
+fragmentation time. </p> </li>
+</ul> </section>
+<section id="GUID-BC1C248D-170D-51AE-B2E5-61FFEC779D61"><title>Descriptor
+headers</title> <p>These are objects of type <xref href="GUID-710B3501-FF22-307D-AC88-D142E9A07CB8.dita"><apiname>SDmaDesHdr</apiname></xref>. </p> <p>A
+descriptor header allows additional information about a descriptor to be stored.
+The header is a separate object from the descriptor because it is difficult
+to embed additional data in a structure whose layout may be hardware-imposed. </p> <p>Descriptors
+and descriptor headers are stored in two parallel arrays allocated at boot-time,
+and each descriptor is always associated with the header of same index, so
+that there is always a one-to-one relationship between the header and the
+descriptor. </p> <fig id="GUID-A635E3EA-883C-5857-8690-E0AE6F43CAC4">
+<image href="GUID-99F7E70F-2733-57B2-94F5-A0C0FF9219FE_d0e10765_href.png" placement="inline"/>
+</fig> <p>In the current design, the only information in the descriptor header
+is a pointer, <codeph>SDmaDesHdr::iNext</codeph>, that is used to chain headers
+together on various lists. So, although the pool of headers is allocated as
+an array, they are almost always accessed by following the chain of pointers
+linking one header to the next. </p> <p>Descriptors are <i>always</i> accessed
+through their associated header. </p> <p>The platform independent layer never
+directly accesses hardware-specific descriptors. It just passes descriptor
+headers to the platform specific layer. However, the platform independent
+layer does directly manipulate the generic descriptors, <xref href="GUID-D7934AD9-38F6-325A-A734-F867D886D7C2.dita"><apiname>SDmaPseudoDes</apiname></xref>. </p> </section>
+<section id="GUID-F4685621-1FAA-544C-B4C0-B4DD566B856F"><title>Transfer Requests</title> <p>A
+transfer request is the way in which a device driver sets up and initiates
+a DMA transfer, and is represented by a <xref href="GUID-780F4D53-5546-3B69-B328-0226C70EBDE2.dita"><apiname>DDmaRequest</apiname></xref> object. </p> <p>A
+transfer request has a number of characteristics: </p> <ul>
+<li id="GUID-D5B73919-B6C8-54F9-8C1E-87467E32EAA0"><p>it is always associated
+with exactly one channel. </p> </li>
+<li id="GUID-FE3326FA-B0CF-50A2-BD4D-72F868226EFB"><p>it stores a client-provided
+callback function, which is invoked when the whole request completes, whether
+successfully or not. </p> </li>
+<li id="GUID-627B7D15-0119-5D72-A517-84832D90C3D1"><p>it can be in one of
+four states: </p> <ul>
+<li id="GUID-1D600F30-F06C-58FB-B258-8167164FE1FC"><p>not configured </p> </li>
+<li id="GUID-194A4B9A-12E6-50B6-816A-73717CD100F9"><p>idle </p> </li>
+<li id="GUID-0B7A0249-9F5D-5D5D-AB3C-4DDE8AFC58E6"><p>being transferred </p> </li>
+<li id="GUID-AF57DDF1-406D-55D4-A001-F62921165189"><p>pending; this state
+only occurs in streaming mode. </p> </li>
+</ul> </li>
+</ul> <p>Internally, a transfer request is represented as a singly linked
+list of descriptor headers. Each header in the list is associated with a descriptor
+that specifies how to transfer one fragment of the whole request. Transfer
+requests have pointers to the first and last headers in the list. </p> <p>When
+the request is idle, the header list ends with a NULL pointer. This is not
+always true when the request is queued (i.e. when the request is being transferred
+or is still pending). The following diagram shows an idle request with three
+fragments. </p> <fig id="GUID-0A5594BD-05E4-5A97-A3F7-459E3F8638A2">
+<image href="GUID-CF252B09-335E-5831-94A6-0B16B64C5030_d0e10851_href.png" placement="inline"/>
+</fig> <p>Splitting a request into fragments is useful because: </p> <ul>
+<li id="GUID-BEA0F4C5-4308-54E9-82AB-91570ACC9ADC"><p>it insulates device
+drivers from the maximum transfer size supported by the underlying DMA controller. </p> </li>
+<li id="GUID-A768A76B-DD9E-5A25-92D3-23A69299C096"><p>the source and destination
+DMA buffers may not be physically contiguous and thus require fragmenting. </p> </li>
+</ul> <p>Both of these situations can be handled by using the generic fragmentation
+algorithm <xref href="GUID-780F4D53-5546-3B69-B328-0226C70EBDE2.dita#GUID-780F4D53-5546-3B69-B328-0226C70EBDE2/GUID-B14B0478-80D6-3F5E-88B6-1676411D9CF2"><apiname>DDmaRequest::Fragment()</apiname></xref>. </p> <p>Some device
+drivers may have to create custom descriptors lists. For example, the USB
+section of the PXA250 manual describes how to build custom lists where a descriptor
+containing data transfer information is followed by another one poking an
+I/O port to issue a command to the USB controller. </p> <p>To cover that case, <xref href="GUID-780F4D53-5546-3B69-B328-0226C70EBDE2.dita"><apiname>DDmaRequest</apiname></xref> provides
+the <xref href="GUID-780F4D53-5546-3B69-B328-0226C70EBDE2.dita#GUID-780F4D53-5546-3B69-B328-0226C70EBDE2/GUID-AAB7C209-7D30-3282-B084-D80E12BB5152"><apiname>DDmaRequest::ExpandDesList()</apiname></xref> member function to allocate
+a list of headers associated with blank descriptors whose content is then
+set by device drivers. Blank descriptors thus created can be accessed in the
+following way (this example was taken and simplified from the PXA250 USB controller
+driver): </p> <codeblock id="GUID-EFA935A1-0D7E-5153-9071-2D0C58E8E920" xml:space="preserve">TDmaChannel* channel;
+TDmaChannel::SCreateInfo info;
+info.x = y;
+if (TDmaChannel::Open(info, channel) != KErrNone)
+    ... return;
+DDmaRequest* req = new DDmaRequest(*channel);
+if (!req)
+    ... return;
+const TDmac* dmac = req-&gt;iChannel.Controller();
+if (req-&gt;ExpandDesList(2) != KErrNone)
+    ... return;
+TDmaDesc* desc1 = static_cast&lt;TDmaDesc*&gt;(dmac-&gt;HdrToHwDes(*req-&gt;iFirstHdr));
+TDmaDesc* desc2 = static_cast&lt;TDmaDesc*&gt;(dmac-&gt;HdrToHwDes(*req-&gt;iFirstHdr-&gt;iNext));
+desc1-&gt;iSrcAddr  = ...;
+desc1-&gt;iDestAddr = ...;
+desc1-&gt;iDescAddr = ...;
+desc1-&gt;iCmd      = ...;
+desc2...
+...
+</codeblock> </section>
+<section id="GUID-4BF7605E-55D4-5B3A-BCD7-1F976765D738"><title>Channels</title> <p>A
+channel is a <xref href="GUID-83882548-FAC5-3EFF-92ED-14D1D9A85D37.dita"><apiname>TDmaChannel</apiname></xref> object, and there is one of these
+for each hardware DMA channel. </p> <p>A channel can be in one of 4 states: </p> <ul>
+<li id="GUID-09581FA5-D01A-502A-9841-52ABDF0BB16E"><p>closed </p> </li>
+<li id="GUID-D03F51BA-1493-5B23-B029-4FF5FCC4DE5E"><p>open and idle </p> </li>
+<li id="GUID-606FA290-FB8D-5CBE-88C2-BCD03062EE25"><p>open and transferring
+data </p> </li>
+<li id="GUID-2E845C88-292D-54B9-9F99-AAC3775768E4"><p>suspended following
+an error. </p> </li>
+</ul> <p>On opening a channel, the client device driver specifies: </p> <ul>
+<li id="GUID-6F373D39-4078-5C76-BF5E-69294297D8CE"><p>A 32-bit value (cookie)
+that is used by the platform specific layer to select which channel is to
+be opened </p> </li>
+<li id="GUID-71E4D026-4BA5-592B-BB3E-5F5354640E50"><p>The number of descriptors
+that must be reserved for this channel. </p> </li>
+<li id="GUID-4C34A82A-AF7E-5683-986B-A65EA6C8F5B2"><p>A DFC to be used by
+the framework to service DMA interrupts. </p> </li>
+</ul> <p>A channel maintains a queue of transfer requests. If the channel
+is being used for one-shot transfers, the queue will always contain an idle
+or a transferring request. In streaming mode, the queue may contain several
+requests, the first one being transferred and the remaining ones pending.
+When a request is completely transferred, it is removed from the queue. The
+first request is always the one being transferred. </p> <p>A transferring
+channel has a pointer to the header associated with the descriptor being transferred.
+The headers of all queued requests are linked together on one linked list. </p> <p>The
+following diagram shows a DMA channel with a three-fragment request being
+transferred and a two-fragment one pending. The fragment currently being transferred
+is the second one of the first request. </p> <fig id="GUID-36E11A64-4626-53F9-925C-3DC323DEA895">
+<image href="GUID-86C21C9B-9F08-579F-84E9-CBE46F756373_d0e10964_href.png" placement="inline"/>
+</fig> <p>The <xref href="GUID-83882548-FAC5-3EFF-92ED-14D1D9A85D37.dita"><apiname>TDmaChannel</apiname></xref> class contains the code and data
+that is common to all of the channel types. The code and data for the specific
+channel types: single buffer, double buffer, and scatter/gather channels,
+are implemented in the derived classes: <xref href="GUID-A8B4AD1B-770C-363E-A0DE-C78A9786CBDC.dita"><apiname>TDmaSbChannel</apiname></xref>, <xref href="GUID-FD76AF08-6250-3054-8A06-16343E385B23.dita"><apiname>TDmaDbChannel</apiname></xref>,
+and <xref href="GUID-2D4CFBB1-8D64-3CF5-B6F0-B24D16D5BAD4.dita"><apiname>TDmaSgChannel</apiname></xref> respectively. </p> <p><b>TDmaSbChannel
+State Machine</b> </p> <p>For reference purposes, the following diagram shows
+the state machine that <xref href="GUID-A8B4AD1B-770C-363E-A0DE-C78A9786CBDC.dita"><apiname>TDmaSbChannel</apiname></xref> implements to deal
+with a single buffer channel. </p> <fig id="GUID-82A8742D-CE5E-5EA2-A19E-6DCA30D9AE61">
+<image href="GUID-85332468-292D-589B-891B-0E7ACBADC7BA_d0e11000_href.png" placement="inline"/>
+</fig> <p><b>TDmaDbChannel
+State Machine</b> </p> <p>For reference purposes, the following diagram shows
+the state machine that <xref href="GUID-FD76AF08-6250-3054-8A06-16343E385B23.dita"><apiname>TDmaDbChannel</apiname></xref> implements to deal
+with a double buffer channel. </p> <fig id="GUID-1CF4D292-310C-5D75-9E3B-2DB65217FEEA">
+<image href="GUID-91958EA5-9444-5895-B4B8-F2C670B81CD7_d0e11017_href.png" placement="inline"/>
+</fig> <p><b>TDmaSgChannel
+State Machine</b> </p> <p>For reference purposes, the following diagram shows
+the state machine that <xref href="GUID-2D4CFBB1-8D64-3CF5-B6F0-B24D16D5BAD4.dita"><apiname>TDmaSgChannel</apiname></xref> implements to deal
+with a scatter/gather channel. </p> <fig id="GUID-1206C662-9856-57A1-A0C5-FDF74F2A3BD3">
+<image href="GUID-09EE01E2-BF5E-5302-BA25-46C440ADECF5_d0e11034_href.png" placement="inline"/>
+</fig> </section>
+<section id="GUID-2F8979D3-A4DC-5919-B027-F8C17739A05D"><title>Streaming and
+Scatter/Gather DMA Controllers</title> <p>When a transfer request is queued
+onto a channel that is already transferring data, the header descriptor for
+the new list of descriptors is appended to the header of the previous request
+on the queue. If the underlying DMA controller supports hardware descriptors,
+they must also be linked together. </p> <p>The following diagram shows how
+headers and descriptors for a new request are appended to the existing ones
+for a DMA controller. The dashed arrows represent the new links. </p> <fig id="GUID-7E06E92E-C8D1-53FF-AF03-5B1A3EBC1EA5">
+<image href="GUID-28F3F720-A2E0-59C9-8BB4-B6124CFC6C89_d0e11050_href.png" placement="inline"/>
+</fig> <p> <i>Note that hardware descriptors are linked together using physical
+addresses, not virtual ones.</i>  </p> <p>Linking hardware descriptors together
+is implemented in the platform specific layer. There are two issues to consider: </p> <ul>
+<li id="GUID-4236DD82-FFAD-56D3-B46F-9D2198E0349A"><p>The channel may go idle
+before the linking is complete, which means that the data for the new request
+would not be transferred. </p> </li>
+<li id="GUID-48AAA44F-1EEF-5899-9D62-587AA0EC8303"><p>If the channel is transferring
+the last descriptor in the list, then updating the “next” field in the descriptor
+will have no effect because the content of the descriptor will already have
+been loaded in the controller registers. Again the channel would go idle without
+transferring the data associated with the new request. </p> </li>
+</ul> <p>The solutions available when porting the DMA Framework are: </p> <ul>
+<li id="GUID-DC8EBCE6-E355-5D93-A265-0D591F06841C"><p>If the DMA controller
+has hardware support for appending descriptors while transferring data, then
+there is no problem. </p> </li>
+<li id="GUID-77DE96E7-9D9A-543F-8CD9-A36055F38E7A"><p>If the peripheral attached
+to the channel can withstand a short disruption in the transfer flow, then
+the channel can be suspended while the appending takes place. This should
+be done with interrupts disabled to minimise disruption. </p> </li>
+<li id="GUID-962DAD2E-2684-5F51-8F80-A1E3C86BC8F7"><p>The alternative technique
+is to append the new list with interrupts disabled and set a flag. When the
+next interrupt occurs, if the flag is set and the channel idle, then the interrupt
+service routine must restart the transfer. </p> </li>
+</ul> <p>See <xref href="GUID-0D2F811C-81C3-526F-8EA4-98E50261BF4B.dita#GUID-0D2F811C-81C3-526F-8EA4-98E50261BF4B/GUID-4BF7605E-55D4-5B3A-BCD7-1F976765D738">Channels</xref>. </p> </section>
+<section id="GUID-106BBBE0-C18B-5321-96AE-F1A65FAB4FF7"><title>Interrupt Service
+Routine (ISR) and DFC Issues</title> <p>The platform specific layer must notify
+the platform independent layer when the following events occur: </p> <ul>
+<li id="GUID-13589C1E-5146-5044-9587-092C4347D4EC"><p>when an error occurs. </p> </li>
+<li id="GUID-47C15152-8C06-5864-9292-4EF6A9A458E6"><p>when each fragment completes,
+for single-buffer and double-buffer controllers. </p> </li>
+<li id="GUID-BCDD4ECD-4396-5F2C-9A3A-B0C3B20DCC90"><p>when the last fragment
+of a request completes, for scatter/gather controllers. </p> </li>
+</ul> <p>The ISR, as implemented in the platform specific layer, must: </p> <ul>
+<li id="GUID-037B8F96-3C27-5D2F-8E70-35C66C601D63"><p>determine which channel
+the interrupt is for. If the DMA controller uses dedicated interrupt lines
+per channel, the ASSP/variant interrupt dispatcher will do this. See <xref href="GUID-3C34724F-B476-5329-B0B1-6D5A34294979.dita">Interrupt Dispatcher Tutorial</xref>. </p> </li>
+<li id="GUID-58A2D3AE-BF42-56E6-9EB1-B77DC9B2B934"><p>determine whether the
+interrupt was asserted following a successful transfer completion or a failure.
+If the DMA controller uses different interrupt lines for completion and failure,
+the ASSP/variant interrupt dispatcher will do this. </p> </li>
+<li id="GUID-F9D50FBF-171A-5D26-851E-3FDDB4AE38BB"><p>Call <xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita#GUID-25398075-927B-36E4-B953-16785EC4086C/GUID-187EBCEB-4488-3606-BB71-8813111D8AF4"><apiname>TDmac::HandleIsr()</apiname></xref> in
+the platform specific layer. This function queues the DFC associated with
+the relevant channel. It takes care of the case where several interrupts occur
+before the DFC gets a chance to run. </p> </li>
+</ul> <p>The DFC updates the state of the channel and, for single and double
+buffer DMA controllers, configures the next fragment to transfer, if any.
+When all fragments making up a request have been transferred, the DFC calls
+the client-supplied callback associated with the completed request. The callback
+is also called if an error occurs during transfer. </p> </section>
+<section id="GUID-2CB7E268-0535-5AD0-8B08-3FEDBA39016D"><title>Locking Strategy</title> <p>For
+a given device driver, <xref href="GUID-83882548-FAC5-3EFF-92ED-14D1D9A85D37.dita"><apiname>TDmaChannel</apiname></xref> and <xref href="GUID-780F4D53-5546-3B69-B328-0226C70EBDE2.dita"><apiname>DDmaRequest</apiname></xref> instances
+can be accessed concurrently from the device driver thread and from a DFC
+queue thread. To avoid race conditions, each <xref href="GUID-83882548-FAC5-3EFF-92ED-14D1D9A85D37.dita"><apiname>TDmaChannel</apiname></xref> instance
+has a fast mutex, the protected data member <codeph>TDmaChannel::iLock</codeph>.
+This lock is acquired when queuing a new request, cancelling requests and
+executing the DFC. </p> <p> <xref href="GUID-83882548-FAC5-3EFF-92ED-14D1D9A85D37.dita"><apiname>TDmaChannel</apiname></xref> and <xref href="GUID-780F4D53-5546-3B69-B328-0226C70EBDE2.dita"><apiname>DDmaRequest</apiname></xref> instances
+are not protected against concurrent access from several client threads because
+this is assumed to be an exceptional case. A device driver with such need
+would have to implement its own locking scheme around calls to <xref href="GUID-83882548-FAC5-3EFF-92ED-14D1D9A85D37.dita"><apiname>TDmaChannel</apiname></xref> and <xref href="GUID-780F4D53-5546-3B69-B328-0226C70EBDE2.dita"><apiname>DDmaRequest</apiname></xref> member
+functions. </p> <p>Each <xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita"><apiname>TDmac</apiname></xref> instance includes a fast
+mutex, the private member <codeph>TDmac::iLock</codeph> to protect descriptor
+reservation and allocation, because several device drivers may try to reserve
+or allocate descriptors concurrently. </p> <p>The <xref href="GUID-176B8E0D-0422-341B-A134-7C85432E1303.dita"><apiname>DmaChannelMgr</apiname></xref> static
+class includes a fast mutex which is used to protect channel opening as several
+device drivers may compete for the same channel. This lock is also used at
+channel closing time. </p> </section>
+</conbody></concept>
\ No newline at end of file