|
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 << blkSzLog2; |
|
71 const TInt minorBufLen = Max(KDiskSectorSize, blkSz); |
|
72 |
|
73 const TInt KMinBlocksInBuffer = 8; |
|
74 const TInt cchBufLen = KMinBlocksInBuffer << 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<TUint8*>(bufChunk->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 & ~KWordMask; |
|
135 *aPhysEnd = (aEnd + KWordMask) & ~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->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& 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 && 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& aCmd) |
|
691 { |
|
692 TUint8* bufPtr = reinterpret_cast<TUint8*>(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& 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() > 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 && 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& 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& 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->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& 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 & 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> |