Adaptation/GUID-535E5C2A-DCFD-4BCB-B26B-11E88BDB8A8A.dita
changeset 15 307f4279f433
equal deleted inserted replaced
14:578be2adaf3e 15:307f4279f433
       
     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-535E5C2A-DCFD-4BCB-B26B-11E88BDB8A8A" xml:lang="en"><title>TDmac Derived Class Implementation</title><shortdesc>Implementing the hardware-specific DMA controller.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    13 <p>The <xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita"><apiname>TDmac</apiname></xref> class is part of the PIL. It is a
       
    14 container for the DMA controller's channels, descriptors and descriptor
       
    15 headers. It also defines virtual functions for operations that require
       
    16 a PSL implementation.</p>
       
    17 <p>You need to derive <xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita"><apiname>TDmac</apiname></xref> for each distinct type
       
    18 of DMA controller on your device, and implement these virtual functions.</p>
       
    19 <p><table id="GUID-2AB9BEBC-9C41-4CAC-A222-24083FAD5F2B">
       
    20 <tgroup cols="3"><colspec colname="col1"/><colspec colname="COLSPEC1" colwidth="1.00*"/><colspec colname="col2"/>
       
    21 <thead>
       
    22 <row>
       
    23 <entry valign="top">Function</entry>
       
    24 <entry valign="top">Mandatory/Conditional</entry>
       
    25 <entry valign="top">Description</entry>
       
    26 </row>
       
    27 </thead>
       
    28 <tbody>
       
    29 <row>
       
    30 <entry><xref href="GUID-E0617B44-6C99-3327-9E20-2975E465AA8C.dita"><apiname>Transfer()</apiname></xref></entry>
       
    31 <entry>Mandatory</entry>
       
    32 <entry>For single buffer and scatter/gather, this starts the DMA transfer.
       
    33 For double buffer, this prepares the next fragment to transfer while
       
    34 a current transfer is in operation</entry>
       
    35 </row>
       
    36 <row>
       
    37 <entry><xref href="GUID-267716ED-F59A-35FB-89CC-FB82540FEA79.dita"><apiname>StopTransfer()</apiname></xref></entry>
       
    38 <entry>Mandatory</entry>
       
    39 <entry>Stop the specified channel synchronously. Must not return to
       
    40 the PSL implementation until the channel has stopped.</entry>
       
    41 </row>
       
    42 <row>
       
    43 <entry><xref href="GUID-ACF1D126-591B-3A84-9F53-94370B1BFA7B.dita"><apiname>IsIdle()</apiname></xref></entry>
       
    44 <entry>Mandatory</entry>
       
    45 <entry>Returns <codeph>ETrue</codeph> if specified channel is idle,
       
    46 otherwise <codeph>EFalse</codeph></entry>
       
    47 </row>
       
    48 <row>
       
    49 <entry><xref href="GUID-D8ECA8CE-7F7C-356D-9C9F-4BD37ED2618C.dita"><apiname>MaxTransferSize()</apiname></xref></entry>
       
    50 <entry>Optional</entry>
       
    51 <entry>Takes the parameters and evaluates the maximum transfer size
       
    52 in bytes.</entry>
       
    53 </row>
       
    54 <row>
       
    55 <entry><xref href="GUID-F6CBDDF7-A9C1-3534-9F5E-5B4FC77E888B.dita"><apiname>MemAlignMask()</apiname></xref></entry>
       
    56 <entry>Optional</entry>
       
    57 <entry><i>This applies to DMA v1 only.</i></entry>
       
    58 </row>
       
    59 <row>
       
    60 <entry><xref href="GUID-AA9217AF-EF1C-3010-AA7E-A4D3FCA14B30.dita"><apiname>InitHwDes()</apiname></xref></entry>
       
    61 <entry>Optional</entry>
       
    62 <entry>For scatter-gather, initialise the array of memory areas and
       
    63 set up the first block of data to be transferred.</entry>
       
    64 </row>
       
    65 <row>
       
    66 <entry><xref href="GUID-DCEFF8BA-BC74-3DA4-88CC-6A2C2E928BFE.dita"><apiname>ChainHwDes()</apiname></xref></entry>
       
    67 <entry>Optional</entry>
       
    68 <entry>For scatter-gather, add additional blocks of data to transfer
       
    69 to the list of memory areas.</entry>
       
    70 </row>
       
    71 <row>
       
    72 <entry><xref href="GUID-7076A78C-24F8-36B0-8FC2-F4DA8AB6DC14.dita"><apiname>AppendHwDes()</apiname></xref></entry>
       
    73 <entry>Optional</entry>
       
    74 <entry>For scatter-gather, add to the array of memory areas while
       
    75 the transfer is active. This is used in particular for streaming data
       
    76 where new descriptors can be added to the end of the chain while data
       
    77 earlier in the train is being transferred. E.g. video streaming.</entry>
       
    78 </row>
       
    79 <row>
       
    80 <entry><xref href="GUID-9D519453-8CA5-3200-8E9A-BB1599C25CE9.dita"><apiname>UnlinkHwDes()</apiname></xref></entry>
       
    81 <entry>Optional</entry>
       
    82 <entry>For scatter-gather, remove items from the array of memory areas.</entry>
       
    83 </row>
       
    84 <row>
       
    85 <entry><xref href="GUID-5569F5DA-D5FD-3368-99E4-F9AE6E1A7752.dita"><apiname>FailNext()</apiname></xref></entry>
       
    86 <entry>Optional</entry>
       
    87 <entry>For a sequence of memory transfers, tell the next one to fail. </entry>
       
    88 </row>
       
    89 <row>
       
    90 <entry><xref href="GUID-ED81D339-84D6-3811-AC39-184D6AC723C0.dita"><apiname>MissNextInterrupts()</apiname></xref></entry>
       
    91 <entry>Optional</entry>
       
    92 <entry>DMA transfers start on the next interrupt, but sometimes you
       
    93 want to skip the next interrupt for synchronisation or other reasons.</entry>
       
    94 </row>
       
    95 <row>
       
    96 <entry><xref href="GUID-93A3F01A-3489-37E5-921C-5EA5228545AA.dita"><apiname>Extension()</apiname></xref></entry>
       
    97 <entry>Optional</entry>
       
    98 <entry>Pass a command from the application/client down to the DMA
       
    99 chipset. Hardware dependent.</entry>
       
   100 </row>
       
   101 </tbody>
       
   102 </tgroup>
       
   103 </table></p>
       
   104 <section id="GUID-525949BF-21B1-40DA-888E-D05B204BC382"><title>Implement
       
   105 the mandatory controller virtual functions</title> <p>The <xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita"><apiname>TDmac</apiname></xref> class contains several pure virtual functions that
       
   106 must be implemented by the PSL implementation: </p><ul>
       
   107 <li id="GUID-5FE89E59-2C8F-417E-AC84-77C8F20EA2E7"><xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita#GUID-25398075-927B-36E4-B953-16785EC4086C/GUID-81921A9D-41F5-34BC-B882-60CC4CD807FB"><apiname>TDmac::Transfer()</apiname></xref></li>
       
   108 <li id="GUID-1D62C97A-5DC6-4BEE-B3EC-9120808FBFD6"><xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita#GUID-25398075-927B-36E4-B953-16785EC4086C/GUID-B738D1B9-80FA-334D-ABEB-DFFF093E0B9D"><apiname>TDmac::StopTransfer()</apiname></xref></li>
       
   109 <li id="GUID-1708E632-4C79-4274-9363-4528095342A6"><xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita#GUID-25398075-927B-36E4-B953-16785EC4086C/GUID-7422834D-CE6B-32DB-A040-7762A8BAB7D7"><apiname>TDmac::IsIdle()</apiname></xref></li>
       
   110 </ul> <p>These functions start and stop transfers on a DMA channel
       
   111 and are the main interface between the PIL and the PSL. The implementation
       
   112 of these functions depends on the hardware available for performing
       
   113 DMA, and on the characteristics used to specify a DMA transfer: </p><ul>
       
   114 <li id="GUID-93F00482-7DB7-4D0B-9BBC-62D0DEDFC669">the source and
       
   115 destination addresses </li>
       
   116 <li id="GUID-2BF651D7-261B-4B70-A281-07C14C0837D0">the burst size </li>
       
   117 <li id="GUID-638B0F70-6595-4B8C-8B46-22023B5AAF12">the maximum transfer
       
   118 size </li>
       
   119 <li id="GUID-879FE6AA-0D3E-4BAD-AB32-C3F6B4CB6758">the transfer width,
       
   120 i.e. number of bits per memory access </li>
       
   121 <li id="GUID-FD9A86D2-2BE6-4600-B0EF-54CCC2854D5D">the memory alignment
       
   122 and endianness. </li>
       
   123 </ul> <p>The DMA Framework manages the transfer descriptors according
       
   124 to the descriptor parameter passed into the <xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita"><apiname>TDmac</apiname></xref> constructor by the derived class constructor; the descriptor parameter
       
   125 is a <xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita#GUID-25398075-927B-36E4-B953-16785EC4086C/GUID-BBD2153C-4B41-357C-9299-D710930AFCBE"><apiname>TDmac::SCreateInfo</apiname></xref> structure. The per-request
       
   126 transfer parameters are passed into the descriptors for each request
       
   127 issued by a driver. </p></section>
       
   128 <section id="GUID-9D4B491F-2E42-407F-BC99-E1F32AE6549E"><title>The
       
   129 transfer function: Transfer()</title> <p>This function initiates a
       
   130 previously constructed request on a specific channel. This is the
       
   131 template implementation: </p> <codeblock xml:space="preserve">
       
   132 void TTemplateDmac::Transfer(const TDmaChannel&amp; aChannel, const SDmaDesHdr&amp; aHdr)
       
   133 //
       
   134 // Initiates a (previously constructed) request on a specific channel.
       
   135 //
       
   136     {
       
   137     const TUint8 i = static_cast&amp;&lt;TUint8&amp;&gt;(aChannel.PslId());
       
   138     TDmaDesc* pD = HdrToHwDes(aHdr);
       
   139 
       
   140     __KTRACE_OPT(KDMA, Kern::Printf("&amp;&gt;TTemplateDmac::Transfer channel=%d des=0x%08X", i, pD));
       
   141 
       
   142     // Load the first descriptor address into the DMAC and start it
       
   143     // by setting the RUN bit.
       
   144     (void) *pD, (void) i;
       
   145 
       
   146     }
       
   147 </codeblock> </section>
       
   148 <section id="GUID-56D77E64-1AD3-4F17-AD26-562AEB97DC56"><title>The
       
   149 stop transfer function: StopTransfer()</title> <p>This is the template
       
   150 implementation: </p> <codeblock xml:space="preserve">void TTemplateDmac::StopTransfer(const TDmaChannel&amp; aChannel)
       
   151 //
       
   152 // Stops a running channel.
       
   153 //
       
   154     {
       
   155     const TUint8 i = static_cast&amp;&lt;TUint8&amp;&gt;(aChannel.PslId());
       
   156 
       
   157     __KTRACE_OPT(KDMA, Kern::Printf("&amp;&gt;TTemplateDmac::StopTransfer channel=%d", i));
       
   158 
       
   159     }
       
   160 </codeblock></section>
       
   161 <section id="GUID-C2427406-8F3A-407D-8D3D-9B3040542054"><title>The
       
   162 function: IsIdle()</title> <p><xref href="GUID-ACF1D126-591B-3A84-9F53-94370B1BFA7B.dita"><apiname>IsIdle()</apiname></xref> returns
       
   163 the state of a given channel. This is the template implementation: </p> <codeblock xml:space="preserve">TBool TTemplateDmac::IsIdle(const TDmaChannel&amp; aChannel)
       
   164 //
       
   165 // Returns the state of a given channel.
       
   166 //
       
   167     {
       
   168     const TUint8 i = static_cast&amp;&lt;TUint8&amp;&gt;(aChannel.PslId());
       
   169 
       
   170     __KTRACE_OPT(KDMA, Kern::Printf("&amp;&gt;TTemplateDmac::IsIdle channel=%d", i));
       
   171 
       
   172     return ETrue;
       
   173     }
       
   174 </codeblock> </section>
       
   175 <section id="GUID-A385DE6A-E267-4F0C-A0AC-A85316706D68"><title>Implement
       
   176 the non-mandatory controller virtual functions</title> <p>The following
       
   177 auxiliary functions are used to implement the scatter-gather transfer
       
   178 mode behavior by creating and manipulating the linked list of transfer
       
   179 fragment headers that describe a given scatter-gather transaction.
       
   180 They are called by the <xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita"><apiname>TDmac</apiname></xref> base class functions
       
   181 when the instance of the <xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita"><apiname>TDmac</apiname></xref> derived class reports
       
   182 itself as being capable of scatter-gather operations. </p> <ul>
       
   183 <li id="GUID-8CFB839A-A2A2-47C5-A75A-062CE205FB0A"><xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita#GUID-25398075-927B-36E4-B953-16785EC4086C/GUID-90AC3E58-E589-3F91-85F7-16A4ADFFFA69"><apiname>TDmac::InitHwDes()</apiname></xref></li>
       
   184 <li id="GUID-58BDB319-0A8D-4C1B-8C75-6C9E119D26DF"><xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita#GUID-25398075-927B-36E4-B953-16785EC4086C/GUID-05021B05-75DE-3F75-92C6-8B9445EB86D3"><apiname>TDmac::ChainHwDes()</apiname></xref></li>
       
   185 <li id="GUID-2998E58B-2A02-4A66-87F5-A87F1915F47C"><xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita#GUID-25398075-927B-36E4-B953-16785EC4086C/GUID-AFCDDA16-991D-3BDA-B90B-87BCAFF66E5C"><apiname>TDmac::AppendHwDes()</apiname></xref></li>
       
   186 </ul></section>
       
   187 <section id="GUID-4B1544BB-A3BC-4938-8832-FCD86C647953"><title>First
       
   188 scatter-gather support function: InitHwDes()</title> <p>This is a
       
   189 function for creating a scatter-gather list. From the information
       
   190 in the passed-in request, the function sets up the descriptor with
       
   191 that fragment's: </p><ul>
       
   192 <li id="GUID-A585C7E8-0C14-4F62-BB6B-C34FB4DEC0D1">source and destination
       
   193 address </li>
       
   194 <li id="GUID-5A58FD8F-BC32-48B9-BFA3-B376E4BD2ACC">size </li>
       
   195 <li id="GUID-C5BC6402-011F-497A-B3C2-C3AB5F29E1C7">driver/DMA controller
       
   196 specific transfer parameters: memory/peripheral, burst size, transfer
       
   197 width. </li>
       
   198 </ul> <p>This is the template implementation: </p> <codeblock xml:space="preserve">void TTemplateDmac::InitHwDes(const SDmaDesHdr&amp; aHdr, TUint32 aSrc, TUint32 aDest, TInt aCount,
       
   199                               TUint aFlags, TUint32 aPslInfo, TUint32 /*aCookie*/)
       
   200 //
       
   201 // Sets up (from a passed in request) the descriptor with that fragment's source and destination address,
       
   202 // the fragment size, and the (driver/DMA controller) specific transfer parameters (mem/peripheral,
       
   203 // burst size, transfer width).
       
   204 //
       
   205     {
       
   206     TDmaDesc* pD = HdrToHwDes(aHdr);
       
   207 
       
   208     __KTRACE_OPT(KDMA, Kern::Printf("TTemplateDmac::InitHwDes 0x%08X", pD));
       
   209 
       
   210     // Unaligned descriptor? Error in generic layer!
       
   211     __DMA_ASSERTD(IsHwDesAligned(pD));
       
   212 
       
   213     pD-&amp;&gt;iSrcAddr = (aFlags &amp; KDmaPhysAddrSrc) ? aSrc : Epoc::LinearToPhysical(aSrc);
       
   214     pD-&amp;&gt;iDestAddr = (aFlags &amp; KDmaPhysAddrDest) ? aDest : Epoc::LinearToPhysical(aDest);
       
   215     pD-&amp;&gt;iCmd = DcmdReg(aCount, aFlags, aPslInfo);
       
   216     pD-&amp;&gt;iDescAddr = TDmaDesc::KStopBitMask;
       
   217     }
       
   218 </codeblock> </section>
       
   219 <section id="GUID-FAAE402C-959D-40CD-B208-C5AB9E495CAB"><title>Second
       
   220 scatter-gather support function: ChainHwDes()</title> <p>If the framework
       
   221 needs to fragment the client’s request, either because of the transfer
       
   222 size or because the memory is not a single contiguous block, then
       
   223 the framework calls this function. It chains hardware descriptors
       
   224 together by setting the next pointer of the original descriptor to
       
   225 the physical address of the descriptor to be chained. It assumes that
       
   226 the DMAC channel is quiescent when called. </p> <p>This is the template
       
   227 implementation: </p> <codeblock xml:space="preserve">void TTemplateDmac::ChainHwDes(const SDmaDesHdr&amp; aHdr, const SDmaDesHdr&amp; aNextHdr)
       
   228 //
       
   229 // Chains hardware descriptors together by setting the next pointer of the original descriptor
       
   230 // to the physical address of the descriptor to be chained.
       
   231 //
       
   232     {
       
   233     TDmaDesc* pD = HdrToHwDes(aHdr);
       
   234     TDmaDesc* pN = HdrToHwDes(aNextHdr);
       
   235 
       
   236     __KTRACE_OPT(KDMA, Kern::Printf("TTemplateDmac::ChainHwDes des=0x%08X next des=0x%08X", pD, pN));
       
   237 
       
   238     // Unaligned descriptor? Error in generic layer!
       
   239     __DMA_ASSERTD(IsHwDesAligned(pD) &amp;&amp; IsHwDesAligned(pN));
       
   240 
       
   241     pD-&amp;&gt;iDescAddr = DesLinToPhys(pN);
       
   242     }
       
   243 </codeblock></section>
       
   244 <section id="GUID-60013038-5A06-4926-A7F4-68D6FBA79ABC"><title>Third
       
   245 scatter-gather support function: AppendHwDes() </title> <p>This function
       
   246 is called by the <xref href="GUID-25398075-927B-36E4-B953-16785EC4086C.dita"><apiname>TDmac</apiname></xref> base class when a driver
       
   247 request is called for a channel that is still active, i.e. where the
       
   248 intent is to provide data streaming so that the target device is constantly
       
   249 provided with data; for example, an audio device playing a track.
       
   250 In this case, the function provided by the derived class must: </p> <ul>
       
   251 <li id="GUID-484E794E-A446-4AFD-8956-D072C6B5EC81">stop the DMAC to
       
   252 prevent any corruption of the scatter-gather list while appending
       
   253 the new fragment descriptor </li>
       
   254 <li id="GUID-2D05CB0A-450A-45DF-8736-E406CFC1C6A2">append the new
       
   255 descriptor </li>
       
   256 <li id="GUID-E638DFC8-8078-4D5A-AC78-1A06B01DDBE5">re-enable the channel,
       
   257 ideally before the target has detected the gap in service. </li>
       
   258 </ul> <p>This is the template implementation: </p> <codeblock xml:space="preserve">void TTemplateDmac::AppendHwDes(const TDmaChannel&amp; aChannel, const SDmaDesHdr&amp; aLastHdr,
       
   259                                 const SDmaDesHdr&amp; aNewHdr)
       
   260 //
       
   261 // Appends a descriptor to the chain while the channel is running.
       
   262 //
       
   263     {
       
   264     const TUint8 i = static_cast&amp;&lt;TUint8&amp;&gt;(aChannel.PslId());
       
   265 
       
   266     TDmaDesc* pL = HdrToHwDes(aLastHdr);
       
   267     TDmaDesc* pN = HdrToHwDes(aNewHdr);
       
   268 
       
   269     __KTRACE_OPT(KDMA, Kern::Printf("&amp;&gt;TTemplateDmac::AppendHwDes channel=%d last des=0x%08X new des=0x%08X",
       
   270                                     i, pL, pN));
       
   271     // Unaligned descriptor? Error in generic layer!
       
   272     __DMA_ASSERTD(IsHwDesAligned(pL) &amp;&amp; IsHwDesAligned(pN));
       
   273 
       
   274     TPhysAddr newPhys = DesLinToPhys(pN);
       
   275 
       
   276     const TInt irq = NKern::DisableAllInterrupts();
       
   277     StopTransfer(aChannel);
       
   278 
       
   279     pL-&amp;&gt;iDescAddr = newPhys;
       
   280     const TTemplateSgChannel&amp; channel = static_cast&amp;&lt;const TTemplateSgChannel&amp;&amp;&gt;(aChannel);
       
   281     TDmaDesc* pD = channel.iTmpDes;
       
   282 
       
   283     (void) *pD, (void) i;
       
   284 
       
   285     NKern::RestoreInterrupts(irq);
       
   286 
       
   287     __KTRACE_OPT(KDMA, Kern::Printf("&amp;&lt;TTemplateDmac::AppendHwDes"));
       
   288     }
       
   289 </codeblock></section>
       
   290 </conbody><related-links>
       
   291 <link href="GUID-4E3C086B-25BE-4DAC-9E21-CFC4F8B792A5.dita"><linktext>DMA
       
   292 Technology Guide</linktext></link>
       
   293 <link href="GUID-95A33491-17AC-4F12-948E-A1352ADDA483.dita"><linktext>DMA
       
   294 Implementation Guide</linktext></link>
       
   295 </related-links></concept>