Adaptation/GUID-C74770A5-ADD4-4AB1-946F-77105E2B8C10-GENID-1-2-1-10-1-5-1-5-1-1-7-1-9-1-6-1.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-C74770A5-ADD4-4AB1-946F-77105E2B8C10-GENID-1-2-1-10-1-5-1-5-1-1-7-1-9-1-6-1" xml:lang="en"><title>DMA Request Operations</title><shortdesc>Describes the operations which a device driver performs
       
    13 on a DMA request.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <p>After doing the required DMA initialisation, a driver can start
       
    15 a DMA operation. To do this, the driver fragments the request and
       
    16 then queues the request. </p>
       
    17 <section id="GUID-24567A76-814B-4E1C-81CA-61D9142B442B-GENID-1-2-1-10-1-5-1-5-1-1-7-1-9-1-6-1-3-2"><title>Fragment</title> <p>A DMA request must be split into different fragments that are
       
    18 small enough to be transferred by the DMAC in a single transaction.
       
    19 The size of each fragment is smaller than or equal to the maximum
       
    20 transfer size supported by the DMAC. To fragment a DMA request, a
       
    21 source and destination address, and the size of data to be transferred,
       
    22 must be provided. If the source and/or destination is in memory, each
       
    23 fragment points to memory which is physically contiguous. </p> <p>The kind of transfer to perform is specified using a set of flags
       
    24 and hardware-specific information. The flags can be: </p> <table id="GUID-52098463-21DE-5D42-8F35-9B6D67CE93BC-GENID-1-2-1-10-1-5-1-5-1-1-7-1-9-1-6-1-3-2-4">
       
    25 <tgroup cols="2"><colspec colname="col0"/><colspec colname="col1"/>
       
    26 <tbody>
       
    27 <row>
       
    28 <entry><p> <codeph>KDmaMemSrc</codeph>  </p> </entry>
       
    29 <entry><p>Source is the address of a memory buffer </p> </entry>
       
    30 </row>
       
    31 <row>
       
    32 <entry><p> <codeph>KDmaMmeDest</codeph>  </p> </entry>
       
    33 <entry><p>Destination is the address of a memory buffer </p> </entry>
       
    34 </row>
       
    35 <row>
       
    36 <entry><p> <codeph>KDmaIncSrc</codeph>  </p> </entry>
       
    37 <entry><p>Source address must be post-incremented during transfer </p> </entry>
       
    38 </row>
       
    39 <row>
       
    40 <entry><p> <codeph>KDmaIncDest</codeph>  </p> </entry>
       
    41 <entry><p>Destination address must be post-incremented during transfer </p> </entry>
       
    42 </row>
       
    43 <row>
       
    44 <entry><p> <codeph>KDmaPhysAddrSrc</codeph>  </p> </entry>
       
    45 <entry><p>Source address is a physical address (as opposed to a linear
       
    46 one) </p> </entry>
       
    47 </row>
       
    48 <row>
       
    49 <entry><p> <codeph>KDmaPhysAddrDest</codeph>  </p> </entry>
       
    50 <entry><p>Destination address is a physical address (as opposed to
       
    51 a linear one) </p> </entry>
       
    52 </row>
       
    53 </tbody>
       
    54 </tgroup>
       
    55 </table> <p>The following shows an example of fragmenting a DMA request: </p> <codeblock id="GUID-E2DE10F1-7E22-5EA6-A05C-1A76B98D1F91-GENID-1-2-1-10-1-5-1-5-1-1-7-1-9-1-6-1-3-2-6" xml:space="preserve">/**
       
    56  Start the DMA transfer. This function fragments the DMA request and 
       
    57  queues it for processing and actually triggers the DMA transfer.
       
    58  
       
    59  @param    aSource
       
    60         Source address for DMA transfer
       
    61          
       
    62     @param    aCount
       
    63          Size of data to be transferred            
       
    64              
       
    65  @return    KErrNone on success, else standard error code on failure
       
    66  */    
       
    67 TInt DExDriverUartTxDma::Start(const TUint8* aSource, TInt aCount)
       
    68     {
       
    69     ...
       
    70     // Fragment the DMA request. DDmaRequest::Fragment() creates 
       
    71     // the DMA descriptor with source, destination address, size 
       
    72     // and attributes.
       
    73     // 
       
    74     // Flags KDmaMemSrc|KDmaIncSrc or KDmaMemDest|KDmaIncDest 
       
    75     // should be set if the source/destination is a memory buffer, 
       
    76     // or cleared if the source/destination is a peripheral. If the address 
       
    77     // specified is physical address instead of linear, 
       
    78     // then specify KDmaPhysAddrSrc or KDmaPhysAddrDest accordingly.
       
    79     //
       
    80     TInt retval = iTxDmaRequest-&gt;Fragment((TUint32)buf,
       
    81             (TUint32)(iUartComm-&gt;iPortAddr + KHoUART_THR), aCount,
       
    82             KDmaMemSrc |KDmaIncSrc, // source is a buffer
       
    83             0 ); // no HW Flags    
       
    84     if(retval != KErrNone)
       
    85         {
       
    86         return retval;
       
    87         }
       
    88     ...
       
    89     }</codeblock> </section>
       
    90 <section id="GUID-72984A7F-C2C4-48E5-8656-638D472A2ACD-GENID-1-2-1-10-1-5-1-5-1-1-7-1-9-1-6-1-3-3"><title>Queue</title> <p>DMA transfer is initiated by queuing the DMA request. A device
       
    91 driver queues the request by calling <xref href="GUID-780F4D53-5546-3B69-B328-0226C70EBDE2.dita#GUID-780F4D53-5546-3B69-B328-0226C70EBDE2/GUID-0A83F782-DB62-39ED-8D32-DBD5949C8D3F"><apiname>DDmaRequest::Queue()</apiname></xref> after fragmenting the DMA request. This is an asynchronous call
       
    92 and the transfer of DMA will actually start once the request is scheduled. </p> <codeblock id="GUID-FD225A28-4AFA-5CE0-A341-2261C97E7D1A-GENID-1-2-1-10-1-5-1-5-1-1-7-1-9-1-6-1-3-3-3" xml:space="preserve">/**
       
    93  Start the DMA transfer. This function fragments the DMA request and 
       
    94  queues it for processing and actually triggers the DMA transfer.
       
    95  @param    aSource Source address for DMA transfer
       
    96  @param    aCount Size of data to be transferred            
       
    97  @return    KErrNone on success, else standard error code on failure
       
    98  */
       
    99 TInt DExDriverUartTxDma::Start(const TUint8* aSource, TInt aCount)
       
   100     {
       
   101     ...
       
   102 
       
   103     // Queue the DMA request. DDmaRequest::Queue() queues the 
       
   104     // request on the DFCQ. DMA operation starts at this point.
       
   105     //
       
   106     iTxDmaRequest-&gt;Queue();
       
   107 
       
   108     ...
       
   109     }</codeblock> <p>If the request channel is idle when a request
       
   110 is queued, the request is transferred immediately. Otherwise, it is
       
   111 queued and transferred later. The client is responsible for ensuring
       
   112 cache consistency before and/or after the transfer if necessary. </p></section>
       
   113 <section id="GUID-FA035D89-F593-49C5-84EC-BC5019C63F0B-GENID-1-2-1-10-1-5-1-5-1-1-7-1-9-1-6-1-3-4"><title>Completion
       
   114 notification</title><p>This is done by the DMA service callback function.
       
   115 The completion notification is as follows:</p> <p>Once the DMA request
       
   116 is handled by the DMAC, the DMA service callback function is called
       
   117 by the DMA driver. This runs in a DFC context, that is scheduled from
       
   118 a DMA interrupt service routine. </p> <p>The DMA service callback
       
   119 function pointer must be provided while creating the DMA request: </p> <codeblock id="GUID-0A15F944-F066-52E2-BFB6-D008DF690BA6-GENID-1-2-1-10-1-5-1-5-1-1-7-1-9-1-6-1-3-4-5" xml:space="preserve">iTxDmaRequest = new DDmaRequest(*iTxDmaChannel, TxDmaService, this);</codeblock> <p>The DMA callback function is called for both success and failure
       
   120 of the request, so it needs to check the request result. On success,
       
   121 the function should either initiate another DMA request, or stop DMA
       
   122 and close the request. On failure, the function should stop DMA. </p> <codeblock id="GUID-BD28E559-FA5B-564E-BC00-3BD98C61F201-GENID-1-2-1-10-1-5-1-5-1-1-7-1-9-1-6-1-3-4-7" xml:space="preserve">/**
       
   123  DMA service callback function for transmit. This static function is 
       
   124  called on the completion of DMA transfer request. This function 
       
   125  pointer is provided while creating the DMA request, i.e. in     
       
   126  DDmaRequest(). After the request is queued, the System DMA controller 
       
   127  completes the request and calls this service function. Here, we do 
       
   128  the processing that needs to be done post the DMA request  
       
   129  completion.
       
   130  
       
   131  This function shall be called both when the DMA request succeeds or fails, 
       
   132     so both must be handled appropriately.
       
   133  
       
   134  @param    aResult    
       
   135      DMA result, can be DDmaRequest::EOk in case of success, else error
       
   136              
       
   137  @param    aArg pointer passed at time of registration, typically &lt;this&gt; 
       
   138         pointer
       
   139  
       
   140  @return    none 
       
   141  */
       
   142 static void TxDmaService(DDmaRequest::TResult aResult, TAny* aArg)
       
   143     {
       
   144     // Check the result of DMA service function call. It can be 
       
   145     // either of the DDmaRequest::TResult enumerated values.
       
   146     //
       
   147     if ( aResult != DDmaRequest::EOk)
       
   148         {
       
   149         // DMA request failed, so stop the DMA. 
       
   150         Stop ();
       
   151 
       
   152         // Notify request completion with an error result
       
   153         ...
       
   154         }
       
   155     else
       
   156         {
       
   157         // DMA request was successful. 
       
   158      // The program can start another DMA request, or stop 
       
   159         // the DMA, if no more DMA requests are needed.
       
   160         // Notify request operation complete with success.
       
   161         ...
       
   162         }
       
   163     }</codeblock></section>
       
   164 </conbody><related-links>
       
   165 <link href="GUID-6AC01B10-92C1-4E56-813B-6853DFCF3386-GENID-1-2-1-9-1-6-1-8-1-7-1-5-1.dita"><linktext>DMA
       
   166 Requests</linktext></link>
       
   167 </related-links></concept>