Symbian3/PDK/Source/GUID-C74770A5-ADD4-4AB1-946F-77105E2B8C10.dita
changeset 1 25a17d01db0c
child 3 46218c8b8afa
equal deleted inserted replaced
0:89d6a7a84779 1:25a17d01db0c
       
     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" xml:lang="en"><title>DMA
       
    13 Request Operations</title><shortdesc>This document describes the operations which a device driver performs
       
    14 on a DMA request.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    15 <p>After doing the required DMA initialisation, a driver can start a DMA operation.
       
    16 To do this, the driver fragments the request and then queues the request. </p>
       
    17 <section id="GUID-24567A76-814B-4E1C-81CA-61D9142B442B"><title>Fragment</title> <p>A
       
    18 DMA request can be split into different fragments that are small enough to
       
    19 be sent to DMAC. The size of each fragment is smaller than or equal to the
       
    20 maximum 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, must
       
    22 be provided. If the source and/or destination is in memory, each fragment
       
    23 points to memory which is physically contiguous. </p> <p>The kind of transfer
       
    24 to perform is specified using a set of flags and hardware-specific information.
       
    25 The flags can be: </p> <table id="GUID-52098463-21DE-5D42-8F35-9B6D67CE93BC">
       
    26 <tgroup cols="2"><colspec colname="col0"/><colspec colname="col1"/>
       
    27 <tbody>
       
    28 <row>
       
    29 <entry><p> <xref href="GUID-F607BDD4-4ED7-3841-B355-C5099C42612A.dita"><apiname>KDmaMemSrc</apiname></xref>  </p> </entry>
       
    30 <entry><p>Source is the address of a memory buffer </p> </entry>
       
    31 </row>
       
    32 <row>
       
    33 <entry><p> <xref href="GUID-B9018464-BBE0-3CF6-9B15-94E9658D1821.dita"><apiname>KDmaMmeDest </apiname></xref>  </p> </entry>
       
    34 <entry><p>Destination is the address of a memory buffer </p> </entry>
       
    35 </row>
       
    36 <row>
       
    37 <entry><p> <xref href="GUID-018CF7EC-55F3-38CB-9AC5-31ADE568F20B.dita"><apiname>KDmaIncSrc</apiname></xref>  </p> </entry>
       
    38 <entry><p>Source address must be post-incremented during transfer </p> </entry>
       
    39 </row>
       
    40 <row>
       
    41 <entry><p> <xref href="GUID-74D836AD-5A93-3971-9C73-583B4471AB18.dita"><apiname>KDmaIncDest</apiname></xref>  </p> </entry>
       
    42 <entry><p>Destination address must be post-incremented during transfer </p> </entry>
       
    43 </row>
       
    44 <row>
       
    45 <entry><p> <xref href="GUID-45E60D7F-0309-3EC0-B621-A1DF4A3358B9.dita"><apiname>KDmaPhysAddrSrc</apiname></xref>  </p> </entry>
       
    46 <entry><p>Source address is a physical address (as opposed to a linear one) </p> </entry>
       
    47 </row>
       
    48 <row>
       
    49 <entry><p> <xref href="GUID-82B3046B-F41C-3C99-8EAD-2F072D210BEF.dita"><apiname>KDmaPhysAddrDest</apiname></xref>  </p> </entry>
       
    50 <entry><p>Destination address is a physical address (as opposed to a linear
       
    51 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" 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"><title>Queue</title> <p>DMA transfer is initiated by queuing the
       
    91 DMA request. A device 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
       
    92 fragmenting the DMA request. This is an asynchronous call and the transfer
       
    93 of DMA will actually start once the request is scheduled. </p> <codeblock id="GUID-FD225A28-4AFA-5CE0-A341-2261C97E7D1A" xml:space="preserve">/**
       
    94  Start the DMA transfer. This function fragments the DMA request and 
       
    95  queues it for processing and actually triggers the DMA transfer.
       
    96  @param    aSource Source address for DMA transfer
       
    97  @param    aCount Size of data to be transferred            
       
    98  @return    KErrNone on success, else standard error code on failure
       
    99  */
       
   100 TInt DExDriverUartTxDma::Start(const TUint8* aSource, TInt aCount)
       
   101     {
       
   102     ...
       
   103 
       
   104     // Queue the DMA request. DDmaRequest::Queue() queues the 
       
   105     // request on the DFCQ. When it is processed, the SDMAC driver calls 
       
   106     // the helper ChannelTransfer() to start the transfer on the 
       
   107     // device. DMA operation starts at this point.
       
   108     //
       
   109     iTxDmaRequest-&gt;Queue();
       
   110 
       
   111     ...
       
   112     }</codeblock> <p>If the request channel is idle when a request is queued,
       
   113 the request is transferred immediately. Otherwise, it is queued and transferred
       
   114 later. The client is responsible for ensuring cache consistency before and/or
       
   115 after the transfer if necessary. </p></section>
       
   116 <section id="GUID-FA035D89-F593-49C5-84EC-BC5019C63F0B"><title>Completion notification</title> <p>Once the DMA request is
       
   117 handled by the DMAC, the DMA service callback function is called by the DMA
       
   118 driver. This runs in a DFC context, that is scheduled from a DMA interrupt
       
   119 service routine. </p> <p>The DMA service callback function pointer must be
       
   120 provided while creating the DMA request: </p> <codeblock id="GUID-0A15F944-F066-52E2-BFB6-D008DF690BA6" xml:space="preserve">iTxDmaRequest = new DDmaRequest(*iTxDmaChannel, TxDmaService, this);</codeblock> <p>The DMA callback function is called for both success and failure of the
       
   121 request, so it needs to check the request result. On success, the function
       
   122 should either initiate another DMA request, or stop DMA and close the request.
       
   123 On failure, the function should stop DMA by cancelling the request. </p> <codeblock id="GUID-BD28E559-FA5B-564E-BC00-3BD98C61F201" xml:space="preserve">/**
       
   124  DMA service callback function for transmit. This static function is 
       
   125  called on the completion of DMA transfer request. This function 
       
   126  pointer is provided while creating the DMA request, i.e. in     
       
   127  DDmaRequest(). After the request is queued, the System DMA controller 
       
   128  completes the request and calls this service function. Here, we do 
       
   129  the processing that needs to be done post the DMA request  
       
   130  completion.
       
   131  
       
   132  This function shall be called both when the DMA request succeeds or fails, 
       
   133     so both must be handled appropriately.
       
   134  
       
   135  @param    aResult    
       
   136      DMA result, can be DDmaRequest::EOk in case of success, else error
       
   137              
       
   138  @param    aArg pointer passed at time of registration, typically &lt;this&gt; 
       
   139         pointer
       
   140  
       
   141  @return    none 
       
   142  */
       
   143 static void TxDmaService(DDmaRequest::TResult aResult, TAny* aArg)
       
   144     {
       
   145     // Check the result of DMA service function call. It can be 
       
   146     // either of the DDmaRequest::TResult enumerated values.
       
   147     //
       
   148     if ( aResult != DDmaRequest::EOk)
       
   149         {
       
   150         // DMA request failed, so stop the DMA. 
       
   151         Stop ();
       
   152 
       
   153         // Notify request completion with an error result
       
   154         ...
       
   155         }
       
   156     else
       
   157         {
       
   158         // DMA request was successful. 
       
   159      // The program can start another DMA request, or stop 
       
   160         // the DMA, if no more DMA requests are needed.
       
   161         // Notify request operation complete with success.
       
   162         ...
       
   163         }
       
   164     }</codeblock></section>
       
   165 </conbody></concept>