|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. --> |
|
3 <!-- This component and the accompanying materials are made available under the terms of the License |
|
4 "Eclipse Public License v1.0" which accompanies this distribution, |
|
5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". --> |
|
6 <!-- Initial Contributors: |
|
7 Nokia Corporation - initial contribution. |
|
8 Contributors: |
|
9 --> |
|
10 <!DOCTYPE concept |
|
11 PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd"> |
|
12 <concept id="GUID-0D2F811C-81C3-526F-8EA4-98E50261BF4B" xml:lang="en"><title>DMA |
|
13 Framework Technology</title><shortdesc>Describes the classes that the DMA Framework provides to transfer |
|
14 data using DMA. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
15 <p>The following diagram shows the general relationship between the various |
|
16 classes and structs that form the DMA Framework. The individual items are |
|
17 described in more detail below. </p> |
|
18 <fig id="GUID-C6B032F0-7E05-5E29-8024-B713C42A2434"> |
|
19 <image href="GUID-D43AB2F5-32AE-540C-80D8-DE8B2072F1E6_d0e10612_href.png" placement="inline"/> |
|
20 </fig> |
|
21 <section id="GUID-D9855D5F-3D4D-5A65-A1BB-B7CB94E60316"><title>The DMA Software |
|
22 Controller</title> <p>This is the <xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita"><apiname>TDmac</apiname></xref> object. It has |
|
23 two purposes: </p> <ul> |
|
24 <li id="GUID-E4C8A5C5-192B-5E3E-A2F1-D884BF7FE641"><p>It defines the main |
|
25 interface between the platform independent and platform specific layers. </p> </li> |
|
26 <li id="GUID-98888CE1-5AA6-5D91-A5C5-E60F1200465A"><p>it is a container for |
|
27 channels, descriptors and descriptor headers </p> </li> |
|
28 </ul> </section> |
|
29 <section id="GUID-37DF82BE-5F8E-5497-90E8-C48F44C2A7F1"><title>The Channel |
|
30 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 |
|
31 a static class defined by the platform independent layer but implemented in |
|
32 the platform specific layer. The functionality is used by the platform independent |
|
33 layer. It contains: </p> <ul> |
|
34 <li id="GUID-B5626DA4-1465-5469-BE3D-36F31996C75A"><p>a function to open a |
|
35 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> |
|
36 <li id="GUID-67C7DE2F-196E-5919-BA80-99898DF6837D"><p>a function that is called |
|
37 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> |
|
38 <li id="GUID-F044E05A-A307-51B0-BDD5-8A29A950BE5F"><p>a function that can |
|
39 be used to extend the framework with platform specific functionality on a |
|
40 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> |
|
41 </ul> </section> |
|
42 <section id="GUID-34B8E965-9C5C-533E-BFE6-EB9B486A81BB"><title>Descriptors</title> <p>DMA |
|
43 controllers operating in scatter/gather mode are configured via a linked list |
|
44 of small data structures describing the data to be transferred. These data |
|
45 structures are called descriptors. (Note that the use of the term descriptor |
|
46 in the context of DMA should not be confused with the same term widely used |
|
47 in Symbian platform to refer to the family of <xref href="GUID-52D07F46-2162-380C-A775-C3BB335C42F5.dita"><apiname>TDesC</apiname></xref> derived |
|
48 classes). </p> <p>The Symbian platform DMA Framework always uses descriptor |
|
49 data structures to store transfer-configuration-information, even if the underlying |
|
50 DMA controller does not support scatter/gather mode. </p> <p>The following |
|
51 example illustrates the idea: assume that a device driver needs to transfer |
|
52 two disjoint blocks of memory, A and B, into another block C. Block A starts |
|
53 at address 1000 and is 300 bytes long. Block B starts at address 2000 and |
|
54 is 700 bytes long. The destination buffer C starts at address 5000 and is |
|
55 1000 bytes long. Assume that the DMA descriptors are allocated in a pool starting |
|
56 at address 600. The following diagram shows the scatter/gather list that the |
|
57 device driver might create: </p> <fig id="GUID-966DC875-FA9E-59E5-A1CA-842F4A82592D"> |
|
58 <image href="GUID-EA0C5715-7CE8-5415-A915-D5701E3C957A_d0e10709_href.png" placement="inline"/> |
|
59 </fig> <p>If the DMA controller supports the scatter/gather arrangement, then |
|
60 the framework uses a structure that will be specific to the hardware. This |
|
61 structure is defined in the platform specific layer. </p> <p>If the DMA controller |
|
62 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 |
|
63 the following information: </p> <ul> |
|
64 <li id="GUID-D5EA7DC2-FC49-5FF3-95FE-6E5426D25BFF"><p>a set of generic flags |
|
65 that characterise the transfer. For example, is the source of the data memory |
|
66 or a peripheral; is the destination memory or peripheral; what addressing |
|
67 mode is to be used? </p> </li> |
|
68 <li id="GUID-4D54D3E6-0252-5F15-9966-E7F09A10020E"><p>the source and destination |
|
69 location. This is in the form of the base virtual address for a memory buffer, |
|
70 and a 32-bit value (or cookie) for peripherals. The meaning of the 32-bit |
|
71 value is interpreted by the platform specific layer. </p> </li> |
|
72 <li id="GUID-416CB113-5973-50AD-9FF3-F3AF78B47D0C"><p>The number of bytes |
|
73 to be transferred. </p> </li> |
|
74 <li id="GUID-D76CE2CE-5005-5C2F-B17D-F882D6BD7EB8"><p>A word that only has |
|
75 meaning for the platform specific layer, and passed by the client at request |
|
76 fragmentation time. </p> </li> |
|
77 </ul> </section> |
|
78 <section id="GUID-BC1C248D-170D-51AE-B2E5-61FFEC779D61"><title>Descriptor |
|
79 headers</title> <p>These are objects of type <xref href="GUID-710B3501-FF22-307D-AC88-D142E9A07CB8.dita"><apiname>SDmaDesHdr</apiname></xref>. </p> <p>A |
|
80 descriptor header allows additional information about a descriptor to be stored. |
|
81 The header is a separate object from the descriptor because it is difficult |
|
82 to embed additional data in a structure whose layout may be hardware-imposed. </p> <p>Descriptors |
|
83 and descriptor headers are stored in two parallel arrays allocated at boot-time, |
|
84 and each descriptor is always associated with the header of same index, so |
|
85 that there is always a one-to-one relationship between the header and the |
|
86 descriptor. </p> <fig id="GUID-A635E3EA-883C-5857-8690-E0AE6F43CAC4"> |
|
87 <image href="GUID-99F7E70F-2733-57B2-94F5-A0C0FF9219FE_d0e10765_href.png" placement="inline"/> |
|
88 </fig> <p>In the current design, the only information in the descriptor header |
|
89 is a pointer, <codeph>SDmaDesHdr::iNext</codeph>, that is used to chain headers |
|
90 together on various lists. So, although the pool of headers is allocated as |
|
91 an array, they are almost always accessed by following the chain of pointers |
|
92 linking one header to the next. </p> <p>Descriptors are <i>always</i> accessed |
|
93 through their associated header. </p> <p>The platform independent layer never |
|
94 directly accesses hardware-specific descriptors. It just passes descriptor |
|
95 headers to the platform specific layer. However, the platform independent |
|
96 layer does directly manipulate the generic descriptors, <xref href="GUID-D7934AD9-38F6-325A-A734-F867D886D7C2.dita"><apiname>SDmaPseudoDes</apiname></xref>. </p> </section> |
|
97 <section id="GUID-F4685621-1FAA-544C-B4C0-B4DD566B856F"><title>Transfer Requests</title> <p>A |
|
98 transfer request is the way in which a device driver sets up and initiates |
|
99 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 |
|
100 transfer request has a number of characteristics: </p> <ul> |
|
101 <li id="GUID-D5B73919-B6C8-54F9-8C1E-87467E32EAA0"><p>it is always associated |
|
102 with exactly one channel. </p> </li> |
|
103 <li id="GUID-FE3326FA-B0CF-50A2-BD4D-72F868226EFB"><p>it stores a client-provided |
|
104 callback function, which is invoked when the whole request completes, whether |
|
105 successfully or not. </p> </li> |
|
106 <li id="GUID-627B7D15-0119-5D72-A517-84832D90C3D1"><p>it can be in one of |
|
107 four states: </p> <ul> |
|
108 <li id="GUID-1D600F30-F06C-58FB-B258-8167164FE1FC"><p>not configured </p> </li> |
|
109 <li id="GUID-194A4B9A-12E6-50B6-816A-73717CD100F9"><p>idle </p> </li> |
|
110 <li id="GUID-0B7A0249-9F5D-5D5D-AB3C-4DDE8AFC58E6"><p>being transferred </p> </li> |
|
111 <li id="GUID-AF57DDF1-406D-55D4-A001-F62921165189"><p>pending; this state |
|
112 only occurs in streaming mode. </p> </li> |
|
113 </ul> </li> |
|
114 </ul> <p>Internally, a transfer request is represented as a singly linked |
|
115 list of descriptor headers. Each header in the list is associated with a descriptor |
|
116 that specifies how to transfer one fragment of the whole request. Transfer |
|
117 requests have pointers to the first and last headers in the list. </p> <p>When |
|
118 the request is idle, the header list ends with a NULL pointer. This is not |
|
119 always true when the request is queued (i.e. when the request is being transferred |
|
120 or is still pending). The following diagram shows an idle request with three |
|
121 fragments. </p> <fig id="GUID-0A5594BD-05E4-5A97-A3F7-459E3F8638A2"> |
|
122 <image href="GUID-CF252B09-335E-5831-94A6-0B16B64C5030_d0e10851_href.png" placement="inline"/> |
|
123 </fig> <p>Splitting a request into fragments is useful because: </p> <ul> |
|
124 <li id="GUID-BEA0F4C5-4308-54E9-82AB-91570ACC9ADC"><p>it insulates device |
|
125 drivers from the maximum transfer size supported by the underlying DMA controller. </p> </li> |
|
126 <li id="GUID-A768A76B-DD9E-5A25-92D3-23A69299C096"><p>the source and destination |
|
127 DMA buffers may not be physically contiguous and thus require fragmenting. </p> </li> |
|
128 </ul> <p>Both of these situations can be handled by using the generic fragmentation |
|
129 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 |
|
130 drivers may have to create custom descriptors lists. For example, the USB |
|
131 section of the PXA250 manual describes how to build custom lists where a descriptor |
|
132 containing data transfer information is followed by another one poking an |
|
133 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 |
|
134 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 |
|
135 a list of headers associated with blank descriptors whose content is then |
|
136 set by device drivers. Blank descriptors thus created can be accessed in the |
|
137 following way (this example was taken and simplified from the PXA250 USB controller |
|
138 driver): </p> <codeblock id="GUID-EFA935A1-0D7E-5153-9071-2D0C58E8E920" xml:space="preserve">TDmaChannel* channel; |
|
139 TDmaChannel::SCreateInfo info; |
|
140 info.x = y; |
|
141 if (TDmaChannel::Open(info, channel) != KErrNone) |
|
142 ... return; |
|
143 DDmaRequest* req = new DDmaRequest(*channel); |
|
144 if (!req) |
|
145 ... return; |
|
146 const TDmac* dmac = req->iChannel.Controller(); |
|
147 if (req->ExpandDesList(2) != KErrNone) |
|
148 ... return; |
|
149 TDmaDesc* desc1 = static_cast<TDmaDesc*>(dmac->HdrToHwDes(*req->iFirstHdr)); |
|
150 TDmaDesc* desc2 = static_cast<TDmaDesc*>(dmac->HdrToHwDes(*req->iFirstHdr->iNext)); |
|
151 desc1->iSrcAddr = ...; |
|
152 desc1->iDestAddr = ...; |
|
153 desc1->iDescAddr = ...; |
|
154 desc1->iCmd = ...; |
|
155 desc2... |
|
156 ... |
|
157 </codeblock> </section> |
|
158 <section id="GUID-4BF7605E-55D4-5B3A-BCD7-1F976765D738"><title>Channels</title> <p>A |
|
159 channel is a <xref href="GUID-83882548-FAC5-3EFF-92ED-14D1D9A85D37.dita"><apiname>TDmaChannel</apiname></xref> object, and there is one of these |
|
160 for each hardware DMA channel. </p> <p>A channel can be in one of 4 states: </p> <ul> |
|
161 <li id="GUID-09581FA5-D01A-502A-9841-52ABDF0BB16E"><p>closed </p> </li> |
|
162 <li id="GUID-D03F51BA-1493-5B23-B029-4FF5FCC4DE5E"><p>open and idle </p> </li> |
|
163 <li id="GUID-606FA290-FB8D-5CBE-88C2-BCD03062EE25"><p>open and transferring |
|
164 data </p> </li> |
|
165 <li id="GUID-2E845C88-292D-54B9-9F99-AAC3775768E4"><p>suspended following |
|
166 an error. </p> </li> |
|
167 </ul> <p>On opening a channel, the client device driver specifies: </p> <ul> |
|
168 <li id="GUID-6F373D39-4078-5C76-BF5E-69294297D8CE"><p>A 32-bit value (cookie) |
|
169 that is used by the platform specific layer to select which channel is to |
|
170 be opened </p> </li> |
|
171 <li id="GUID-71E4D026-4BA5-592B-BB3E-5F5354640E50"><p>The number of descriptors |
|
172 that must be reserved for this channel. </p> </li> |
|
173 <li id="GUID-4C34A82A-AF7E-5683-986B-A65EA6C8F5B2"><p>A DFC to be used by |
|
174 the framework to service DMA interrupts. </p> </li> |
|
175 </ul> <p>A channel maintains a queue of transfer requests. If the channel |
|
176 is being used for one-shot transfers, the queue will always contain an idle |
|
177 or a transferring request. In streaming mode, the queue may contain several |
|
178 requests, the first one being transferred and the remaining ones pending. |
|
179 When a request is completely transferred, it is removed from the queue. The |
|
180 first request is always the one being transferred. </p> <p>A transferring |
|
181 channel has a pointer to the header associated with the descriptor being transferred. |
|
182 The headers of all queued requests are linked together on one linked list. </p> <p>The |
|
183 following diagram shows a DMA channel with a three-fragment request being |
|
184 transferred and a two-fragment one pending. The fragment currently being transferred |
|
185 is the second one of the first request. </p> <fig id="GUID-36E11A64-4626-53F9-925C-3DC323DEA895"> |
|
186 <image href="GUID-86C21C9B-9F08-579F-84E9-CBE46F756373_d0e10964_href.png" placement="inline"/> |
|
187 </fig> <p>The <xref href="GUID-83882548-FAC5-3EFF-92ED-14D1D9A85D37.dita"><apiname>TDmaChannel</apiname></xref> class contains the code and data |
|
188 that is common to all of the channel types. The code and data for the specific |
|
189 channel types: single buffer, double buffer, and scatter/gather channels, |
|
190 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>, |
|
191 and <xref href="GUID-2D4CFBB1-8D64-3CF5-B6F0-B24D16D5BAD4.dita"><apiname>TDmaSgChannel</apiname></xref> respectively. </p> <p><b>TDmaSbChannel |
|
192 State Machine</b> </p> <p>For reference purposes, the following diagram shows |
|
193 the state machine that <xref href="GUID-A8B4AD1B-770C-363E-A0DE-C78A9786CBDC.dita"><apiname>TDmaSbChannel</apiname></xref> implements to deal |
|
194 with a single buffer channel. </p> <fig id="GUID-82A8742D-CE5E-5EA2-A19E-6DCA30D9AE61"> |
|
195 <image href="GUID-85332468-292D-589B-891B-0E7ACBADC7BA_d0e11000_href.png" placement="inline"/> |
|
196 </fig> <p><b>TDmaDbChannel |
|
197 State Machine</b> </p> <p>For reference purposes, the following diagram shows |
|
198 the state machine that <xref href="GUID-FD76AF08-6250-3054-8A06-16343E385B23.dita"><apiname>TDmaDbChannel</apiname></xref> implements to deal |
|
199 with a double buffer channel. </p> <fig id="GUID-1CF4D292-310C-5D75-9E3B-2DB65217FEEA"> |
|
200 <image href="GUID-91958EA5-9444-5895-B4B8-F2C670B81CD7_d0e11017_href.png" placement="inline"/> |
|
201 </fig> <p><b>TDmaSgChannel |
|
202 State Machine</b> </p> <p>For reference purposes, the following diagram shows |
|
203 the state machine that <xref href="GUID-2D4CFBB1-8D64-3CF5-B6F0-B24D16D5BAD4.dita"><apiname>TDmaSgChannel</apiname></xref> implements to deal |
|
204 with a scatter/gather channel. </p> <fig id="GUID-1206C662-9856-57A1-A0C5-FDF74F2A3BD3"> |
|
205 <image href="GUID-09EE01E2-BF5E-5302-BA25-46C440ADECF5_d0e11034_href.png" placement="inline"/> |
|
206 </fig> </section> |
|
207 <section id="GUID-2F8979D3-A4DC-5919-B027-F8C17739A05D"><title>Streaming and |
|
208 Scatter/Gather DMA Controllers</title> <p>When a transfer request is queued |
|
209 onto a channel that is already transferring data, the header descriptor for |
|
210 the new list of descriptors is appended to the header of the previous request |
|
211 on the queue. If the underlying DMA controller supports hardware descriptors, |
|
212 they must also be linked together. </p> <p>The following diagram shows how |
|
213 headers and descriptors for a new request are appended to the existing ones |
|
214 for a DMA controller. The dashed arrows represent the new links. </p> <fig id="GUID-7E06E92E-C8D1-53FF-AF03-5B1A3EBC1EA5"> |
|
215 <image href="GUID-28F3F720-A2E0-59C9-8BB4-B6124CFC6C89_d0e11050_href.png" placement="inline"/> |
|
216 </fig> <p> <i>Note that hardware descriptors are linked together using physical |
|
217 addresses, not virtual ones.</i> </p> <p>Linking hardware descriptors together |
|
218 is implemented in the platform specific layer. There are two issues to consider: </p> <ul> |
|
219 <li id="GUID-4236DD82-FFAD-56D3-B46F-9D2198E0349A"><p>The channel may go idle |
|
220 before the linking is complete, which means that the data for the new request |
|
221 would not be transferred. </p> </li> |
|
222 <li id="GUID-48AAA44F-1EEF-5899-9D62-587AA0EC8303"><p>If the channel is transferring |
|
223 the last descriptor in the list, then updating the “next” field in the descriptor |
|
224 will have no effect because the content of the descriptor will already have |
|
225 been loaded in the controller registers. Again the channel would go idle without |
|
226 transferring the data associated with the new request. </p> </li> |
|
227 </ul> <p>The solutions available when porting the DMA Framework are: </p> <ul> |
|
228 <li id="GUID-DC8EBCE6-E355-5D93-A265-0D591F06841C"><p>If the DMA controller |
|
229 has hardware support for appending descriptors while transferring data, then |
|
230 there is no problem. </p> </li> |
|
231 <li id="GUID-77DE96E7-9D9A-543F-8CD9-A36055F38E7A"><p>If the peripheral attached |
|
232 to the channel can withstand a short disruption in the transfer flow, then |
|
233 the channel can be suspended while the appending takes place. This should |
|
234 be done with interrupts disabled to minimise disruption. </p> </li> |
|
235 <li id="GUID-962DAD2E-2684-5F51-8F80-A1E3C86BC8F7"><p>The alternative technique |
|
236 is to append the new list with interrupts disabled and set a flag. When the |
|
237 next interrupt occurs, if the flag is set and the channel idle, then the interrupt |
|
238 service routine must restart the transfer. </p> </li> |
|
239 </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> |
|
240 <section id="GUID-106BBBE0-C18B-5321-96AE-F1A65FAB4FF7"><title>Interrupt Service |
|
241 Routine (ISR) and DFC Issues</title> <p>The platform specific layer must notify |
|
242 the platform independent layer when the following events occur: </p> <ul> |
|
243 <li id="GUID-13589C1E-5146-5044-9587-092C4347D4EC"><p>when an error occurs. </p> </li> |
|
244 <li id="GUID-47C15152-8C06-5864-9292-4EF6A9A458E6"><p>when each fragment completes, |
|
245 for single-buffer and double-buffer controllers. </p> </li> |
|
246 <li id="GUID-BCDD4ECD-4396-5F2C-9A3A-B0C3B20DCC90"><p>when the last fragment |
|
247 of a request completes, for scatter/gather controllers. </p> </li> |
|
248 </ul> <p>The ISR, as implemented in the platform specific layer, must: </p> <ul> |
|
249 <li id="GUID-037B8F96-3C27-5D2F-8E70-35C66C601D63"><p>determine which channel |
|
250 the interrupt is for. If the DMA controller uses dedicated interrupt lines |
|
251 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> |
|
252 <li id="GUID-58A2D3AE-BF42-56E6-9EB1-B77DC9B2B934"><p>determine whether the |
|
253 interrupt was asserted following a successful transfer completion or a failure. |
|
254 If the DMA controller uses different interrupt lines for completion and failure, |
|
255 the ASSP/variant interrupt dispatcher will do this. </p> </li> |
|
256 <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 |
|
257 the platform specific layer. This function queues the DFC associated with |
|
258 the relevant channel. It takes care of the case where several interrupts occur |
|
259 before the DFC gets a chance to run. </p> </li> |
|
260 </ul> <p>The DFC updates the state of the channel and, for single and double |
|
261 buffer DMA controllers, configures the next fragment to transfer, if any. |
|
262 When all fragments making up a request have been transferred, the DFC calls |
|
263 the client-supplied callback associated with the completed request. The callback |
|
264 is also called if an error occurs during transfer. </p> </section> |
|
265 <section id="GUID-2CB7E268-0535-5AD0-8B08-3FEDBA39016D"><title>Locking Strategy</title> <p>For |
|
266 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 |
|
267 can be accessed concurrently from the device driver thread and from a DFC |
|
268 queue thread. To avoid race conditions, each <xref href="GUID-83882548-FAC5-3EFF-92ED-14D1D9A85D37.dita"><apiname>TDmaChannel</apiname></xref> instance |
|
269 has a fast mutex, the protected data member <codeph>TDmaChannel::iLock</codeph>. |
|
270 This lock is acquired when queuing a new request, cancelling requests and |
|
271 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 |
|
272 are not protected against concurrent access from several client threads because |
|
273 this is assumed to be an exceptional case. A device driver with such need |
|
274 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 |
|
275 functions. </p> <p>Each <xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita"><apiname>TDmac</apiname></xref> instance includes a fast |
|
276 mutex, the private member <codeph>TDmac::iLock</codeph> to protect descriptor |
|
277 reservation and allocation, because several device drivers may try to reserve |
|
278 or allocate descriptors concurrently. </p> <p>The <xref href="GUID-176B8E0D-0422-341B-A134-7C85432E1303.dita"><apiname>DmaChannelMgr</apiname></xref> static |
|
279 class includes a fast mutex which is used to protect channel opening as several |
|
280 device drivers may compete for the same channel. This lock is also used at |
|
281 channel closing time. </p> </section> |
|
282 </conbody></concept> |