Adaptation/GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.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-E55B4FE5-517C-5A23-8ACA-E28EE202330B" xml:lang="en"><title>Platform
       
    13 Specific Layer Implementation</title><shortdesc>Describes how to implement the Platform Specific Layer of the MMC
       
    14 Controller. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    15 <section id="GUID-4C6CA873-A798-5C79-8838-0CC3C9E914FB"><title>DMMCStack derived
       
    16 class</title> <p>This class controls access to the MultiMediaCard stack. This
       
    17 class has a number of pure virtual functions that need to be implemented in
       
    18 your Variant DLL. The diagram at <xref href="GUID-BE6AFD38-5952-537F-848C-C76C8F5FA9BF.dita#GUID-BE6AFD38-5952-537F-848C-C76C8F5FA9BF/GUID-92F5EBE4-C9AD-5D9A-A80E-9AFD1A09B6B3">MultiMediaCard
       
    19 controller basic structure</xref> shows the class in context. </p> <p>There
       
    20 is one virtual function with a default implementation that needs to be overridden. </p> <ul>
       
    21 <li id="GUID-01ABEA80-002F-5490-B90F-3AE83927220B"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-0B55A650-E9ED-56CB-B06F-B1113ACDF282">Init()</xref>  </p> </li>
       
    22 <li id="GUID-04245FCC-D55A-5840-98CC-2113E7B6D9E4"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-CEF0EDF7-4B33-5452-8635-51C5319F78AE">MachineInfo()</xref> </p> </li>
       
    23 <li id="GUID-C5C86175-9100-5687-96EB-F4AEAF0CE161"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-F41EA0A6-1CBF-5AE2-9C66-DD6E3B7312E0">ProgramPeriodInMilliSeconds()</xref>  </p> </li>
       
    24 <li id="GUID-12B3B751-9EFE-5273-844B-A18D99E2A7FF"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-A7EC6536-3822-58C8-9A65-B71FDDBA10F3">AdjustPartialRead()</xref> </p> </li>
       
    25 <li id="GUID-AF40CF60-918D-5D9D-96C3-D96FDAD94B85"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-8A3E9782-C8D4-562D-9470-5CCE0ED1C303">GetBufferInfo()</xref> </p> </li>
       
    26 <li id="GUID-60AC1F94-4936-5AB1-B31E-CEDBDE59E08E"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-BC742EB6-7063-5D00-B422-96B3772605D5">SetBusConfigDefaults()</xref> </p> </li>
       
    27 <li id="GUID-592CDEF6-F450-572A-878E-077ED633C621"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-49DF2E60-AE31-502E-B7CB-694AFAF69F1B">InitClockOff()</xref>  </p> </li>
       
    28 <li id="GUID-82080A27-BCB7-5EC3-8F3E-2C1CDEDCA601"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-0DF60D11-AAD6-59E2-AE81-16E0DF96291B">ASSPDisengage()</xref> </p> </li>
       
    29 <li id="GUID-5E0E9EC9-742A-5265-9429-C52B60D83863"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-99AC4F3B-E273-515E-8690-983E98E17256">ASSPReset()</xref> </p> </li>
       
    30 <li id="GUID-DA38EA59-0A91-5498-9B3A-1F17D4511EFC"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-6EEE7EF6-4272-5116-BCEF-A852BB7B8FBD">CardDetect()</xref> </p> </li>
       
    31 <li id="GUID-9F025A5A-F303-55C8-85C4-BAC0BF0C27E4"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-3F34865D-5B16-5F53-AF9E-9F52DB5D0FB5">WriteProtected()</xref> </p> </li>
       
    32 <li id="GUID-D1B3A73F-E3AC-55C6-84E4-11A2AA9C3A7F"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-65547330-E112-55F2-AD4A-9B9CA5617E33">DoPowerDown()</xref> </p> </li>
       
    33 <li id="GUID-4117DD14-59D4-5257-AAAD-79498391979E"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-C8C15101-4614-5DEC-A620-6EAE8EC463ED">DoPowerUpSM()</xref> </p> </li>
       
    34 <li id="GUID-D93B8DEC-CFA0-5FC9-AF46-81A3B21F3545"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-C976320E-80FF-50F8-A882-F89C74F76ED3">InitClockOnSM()</xref> </p> </li>
       
    35 <li id="GUID-F6BB7D3C-8A9A-5228-88ED-2F28980373D8"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-FABAED76-FC63-577B-9436-DC7C8978E2AE">IssueMMCCommandSM()</xref>  </p> </li>
       
    36 </ul> <p id="GUID-0B55A650-E9ED-56CB-B06F-B1113ACDF282"><b>Init()</b> </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-43A06EF7-FA7B-3653-97B4-B04336E3EB54"><apiname>DMMCStack::Init()</apiname></xref>  </p> <p>The
       
    37 function is intended to initialize the stack, and is called during initialization
       
    38 of the MultiMediaCard controller Variant DLL from <xref href="GUID-45B97680-1756-3559-8A2D-2F2E851AD6A7.dita#GUID-45B97680-1756-3559-8A2D-2F2E851AD6A7/GUID-18825E56-F155-38D0-A4DF-A7C57D73C1EF"><apiname>DMMCSocket::Init()</apiname></xref>: </p> <p>You
       
    39 will almost certainly need to provide your own implementation to perform any
       
    40 platform-specific MultiMediaCard stack initialization. Whatever your implementation
       
    41 provides, <i>it is important that you call the base class function from within
       
    42 your derived version</i>. </p> <p>Return <xref href="GUID-6CA4F1ED-7947-3087-B618-D35858FAA3BC.dita"><apiname>KErrNone</apiname></xref> if initialization
       
    43 is successful, otherwise return one of the system-wide error codes to indicate
       
    44 initialization failure. Note that returning a value other than <xref href="GUID-6CA4F1ED-7947-3087-B618-D35858FAA3BC.dita"><apiname>KErrNone</apiname></xref> will
       
    45 cause the kernel to panic and to fail to boot. </p> <p>You will allocate a
       
    46 data transfer buffer here. The MultiMediaCard media driver needs a memory
       
    47 buffer to perform data transfer operations. Where supported, DMA is generally
       
    48 used to do this, and requires physically contiguous memory. However, the media
       
    49 driver is created each time a card is inserted into a machine and destroyed
       
    50 when the card is removed, and giving the media driver the responsibility for
       
    51 allocating the memory buffer means that it might not always be possible to
       
    52 allocate physically contiguous pages for it as memory becomes fragmented over
       
    53 time. </p> <p>The MultiMediaCard media driver uses the <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-8A3E9782-C8D4-562D-9470-5CCE0ED1C303">GetBufferInfo()</xref> function each time it is created to get a pointer
       
    54 to the buffer, and to get its length. </p> <p>Although the MultiMediaCard
       
    55 media driver only expects a single buffer, it actually uses this as two separate
       
    56 buffers: </p> <ul>
       
    57 <li id="GUID-21E69407-DEB2-5DBE-9614-ADFF7DBF06B6"><p>a minor buffer which
       
    58 must have at least enough space for the MBR (512 bytes) </p> </li>
       
    59 <li id="GUID-1FF25456-0CE3-582C-9FEC-B5913C1E437A"><p>a cache buffer to cache
       
    60 data blocks from the card. </p> </li>
       
    61 </ul> <p>The ideal size of the cache buffer depends on the characteristics
       
    62 of the card present at the time, and it is possible to customize the MultiMediaCard
       
    63 controller at the platform specific layer for a particular card. </p> <p>The
       
    64 following example code allocates a physically contiguous buffer - a minor
       
    65 buffer size of one block is allocated together with a cache buffer size of
       
    66 eight blocks. The whole buffer is then rounded up to a whole number of memory
       
    67 pages. </p> <codeblock id="GUID-B01B50BE-6574-5A81-BA25-8FDFEB2C5620" xml:space="preserve">// The constant calculations could be explicitly folded, but this illustrates
       
    68 // how the values are derived.
       
    69 const TUint blkSzLog2 = 9;                    
       
    70 const TUint blkSz = 1 &lt;&lt; blkSzLog2;
       
    71 const TInt minorBufLen = Max(KDiskSectorSize, blkSz);
       
    72 
       
    73 const TInt KMinBlocksInBuffer = 8;
       
    74 const TInt cchBufLen = KMinBlocksInBuffer &lt;&lt; blkSzLog2;
       
    75 
       
    76 TInt totalBufLen = minorBufLen + cchBufLen;
       
    77 
       
    78 // Allocate contiguous physical memory
       
    79 totalBufLen = Kern::RoundToPageSize(totalBufLen);
       
    80 
       
    81 TPhysAddr physAddr = 0;
       
    82 r = Epoc::AllocPhysicalRam(totalBufLen, physAddr);
       
    83 __KTRACE_OPT(KHARDWARE, Kern::Printf("mmc:ini:physical = %08x", physAddr));
       
    84 if (r != KErrNone)
       
    85     {
       
    86     return r;
       
    87     }
       
    88 
       
    89 DPlatChunkHw* bufChunk = NULL;
       
    90 r = DPlatChunkHw::New(bufChunk, physAddr, totalBufLen, EMapAttrCachedWBRA|EMapAttrSupRw);
       
    91 
       
    92 if(r != KErrNone)
       
    93     {
       
    94     if (physAddr)
       
    95         {
       
    96         Epoc::FreePhysicalRam(physAddr, totalBufLen);
       
    97         }
       
    98     return r;
       
    99     }
       
   100           
       
   101 iMDBuf = reinterpret_cast&lt;TUint8*&gt;(bufChunk-&gt;LinearAddress());
       
   102 iMDBufLen = totalBufLen;
       
   103 </codeblock> <p id="GUID-CEF0EDF7-4B33-5452-8635-51C5319F78AE"><b>MachineInfo()</b> </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-3E5532A5-4645-3F77-A7A9-7AFF334FA5A4"><apiname>DMMCStack::MachineInfo()</apiname></xref>  </p> <p>The
       
   104 function returns configuration information for the MultiMediaCard stack. </p> <p>The
       
   105 function takes a reference to a <xref href="GUID-3F9D89E8-44F0-35B3-9404-6CCAC79763E8.dita"><apiname>TMMCMachineInfo</apiname></xref> object,
       
   106 and your implementation must fill the public data members of the object. </p> <p id="GUID-F41EA0A6-1CBF-5AE2-9C66-DD6E3B7312E0"><b>ProgramPeriodInMilliSeconds()</b> </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-C0998F1F-EE3B-32C1-9898-288EA1D71AC0"><apiname>DMMCStack::ProgramPeriodInMilliSeconds()</apiname></xref>  </p> <p>When a data block is written to a card, the data is read into an
       
   107 internal buffer on the card and is then programmed into the payload memory.
       
   108 While the card is in <i>programming mode</i>, it cannot be read from, or written
       
   109 to, but it is possible to query its status using CMD13. </p> <p>Immediately
       
   110 after a block of data is written by <codeph>CIMReadWriteBlocksSM()</codeph>,
       
   111 the MultiMediaCard controller requests the card's state using CMD13. If the
       
   112 card is still in the programming state, then the state machine <codeph>ProgramTimerSM()</codeph> launches
       
   113 a timer with the period returned by <codeph>ProgramPeriodInMilliSeconds()</codeph>.
       
   114 The state of the card is periodically checked until it is no longer in programming
       
   115 mode. </p> <p>For platforms that do not provide an interrupt to indicate when
       
   116 programming mode is finished, <codeph>ProgramPeriodInMilliSeconds()</codeph> should
       
   117 return the interval, in milliseconds, to be used by the poll timer. </p> <p id="GUID-A7EC6536-3822-58C8-9A65-B71FDDBA10F3"><b>AdjustPartialRead()</b> </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-7FEC1574-5448-3DF5-8BD2-AABDBD0211C3"><apiname>DMMCStack::AdjustPartialRead()</apiname></xref>  </p> <p>Some
       
   118 cards support a partial read feature, which is indicated by the <codeph>READ_BL_PARTIAL</codeph> bit
       
   119 in the <codeph>CSD</codeph> register. When this is the case, it is possible
       
   120 to read a section within a single physical block, without having to read the
       
   121 entire block. </p> <p>The MultiMediaCard media driver uses this feature to
       
   122 read small amounts of data more quickly. However, many hardware implementations
       
   123 impose restrictions on the granularity of the data that can be read from the
       
   124 card. For example, they may use a 32-bit FIFO. </p> <p>This function allows
       
   125 you to enforce the limits imposed by the hardware. </p> <p>The <codeph>aStart</codeph> and <codeph>aEnd</codeph> arguments
       
   126 of <codeph>AdjustPartialRead()</codeph> define the range on the card from
       
   127 which the media driver would like to read. Your implementation should return
       
   128 in <codeph>*aPhysStart</codeph> and <codeph>*aPhysEnd</codeph> the range that
       
   129 the hardware will allow to be read. </p> <p>For example, to word align data,
       
   130 the function would be implemented using the following code: </p> <codeblock id="GUID-30DE526C-70C2-5118-BFBB-72759EFC8C93" xml:space="preserve">void AdjustPartialRead(const TMMCard* aCard, TUint32 aStart, TUint32 aEnd, TUint32* aPhysStart, TUint32* aPhysEnd);
       
   131     {
       
   132     ...
       
   133     const TUint32 KWordMask = 3;
       
   134     *aPhysStart = aStart &amp; ~KWordMask;
       
   135     *aPhysEnd = (aEnd + KWordMask) &amp; ~KWordMask;
       
   136     ...
       
   137     }
       
   138 </codeblock> <p id="GUID-8A3E9782-C8D4-562D-9470-5CCE0ED1C303"><b>GetBufferInfo()</b> </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-EC9B740A-3A07-35AB-BACE-2EC1F96EEF0F"><apiname>DMMCStack::GetBufferInfo()</apiname></xref>  </p> <p>The
       
   139 MultiMediaCard media driver needs a memory buffer to perform data transfer
       
   140 operations, and this is, typically, allocated once only by the <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-0B55A650-E9ED-56CB-B06F-B1113ACDF282">Init()</xref> function when this stack object is initialized. </p> <p>The
       
   141 MultiMediaCard media driver is created each time a card is inserted into a
       
   142 machine and destroyed when the card is removed, and it uses this function,
       
   143 each time it is created to get a pointer to the memory buffer, and to get
       
   144 its length. The MultiMediaCard media driver then uses this buffer, over its
       
   145 lifetime, for data transfer operations. </p> <p id="GUID-BC742EB6-7063-5D00-B422-96B3772605D5"><b>SetBusConfigDefaults()</b> </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-C7297E13-5F78-396D-842B-FB16D3424374"><apiname>DMMCStack::SetBusConfigDefaults()</apiname></xref>  </p> <p>The function returns information about the MultiMediaCard bus configuration
       
   146 for this platform. </p> <p>The function takes a <xref href="GUID-F9432D7B-41C9-3048-AC50-B5BCF8BE11D0.dita"><apiname>TUint</apiname></xref> value
       
   147 containing the bus speed that the controller intends to use, and a reference
       
   148 to a <xref href="GUID-C0E2780A-47B3-31A2-827C-AF89C1B65F2E.dita"><apiname>TMMCBusConfig</apiname></xref> object. The implementation of this function
       
   149 must fill the public data members of this object. See the class reference
       
   150 documentation for the data members. </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita"><apiname>DMMCStack</apiname></xref> has
       
   151 two private data members of type <xref href="GUID-75FF770B-07D1-3C07-9577-5A37841E53E7.dita"><apiname>TMMCStackConfig</apiname></xref>: </p> <ul>
       
   152 <li id="GUID-A56BF364-F02F-54EA-80F8-E4AB5E7A10C9"><p> <codeph>iMasterConfig</codeph>  </p> </li>
       
   153 <li id="GUID-C94FFA4E-51C7-5CBA-BFBB-F692438412FE"><p> <codeph>iConfig</codeph>  </p> </li>
       
   154 </ul> <p>The information returned by the call to <codeph>SetBusConfigDefaults()</codeph> is
       
   155 stored in <codeph>iMasterConfig</codeph>'s <codeph>iBusConfig</codeph> private
       
   156 data member. </p> <p> <codeph>iMasterConfig</codeph> contains the master bus
       
   157 configuration settings for the platform. Each time a new session is made current,
       
   158 the master bus configuration settings are merged with the specific bus configuration
       
   159 settings for that session, (as set up in the public data member <xref href="GUID-0186BEDE-8E28-3F8C-8CAE-A8B92F41F47A.dita#GUID-0186BEDE-8E28-3F8C-8CAE-A8B92F41F47A/GUID-73BC8CE4-593E-3BAC-909A-FB8F419895C8"><apiname>DMMCSession::iConfig</apiname></xref>),
       
   160 and the result is stored in <codeph>iConfig</codeph>. It is these merged bus
       
   161 configuration settings that are used to configure the hardware interface.
       
   162 The platform specific layer can access these settings with a call to Master<xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-E0275614-109E-3803-A0AE-3313E1E0038B"><apiname>DMMCStack::BusConfig()</apiname></xref>. </p> <p> <codeph> SetBusConfigDefaults()</codeph> is called at two stages in the execution of the macro CIM_UPDATE_ACQ to
       
   163 update the <codeph>iMasterConfig</codeph> object. </p> <ul>
       
   164 <li id="GUID-5C98DB8C-60AF-5333-A250-5D6509D754E5"><p>First, it is called
       
   165 at the start of the card initialization stage with the bus speed argument, <codeph>aClock</codeph>,
       
   166 set to the fOD rate (400kHz). </p> </li>
       
   167 <li id="GUID-0CD15184-15F8-5104-908F-612CCBCA953A"><p>Second, it is called
       
   168 after the CSD registers for each card have been read with the bus speed argument, <codeph>aClock</codeph>,
       
   169 set to the slowest maximum transfer rate (TRAN_SPEED) reported by any of the
       
   170 CSD registers. </p> </li>
       
   171 </ul> <p id="GUID-49DF2E60-AE31-502E-B7CB-694AFAF69F1B"><b> InitClockOff()</b> </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-BF94B298-7F72-33F7-A2F0-F19807BF2CDC"><apiname>DMMCStack::InitClockOff()</apiname></xref>  </p> <p>Switches
       
   172 from identification mode of operation to data transfer mode operation. </p> <p>When
       
   173 this function is called, the clock information in the <codeph>iBusConfig</codeph> member
       
   174 (see <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-BC742EB6-7063-5D00-B422-96B3772605D5">SetBusConfigDefaults()</xref>)
       
   175 will not have been updated to the new data transfer rate. </p> <p>This function
       
   176 should, in general, just switch from open drain to push-pull bus mode, with
       
   177 the clock rate being changed at the start of <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-A48C1C16-B465-3DDA-9C83-00DEB8D27B68"><apiname>DMMCStack::IssueMMCCommandSM()</apiname></xref>,
       
   178 when <codeph>iBusConfig</codeph> will be valid. </p> <p id="GUID-0DF60D11-AAD6-59E2-AE81-16E0DF96291B"><b> ASSPDisengage()</b> </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-36C720F9-DEAF-3896-A12A-2AE2581AA347"><apiname>DMMCStack::ASSPDisengage()</apiname></xref>  </p> <p>This
       
   179 function is called by the platform independent layer each time a session has
       
   180 completed or has been aborted. </p> <p>The function gives the platform specific
       
   181 layer the chance to free resources or disable any activities that were required
       
   182 to perform the session. </p> <p>The implementation should not turn off the
       
   183 clock to the hardware interface as this will be turned off by the inactivity
       
   184 timer. Typically, the implementation disables DMA and interface interrupts,
       
   185 and forces the hardware interface into idle. </p> <p>At the end of your implementation,
       
   186 you must add a call <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-3DFCBE96-E9F3-3FF3-97BC-A3A3024089BD"><apiname>DMMCStack::ReportASSPDisengaged()</apiname></xref> to
       
   187 report to the platform independent layer that platform specific layer resources
       
   188 have been disengaged. </p> <p id="GUID-99AC4F3B-E273-515E-8690-983E98E17256"><b>ASSPReset()</b> </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-36D3F4D9-A2FC-3355-ABE0-31C9F7397E2D"><apiname>DMMCStack::ASSPReset()</apiname></xref>  </p> <p>This
       
   189 function is called by the platform independent layer when the current session
       
   190 is being aborted, and platform specific asynchronous activity is to be cancelled.
       
   191 The function may also be called by the platform specific layer as part of
       
   192 the <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-65547330-E112-55F2-AD4A-9B9CA5617E33">DoPowerDown()</xref> implementation. </p> <p>The function gives the platform specific layer the chance to stop all activities
       
   193 on the host stack. It will, in general, perform the same operations as <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-0DF60D11-AAD6-59E2-AE81-16E0DF96291B">ASSPDisengage()</xref> but,
       
   194 in addition, will turn off the clock to the hardware interface and release
       
   195 any requested power requirements made on the power model, i.e. release any
       
   196 power requirements made by <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-C976320E-80FF-50F8-A882-F89C74F76ED3">InitClockOnSM()</xref>. </p> <p>At the end of your implementation, you must add a call <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-3DFCBE96-E9F3-3FF3-97BC-A3A3024089BD"><apiname>DMMCStack::ReportASSPDisengaged()</apiname></xref> to
       
   197 report to the platform independent layer that platform specific layer resources
       
   198 have been disengaged. </p> <p id="GUID-6EEE7EF6-4272-5116-BCEF-A852BB7B8FBD"><b>CardDetect()</b> </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-02C4D1A0-6149-389D-9F31-3E7EBF1DCA66"><apiname>DMMCStack::CardDetect()</apiname></xref>  </p> <p>Implement
       
   199 this function to report whether a card is present in a specified card socket. </p> <p>This
       
   200 function takes a <xref href="GUID-F9432D7B-41C9-3048-AC50-B5BCF8BE11D0.dita"><apiname>TUint</apiname></xref> value containing the card socket
       
   201 that is to be queried. </p> <p id="GUID-3F34865D-5B16-5F53-AF9E-9F52DB5D0FB5"><b>WriteProtected()</b> </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-E7E97501-10E7-38E6-9F8C-2A62F260BA46"><apiname>DMMCStack::WriteProtected()</apiname></xref>  </p> <p>Implement
       
   202 this function to report whether a card in a specified card socket is mechanically
       
   203 write protected. </p> <p>This function takes a <xref href="GUID-F9432D7B-41C9-3048-AC50-B5BCF8BE11D0.dita"><apiname>TUint</apiname></xref> value
       
   204 containing the card socket that is to be queried. </p> <p id="GUID-65547330-E112-55F2-AD4A-9B9CA5617E33"><b>DoPowerDown()</b> </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-3E90AF73-F4D3-34C5-B6D3-6BF69C6137C8"><apiname>DMMCStack::DoPowerDown()</apiname></xref>  </p> <p>This
       
   205 function is called as part of the bus power down sequence: </p> <ul>
       
   206 <li id="GUID-E9E072D3-A2F7-5DD2-B7D9-A89840BBA914"><p>by the power model,
       
   207 in power standby and power emergency standby situations </p> </li>
       
   208 <li id="GUID-1EFB0616-45B9-5EC2-9456-54F7D10D2894"><p>when a door-open event
       
   209 occurs </p> </li>
       
   210 <li id="GUID-83F42DEB-C6EE-5558-8907-CFD141461456"><p>when the bus inactivity
       
   211 timer has timed out </p> </li>
       
   212 <li id="GUID-0EA77E57-E2D0-599D-8E90-ECE1D21BC329"><p>if a power supply unit
       
   213 (PSU) voltage check fails. </p> </li>
       
   214 </ul> <p>The function should stop all activities on the host stack, turn off
       
   215 the clock to the hardware interface and release any requested power requirements
       
   216 made on the power model. The function is very often implemented as a call
       
   217 of <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-99AC4F3B-E273-515E-8690-983E98E17256">ASSPReset()</xref>. </p> <p>The
       
   218 function should not turn off the MultiMediaCard power supply unit as this
       
   219 will be performed immediately afterwards by a call to the <xref href="GUID-FBCEFDB6-28FF-3201-8E13-F12E3759E36B.dita#GUID-FBCEFDB6-28FF-3201-8E13-F12E3759E36B/GUID-4DF0741F-B143-3B46-82BE-9CD0261C27E5"><apiname>DMMCPsu::DoSetState()</apiname></xref> derived
       
   220 class function from the platform independent layer. </p> <p id="GUID-C8C15101-4614-5DEC-A620-6EAE8EC463ED"><b> DoPowerUpSM()</b> </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-791BCA03-61F3-3C1C-BA2D-D633A94AF299"><apiname>DMMCStack::DoPowerUpSM()</apiname></xref>  </p> <p>This
       
   221 is a state machine function, called as a child function at the start of the <codeph>CIM_UPDATE_ACQ</codeph> macro
       
   222 state machine. </p> <p>The function should perform the necessary platform
       
   223 specific actions associated with powering up the bus. This includes turning
       
   224 on the MultiMediaCard PSU. However, the hardware interface clock should <i>not</i> be
       
   225 turned on as part of this function. </p> <p>If the controller has to request
       
   226 power resources from the power model, e.g. where a fast system clock is required
       
   227 all the time the bus is powered, then this state machine function can be used
       
   228 to wait asynchronously for this resource to become available. </p> <p>If the
       
   229 activity performed by this function completes successfully: </p> <ul>
       
   230 <li id="GUID-7C64DB32-139B-5F45-9F2C-6693F9E16F83"><p>it must call <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-40973A35-3A73-3DBD-9EB7-99CE55E6D694"><apiname>DMMCStack::ReportPowerUp()</apiname></xref>. </p> </li>
       
   231 <li id="GUID-42E872B5-EA6A-5901-AD93-5F9B99C81D69"><p>it returns <xref href="GUID-E7D46003-E502-39D1-AF52-83B87AE6930B.dita"><apiname>KMMCErrNone</apiname></xref>. </p> </li>
       
   232 </ul> <p>The function should return <xref href="GUID-E7D46003-E502-39D1-AF52-83B87AE6930B.dita"><apiname>KMMCErrNone</apiname></xref> if it completes
       
   233 successfully or one of the other <xref href="GUID-FF4AB1CF-7A2C-3FC6-B123-D6819E1BCDCA.dita"><apiname>TMMCErr</apiname></xref> error codes. </p> <p>See
       
   234 the general background information on <xref href="GUID-80E0DB93-A96A-54A8-A201-E11935418BE7.dita">the
       
   235 state machine</xref>. </p> <p id="GUID-C976320E-80FF-50F8-A882-F89C74F76ED3"><b>InitClockOnSM()</b> </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-7B91EF52-26E5-333C-A037-B142B492BCC4"><apiname>DMMCStack::InitClockOnSM()</apiname></xref>  </p> <p>This
       
   236 is a state machine function, called as part of the <codeph>CIM_UPDATE_ACQ</codeph> macro
       
   237 state machine. </p> <p>The function should turn on the clock to the hardware
       
   238 interface. The function is so named because this clock is always first turned
       
   239 on at the identification mode frequency. </p> <p>The function is implemented
       
   240 as a state machine function because it may be necessary to include a short
       
   241 delay after the clock has been turned on to allow it to stabilize. </p> <p>If
       
   242 it is necessary for the MultiMediaCard controller to request any power resources
       
   243 from the power model on this platform, for example, requesting a necessary
       
   244 system clock, then it should be performed as part of this function. In some
       
   245 cases, it may be necessary to wait for this power resource to become available. </p> <p>At
       
   246 the <i>beginning</i> of your implementation, you must add a call <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-D797747A-0AF6-36B1-BD92-3D6950A3B7B4"><apiname>DMMCStack::ReportASSPEngaged()</apiname></xref> to
       
   247 report to the platform independent layer that platform specific layer resources
       
   248 have been engaged. </p> <p>The function should return <xref href="GUID-E7D46003-E502-39D1-AF52-83B87AE6930B.dita"><apiname>KMMCErrNone</apiname></xref> if
       
   249 it completes successfully or one of the other <xref href="GUID-FF4AB1CF-7A2C-3FC6-B123-D6819E1BCDCA.dita"><apiname>TMMCErr</apiname></xref> error
       
   250 codes. </p> <p>Note: </p> <ul>
       
   251 <li id="GUID-2474710D-C595-5331-9182-A2EF97A1EB27"><p>the function is only
       
   252 called once for each invocation of the CIM_UPDATE_ACQ macro and the important
       
   253 thing to stress is that the interface clock is being turned on after a period
       
   254 when it has been off, and therefore often requires time to stabilize. </p> </li>
       
   255 <li id="GUID-FE92334D-757D-5C08-AF98-9E0912BA2820"><p>In the course of executing
       
   256 a session, the MultiMediaCard controller may switch the clock more than once
       
   257 between the identification mode frequency and the data transfer mode frequency,
       
   258 but this function only ever gets called once. </p> </li>
       
   259 </ul> <p>See the general background information on <xref href="GUID-80E0DB93-A96A-54A8-A201-E11935418BE7.dita">the
       
   260 state machine</xref>. </p> <p id="GUID-FABAED76-FC63-577B-9436-DC7C8978E2AE"><b> IssueMMCCommandSM()</b> </p> <p> <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-A48C1C16-B465-3DDA-9C83-00DEB8D27B68"><apiname>DMMCStack::IssueMMCCommandSM()</apiname></xref>  </p> <p>This
       
   261 is a <xref href="GUID-80E0DB93-A96A-54A8-A201-E11935418BE7.dita">state machine</xref> function
       
   262 that executes a single command over the bus. The implementation of this function
       
   263 is an important part in the process of porting the MultiMediaCard controller. </p> <p>The
       
   264 input parameters for the command are passed via the current command descriptor,
       
   265 an instance of the <xref href="GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A.dita"><apiname>TMMCCommandDesc</apiname></xref> class, on the session’s
       
   266 command stack. The parameters contain information such as: the type of command,
       
   267 the response type, the command arguments, the data source/destination for
       
   268 data transfer commands etc. Use <xref href="GUID-0186BEDE-8E28-3F8C-8CAE-A8B92F41F47A.dita#GUID-0186BEDE-8E28-3F8C-8CAE-A8B92F41F47A/GUID-931547BD-665D-326A-92B5-909B2D57F8C6"><apiname>DMMCSession::Command()</apiname></xref> to
       
   269 get the current command descriptor. </p> <p>Information about the command
       
   270 response, the number of bytes transferred etc., is passed back using the same
       
   271 command descriptor. Specifically, the platform independent layer relies on
       
   272 responses to the following commands being returned in the <xref href="GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A.dita#GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A/GUID-86553172-AE4E-3707-A0D2-8C2BB8880253"><apiname>TMMCCommandDesc::iResponse</apiname></xref> member,
       
   273 in big-endian format: </p> <ul>
       
   274 <li id="GUID-45605105-B91A-506B-A0F9-A317CA84D5EF"><p>Returns the OCR register
       
   275 value in response to a SEND_OP_COND command (CMD1). Note that there is <i>no
       
   276 CRC</i> with this response. Your code should ignore any CRC failure indication
       
   277 from the MultiMediaCard controller hardware, and just copy the response into <xref href="GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A.dita#GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A/GUID-86553172-AE4E-3707-A0D2-8C2BB8880253"><apiname>TMMCCommandDesc::iResponse</apiname></xref>. </p> </li>
       
   278 <li id="GUID-3E8B7D20-71F1-5609-8A16-24C6E2A7186A"><p>Returns the CID register
       
   279 value in response to an ALL_SEND_CID command (CMD2) and a SEND_CID command
       
   280 (CMD10). </p> </li>
       
   281 <li id="GUID-8D051F10-65BB-57AF-8B75-247829DC239A"><p>Returns the CSD register
       
   282 value in response to a SEND_CSD command (CMD9). </p> </li>
       
   283 <li id="GUID-C899645F-8478-57BF-8E1E-58AC50EB9FE3"><p>Returns the card status
       
   284 in response to all R1 and R1b commands. </p> </li>
       
   285 </ul> <p>Note that you can use the functions <xref href="GUID-32036692-8BA3-3AAF-9FD8-D135DFADAE77.dita#GUID-32036692-8BA3-3AAF-9FD8-D135DFADAE77/GUID-D2EFC17B-FC2E-3FDC-AE7A-E2AA109D4B40"><apiname>TMMC::BigEndian4Bytes()</apiname></xref> and
       
   286 TMC::to help with conversion to big-endian format. </p> <p>The function should
       
   287 return <xref href="GUID-E7D46003-E502-39D1-AF52-83B87AE6930B.dita"><apiname>KMMCErrNone</apiname></xref> if it completes successfully or one
       
   288 of the other <xref href="GUID-FF4AB1CF-7A2C-3FC6-B123-D6819E1BCDCA.dita"><apiname>TMMCErr</apiname></xref> error codes. </p> <p>See also background
       
   289 information: </p> <ul>
       
   290 <li id="GUID-0667980A-4A9E-5BD0-952E-97AD4C83B939"><p> <xref href="GUID-C059F39F-BC53-5C92-B05E-863B8CF22859.dita">Issuing
       
   291 commands</xref>  </p> </li>
       
   292 <li id="GUID-DF2B96DD-DD85-52C2-9EC8-30379E03D1DA"><p> <xref href="GUID-80E0DB93-A96A-54A8-A201-E11935418BE7.dita">The
       
   293 state machine</xref>. </p> </li>
       
   294 </ul> </section>
       
   295 <section id="GUID-3A1E907E-A74D-59CB-A1D6-FEF4849EF2D5"><title>DMMCPsu derived
       
   296 class</title> <p>This class controls the MultiMediaCard socket's power supply.
       
   297 A class needs to be derived from this in the platform specific layer to handle
       
   298 the Variant specific functionality of the power supply. </p> <p>This class
       
   299 has a number of pure virtual functions that need to be implemented in your
       
   300 Variant DLL. The diagram at <xref href="GUID-BE6AFD38-5952-537F-848C-C76C8F5FA9BF.dita#GUID-BE6AFD38-5952-537F-848C-C76C8F5FA9BF/GUID-92F5EBE4-C9AD-5D9A-A80E-9AFD1A09B6B3">MultiMediaCard
       
   301 controller basic structure</xref> shows the class in context. </p> <p>There
       
   302 is one virtual function with an empty default implementation that needs to
       
   303 be overridden. </p> <ul>
       
   304 <li id="GUID-025272EF-9DE8-5975-8993-006EE4D56E80"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-6EB8EF1C-BCCB-54A1-8CBA-4E8A2A20CABE">DoCreate()</xref>  </p> </li>
       
   305 <li id="GUID-6BAFE3AA-6CCA-581B-A96C-D1FD89D1D8CD"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-99529E84-17E1-5F23-9A1B-EBE3976D9B14">PsuInfo()</xref>  </p> </li>
       
   306 <li id="GUID-7419D681-D0CC-5CA7-8EE7-0D5A20779921"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-5809318D-E3E1-5261-AABA-604EBE72523F">DoSetState()</xref>  </p> </li>
       
   307 <li id="GUID-E570E830-B57E-5A39-9EF1-CF68F3853AFF"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-B5030D2E-A466-596C-A2C3-73F38CF9C1A7">DoCheckVoltage()</xref>  </p> </li>
       
   308 </ul> <p id="GUID-6EB8EF1C-BCCB-54A1-8CBA-4E8A2A20CABE"><b>DoCreate()</b> </p> <p> <xref href="GUID-FBCEFDB6-28FF-3201-8E13-F12E3759E36B.dita#GUID-FBCEFDB6-28FF-3201-8E13-F12E3759E36B/GUID-32771B9D-D2B8-33F5-AFC5-4476165C0A76"><apiname>DMMCPsu::DoCreate()</apiname></xref>  </p> <p>The
       
   309 function is intended to perform hardware initialization on the MultiMediaCard
       
   310 power supply, for example, setting port direction registers. </p> <p>The function
       
   311 is called after creation of the <xref href="GUID-FBCEFDB6-28FF-3201-8E13-F12E3759E36B.dita"><apiname>DMMCPsu</apiname></xref> derived class instance,
       
   312 which is done during kernel initialization when the MultiMediaCard controller
       
   313 Variant DLL extension is loaded. </p> <p>The function has a default implementation
       
   314 that just returns <xref href="GUID-6CA4F1ED-7947-3087-B618-D35858FAA3BC.dita"><apiname>KErrNone</apiname></xref>. </p> <p>Your implementation
       
   315 should <xref href="GUID-6CA4F1ED-7947-3087-B618-D35858FAA3BC.dita"><apiname>KErrNone</apiname></xref> if the hardware initialization is successful,
       
   316 otherwise it should return one of the system-wide error codes to indicate
       
   317 initialization failure. Note that returning a value other than <xref href="GUID-6CA4F1ED-7947-3087-B618-D35858FAA3BC.dita"><apiname>KErrNone</apiname></xref> will
       
   318 cause the kernel to panic and to fail to boot. </p> <p id="GUID-99529E84-17E1-5F23-9A1B-EBE3976D9B14"><b>PsuInfo()</b> </p> <p> <xref href="GUID-FBCEFDB6-28FF-3201-8E13-F12E3759E36B.dita#GUID-FBCEFDB6-28FF-3201-8E13-F12E3759E36B/GUID-C7600EDA-B564-31E2-835C-9C580A29FC1D"><apiname>DMMCPsu::PsuInfo()</apiname></xref>  </p> <p>The
       
   319 function returns information about the MultiMediaCard power supply. </p> <p>The
       
   320 function takes a reference to a <xref href="GUID-E3BB783F-423F-352A-9B6E-FD23EC80AA8D.dita"><apiname>TPBusPsuInfo</apiname></xref> object, and
       
   321 your implementation must fill the public data members of the object. </p> <p>Note: </p> <ul>
       
   322 <li id="GUID-B8527FE4-61BB-574A-A200-5EA083A76A6D"><p>You can use the constant <xref href="GUID-3B63FFD6-AE21-366A-B435-AE6213AA2EE0.dita"><apiname>KMMCAdjustableOpVoltage</apiname></xref> to
       
   323 set bit 31 in <xref href="GUID-E3BB783F-423F-352A-9B6E-FD23EC80AA8D.dita#GUID-E3BB783F-423F-352A-9B6E-FD23EC80AA8D/GUID-6B1E1CDD-A0E7-3AA5-989E-8D7A199ADE2A"><apiname>TPBusPsuInfo::iVoltageSupported</apiname></xref>. </p> </li>
       
   324 <li id="GUID-694DB272-C66E-5392-8C7E-DC1B875E9DD3"><p>Set <xref href="GUID-E3BB783F-423F-352A-9B6E-FD23EC80AA8D.dita#GUID-E3BB783F-423F-352A-9B6E-FD23EC80AA8D/GUID-8C9792BC-8FAA-3DE5-8032-7546887FA8FB"><apiname>TPBusPsuInfo::iNotLockedTimeOut</apiname></xref> to
       
   325 0. </p> </li>
       
   326 </ul> <p id="GUID-5809318D-E3E1-5261-AABA-604EBE72523F"><b> DoSetState()</b> </p> <p> <xref href="GUID-FBCEFDB6-28FF-3201-8E13-F12E3759E36B.dita#GUID-FBCEFDB6-28FF-3201-8E13-F12E3759E36B/GUID-4DF0741F-B143-3B46-82BE-9CD0261C27E5"><apiname>DMMCPsu::DoSetState()</apiname></xref>  </p> <p>The
       
   327 function is called to turn the PSU on or off. </p> <p>The requested state
       
   328 of the PSU depends on the <xref href="GUID-CD00D507-CC86-33BE-91A7-FAF7EAFD4840.dita"><apiname>TPBusPsuState</apiname></xref> value passed to
       
   329 it. </p> <p>If the PSU supports voltage adjustment, rather than a single fixed
       
   330 value, then the required voltage setting is contained in the protected data
       
   331 member <xref href="GUID-FBCEFDB6-28FF-3201-8E13-F12E3759E36B.dita#GUID-FBCEFDB6-28FF-3201-8E13-F12E3759E36B/GUID-7A625108-D5AE-301F-9CAB-2625DAD0C0B0"><apiname>DMMCPsu::iVoltageSetting</apiname></xref>. </p> <p>Note that the
       
   332 stack may call this function to request the power to be turned on when it
       
   333 is already on. You should check for this and do nothing if the power is already
       
   334 in the requested state. </p> <p id="GUID-B5030D2E-A466-596C-A2C3-73F38CF9C1A7"><b>DoCheckVoltage()</b> </p> <p> <xref href="GUID-FBCEFDB6-28FF-3201-8E13-F12E3759E36B.dita#GUID-FBCEFDB6-28FF-3201-8E13-F12E3759E36B/GUID-17AC2A1C-5430-38B1-BD3F-966CE4936940"><apiname>DMMCPsu::DoCheckVoltage()</apiname></xref>  </p> <p>The
       
   335 function is called to check that the voltage level of the PSU is as expected. </p> <p>Checking
       
   336 the voltage level may be a long running operation (e.g. using an ADC), and
       
   337 it may not always be appropriate to perform and complete the check directly
       
   338 within this function. </p> <p>When voltage checking is complete, either synchronously
       
   339 in this function, or asynchronously at some later stage, the result should
       
   340 be returned by calling the base class function <xref href="GUID-A8B5FB5A-4709-3F29-B2CB-81FC5B0E7D63.dita#GUID-A8B5FB5A-4709-3F29-B2CB-81FC5B0E7D63/GUID-5643935F-9E97-35B0-9D92-88CA613F0016"><apiname>DPBusPsuBase::ReceiveVoltageCheckResult()</apiname></xref>.
       
   341 Pass <xref href="GUID-6CA4F1ED-7947-3087-B618-D35858FAA3BC.dita"><apiname>KErrNone</apiname></xref> to indicate a successful check; pass <xref href="GUID-A94AC24A-EADF-3913-8345-708ED637968E.dita"><apiname>KErrGeneral</apiname></xref> to
       
   342 indicate a failed check. </p> <p>Note that this function is not called as
       
   343 part of <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-791BCA03-61F3-3C1C-BA2D-D633A94AF299"><apiname>DMMCStack::DoPowerUpSM()</apiname></xref> processing, which means
       
   344 that it is not possible to use this function to introduce a delay until power
       
   345 is stable when the PSU is turned on. If such a delay is required while the
       
   346 power lines stabilize, then it will be necessary to make this function part
       
   347 of the DoPowerUpSM state machine. </p> </section>
       
   348 <section id="GUID-C80E57B1-933B-55D7-949B-E68DB9B96B94"><title>DMMCMediaChange
       
   349 derived class</title> <p>This class provides support for dealing with media
       
   350 change events, i.e. the insertion and removal of removable media. </p> <p>A
       
   351 class needs to be derived from this in the platform specific layer to handle
       
   352 the Variant specific functionality. </p> <p>This class has a number of pure
       
   353 virtual functions that need to be implemented in your Variant DLL. The diagram
       
   354 at <xref href="GUID-BE6AFD38-5952-537F-848C-C76C8F5FA9BF.dita#GUID-BE6AFD38-5952-537F-848C-C76C8F5FA9BF/GUID-92F5EBE4-C9AD-5D9A-A80E-9AFD1A09B6B3">MultiMediaCard
       
   355 controller basic structure</xref> shows the class in context. </p> <p>There
       
   356 is one virtual function with an empty default implementation that needs to
       
   357 be overridden. </p> <ul>
       
   358 <li id="GUID-1BAEFE73-3B73-5BA7-872D-89C3B3F8BF75"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-BFC23CC1-102F-5740-A608-CF91C2BC3897">Create()</xref> </p> </li>
       
   359 <li id="GUID-C1235A87-68BB-5AF4-80F6-DFB7DBA8432C"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-726A2A5F-18D3-55BD-9B92-0676266794C6">MediaState()</xref>  </p> </li>
       
   360 <li id="GUID-BBAEC56C-DBA7-586C-A9CC-1E4E70A81096"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-1ADD0F5A-B561-54AE-BB2F-81AC3E8D81A4">DoDoorOpen()</xref>  </p> </li>
       
   361 <li id="GUID-22D6992C-868B-5E18-9AA0-624EA51DB529"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-58829228-43A9-546B-8CFD-31DF8FBB0078">DoDoorClosed()</xref>  </p> </li>
       
   362 <li id="GUID-04B7E650-7DA8-5F61-9D8E-89FC2B93AE20"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-F91B9434-5B90-5221-B5E6-D57F50391D81">ForceMediaChange()</xref>  </p> </li>
       
   363 </ul> <p id="GUID-BFC23CC1-102F-5740-A608-CF91C2BC3897"><b>Create()</b> </p> <p> <xref href="GUID-2F974AD8-551B-35F0-B72C-99122913714D.dita#GUID-2F974AD8-551B-35F0-B72C-99122913714D/GUID-F96EF34B-7B38-37DC-9B34-E0D4D1963622"><apiname>DMMCMediaChange::Create()</apiname></xref>  </p> <p>The
       
   364 function is intended to perform hardware initialization on the MultiMediaCard
       
   365 media change hardware, for example, setting port direction registers, binding
       
   366 to the door open interrupt etc. </p> <p>The function is called after creation
       
   367 of the <xref href="GUID-2F974AD8-551B-35F0-B72C-99122913714D.dita"><apiname>DMMCMediaChange</apiname></xref> derived class instance, which is
       
   368 done during kernel initialization when the MultiMediaCard controller Variant
       
   369 DLL extension is loaded. </p> <p>The function has a default implementation
       
   370 that just returns <xref href="GUID-6CA4F1ED-7947-3087-B618-D35858FAA3BC.dita"><apiname>KErrNone</apiname></xref>. </p> <p>Your implementation
       
   371 should return <xref href="GUID-6CA4F1ED-7947-3087-B618-D35858FAA3BC.dita"><apiname>KErrNone</apiname></xref> if the hardware initialization is
       
   372 successful, otherwise it should return one of the system-wide error codes
       
   373 to indicate initialization failure. Note that returning a value other than <xref href="GUID-6CA4F1ED-7947-3087-B618-D35858FAA3BC.dita"><apiname>KErrNone</apiname></xref> will
       
   374 cause the kernel to panic and to fail to boot. </p> <p id="GUID-726A2A5F-18D3-55BD-9B92-0676266794C6"><b> MediaState()</b> </p> <p> <xref href="GUID-2F974AD8-551B-35F0-B72C-99122913714D.dita#GUID-2F974AD8-551B-35F0-B72C-99122913714D/GUID-A951EF31-83F1-3E07-A5BD-5342B6125ACF"><apiname>DMMCMediaChange::MediaState()</apiname></xref>  </p> <p>The
       
   375 function should return the current state of the media, i.e. whether the media
       
   376 door is open or closed. To indicate the state, it should return one of the <xref href="GUID-49F96729-2DDB-37E0-AE39-9BEF2B7FF7F9.dita"><apiname>TMediaState</apiname></xref> enum
       
   377 values. </p> <p id="GUID-1ADD0F5A-B561-54AE-BB2F-81AC3E8D81A4"><b>DoDoorOpen()</b> </p> <p> <xref href="GUID-2F974AD8-551B-35F0-B72C-99122913714D.dita#GUID-2F974AD8-551B-35F0-B72C-99122913714D/GUID-6F734353-3458-3A8B-93E7-317674A1CAA4"><apiname>DMMCMediaChange::DoDoorOpen()</apiname></xref>  </p> <p>This
       
   378 function should handle a media door open event. What needs to be done depends
       
   379 on how door open and door closed events are detected. </p> <p>The most common
       
   380 pattern is where the platform hardware is capable of generating an interrupt
       
   381 when a door open event occurs, but cannot generate an interrupt when a door
       
   382 closed event occurs. In this situation, the hardware provides a readable door
       
   383 status that can be checked for the door closed state on a periodic basis (i.e.
       
   384 polling). </p> <p>Assuming this, <codeph>DoDoorOpen()</codeph> would need
       
   385 to enable a tick timer to poll for the door closing. The timer callback function
       
   386 would check the state of the door, and if this showed a closed door, the timer
       
   387 would be disabled and the function <xref href="GUID-C122D579-BB08-3084-A30E-DC857D6E7282.dita#GUID-C122D579-BB08-3084-A30E-DC857D6E7282/GUID-4F53C9F7-89C5-3CB6-A3D5-7DF40DAFF37F"><apiname>DMediaChangeBase::DoorClosedService()</apiname></xref> called.
       
   388 This results in a call to <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-58829228-43A9-546B-8CFD-31DF8FBB0078">DoDoorClosed()</xref>. </p> <p>Note that the door open interrupt is cleared before this function is
       
   389 called. The interrupt results in a call to <xref href="GUID-C122D579-BB08-3084-A30E-DC857D6E7282.dita#GUID-C122D579-BB08-3084-A30E-DC857D6E7282/GUID-6197984B-3884-367B-AE91-8E7E25203C95"><apiname>DMediaChangeBase::DoorOpenService()</apiname></xref>,
       
   390 which in turn results in a call to this function <codeph>DoDoorOpen()</codeph>. </p> <p>Your
       
   391 implementation would necessarily be different if an open door event could
       
   392 not be signalled by an interrupt and a tick timer were to be used to poll
       
   393 for an open door status. </p> <p id="GUID-58829228-43A9-546B-8CFD-31DF8FBB0078"><b>DoDoorClosed()</b> </p> <p> <xref href="GUID-2F974AD8-551B-35F0-B72C-99122913714D.dita#GUID-2F974AD8-551B-35F0-B72C-99122913714D/GUID-F26714BC-6648-349D-812D-6FD911602754"><apiname>DMMCMediaChange::DoDoorClosed()</apiname></xref>  </p> <p>This
       
   394 function should handle a media door closed event. What needs to be done depends
       
   395 on how door open and door closed events are detected. </p> <p>The most common
       
   396 pattern is where the platform hardware is capable of generating an interrupt
       
   397 when a door open event occurs, but cannot generate an interrupt when a door
       
   398 closed event occurs. In this situation, the hardware provides a readable door
       
   399 status that can be checked for the door closed state on a periodic basis (i.e.
       
   400 polling). </p> <p>Assuming this, <codeph>DoDoorClosed()</codeph> would be
       
   401 called by the timer callback function established by <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-1ADD0F5A-B561-54AE-BB2F-81AC3E8D81A4">DoDoorOpen()</xref> when the door status indicates a closed door; the function
       
   402 would need to re-enable the door open interrupt. </p> <p>Your implementation
       
   403 would necessarily be different if a closed door event were to be signalled
       
   404 by an interrupt. </p> <p id="GUID-F91B9434-5B90-5221-B5E6-D57F50391D81"><b> ForceMediaChange()</b> </p> <p> <xref href="GUID-2F974AD8-551B-35F0-B72C-99122913714D.dita#GUID-2F974AD8-551B-35F0-B72C-99122913714D/GUID-2DB81D37-C930-3B3C-A64E-B734039A2C95"><apiname>DMMCMediaChange::ForceMediaChange()</apiname></xref>  </p> <p>This function is called by the local media device driver to force a remount
       
   405 of the media device. For example to reopen a media driver in secure mode. </p> <p>It
       
   406 should result in the same sequence of operations as would occur if a door
       
   407 open event had taken place; for example, disabling the door open interrupt
       
   408 and calling <xref href="GUID-C122D579-BB08-3084-A30E-DC857D6E7282.dita#GUID-C122D579-BB08-3084-A30E-DC857D6E7282/GUID-6197984B-3884-367B-AE91-8E7E25203C95"><apiname>DMediaChangeBase::DoorOpenService()</apiname></xref>. </p> </section>
       
   409 <section id="GUID-7E709B21-8D38-5041-846F-CB7983B66834"><title>TMMCardControllerInterface
       
   410 derived class (The factory class)</title> <p>This is a class, also known as <xref href="GUID-BE6AFD38-5952-537F-848C-C76C8F5FA9BF.dita#GUID-BE6AFD38-5952-537F-848C-C76C8F5FA9BF/GUID-26CFDD03-A4C4-5C96-88D4-5E750FDF69A3">the
       
   411 controller factory</xref> that is responsible for deciding which peripheral
       
   412 bus sockets are sockets that have been designated as a MultiMediaCard sockets
       
   413 on this platform. It is also responsible for creating the platform-specific
       
   414 layer objects associated with those MultiMediaCard sockets, i.e. the DMMCSocket,
       
   415 DMMCStack, DMMCMediaChange, and DMMCPsu objects. </p> <p>This class defines
       
   416 a number of pure virtual functions that need to be implemented in your Variant
       
   417 DLL to provide the functionality that is specific to your platform. </p> <p>An
       
   418 instance of your <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita"><apiname>TMMCardControllerInterface</apiname></xref> derived class
       
   419 is created in the <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-732EDE1D-452A-5A48-B5DB-1196C5F8BEBD">Variant
       
   420 DLL entry point code</xref>. </p> <ul>
       
   421 <li id="GUID-61BF196A-EFD3-57E1-98C2-A5B6350AC82E"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-2477BA25-2ADD-55CB-93F2-84F114221EBA">IsMMCSocket()</xref> </p> </li>
       
   422 <li id="GUID-0FED2860-6710-517D-BB60-7FCBD043CEFB"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-829E686F-58F9-56A9-9EC4-CD59B14E127B">NewSocket()</xref> </p> </li>
       
   423 <li id="GUID-3213A9CF-3155-513D-9F29-AB573018F23B"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-E0F612EB-85BC-533D-A71C-3FC93D9CC708">NewStack()</xref>  </p> </li>
       
   424 <li id="GUID-9C8219D2-67EF-55B0-B01E-ACB2B0AC63CB"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-33A9C3DE-80EF-5895-BC7D-EA2ED6EB083B">MediaChangeID()</xref>  </p> </li>
       
   425 <li id="GUID-B8309E5D-7F8A-5B62-81B3-6679AFBC9319"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-6B1FE81F-1497-5447-9286-B0BE54AE6831">NewMediaChange()</xref> </p> </li>
       
   426 <li id="GUID-62725219-BAD2-528E-BC6A-84ACBA0A5C87"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-E969F613-01A3-54A7-8CC6-67F4A8E9558F">VccID()</xref>  </p> </li>
       
   427 <li id="GUID-67AE2495-BCF2-51B6-9F52-78FA36A65F2A"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-083F38DB-AC65-5257-B169-2099194D3082">NewVcc()</xref>  </p> </li>
       
   428 <li id="GUID-428FA30E-1E9A-50EA-BE3F-02E9B279E868"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-81A8BF8E-FB8B-596D-8C9A-690CD6449C12">Init()</xref>  </p> </li>
       
   429 </ul> <p id="GUID-2477BA25-2ADD-55CB-93F2-84F114221EBA"><b>IsMMCSocket()</b> </p> <p> <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita#GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A/GUID-5EC9F2EE-5D14-37F9-9EFE-95BD1062C681"><apiname>TMMCardControllerInterface::IsMMCSocket()</apiname></xref>  </p> <p>Implement this function to indicate whether the peripheral bus socket, as
       
   430 identified by the specified peripheral bus socket number, is designated as
       
   431 a MultiMediaCard socket on this platform. It should return <xref href="GUID-781E8158-805B-3784-8FED-D7A191822FC3.dita"><apiname>ETrue</apiname></xref> if
       
   432 the socket has been so designated, and return <xref href="GUID-A759CA2D-8327-348F-9337-4886E619D920.dita"><apiname>EFalse</apiname></xref> if
       
   433 not. </p> <p>The function is called from <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita#GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A/GUID-2C6EA849-1B62-3158-A328-DB2A7149346C"><apiname>TMMCardControllerInterface::Create()</apiname></xref>,
       
   434 which passes a socket number that can fall into the range 0 to <xref href="GUID-2C5A5F8F-381C-3B99-AADE-44474E629CC4.dita"><apiname>KMaxPBusSockets</apiname></xref>. </p> <p>Internally,
       
   435 Symbian platform reserves space for an array of pointers to <xref href="GUID-C988CAE6-9073-3851-A0B0-5479D1A34CFB.dita"><apiname>DPBusSocket</apiname></xref> objects,
       
   436 and this function allows the platform specific layer to identify which slot
       
   437 is to be used for the <xref href="GUID-45B97680-1756-3559-8A2D-2F2E851AD6A7.dita"><apiname>DMMCSocket</apiname></xref> object. </p> <codeblock id="GUID-F1E0478A-8CE8-5E2F-87F8-AAFCCCE8A042" xml:space="preserve">GLDEF_D DPBusSocket* TheSockets[KMaxPBusSockets];</codeblock> <p>(This
       
   438 array is internal to Symbian platform.) </p> <p>If, on this platform, a socket
       
   439 has been designated as a MultiMediaCard stack, then the function not only
       
   440 returns <xref href="GUID-781E8158-805B-3784-8FED-D7A191822FC3.dita"><apiname>ETrue</apiname></xref>, but also provides the media information
       
   441 for that socket, by filling in the members of the <xref href="GUID-FC0F974E-9ABB-348B-9AE9-778B3A1F413A.dita"><apiname>SMediaDeviceInfo</apiname></xref> object
       
   442 passed in. </p> <p id="GUID-829E686F-58F9-56A9-9EC4-CD59B14E127B"><b>NewSocket()</b> </p> <p> <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita#GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A/GUID-90615A9A-BFC2-3E1B-B2AC-7D1CF322FC65"><apiname>TMMCardControllerInterface::NewSocket()</apiname></xref>  </p> <p>Implement
       
   443 this function to create, and return a pointer to, an instance of the <xref href="GUID-45B97680-1756-3559-8A2D-2F2E851AD6A7.dita"><apiname>DMMCSocket</apiname></xref> class.
       
   444 This can be a class derived from <codeph>DMMCSocket</codeph>, but this should
       
   445 rarely be necessary. </p> <p>The function is called from <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita#GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A/GUID-2C6EA849-1B62-3158-A328-DB2A7149346C"><apiname>TMMCardControllerInterface::Create()</apiname></xref>. </p> <p>If
       
   446 you create a <xref href="GUID-45B97680-1756-3559-8A2D-2F2E851AD6A7.dita"><apiname>DMMCSocket</apiname></xref> object, simply forward the peripheral
       
   447 bus socket number and pointer to the password store; there is no need to do
       
   448 anything with them. </p> <p>If you create an instance of a <xref href="GUID-45B97680-1756-3559-8A2D-2F2E851AD6A7.dita"><apiname>DMMCSocket</apiname></xref> derived
       
   449 class, then just pass the socket number and pointer to the <codeph>DMMCSocket</codeph> constructor
       
   450 in your constructor's ctor list. </p> <p>Note: </p> <ul>
       
   451 <li id="GUID-FA8D57D9-0827-5090-A12B-A47C936B6F70"><p>The socket number can
       
   452 fall into the range 0 to <xref href="GUID-2C5A5F8F-381C-3B99-AADE-44474E629CC4.dita"><apiname>KMaxPBusSockets</apiname></xref>, and is a value
       
   453 for which <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-2477BA25-2ADD-55CB-93F2-84F114221EBA">IsMMCSocket()</xref> returned <xref href="GUID-781E8158-805B-3784-8FED-D7A191822FC3.dita"><apiname>ETrue</apiname></xref>. </p> </li>
       
   454 <li id="GUID-3C4FCA1F-558D-5964-91F5-98588694DA70"><p>This function is only
       
   455 called for sockets that are associated with MultiMediaCard devices as reported
       
   456 by the function <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-2477BA25-2ADD-55CB-93F2-84F114221EBA">IsMMCSocket()</xref>. </p> </li>
       
   457 </ul> <p id="GUID-E0F612EB-85BC-533D-A71C-3FC93D9CC708"><b>NewStack()</b> </p> <p> <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita#GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A/GUID-E2F99378-DD63-3BE0-8550-66EBF2C5D087"><apiname>TMMCardControllerInterface::NewStack()</apiname></xref>  </p> <p>Implement
       
   458 this function to create, and return a pointer to, an instance of a <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-4C6CA873-A798-5C79-8838-0CC3C9E914FB">DMMCStack derived class</xref>. </p> <p>The function is called from <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita#GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A/GUID-2C6EA849-1B62-3158-A328-DB2A7149346C"><apiname>TMMCardControllerInterface::Create()</apiname></xref>. </p> <p>The
       
   459 peripheral bus socket number and pointer to the socket object should be forwarded
       
   460 to the <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita"><apiname>DMMCStack</apiname></xref> constructor in your class constructor's
       
   461 ctor list. </p> <p>Note: </p> <ul>
       
   462 <li id="GUID-CE363D03-6FEA-5AFE-A085-98D0FBAA9D52"><p>The socket number can
       
   463 fall into the range 0 to <xref href="GUID-2C5A5F8F-381C-3B99-AADE-44474E629CC4.dita"><apiname>KMaxPBusSockets</apiname></xref>, and is a value
       
   464 for which <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-2477BA25-2ADD-55CB-93F2-84F114221EBA">IsMMCSocket()</xref> returned <xref href="GUID-781E8158-805B-3784-8FED-D7A191822FC3.dita"><apiname>ETrue</apiname></xref>. </p> </li>
       
   465 <li id="GUID-7F8F2267-E8C3-5AC5-92AB-7D3179BA6D10"><p>The socket is the object
       
   466 created by <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-829E686F-58F9-56A9-9EC4-CD59B14E127B">NewSocket()</xref>. </p> </li>
       
   467 <li id="GUID-DF7C2369-D225-54E4-B6F1-D444343E7084"><p>This function is only
       
   468 called for sockets that are associated with MultiMediaCard devices as reported
       
   469 by the function <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-2477BA25-2ADD-55CB-93F2-84F114221EBA">IsMMCSocket()</xref>. </p> </li>
       
   470 </ul> <p id="GUID-33A9C3DE-80EF-5895-BC7D-EA2ED6EB083B"><b>MediaChangeID()</b> </p> <p> <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita#GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A/GUID-10B49F15-8ED5-3CA9-873A-788B87078367"><apiname>TMMCardControllerInterface::MediaChangeID()</apiname></xref>  </p> <p>Implement this function to report which media change object is to be
       
   471 associated with the specified peripheral bus socket number. </p> <p>The function
       
   472 is called from <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita#GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A/GUID-2C6EA849-1B62-3158-A328-DB2A7149346C"><apiname>TMMCardControllerInterface::Create()</apiname></xref>. </p> <p>The
       
   473 media change object is represented by a number, which is simply an index value
       
   474 that ranges from 0 to <xref href="GUID-92555AA1-73A5-3F88-8227-8D20C977F046.dita"><apiname>KMaxMediaChanges</apiname></xref>. Internally, Symbian
       
   475 platform reserves space for an array of pointers to <xref href="GUID-C122D579-BB08-3084-A30E-DC857D6E7282.dita"><apiname>DMediaChangeBase</apiname></xref> objects,
       
   476 and this function allows the platform specific layer to identify which slot
       
   477 is to be used for the <xref href="GUID-2F974AD8-551B-35F0-B72C-99122913714D.dita"><apiname>DMMCMediaChange</apiname></xref> object that will
       
   478 correspond to the specified socket number. </p> <codeblock id="GUID-08AE1956-86E0-544A-A95C-0D16DE6694D3" xml:space="preserve">GLDEF_D DMediaChangeBase* TheMediaChanges[KMaxMediaChanges];</codeblock> <p>(This array is internal to Symbian platform.) </p> <p>Note: </p> <ul>
       
   479 <li id="GUID-1A4ED330-90E5-5215-8149-093987DD5D9B"><p>The socket number can
       
   480 fall into the range 0 to <xref href="GUID-2C5A5F8F-381C-3B99-AADE-44474E629CC4.dita"><apiname>KMaxPBusSockets</apiname></xref>, and is a value
       
   481 for which <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-2477BA25-2ADD-55CB-93F2-84F114221EBA">IsMMCSocket()</xref> returned <xref href="GUID-781E8158-805B-3784-8FED-D7A191822FC3.dita"><apiname>ETrue</apiname></xref>. </p> </li>
       
   482 <li id="GUID-5EA3662D-82B2-529B-8DF4-2EAA9429990A"><p>This function is only
       
   483 called for sockets that are associated with MultiMediaCard devices as reported
       
   484 by the function <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-2477BA25-2ADD-55CB-93F2-84F114221EBA">IsMMCSocket()</xref>. </p> </li>
       
   485 </ul> <p id="GUID-6B1FE81F-1497-5447-9286-B0BE54AE6831"><b>NewMediaChange()</b> </p> <p> <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita#GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A/GUID-2961273F-0D5A-3B9E-94D8-1FE216A57985"><apiname>TMMCardControllerInterface::NewMediaChange()</apiname></xref>  </p> <p>Implement this function to create, and return a pointer to, an instance
       
   486 of a <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-C80E57B1-933B-55D7-949B-E68DB9B96B94">DMMCMediaChange
       
   487 derived class</xref>. </p> <p>The function is called from <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita#GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A/GUID-2C6EA849-1B62-3158-A328-DB2A7149346C"><apiname>TMMCardControllerInterface::Create()</apiname></xref>. </p> <p>The
       
   488 media change number should be forwarded to the <xref href="GUID-2F974AD8-551B-35F0-B72C-99122913714D.dita"><apiname>DMMCMediaChange</apiname></xref> constructor
       
   489 in your class constructor's ctor list. </p> <p>Note: </p> <ul>
       
   490 <li id="GUID-69B6384E-1B3C-567B-89AD-E0BE42E1F043"><p>The media change number
       
   491 can fall into the range 0 to <xref href="GUID-92555AA1-73A5-3F88-8227-8D20C977F046.dita"><apiname>KMaxMediaChanges</apiname></xref>, and is the
       
   492 value returned by <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-33A9C3DE-80EF-5895-BC7D-EA2ED6EB083B">MediaChangeID()</xref>. </p> </li>
       
   493 <li id="GUID-FD2DA86D-5D0E-5661-AC09-55F10087D7A2"><p>This function is only
       
   494 called for sockets that are associated with MultiMediaCard devices as reported
       
   495 by the function <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-2477BA25-2ADD-55CB-93F2-84F114221EBA">IsMMCSocket()</xref>. </p> </li>
       
   496 </ul> <p id="GUID-E969F613-01A3-54A7-8CC6-67F4A8E9558F"><b>VccID()</b> </p> <p> <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita#GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A/GUID-1553B339-4171-396B-89E6-6C47C539D21F"><apiname>TMMCardControllerInterface::VccID()</apiname></xref>  </p> <p>Implement
       
   497 this function to report which power supply unit (PSU) object is to be associated
       
   498 with the specified peripheral bus socket number. </p> <p>The function is called
       
   499 from <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita#GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A/GUID-2C6EA849-1B62-3158-A328-DB2A7149346C"><apiname>TMMCardControllerInterface::Create()</apiname></xref>. </p> <p>The
       
   500 PSU object is represented by a number, which is simply an index value that
       
   501 ranges from 0 to <xref href="GUID-E5DEB888-EC0E-3160-BA7D-76954B282D43.dita"><apiname>KMaxPBusVccs</apiname></xref>. Internally, Symbian platform
       
   502 reserves space for an array of pointers to <xref href="GUID-A8B5FB5A-4709-3F29-B2CB-81FC5B0E7D63.dita"><apiname>DPBusPsuBase</apiname></xref> objects,
       
   503 and this function allows the platform specific layer to identify which slot
       
   504 is to be used for the <xref href="GUID-FBCEFDB6-28FF-3201-8E13-F12E3759E36B.dita"><apiname>DMMCPsu</apiname></xref> object that will correspond
       
   505 to the specified socket number. </p> <codeblock id="GUID-99CD9798-2CFB-533D-82E0-352B84FA5AC9" xml:space="preserve">GLDEF_D DPBusPsuBase* TheVccs[KMaxPBusVccs];
       
   506 </codeblock> <p>(This array is internal to Symbian platform.) </p> <p>Note: </p> <ul>
       
   507 <li id="GUID-2C77F138-1444-5815-AB12-16D3ED6D908E"><p>The socket number can
       
   508 fall into the range 0 to <xref href="GUID-2C5A5F8F-381C-3B99-AADE-44474E629CC4.dita"><apiname>KMaxPBusSockets</apiname></xref>, and is a value
       
   509 for which <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-2477BA25-2ADD-55CB-93F2-84F114221EBA">IsMMCSocket()</xref> returned <xref href="GUID-781E8158-805B-3784-8FED-D7A191822FC3.dita"><apiname>ETrue</apiname></xref>. </p> </li>
       
   510 <li id="GUID-F8F4E84D-C46D-5547-AD19-61FB30E2CC3F"><p>This function is only
       
   511 called for sockets that are associated with MultiMediaCard devices as reported
       
   512 by the function <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-2477BA25-2ADD-55CB-93F2-84F114221EBA">IsMMCSocket()</xref>. </p> </li>
       
   513 </ul> <p id="GUID-083F38DB-AC65-5257-B169-2099194D3082"><b>NewVcc()</b> </p> <p> <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita#GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A/GUID-600A5477-E99A-39BC-9982-D54C07A528BE"><apiname>TMMCardControllerInterface::NewVcc()</apiname></xref>  </p> <p>The
       
   514 function should create, and return a pointer to, an instance of a <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-3A1E907E-A74D-59CB-A1D6-FEF4849EF2D5">DMMCPsu derived class</xref>. </p> <p>The function is called from <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita#GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A/GUID-2C6EA849-1B62-3158-A328-DB2A7149346C"><apiname>TMMCardControllerInterface::Create()</apiname></xref>. </p> <p>The
       
   515 Power Supply Unit (PSU) number and the media change number should be forwarded
       
   516 to the <xref href="GUID-FBCEFDB6-28FF-3201-8E13-F12E3759E36B.dita"><apiname>DMMCPsu</apiname></xref> constructor in your class constructor's
       
   517 ctor list. </p> <p>Note: </p> <ul>
       
   518 <li id="GUID-833A0119-6A98-5F5F-BAEE-5070C7C23A55"><p>The PSU number can fall
       
   519 into the range 0 to <xref href="GUID-E5DEB888-EC0E-3160-BA7D-76954B282D43.dita"><apiname>KMaxPBusVccs</apiname></xref>, and is the value returned
       
   520 by <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-E969F613-01A3-54A7-8CC6-67F4A8E9558F">VccID()</xref>. </p> </li>
       
   521 <li id="GUID-25D7430A-2C12-50CF-BF84-FD2309732FC8"><p>The media change number
       
   522 can fall into the range 0 to <xref href="GUID-92555AA1-73A5-3F88-8227-8D20C977F046.dita"><apiname>KMaxMediaChanges</apiname></xref>, and is the
       
   523 value returned by <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-33A9C3DE-80EF-5895-BC7D-EA2ED6EB083B">MediaChangeID()</xref>. </p> </li>
       
   524 <li id="GUID-A8908747-E292-5D01-91E2-045DE2F341B2"><p>This function is only
       
   525 called for sockets that are associated with MultiMediaCard devices as reported
       
   526 by the function <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-2477BA25-2ADD-55CB-93F2-84F114221EBA">IsMMCSocket()</xref>. </p> </li>
       
   527 </ul> <p id="GUID-81A8BF8E-FB8B-596D-8C9A-690CD6449C12"><b>Init()</b> </p> <p> <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita#GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A/GUID-1F0C99EC-D8A9-304A-A738-BACAB5C766A6"><apiname>TMMCardControllerInterface::Init()</apiname></xref>  </p> <p>Implement
       
   528 this function to perform any initialization that the platform specific layer
       
   529 needs to do. </p> <p>It should return <xref href="GUID-6CA4F1ED-7947-3087-B618-D35858FAA3BC.dita"><apiname>KErrNone</apiname></xref> to indicate
       
   530 successful completion, or return one of the other system-wide error codes
       
   531 to indicate initialization failure. </p> <p>Note that you should <i>not</i> do
       
   532 any initialization that is specifically associated with: </p> <ul>
       
   533 <li id="GUID-9D706630-C477-5163-B0B2-5745D5D04559"><p>the stack - use <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-0B55A650-E9ED-56CB-B06F-B1113ACDF282">DMMCStack::Init()</xref> for
       
   534 this. </p> </li>
       
   535 <li id="GUID-99B883A6-FE47-5B7F-A9D1-01CCD7954DCD"><p>the power supply unit
       
   536 - use <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-6EB8EF1C-BCCB-54A1-8CBA-4E8A2A20CABE">DMMCPsu::DoCreate()</xref> for
       
   537 this. </p> </li>
       
   538 <li id="GUID-C7EAE4E6-DEE4-515A-83B1-E40EE8D37F32"><p>dealing with media change
       
   539 events - use <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-BFC23CC1-102F-5740-A608-CF91C2BC3897">DMMCMediaChange::Create()</xref> for
       
   540 this. </p> </li>
       
   541 </ul> </section>
       
   542 <section id="GUID-732EDE1D-452A-5A48-B5DB-1196C5F8BEBD"><title> Variant DLL
       
   543 entry point code</title> <p>The platform-specific layer as implemented in
       
   544 the Variant DLL is a standard kernel extension. The entry point for all standard
       
   545 kernel extensions is declared by a </p> <codeblock id="GUID-8835A131-2CDC-51AC-9C59-D72BAD651EA6" xml:space="preserve">DECLARE_STANDARD_EXTENSION()</codeblock> <p>statement,
       
   546 followed by the block of code that runs on entry to the DLL. </p> <p>Initialization
       
   547 of the MultiMediaCard DLL is done at this point, and follows the pattern shown
       
   548 below. It needs to create an instance of your <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita"><apiname>TMMCardControllerInterface</apiname></xref> derived
       
   549 class, followed by a call to <codeph>Create()</codeph> on this object. This
       
   550 starts a cascade of effects resulting in calls to your implementation of the <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita"><apiname>TMMCardControllerInterface</apiname></xref> functions,
       
   551 which in turn result in the creation of the platform-specific layer objects
       
   552 associated with the MultiMediaCard sockets, i.e. the DMMCSocket, DMMCStack,
       
   553 DMMCMediaChange, and DMMCPsu objects. </p> <codeblock id="GUID-16F754D1-6161-5E05-8BEA-2A89CC80CC41" xml:space="preserve">DECLARE_STANDARD_EXTENSION()
       
   554 //
       
   555 // Extension Entry Point
       
   556 //
       
   557     {
       
   558     __KTRACE_OPT(KPBUS1,Kern::Printf("Starting MMC interface"));
       
   559 
       
   560     TInt r=KErrNoMemory;
       
   561     TVARMMCardControllerInterface* pI=new TVARMMCardControllerInterface;
       
   562     if (pI)
       
   563         {
       
   564         r=pI-&gt;Create();
       
   565         }
       
   566 
       
   567     __KTRACE_OPT(KPBUS1,Kern::Printf("MMC: Returns %d",r));
       
   568     return r;
       
   569     }
       
   570 </codeblock> <p>In this example, <codeph>TVARMMCardControllerInterface</codeph> is
       
   571 your class derived from <xref href="GUID-B1F2C60B-E098-395F-8ED0-FF33E3EC9E4A.dita"><apiname>TMMCardControllerInterface</apiname></xref>  </p> </section>
       
   572 <section id="GUID-00F918D3-761B-5500-805F-AB4DEE72144E"><title>Direct memory
       
   573 addressing</title> <p>To transfer data between a user side process and the
       
   574 media device, the Platform Specific Layer allocates a DMA-safe buffer at initialization.
       
   575 This buffer is allocated from physical memory. The memory in the user side
       
   576 process is virtual and you perform an inter-process copy of data between the
       
   577 user side process and the buffer allocated by the Platform Specific Layer. </p> <p>Data
       
   578 transfer is faster if the MultiMediaCard controller knows that an address
       
   579 passed in an I/O request is a physical address. The File caching and Demand
       
   580 Paging features in the file server and kernel can pass physical addresses.
       
   581 A physical address avoids the need for an inter-process copy operation. </p> <p>If
       
   582 you use a mechanism like <xref href="GUID-DF2F0439-AE1A-599C-91B9-6EF2177C3C7E.dita">DMA</xref> to
       
   583 transfer data, and your platform specific layer can deal with physical addresses,
       
   584 you need to make changes to the platform specific layer listed below. </p> <ul>
       
   585 <li id="GUID-04D498F3-F4BB-5A15-BE31-8DF6F11DB9BD"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-E50081BC-C923-5DAF-950C-9E1411916FED">Implement double buffers</xref>  </p> </li>
       
   586 <li id="GUID-39F10C4A-4291-579E-878B-E5BD2FB9C9D0"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-575211BC-BF66-5817-9825-EE402648D0CD">Register support for physical addresses</xref>  </p> </li>
       
   587 <li id="GUID-5638CD98-469C-587C-87B2-CA470D76F474"><p> <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-27FCEF7D-0AAB-599C-8405-4BD284308314">Modify the data transfer phase to handle physical memory</xref>  </p> </li>
       
   588 </ul> <p id="GUID-E50081BC-C923-5DAF-950C-9E1411916FED"><b>Implement double buffers</b> </p> <p>If
       
   589 you enable double buffer behavior, the MultiMediaCard subsystem can perform
       
   590 multiple data transfers in a single bus transaction. The double buffer implementation
       
   591 performs many data transfers in a single bus transaction. The MultiMediaCard
       
   592 subsystem logically splits the buffer allocated by the platform specific layer
       
   593 into two segments. Data transfer to the media device is in progress from one
       
   594 segment - this is the active segment. Concurrently, the media driver can prepare
       
   595 data in the other segment. </p> <p>To implement double buffers, you need to
       
   596 make changes to the platform specific layer. </p> <p><b>Use the command descriptor functions </b> </p> <ul>
       
   597 <li id="GUID-9471B51C-CB76-537F-B958-F61466A6B8F7"><p>Use the function <xref href="GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A.dita#GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A/GUID-7BDD7C93-65D3-312B-B99E-B4B07AA32B2C"><apiname>TMMCCommandDesc::BlockLength()</apiname></xref> to
       
   598 get the block length of the transaction. Find all direct references in the
       
   599 source code of the platform specific layer to <codeph>TMMCCommandDesc::iBlockLength</codeph>.
       
   600 Replace each reference with a call to <xref href="GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A.dita#GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A/GUID-7BDD7C93-65D3-312B-B99E-B4B07AA32B2C"><apiname>TMMCCommandDesc::BlockLength()</apiname></xref>  </p> </li>
       
   601 <li id="GUID-902FFE84-8F97-511D-B554-41283550DB16"><p>Use the function <xref href="GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A.dita#GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A/GUID-65B1C01B-1C8D-373A-83DB-0CEFF17667FC"><apiname>TMMCCommandDesc::BufferLength()</apiname></xref> to
       
   602 get the length of the next active segment. Find all references to <codeph>TMMCCommandDesc::iTotalLength</codeph>.
       
   603 There are two areas in the code where this data member can be referenced: </p> <ul>
       
   604 <li id="GUID-626ACF48-ADD0-5530-8CDB-373A3855FF81"><p>code where you test
       
   605 the progress of the data transfer operation and set up the MMC command. Do
       
   606 not change this code, because <codeph>TMMCCommandDesc::iTotalLength</codeph> still
       
   607 represents the total amount of data to be transferred. </p> </li>
       
   608 <li id="GUID-25A1A62A-9B80-5ACB-B9BB-6884B4331CD7"><p>code where you set up
       
   609 the DMA controller to transfer a number of blocks of data. Replace references
       
   610 to <codeph>TMMCCommandDesc::iTotalLength</codeph> with calls to <xref href="GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A.dita#GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A/GUID-65B1C01B-1C8D-373A-83DB-0CEFF17667FC"><apiname>TMMCCommandDesc::BufferLength()</apiname></xref>.
       
   611 This describes the size of the current segment. Note that if double buffers
       
   612 are not enabled, the value returned by this function is the same as <codeph>TMMCCommandDesc::iTotalLength</codeph>. </p> </li>
       
   613 </ul> </li>
       
   614 <li id="GUID-860835C7-D3FD-5727-9ADA-60E080EB1669"><p>You can use the function <xref href="GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A.dita#GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A/GUID-DFD121A5-0C03-31A3-AF20-6E693EDC8502"><apiname>TMMCCommandDesc::IsDoubleBuffered()</apiname></xref> to
       
   615 determine if the current transaction uses double buffers. </p> </li>
       
   616 </ul> <p><b>Separate the command and data phases </b> </p> <p>Without double buffer
       
   617 behavior, a single MMC command is always associated with a single buffer into
       
   618 which the hardware transfers data. With double buffer behavior, multiple buffers
       
   619 or segments are used to transfer data within a single command. You need to
       
   620 separate the command and data transfer phases. </p> <p>This code fragment
       
   621 is a simplified example of a platform specific layer that sets up the command
       
   622 and the data transfers in separate stages: </p> <codeblock id="GUID-D349BEBB-E983-59AA-AA7F-29928D5491F5" xml:space="preserve">   
       
   623    TMMCErr DExampleMMCStack::IssueMMCCommandSM()
       
   624     {
       
   625     enum states
       
   626         {
       
   627         EStBegin=0,
       
   628         EStSetUpCommand,
       
   629         EStWaitComplete,
       
   630         EStEnd
       
   631         };
       
   632     
       
   633        TMMCCommandDesc&amp; cmd = Command();
       
   634     
       
   635     SMF_BEGIN
       
   636 
       
   637        /** ...omitted for clarity */
       
   638          
       
   639     SMF_STATE(EStSetUpCommand)
       
   640                  
       
   641        /**
       
   642         * Set up the controller to issue the command.  Depending on
       
   643         * the command type, this will prepare DMA transfers and wait
       
   644         * for a response to be received before unblocking the stack.
       
   645         */
       
   646        BlockCurrentSession(KMMCBlockOnASSPFunction);
       
   647     
       
   648        SetupCommand(cmd);
       
   649         
       
   650        If(iDataTransfer)
       
   651           SetupDataTransfer(cmd);
       
   652 
       
   653         /**
       
   654         * Wait for all events to be received
       
   655         *  - command sent, data transferred, response received
       
   656         */
       
   657        SMF_WAITS(EStWaitComplete);
       
   658          
       
   659     SMF_STATE(EStWaitComplete)
       
   660 
       
   661        /**
       
   662         * Command issued, data transferred and response received.
       
   663         *  - check for and report any errors
       
   664         *
       
   665         *  - Note, functionality omitted for clarity – in practice this will
       
   666         *    check the controller status and wait for more events as appropriate.
       
   667         */
       
   668        TMMCErr err = KMMCErrNone;
       
   669 
       
   670        if(iResponseExpected)
       
   671           err = ExtractResponse();
       
   672 
       
   673        if(iDataTransfer &amp;&amp; err == KMMCErrNone)
       
   674           err = CheckDataTransferErrors();
       
   675 
       
   676        if(err)
       
   677            SMF_RETURN(err);
       
   678 
       
   679     SMF_END
       
   680     }
       
   681 
       
   682 </codeblock> <p>If you depend on the MMC controller to signal the completion
       
   683 of data transfer after all blocks have been transmitted or received, change
       
   684 the DMA controller. Change the code to block the stack when DMA transfer starts,
       
   685 and unblock the stack when the current DMA transfer finishes. Do this operation
       
   686 while you wait for the final interrupt that signals the end of the data transfer. </p> <p>The
       
   687 following code fragment shows how to set the <xref href="GUID-8A9A2DD2-C630-3651-8374-17BCF2A09AC4.dita"><apiname>KMMCBlockOnASSPFunction</apiname></xref> blocking
       
   688 condition before the start of DMA transfer. After DMA transfer has finished,
       
   689 unblock the stack in the DMA complete service routine, <xref href="GUID-8B538AA6-9489-309F-8756-2474310CD5DA.dita"><apiname>DmaService()</apiname></xref>. </p> <codeblock id="GUID-FC9573C5-7A01-536B-8DA4-82F6DB493849" xml:space="preserve">
       
   690    void DExampleMMCStack::SetupDataTransfer(const TMMCCommandDesc&amp; aCmd)
       
   691       {
       
   692       TUint8* bufPtr = reinterpret_cast&lt;TUint8*&gt;(aCmd.iDataMemoryP);
       
   693       TUint32 bufLen = aCmd.BufferLength();
       
   694 
       
   695       /** ...omitted for clarity */
       
   696 
       
   697       BlockCurrentSession(KMMCBlockOnASSPFunction);
       
   698       iDmaController::Start(aCmd.Direction(), bufPtr, bufLen);
       
   699       }
       
   700 
       
   701 
       
   702    void DExampleDmaController::DmaService()
       
   703       {
       
   704       /** ...omitted for clarity */
       
   705 
       
   706       Session().iState |= KMMCSessStateDoDFC;
       
   707       UnBlockCurrentSession(KMMCBlockOnASSPFunction, KErrNone);
       
   708       }
       
   709 </codeblock> <p><b>Implement the double buffer state machine </b> </p> <p>Update the platform
       
   710 specific layer to implement the double buffer state machine. You use the function <xref href="GUID-0186BEDE-8E28-3F8C-8CAE-A8B92F41F47A.dita#GUID-0186BEDE-8E28-3F8C-8CAE-A8B92F41F47A/GUID-32596EBB-4315-3EF7-8175-8579DE69F78B"><apiname>DMMCSession::RequestMoreData()</apiname></xref>.
       
   711 The platform specific layer uses this function to tell the MMC subsystem to
       
   712 prepare the next segment for data transfer. You call this function when the
       
   713 hardware is busy performing a DMA transfer for the current segment. This allows
       
   714 the MMC Media Driver to copy data to/from the client process ready for the
       
   715 next transfer while the MMC card is transferring it’s current payload. </p> <p>This
       
   716 function sets the static <codeph>KMMCBlockOnMoreData</codeph> blocking condition.
       
   717 The platform specific layer must use <codeph>SMF_WAITS</codeph> (or equivalent)
       
   718 to suspend the platform specific layer state machine until the media driver
       
   719 has processed the current segment. When finished, the command descriptor is
       
   720 populated with the details of the next segment to be transferred. The <codeph>KMMCBlockOnMoreData</codeph> block
       
   721 condition set by this function can be set with the <codeph>KMMCBlockOnASSPFunction</codeph> condition.
       
   722 It allows the hardware to perform useful work, (for example, transfer the
       
   723 current buffer to or from the card) while the media driver is busy preparing
       
   724 the next buffer. In this case, the platform specific layer is unblocked when
       
   725 both the hardware and media driver have completed their tasks. </p> <p>The
       
   726 following code fragment shows how you do this: </p> <codeblock id="GUID-97151CF9-2C59-57D3-8856-8BCAB9BDC5B9" xml:space="preserve">TMMCErr DExampleMMCStack::IssueMMCCommandSM()
       
   727     {
       
   728     enum states
       
   729        {
       
   730        EStBegin=0,
       
   731        EStSetUpCommand,
       
   732    EStWaitDataTransfer
       
   733        EStWaitComplete,
       
   734        EStEnd
       
   735        };
       
   736     
       
   737        TMMCCommandDesc&amp; cmd = Command();
       
   738     
       
   739     SMF_BEGIN
       
   740 
       
   741        /** ...omitted for clarity */
       
   742          
       
   743     SMF_STATE(EStSetUpCommand)
       
   744                  
       
   745        /**
       
   746         * Set up the controller to issue the command.  Depending on
       
   747         * the command type, this will prepare DMA transfers and wait
       
   748         * for a response to be received before unblocking the stack.
       
   749         */
       
   750        BlockCurrentSession(KMMCBlockOnASSPFunction);
       
   751     
       
   752        SetupCommand(cmd);
       
   753         
       
   754        If(iDataTransfer)
       
   755       {
       
   756           /**
       
   757        * Kick off DMA transfer for the first buffer.
       
   758            * …the stack will be blocked on KMMCBlockOnASSPFunction until DMA complete
       
   759        */
       
   760           SetupDataTransfer(cmd);
       
   761       
       
   762       /**
       
   763        * DMA is now active. Now request the Media Driver to prepare the next 
       
   764        * buffer in parallel. While active, the stack will be blocked with
       
   765        * the KMMCBlockOnMoreData blocking condition and unblocked when complete.
       
   766        */
       
   767       Session().RequestMoreData();      
       
   768       }
       
   769 
       
   770         /**
       
   771         * Wait for DMA and Media Driver completion.
       
   772         */
       
   773        SMF_WAITS(EStWaitDataTransfer);
       
   774          
       
   775     SMF_STATE(EStWaitDataTransfer)
       
   776 
       
   777        /**
       
   778         * DMA is complete and the Media Driver has prepared the next buffer.
       
   779         *  - Start the next DMA transfer and request more data from the media driver.
       
   780         */
       
   781 
       
   782        if(cmd.BufferLength() &gt; 0)
       
   783           {
       
   784           /**
       
   785            * There is more data to transfer.
       
   786            * ..start DMA transfer, prepare the next buffer and wait for completion.
       
   787            */
       
   788           SetupDataTransfer(cmd);
       
   789       Session().RequestMoreData();      
       
   790           SMF_WAITS(EStWaitDataTransfer);
       
   791           }
       
   792 
       
   793        /**
       
   794         * There is no more data to transfer.
       
   795         * ..do whatever we need to do to wait for hardware completion
       
   796         */
       
   797 
       
   798        // …omitted for clarity
       
   799 
       
   800    SMF_WAITS(EStWaitComplete);
       
   801 
       
   802     SMF_STATE(EStWaitComplete)
       
   803 
       
   804        /**
       
   805         * Command issued, data transferred and response received.
       
   806         *  - check for and report any errors
       
   807         *
       
   808         *  - Note, functionality omitted for clarity – in practice this will
       
   809         *    check the controller status and wait for more events as appropriate.
       
   810         */
       
   811        TMMCErr err = KMMCErrNone;
       
   812 
       
   813        if(iResponseExpected)
       
   814           err = ExtractResponse();
       
   815 
       
   816        if(iDataTransfer &amp;&amp; err == KMMCErrNone)
       
   817           err = CheckDataTransferErrors();
       
   818 
       
   819        if(err)
       
   820           SMF_RETURN(err);
       
   821 
       
   822     SMF_END
       
   823     }
       
   824 </codeblock> <p><b>Register support for double buffers with the platform independent layer </b> </p> <p>You
       
   825 must tell the <xref href="GUID-40F2BC43-5022-5F4E-B445-56FEF43FEB8B.dita#GUID-40F2BC43-5022-5F4E-B445-56FEF43FEB8B/GUID-119E4B4A-03DB-5C79-AA97-14434E4BC2CA">platform
       
   826 independent layer</xref> that you support double buffers. Set <xref href="GUID-3F9D89E8-44F0-35B3-9404-6CCAC79763E8.dita#GUID-3F9D89E8-44F0-35B3-9404-6CCAC79763E8/GUID-B11D1DA9-89C2-37E3-A2CD-19EF5706ACB8"><apiname>TMMCMachineInfo::ESupportsDoubleBuffering</apiname></xref> into
       
   827 the <xref href="GUID-3F9D89E8-44F0-35B3-9404-6CCAC79763E8.dita"><apiname>TMMCMachineInfo</apiname></xref> object that you pass to <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-CEF0EDF7-4B33-5452-8635-51C5319F78AE">DMMCStack::MachineInfo()</xref>. </p> <p><b>Choose the size of the buffer </b> </p> <p>To choose the optimum size
       
   828 of buffer, you must perform benchmark tests on your system. A small buffer
       
   829 gives you a lower command setup latency, but DMA transfers and calls to the
       
   830 callback function <xref href="GUID-0186BEDE-8E28-3F8C-8CAE-A8B92F41F47A.dita#GUID-0186BEDE-8E28-3F8C-8CAE-A8B92F41F47A/GUID-32596EBB-4315-3EF7-8175-8579DE69F78B"><apiname>DMMCSession::RequestMoreData()</apiname></xref> occur
       
   831 more frequently. The time taken to set up the DMA transfers can exceed the
       
   832 time taken to transfer the data into or out of the active segment. </p> <p><b>Testing </b> </p> <p>You need to do the standard E32 and F32 automated
       
   833 tests to check the operation of the MMC subsystem. You also need to perform
       
   834 the MMC specific manual test, T_MMCDRV. The test listed below performs data
       
   835 transfers in excess of the PSL buffer size to make sure that double buffer
       
   836 behavior is exercised. </p> <codeblock id="GUID-ED1D5B35-432C-5C54-9A13-92DD499316FD" xml:space="preserve">   
       
   837    /**
       
   838    @SYMTestCaseID PBASE-T_MMCDRV-0558
       
   839    @SYMTestCaseDesc Test Long Read/Write Boundaries
       
   840    @SYMTestPriority High
       
   841 
       
   842    @SYMTestActions  
       
   843 
       
   844    Perform and Write/Read/Verify for the given length (L) of data across the following boundaries.
       
   845    Depending on the length, this will also perform a partial write/read at the end sector.
       
   846 
       
   847              --------------
       
   848             | Start    | End    |
       
   849             |--------------|
       
   850             | 0    | L    |
       
   851             | 507    | L-507    |
       
   852             | 10    | L    |
       
   853             | 0    | L-3    |
       
   854             | 27    | L-512    |
       
   855             | 0    | L-509    |
       
   856             | 3    | L-3    |
       
   857              --------------
       
   858 
       
   859    For each combination, the write/read/verify operations are performed in the following sequence:
       
   860 
       
   861 a: Write and Read in single 512-byte blocks.
       
   862 b: Write in a single operation (multiple blocks), Read in 512-Byte blocks.
       
   863 c: Write in 512-Byte blocks, Read in a single operation (multiple-blocks).
       
   864 d: Write and Read in a single operation (multiple-blocks).
       
   865 
       
   866    In the cases where a partial read/write operation occurs (ie - the start and/or end position
       
   867    don't lie within a sector boundary), the original contents of the start and/or end sectors are
       
   868    read and stored at the start of the test, and compared with the contents of the sectors at the
       
   869    end of the test to ensure that unwritten data within the sectors remain unaffected.
       
   870   
       
   871    @SYMTestExpectedResults All tests must pass
       
   872 
       
   873    @SYMPREQ1389 REQ6951 Double Buffering and SD Switch
       
   874    *
       
   875    */
       
   876 
       
   877 </codeblock> <p>The test T_MMCDRV must be performed on versions of the platform
       
   878 specific layer that has: double buffers enabled, double buffers disabled,
       
   879 and with a number of different buffer sizes (for example, from 32k to 256k). </p> <p>The
       
   880 test cannot dynamically set the size of the buffer. You must do manual configuration
       
   881 of the buffer to test all configurations. </p> <p>To measure performance,
       
   882 use T_FSYSBM, with and without double buffers enable. </p> <p id="GUID-575211BC-BF66-5817-9825-EE402648D0CD"><b>Register support for physical
       
   883 addresses</b> </p> <p>There are three items to do: </p> <ul>
       
   884 <li id="GUID-0E169605-00B8-53F9-AF7A-5410EEE73A70"><p>you must tell the <xref href="GUID-40F2BC43-5022-5F4E-B445-56FEF43FEB8B.dita#GUID-40F2BC43-5022-5F4E-B445-56FEF43FEB8B/GUID-119E4B4A-03DB-5C79-AA97-14434E4BC2CA">platform
       
   885 independent layer</xref> that you support physical addresses in your implementation
       
   886 of <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-CEF0EDF7-4B33-5452-8635-51C5319F78AE">DMMCStack::MachineInfo()</xref>.
       
   887 The function takes a <xref href="GUID-3F9D89E8-44F0-35B3-9404-6CCAC79763E8.dita"><apiname>TMMCMachineInfo</apiname></xref> type. Set the <xref href="GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6.dita#GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6/GUID-CB8D99BA-8EC2-3A98-B3BF-BA5FEE3A6AE1"><apiname>THardwareConfig::ESupportsDMA</apiname></xref> flags
       
   888 into the <codeph>iFlags</codeph> member of <xref href="GUID-3F9D89E8-44F0-35B3-9404-6CCAC79763E8.dita"><apiname>TMMCMachineInfo</apiname></xref>. </p> <p>If
       
   889 you set the <xref href="GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6.dita#GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6/GUID-CB8D99BA-8EC2-3A98-B3BF-BA5FEE3A6AE1"><apiname>THardwareConfig::ESupportsDMA</apiname></xref> flag, you also
       
   890 set the <xref href="GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6.dita#GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6/GUID-3276FBA3-7028-30C2-A820-CEBD77DCF817"><apiname>THardwareConfig::ESupportsDoubleBuffering</apiname></xref> flag
       
   891 automatically. This flag enables double buffer support. You must also<xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-E50081BC-C923-5DAF-950C-9E1411916FED">implement
       
   892 double buffers</xref> if you use physical addresses. </p> </li>
       
   893 <li id="GUID-752318C6-301B-51B0-A064-64EAEBCF0E35"><p>You must tell the <xref href="GUID-40F2BC43-5022-5F4E-B445-56FEF43FEB8B.dita#GUID-40F2BC43-5022-5F4E-B445-56FEF43FEB8B/GUID-119E4B4A-03DB-5C79-AA97-14434E4BC2CA">platform
       
   894 independent layer</xref> the maximum transfer length that you support. This
       
   895 can be a limit imposed on you by the hardware. For example, if you use DMA,
       
   896 the DMA controller can impose a limit. You set one of the flags listed below
       
   897 into the <codeph>iFlags</codeph> member of <xref href="GUID-3F9D89E8-44F0-35B3-9404-6CCAC79763E8.dita"><apiname>TMMCMachineInfo</apiname></xref> in
       
   898 your implementation of <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-CEF0EDF7-4B33-5452-8635-51C5319F78AE">DMMCStack::MachineInfo()</xref>. </p> <p>Each flag represents a maximum transfer length. The MultiMediaCard
       
   899 subsystem splits a data transfer request that is bigger than the maximum into
       
   900 multiple data transfers. </p> <ul>
       
   901 <li id="GUID-1BD38D21-6B02-5610-8495-4C7C194657CF"><p> <xref href="GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6.dita#GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6/GUID-3375EE8E-49B8-3F24-BF40-D780AD8E1B0A"><apiname>THardwareConfig::EMaxTransferLength_256K</apiname></xref> </p> </li>
       
   902 <li id="GUID-D4AB6165-036A-5259-922A-E9E1CB5749C8"><p> <xref href="GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6.dita#GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6/GUID-F3BEFC8A-55F6-3B28-B383-6B33BAD2B5F7"><apiname>THardwareConfig::EMaxTransferLength_512K</apiname></xref> </p> </li>
       
   903 <li id="GUID-72380863-E20E-5478-98D8-FA342C14E80C"><p> <xref href="GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6.dita#GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6/GUID-20FB2892-190F-31C4-9F58-66AAB02DC4E1"><apiname>THardwareConfig::EMaxTransferLength_1M</apiname></xref>  </p> </li>
       
   904 <li id="GUID-68C4292C-5D9D-5E23-8608-DFBA2846A8FA"><p> <xref href="GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6.dita#GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6/GUID-45913568-5C4E-3A6F-A727-8734C303AC3D"><apiname>THardwareConfig::EMaxTransferLength_2M</apiname></xref>  </p> </li>
       
   905 <li id="GUID-D637F68D-4530-5BE5-9B99-A7437E7AF9BC"><p> <xref href="GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6.dita#GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6/GUID-66707CB4-A8E0-305E-9599-D22CBBC41E91"><apiname>THardwareConfig::EMaxTransferLength_4M</apiname></xref>  </p> </li>
       
   906 <li id="GUID-69AD58F1-06F6-564C-B130-BDBF8F1745BB"><p> <xref href="GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6.dita#GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6/GUID-DA25B30F-671C-3B54-B58D-9F58B17BC11F"><apiname>THardwareConfig::EMaxTransferLength_8M,</apiname></xref>  </p> </li>
       
   907 <li id="GUID-AAE1868C-8C51-58DE-8F29-34463E0F7104"><p> <xref href="GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6.dita#GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6/GUID-565830C3-14D4-3AA7-990E-78A199275DDF"><apiname>THardwareConfig::EMaxTransferLength_16M</apiname></xref>  </p> </li>
       
   908 <li id="GUID-BFC9B360-8023-5AC5-A2FC-F52A7D6BFD06"><p> <xref href="GUID-FA278485-D2CC-35D8-A779-8F0BDB691C3F.dita"><apiname>TMMCMachineInfoV4.iFlags</apiname></xref>  </p> </li>
       
   909 </ul> </li>
       
   910 <li id="GUID-54BCDD97-4E54-52D5-9526-BFAC5041F8F8"><p>You must tell the <xref href="GUID-40F2BC43-5022-5F4E-B445-56FEF43FEB8B.dita#GUID-40F2BC43-5022-5F4E-B445-56FEF43FEB8B/GUID-119E4B4A-03DB-5C79-AA97-14434E4BC2CA">platform
       
   911 independent layer</xref> the address scheme that the hardware uses. Mis-alignment
       
   912 of memory can corrupt data. You set <i>one</i> of the flags shown in the list
       
   913 below into the <codeph>iFlags</codeph> member of <xref href="GUID-3F9D89E8-44F0-35B3-9404-6CCAC79763E8.dita"><apiname>TMMCMachineInfo</apiname></xref> in
       
   914 your implementation of <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-CEF0EDF7-4B33-5452-8635-51C5319F78AE">DMMCStack::MachineInfo()</xref>. Each flags represents a different address scheme. You can set only one
       
   915 flag. If you set more than one of these flags, the creation of the media driver
       
   916 fails. </p> <ul>
       
   917 <li id="GUID-3055EE71-56B8-566A-A2B8-6F415F2D1675"><p> <xref href="GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6.dita#GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6/GUID-A36BA08C-2010-3002-8FB2-A8E917700604"><apiname>THardwareConfig::EDma8BitAddressing</apiname></xref>  </p> </li>
       
   918 <li id="GUID-C71091D1-7E53-530B-8AE6-37BD9125B8B2"><p> <xref href="GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6.dita#GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6/GUID-DA9AE183-855B-31A0-BDE3-54BFE894C1F8"><apiname>THardwareConfig::EDma16BitAddressing</apiname></xref>  </p> </li>
       
   919 <li id="GUID-6402A30F-4A49-528B-BF74-EB715521773B"><p> <xref href="GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6.dita#GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6/GUID-6D844C49-AD50-3C73-BEA8-473A44B9E9D4"><apiname>THardwareConfig::EDma32BitAddressing</apiname></xref>  </p> </li>
       
   920 <li id="GUID-F10F9E09-151D-5BB2-B1B6-B0B08B49B8F6"><p> <xref href="GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6.dita#GUID-9E833DE8-E795-3EC8-B27B-CFB6D7E1C4C6/GUID-6F43817F-611B-326C-8A1C-55703FFC6500"><apiname>THardwareConfig::EDma64BitAddressing</apiname></xref>  </p> </li>
       
   921 </ul> </li>
       
   922 </ul> <p>The following code is an example implementation of <xref href="GUID-B5193656-9819-3E00-A335-EEF1726115A5.dita#GUID-B5193656-9819-3E00-A335-EEF1726115A5/GUID-3E5532A5-4645-3F77-A7A9-7AFF334FA5A4"><apiname>DMMCStack::MachineInfo()</apiname></xref>. </p> <codeblock id="GUID-BF942E07-A7E8-5300-9015-3FC06CAB835E" xml:space="preserve">void DVariantMmcHwStack::MachineInfo(TMMCMachineInfoV4&amp; aMachineInfo)
       
   923 /**
       
   924  * Gets the machine info for the hardware variant
       
   925  *
       
   926  * @param aMachineInfo    Info structure to populate
       
   927  */
       
   928     {
       
   929     aMachineInfo.iTotalSockets=MMC_DRIVECOUNT;
       
   930     aMachineInfo.iTotalMediaChanges=0;          // Not used at present
       
   931     aMachineInfo.iTotalPrimarySupplies=0;        // Not used at present
       
   932     
       
   933     aMachineInfo.iBaseBusNumber=0;
       
   934     aMachineInfo.iVersion = TMMCMachineInfoV4::EVersion4;
       
   935     aMachineInfo.iMaxBusWidth = EBusWidth4;
       
   936 
       
   937     // Report support for Physical Addressing
       
   938     aMachineInfo.iFlags  = TMMCMachineInfo::ESupportsDMA;
       
   939     aMachineInfo.iFlags |= TMMCMachineInfo::EMaxTransferLength_1M; 
       
   940     aMachineInfo.iFlags |= TMMCMachineInfo::EDma16BitAddressing;
       
   941 
       
   942     // High voltage (3.6V) power class. Set to maximum = 2000mA RMS
       
   943     aMachineInfo.iHighVoltagePowerClass = TMMCMachineInfoV4::EHi200mA;
       
   944 
       
   945     // Low voltage (1.95V) power class. Set to maximum = 200mA RMS
       
   946     aMachineInfo.iLowVoltagePowerClass = TMMCMachineInfoV4::ELo200mA;
       
   947     
       
   948     // 52 Mhz clock supported
       
   949     aMachineInfo.iMaxClockSpeedInMhz = TMMCMachineInfoV4::EClockSpeed52Mhz;    
       
   950     }</codeblock> <p id="GUID-27FCEF7D-0AAB-599C-8405-4BD284308314"><b>Modify the data transfer
       
   951 phase to handle physical memory </b> </p> <p>The implementation of double
       
   952 buffers has separated the command setup and the data transfer phases. You
       
   953 need to change the data transfer phase to handle physical memory. </p> <ul>
       
   954 <li id="GUID-59E7DD5F-39B6-5CA5-9C8C-CC4847A885DC"><p>The data member <xref href="GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A.dita#GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A/GUID-596E150B-E5F1-3945-9C00-64B8EB24550C"><apiname>TMMCCommandDesc::iDataMemoryP</apiname></xref> contains
       
   955 the source or target memory address for the current data transfer command.
       
   956 Use the function <xref href="GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A.dita#GUID-6B3DDBFD-3A4A-3694-A058-7794700FEC7A/GUID-3A25BD15-A832-3C76-AB68-0B4470710C3A"><apiname>TMMCCommandDesc::IsPhysicalAddress()</apiname></xref> to
       
   957 determine if this address is a physical address or a virtual address. If you
       
   958 do not <xref href="GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B.dita#GUID-E55B4FE5-517C-5A23-8ACA-E28EE202330B/GUID-575211BC-BF66-5817-9825-EE402648D0CD">register
       
   959 support for physical addresses</xref>, this function always returns <xref href="GUID-A759CA2D-8327-348F-9337-4886E619D920.dita"><apiname>EFalse</apiname></xref>. </p> </li>
       
   960 <li id="GUID-B9D101C4-FDD1-5233-9DCB-12DDA47073FC"><p>You do not need to perform
       
   961 virtual address to physical address translation on physical addresses. </p> </li>
       
   962 <li id="GUID-2382A7A0-B0EB-5E1F-9ADE-47389FABABBA"><p>you do not need to perform
       
   963 DMA synchronization for physical addresses, because the local media subsystem
       
   964 performs DMA synchronization for you. You need to perform DMA synchronization
       
   965 for virtual addresses. DMA synchronization is performed by calls to <xref href="GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F.dita#GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F/GUID-3FF3C567-C1BD-3D4E-97E1-B036456A374E"><apiname>Cache::SyncMemoryBeforeDmaRead()</apiname></xref> or <xref href="GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F.dita#GUID-4425E698-EE8A-369B-92CD-09B1CBD2911F/GUID-5F08DEAA-1237-32DE-AE41-CE7B18230972"><apiname>Cache::SyncMemoryBeforeDmaWrite()</apiname></xref>. </p> </li>
       
   966 </ul> <p>The following code is an example of the changes needed for a read
       
   967 operation. </p> <codeblock id="GUID-B92D3E0B-09F3-54C9-83AE-34DA544C0055" xml:space="preserve">TInt DMMCDmaRx::Start(const TMMCCommandDesc&amp; aCmd)
       
   968 /**
       
   969  *  Queues a DMA request after checking the buffer alignment constraints.
       
   970  *
       
   971  *  @param aCmd The command structure containing the details about the command.
       
   972  */
       
   973 {
       
   974
       
   975    TUint flags = KDmaMemDest;
       
   976 
       
   977    // Check if a physical address has been provided with this request
       
   978    if(aCmd.IsPhysicalAddress())
       
   979 {
       
   980        // …if so, set the appropriate flag for this DDmaRequest
       
   981 flags |= KDmaPhysAddrDest;
       
   982 }
       
   983 
       
   984    TInt retval = iRequest-&gt;Fragment(    KMMC_Buf_Dt_Reg,
       
   985                                         (TUint32)aCmd.iDataMemoryP,
       
   986                 aCmd.BufferLength(), 
       
   987                                  flags,
       
   988                                  0 /* no HW Flags*/);
       
   989 
       
   990    if(retval != KErrNone)
       
   991 Kern::Fault("MMC DMA RX Start Fragment", retval);
       
   992 
       
   993
       
   994    return KErrNone;
       
   995 }
       
   996 </codeblock> <codeblock id="GUID-AB1E5042-8680-57C4-87F7-71F362232C37" xml:space="preserve">void DMMCRxDmaHelp::ChannelTransfer(const SDmaPseudoDes&amp; aDes)
       
   997     {
       
   998
       
   999     TPhysAddr dest;
       
  1000 
       
  1001 // Don’t perform Linear to Physical translation if we 
       
  1002     // have already been supplied with a Physical Address
       
  1003     if (aDes.iFlags &amp; KDmaPhysAddrDest)
       
  1004         dest = (TPhysAddr) aDes.iDest;
       
  1005     else
       
  1006         dest = Epoc::LinearToPhysical(aDes.iDest);
       
  1007 
       
  1008     TPlatDma::SetDMARegister(KHoDMA_CDSA(iChno), dest);
       
  1009
       
  1010     }
       
  1011 </codeblock> </section>
       
  1012 </conbody></concept>