279
|
1 |
// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
|
2 |
// All rights reserved.
|
|
3 |
// This component and the accompanying materials are made available
|
|
4 |
// under the terms of the License "Eclipse Public License v1.0"
|
|
5 |
// which accompanies this distribution, and is available
|
|
6 |
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
7 |
//
|
|
8 |
// Initial Contributors:
|
|
9 |
// Nokia Corporation - initial contribution.
|
|
10 |
//
|
|
11 |
// Contributors:
|
|
12 |
//
|
|
13 |
// Description:
|
|
14 |
// This LDD provides a set of direct interface functions with the kernel
|
|
15 |
// MultiMediaCard Controller
|
|
16 |
//
|
|
17 |
//
|
|
18 |
|
|
19 |
#include <kernel/kernel.h>
|
|
20 |
#include <drivers/mmc.h>
|
|
21 |
#include "d_mmctest.h"
|
|
22 |
|
|
23 |
const TInt KMajorVersionNumber=1;
|
|
24 |
const TInt KMinorVersionNumber=0;
|
|
25 |
const TInt KBuildVersionNumber=0;
|
|
26 |
|
|
27 |
const TInt KStackNumber = 0;
|
|
28 |
|
|
29 |
const TInt KMaxMMCCardsPerStack = 4;
|
|
30 |
|
|
31 |
// global Dfc Que
|
|
32 |
TDynamicDfcQue* gDfcQ;
|
|
33 |
|
|
34 |
class DLddFactoryMmcCntrlInterface : public DLogicalDevice
|
|
35 |
{
|
|
36 |
public:
|
|
37 |
DLddFactoryMmcCntrlInterface();
|
|
38 |
virtual ~DLddFactoryMmcCntrlInterface();
|
|
39 |
virtual TInt Install();
|
|
40 |
virtual void GetCaps(TDes8 &aDes) const;
|
|
41 |
virtual TInt Create(DLogicalChannelBase*& aChannel); //overriding pure virtual
|
|
42 |
};
|
|
43 |
|
|
44 |
class DLddMmcCntrlInterface : public DLogicalChannel
|
|
45 |
{
|
|
46 |
public:
|
|
47 |
DLddMmcCntrlInterface();
|
|
48 |
~DLddMmcCntrlInterface();
|
|
49 |
protected:
|
|
50 |
virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
|
|
51 |
virtual void HandleMsg(class TMessageBase *);
|
|
52 |
private:
|
|
53 |
void DoCancel(TInt aReqNo);
|
|
54 |
TInt DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2);
|
|
55 |
TInt DoControl(TInt aFunction, TAny* a1, TAny* a2);
|
|
56 |
TInt PrintCardInfo();
|
|
57 |
private:
|
|
58 |
void Reset();
|
|
59 |
static void SessionEndCallBack(TAny *aPtr);
|
|
60 |
static void SessionEndDfc(TAny *aPtr);
|
|
61 |
static void EventCallBack(TAny* aPtr, TInt aReason, TAny* a1, TAny* a2);
|
|
62 |
|
|
63 |
private:
|
|
64 |
enum TPanic {EReadDes,EWriteDes,EWriteTInt,EUnknownMmcSes};
|
|
65 |
enum TMmcSessionCmd {EMmcSesNone,EMmcSesReadBlk,EMmcSesWriteBlk, EMmcSesReadExtCSD};
|
|
66 |
TInt iStackNum;
|
|
67 |
DMMCSocket* iSocketP;
|
|
68 |
DMMCStack* iStack;
|
|
69 |
TMMCard* iCard;
|
|
70 |
DMMCSession* iSession;
|
|
71 |
TMmcSessionCmd iMmcSessionCmd;
|
|
72 |
TAny* iClientDesPtr;
|
|
73 |
TUint32 iBlkOffet;
|
|
74 |
TRequestStatus* iReadWriteStatusP;
|
|
75 |
TMMCCallBack iSessionEndCallBack;
|
|
76 |
TDfc iSessionEndDfc;
|
|
77 |
TPBusCallBack iBusEventCallback;
|
|
78 |
TRequestStatus* iPowerUpStatusP;
|
|
79 |
// TUint8 iBuf[KDrvBufSizeInBytes]; // iBuf now uses the MMC DMA buffer, until DT issue with H4 is resolved
|
|
80 |
TUint8* iBuf;
|
|
81 |
DThread* iClient;
|
|
82 |
TExtendedCSD iExtendedCSD;
|
|
83 |
};
|
|
84 |
|
|
85 |
DECLARE_STANDARD_LDD()
|
|
86 |
{
|
|
87 |
return new DLddFactoryMmcCntrlInterface;
|
|
88 |
}
|
|
89 |
|
|
90 |
DLddFactoryMmcCntrlInterface::DLddFactoryMmcCntrlInterface()
|
|
91 |
//
|
|
92 |
// Constructor
|
|
93 |
//
|
|
94 |
{
|
|
95 |
|
|
96 |
iParseMask=KDeviceAllowUnit; // Pass stack number as unit
|
|
97 |
iUnitsMask=0xffffffff;
|
|
98 |
iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
|
|
99 |
}
|
|
100 |
|
|
101 |
TInt DLddFactoryMmcCntrlInterface::Create(DLogicalChannelBase*& aChannel)
|
|
102 |
//
|
|
103 |
// Create a new DLddFactoryMmcCntrlInterface on this logical device
|
|
104 |
//
|
|
105 |
{
|
|
106 |
aChannel=new DLddMmcCntrlInterface;
|
|
107 |
return aChannel ? KErrNone : KErrNoMemory;
|
|
108 |
}
|
|
109 |
|
|
110 |
const TInt KDMmcThreadPriority = 27;
|
|
111 |
_LIT(KDMmcThread,"DMmcTestThread");
|
|
112 |
|
|
113 |
TInt DLddFactoryMmcCntrlInterface::Install()
|
|
114 |
//
|
|
115 |
// Install the device driver.
|
|
116 |
//
|
|
117 |
{
|
|
118 |
// Allocate a kernel thread to run the DFC
|
|
119 |
TInt r = Kern::DynamicDfcQCreate(gDfcQ, KDMmcThreadPriority, KDMmcThread);
|
|
120 |
|
|
121 |
if (r != KErrNone)
|
|
122 |
return r;
|
|
123 |
|
|
124 |
TPtrC name=_L("MmcTest");
|
|
125 |
return(SetName(&name));
|
|
126 |
}
|
|
127 |
|
|
128 |
void DLddFactoryMmcCntrlInterface::GetCaps(TDes8 &aDes) const
|
|
129 |
//
|
|
130 |
// Return the Pc Card Contoller Interface ldd's capabilities.
|
|
131 |
//
|
|
132 |
{
|
|
133 |
|
|
134 |
TCapsMmcIfV01 b;
|
|
135 |
b.version=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
|
|
136 |
Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
|
|
137 |
}
|
|
138 |
|
|
139 |
/**
|
|
140 |
Destructor
|
|
141 |
*/
|
|
142 |
DLddFactoryMmcCntrlInterface::~DLddFactoryMmcCntrlInterface()
|
|
143 |
{
|
|
144 |
if (gDfcQ)
|
|
145 |
gDfcQ->Destroy();
|
|
146 |
}
|
|
147 |
|
|
148 |
#pragma warning( disable : 4355 ) // this used in initializer list
|
|
149 |
DLddMmcCntrlInterface::DLddMmcCntrlInterface()
|
|
150 |
//
|
|
151 |
// Constructor
|
|
152 |
//
|
|
153 |
: iSessionEndCallBack(DLddMmcCntrlInterface::SessionEndCallBack,this),
|
|
154 |
iSessionEndDfc(DLddMmcCntrlInterface::SessionEndDfc, this, 1),
|
|
155 |
iBusEventCallback(DLddMmcCntrlInterface::EventCallBack, this)
|
|
156 |
{
|
|
157 |
|
|
158 |
// iMmcController=NULL;
|
|
159 |
// iStackNum=0;
|
|
160 |
// iStack=NULL;
|
|
161 |
// iCard=NULL;
|
|
162 |
// iSession=NULL;
|
|
163 |
// iMmcSessionCmd=EMmcSesNone;
|
|
164 |
// iClientDesPtr=NULL;
|
|
165 |
// iBlkOffet=0;
|
|
166 |
|
|
167 |
iClient=&Kern::CurrentThread();
|
|
168 |
((DObject*)iClient)->Open(); // can't fail since thread is running
|
|
169 |
}
|
|
170 |
#pragma warning( default : 4355 )
|
|
171 |
|
|
172 |
DLddMmcCntrlInterface::~DLddMmcCntrlInterface()
|
|
173 |
//
|
|
174 |
// Destructor
|
|
175 |
//
|
|
176 |
{
|
|
177 |
|
|
178 |
Reset();
|
|
179 |
iBusEventCallback.Remove();
|
|
180 |
delete iSession;
|
|
181 |
Kern::SafeClose((DObject*&)iClient,NULL);
|
|
182 |
}
|
|
183 |
|
|
184 |
TInt DLddMmcCntrlInterface::DoCreate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& aVer)
|
|
185 |
//
|
|
186 |
// Create channel.
|
|
187 |
//
|
|
188 |
{
|
|
189 |
if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer))
|
|
190 |
return(KErrNotSupported);
|
|
191 |
|
|
192 |
//
|
|
193 |
// Obtain the appropriate card from the socket/stack
|
|
194 |
//
|
|
195 |
iSocketP = static_cast<DMMCSocket*>(DPBusSocket::SocketFromId(aUnit));
|
|
196 |
if(iSocketP == NULL)
|
|
197 |
return(KErrNoMemory);
|
|
198 |
|
|
199 |
iStack = static_cast<DMMCStack*>(iSocketP->Stack(KStackNumber));
|
|
200 |
if(iStack == NULL)
|
|
201 |
return(KErrNoMemory);
|
|
202 |
|
|
203 |
// Create an MMC session object
|
|
204 |
iSession = iStack->AllocSession(iSessionEndCallBack);
|
|
205 |
if (iSession==NULL)
|
|
206 |
return(KErrNoMemory);
|
|
207 |
|
|
208 |
iSession->SetStack(iStack);
|
|
209 |
|
|
210 |
TUint8* buf;
|
|
211 |
TInt bufLen;
|
|
212 |
TInt minorBufLen;
|
|
213 |
iStack->BufferInfo(buf, bufLen, minorBufLen);
|
|
214 |
iBuf = buf;
|
|
215 |
|
|
216 |
SetDfcQ(gDfcQ);
|
|
217 |
iMsgQ.Receive();
|
|
218 |
|
|
219 |
iSessionEndDfc.SetDfcQ(gDfcQ);
|
|
220 |
|
|
221 |
iBusEventCallback.SetSocket(aUnit);
|
|
222 |
iBusEventCallback.Add();
|
|
223 |
|
|
224 |
return(KErrNone);
|
|
225 |
}
|
|
226 |
|
|
227 |
void DLddMmcCntrlInterface::DoCancel(TInt /*aReqNo*/)
|
|
228 |
//
|
|
229 |
// Cancel an outstanding request.
|
|
230 |
//
|
|
231 |
{
|
|
232 |
}
|
|
233 |
|
|
234 |
void DLddMmcCntrlInterface::HandleMsg(TMessageBase* aMsg)
|
|
235 |
{
|
|
236 |
TThreadMessage& m=*(TThreadMessage*)aMsg;
|
|
237 |
TInt id=m.iValue;
|
|
238 |
|
|
239 |
if (id==(TInt)ECloseMsg)
|
|
240 |
{
|
|
241 |
m.Complete(KErrNone, EFalse);
|
|
242 |
return;
|
|
243 |
}
|
|
244 |
else if (id==KMaxTInt)
|
|
245 |
{
|
|
246 |
// DoCancel
|
|
247 |
m.Complete(KErrNone,ETrue);
|
|
248 |
return;
|
|
249 |
}
|
|
250 |
|
|
251 |
if (id<0)
|
|
252 |
{
|
|
253 |
// DoRequest
|
|
254 |
TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
|
|
255 |
TInt r=DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
|
|
256 |
if (r!=KErrNone)
|
|
257 |
Kern::RequestComplete(iClient, pS, r);
|
|
258 |
m.Complete(KErrNone,ETrue);
|
|
259 |
}
|
|
260 |
else
|
|
261 |
{
|
|
262 |
// DoControl
|
|
263 |
TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
|
|
264 |
if(r != KErrCompletion)
|
|
265 |
{
|
|
266 |
m.Complete(r,ETrue);
|
|
267 |
}
|
|
268 |
}
|
|
269 |
}
|
|
270 |
|
|
271 |
TInt DLddMmcCntrlInterface::PrintCardInfo()
|
|
272 |
{
|
|
273 |
if(iCard == NULL)
|
|
274 |
{
|
|
275 |
return(KErrNotReady);
|
|
276 |
}
|
|
277 |
const TCSD& csd = iCard->CSD();
|
|
278 |
Kern::Printf("CSD");
|
|
279 |
Kern::Printf("CSDStructure(): %u",csd.CSDStructure());
|
|
280 |
Kern::Printf("SpecVers(): %u",csd.SpecVers());
|
|
281 |
switch (csd.MediaType())
|
|
282 |
{
|
|
283 |
case EMultiMediaROM : Kern::Printf("Read Only Media"); break;
|
|
284 |
case EMultiMediaFlash : Kern::Printf("Writable Media"); break;
|
|
285 |
case EMultiMediaIO : Kern::Printf("IO Media Device"); break;
|
|
286 |
case EMultiMediaOther : Kern::Printf("UNKNOWN Media type"); break;
|
|
287 |
default : Kern::Printf("Media NOT SUPPORTED");
|
|
288 |
}
|
|
289 |
Kern::Printf("----------------------------------");
|
|
290 |
Kern::Printf("Reserved120(): %u",csd.Reserved120());
|
|
291 |
Kern::Printf("TAAC(): %u", csd.TAAC());
|
|
292 |
Kern::Printf("NSAC(): %u", csd.NSAC());
|
|
293 |
Kern::Printf("TranSpeed(): %u", csd.TranSpeed());
|
|
294 |
Kern::Printf("CCC(): %u",csd.CCC());
|
|
295 |
Kern::Printf("ReadBlLen(): %u", csd.ReadBlLen());
|
|
296 |
Kern::Printf("ReadBlPartial(): %u", (TUint)csd.ReadBlPartial());
|
|
297 |
Kern::Printf("WriteBlkMisalign(): %u", (TUint) csd.WriteBlkMisalign());
|
|
298 |
Kern::Printf("ReadBlkMisalign(): %u", (TUint) csd.ReadBlkMisalign());
|
|
299 |
Kern::Printf("DSRImp(): %u", (TUint) csd.DSRImp());
|
|
300 |
Kern::Printf("Reserved74(): %u", csd.Reserved74());
|
|
301 |
Kern::Printf("CSize(): %u", csd.CSize());
|
|
302 |
Kern::Printf("VDDRCurrMin(): %u", csd.VDDRCurrMin());
|
|
303 |
Kern::Printf("VDDRCurrMax(): %u", csd.VDDRCurrMax());
|
|
304 |
Kern::Printf("VDDWCurrMin(): %u", csd.VDDWCurrMin());
|
|
305 |
Kern::Printf("VDDWCurrMax(): %u", csd.VDDWCurrMax());
|
|
306 |
Kern::Printf("CSizeMult(): %u", csd.CSizeMult());
|
|
307 |
Kern::Printf("EraseGrpSize(): %u", csd.EraseGrpSize());
|
|
308 |
Kern::Printf("EraseGrpMult(): %u", csd.EraseGrpMult());
|
|
309 |
Kern::Printf("WPGrpSize(): %u", csd.WPGrpSize());
|
|
310 |
Kern::Printf("WPGrpEnable(): %u", csd.WPGrpEnable());
|
|
311 |
Kern::Printf("DefaultECC(): %u", csd.DefaultECC());
|
|
312 |
Kern::Printf("R2WFactor(): %u", csd.R2WFactor());
|
|
313 |
Kern::Printf("WriteBlLen(): %u", csd.WriteBlLen());
|
|
314 |
Kern::Printf("WriteBlPartial(): %u", (TUint) csd.WriteBlPartial());
|
|
315 |
Kern::Printf("Reserved16(): %u", csd.Reserved16());
|
|
316 |
Kern::Printf("FileFormatGrp(): %u", (TUint) csd.FileFormatGrp());
|
|
317 |
Kern::Printf("Copy(): %u", (TUint) csd.Copy());
|
|
318 |
Kern::Printf("PermWriteProtect(): %u", (TUint) csd.PermWriteProtect());
|
|
319 |
Kern::Printf("TmpWriteProtect(): %u", (TUint) csd.TmpWriteProtect());
|
|
320 |
Kern::Printf("FileFormat(): %u", csd.FileFormat());
|
|
321 |
Kern::Printf("ECC(): %u", csd.ECC());
|
|
322 |
Kern::Printf("CRC(): %u", csd.CRC());
|
|
323 |
Kern::Printf("DeviceSize(): %u", csd.DeviceSize());
|
|
324 |
Kern::Printf("ReadBlockLength(): %u", csd.ReadBlockLength());
|
|
325 |
Kern::Printf("WriteBlockLength(): %u", csd.WriteBlockLength());
|
|
326 |
Kern::Printf("EraseSectorSize(): %u", csd.EraseSectorSize());
|
|
327 |
Kern::Printf("EraseGroupSize(): %u", csd.EraseGroupSize());
|
|
328 |
Kern::Printf("MinReadCurrentInMilliamps(): %u", csd.MinReadCurrentInMilliamps());
|
|
329 |
Kern::Printf("MinWriteCurrentInMilliamps(): %u", csd.MinWriteCurrentInMilliamps());
|
|
330 |
Kern::Printf("MaxReadCurrentInMilliamps(): %u", csd.MaxReadCurrentInMilliamps());
|
|
331 |
Kern::Printf("MaxWriteCurrentInMilliamps(): %u", csd.MaxWriteCurrentInMilliamps());
|
|
332 |
Kern::Printf("MaxTranSpeedInKilohertz(): %u", csd.MaxTranSpeedInKilohertz());
|
|
333 |
|
|
334 |
const TExtendedCSD& extcsd = iCard->iExtendedCSD;
|
|
335 |
Kern::Printf("\nExtended CSD");
|
|
336 |
Kern::Printf("CSDStructureVer: %u", extcsd.CSDStructureVer());
|
|
337 |
Kern::Printf("ExtendedCSDRev: %u", extcsd.ExtendedCSDRev());
|
|
338 |
Kern::Printf("----------------------------------");
|
|
339 |
Kern::Printf("SupportedCmdSet: %u", extcsd.SupportedCmdSet());
|
|
340 |
Kern::Printf("SectorCount: %u", extcsd.SectorCount());
|
|
341 |
Kern::Printf("MinPerfWrite8Bit52Mhz: %u", extcsd.MinPerfWrite8Bit52Mhz());
|
|
342 |
Kern::Printf("MinPerfRead8Bit52Mhz: %u", extcsd.MinPerfRead8Bit52Mhz());
|
|
343 |
Kern::Printf("MinPerfRead8Bit26Mhz_4Bit52Mhz: %u", extcsd.MinPerfRead8Bit26Mhz_4Bit52Mhz());
|
|
344 |
Kern::Printf("MinPerfWrite4Bit26Mhz: %u", extcsd.MinPerfWrite4Bit26Mhz());
|
|
345 |
Kern::Printf("MinPerfRead4Bit26Mhz: %u", extcsd.MinPerfRead4Bit26Mhz());
|
|
346 |
Kern::Printf("PowerClass26Mhz360V: 0x%02X", extcsd.PowerClass26Mhz360V());
|
|
347 |
Kern::Printf("PowerClass52Mhz360V: 0x%02X", extcsd.PowerClass52Mhz360V());
|
|
348 |
Kern::Printf("PowerClass26Mhz195V: 0x%02X", extcsd.PowerClass26Mhz195V());
|
|
349 |
Kern::Printf("PowerClass52Mhz195V: 0x%02X", extcsd.PowerClass52Mhz195V());
|
|
350 |
Kern::Printf("CardType: %u", extcsd.CardType());
|
|
351 |
Kern::Printf("CmdSet: %u", extcsd.CmdSet());
|
|
352 |
Kern::Printf("CmdSetRev: %u", extcsd.CmdSetRev());
|
|
353 |
Kern::Printf("PowerClass: %u", extcsd.PowerClass());
|
|
354 |
Kern::Printf("HighSpeedTiming: %u", extcsd.HighSpeedTiming());
|
|
355 |
Kern::Printf("BusWidthMode: %u", extcsd.BusWidthMode());
|
|
356 |
Kern::Printf("HighCapacityEraseGroupSize: %u", extcsd.HighCapacityEraseGroupSize());
|
|
357 |
Kern::Printf("AccessSize: %u", extcsd.AccessSize());
|
|
358 |
Kern::Printf("BootInfo: %u", extcsd.BootInfo() );
|
|
359 |
Kern::Printf("BootSizeMultiple: %u", extcsd.BootSizeMultiple() );
|
|
360 |
Kern::Printf("EraseTimeoutMultiple: %u", extcsd.EraseTimeoutMultiple() );
|
|
361 |
Kern::Printf("ReliableWriteSector: %u", extcsd.ReliableWriteSector() );
|
|
362 |
Kern::Printf("HighCapWriteProtGroupSize: %u", extcsd.HighCapacityWriteProtectGroupSize() );
|
|
363 |
Kern::Printf("SleepCurrentVcc: %u", extcsd.SleepCurrentVcc() );
|
|
364 |
Kern::Printf("SleepCurrentVccQ: %u", extcsd.SleepCurrentVccQ());
|
|
365 |
Kern::Printf("SleepAwakeTimeout: %u", extcsd.SleepAwakeTimeout());
|
|
366 |
Kern::Printf("BootConfig: %u", extcsd.BootConfig());
|
|
367 |
Kern::Printf("BootBusWidth: %u", extcsd.BootBusWidth());
|
|
368 |
Kern::Printf("EraseGroupDef: %u", extcsd.EraseGroupDef());
|
|
369 |
|
|
370 |
return KErrNone;
|
|
371 |
}
|
|
372 |
|
|
373 |
TInt DLddMmcCntrlInterface::DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2)
|
|
374 |
//
|
|
375 |
// Most Async requests
|
|
376 |
//
|
|
377 |
{
|
|
378 |
|
|
379 |
if (iMmcSessionCmd!=EMmcSesNone)
|
|
380 |
{
|
|
381 |
return(KErrInUse);
|
|
382 |
}
|
|
383 |
|
|
384 |
switch (aFunction)
|
|
385 |
{
|
|
386 |
case RMmcCntrlIf::EReqPwrUp:
|
|
387 |
{
|
|
388 |
if(!iSocketP->CardIsPresent())
|
|
389 |
{
|
|
390 |
Kern::RequestComplete(iClient, aStatus, KErrNotReady);
|
|
391 |
}
|
|
392 |
else if(iSocketP->State() == EPBusOn)
|
|
393 |
{
|
|
394 |
Kern::RequestComplete(iClient, aStatus, KErrNone);
|
|
395 |
}
|
|
396 |
else
|
|
397 |
{
|
|
398 |
iPowerUpStatusP = aStatus;
|
|
399 |
iSocketP->PowerUp();
|
|
400 |
}
|
|
401 |
break;
|
|
402 |
}
|
|
403 |
case RMmcCntrlIf::EReqReadSect:
|
|
404 |
{
|
|
405 |
if(iCard == NULL)
|
|
406 |
{
|
|
407 |
return(KErrNotReady);
|
|
408 |
}
|
|
409 |
|
|
410 |
//TCSD csd=iCard->CSD();
|
|
411 |
iReadWriteStatusP = aStatus;
|
|
412 |
TUint32 srcAddr=((TUint32)a1)<<KSectorSizeShift;
|
|
413 |
TUint readBlLen = 1 << iCard->MaxReadBlLen();
|
|
414 |
TUint readBlMask=(readBlLen-1);
|
|
415 |
iBlkOffet=srcAddr-(srcAddr&(~readBlMask));
|
|
416 |
iClientDesPtr=a2;
|
|
417 |
iMmcSessionCmd=EMmcSesReadBlk;
|
|
418 |
srcAddr&=(~readBlMask);
|
|
419 |
TMMCArgument da(srcAddr);
|
|
420 |
iSession->SetupCIMReadBlock(da,readBlLen,&iBuf[0]);
|
|
421 |
iSession->Engage();
|
|
422 |
break;
|
|
423 |
}
|
|
424 |
case RMmcCntrlIf::EReqWriteSect:
|
|
425 |
{
|
|
426 |
if(iCard == NULL)
|
|
427 |
{
|
|
428 |
return(KErrNotReady);
|
|
429 |
}
|
|
430 |
|
|
431 |
iReadWriteStatusP = aStatus;
|
|
432 |
TUint32 destAddr=((TUint32)a1)<<KSectorSizeShift;
|
|
433 |
TUint writeBlLen=1 << iCard->MaxWriteBlLen();
|
|
434 |
TUint writeBlMask=(writeBlLen-1);
|
|
435 |
iBlkOffet=destAddr-(destAddr&(~writeBlMask));
|
|
436 |
TPtr8* srcDes = (TPtr8*)a2;
|
|
437 |
TPtr8 ptr(&iBuf[iBlkOffet],KSectorSizeInBytes,KSectorSizeInBytes);
|
|
438 |
TInt r = Kern::ThreadDesRead(iClient, srcDes, ptr, 0, KChunkShiftBy0);
|
|
439 |
if(r != KErrNone)
|
|
440 |
{
|
|
441 |
return(r);
|
|
442 |
}
|
|
443 |
|
|
444 |
iMmcSessionCmd=EMmcSesWriteBlk;
|
|
445 |
destAddr&=(~writeBlMask);
|
|
446 |
iSession->SetupCIMWriteBlock(TMMCArgument(destAddr),writeBlLen,&iBuf[0]);
|
|
447 |
iSession->Engage();
|
|
448 |
break;
|
|
449 |
}
|
|
450 |
|
|
451 |
case RMmcCntrlIf::EReqReadExtCSD:
|
|
452 |
{
|
|
453 |
if(iCard == NULL)
|
|
454 |
{
|
|
455 |
return(KErrNotReady);
|
|
456 |
}
|
|
457 |
|
|
458 |
iClientDesPtr = a1;
|
|
459 |
iReadWriteStatusP = aStatus;
|
|
460 |
iMmcSessionCmd = EMmcSesReadExtCSD;
|
|
461 |
|
|
462 |
iSession->SetupDTCommand(
|
|
463 |
ECmdSendExtendedCSD,
|
|
464 |
TMMCArgument(0),
|
|
465 |
KMMCExtendedCSDLength,
|
|
466 |
(TUint8*) &iExtendedCSD);
|
|
467 |
|
|
468 |
iSession->Engage();
|
|
469 |
break;
|
|
470 |
}
|
|
471 |
|
|
472 |
case RMmcCntrlIf::EReqMMCInfoPrint:
|
|
473 |
{
|
|
474 |
// Print CSD & Extended CSD values
|
|
475 |
TInt r = PrintCardInfo();
|
|
476 |
Kern::RequestComplete(iClient, aStatus, r);
|
|
477 |
break;
|
|
478 |
}
|
|
479 |
|
|
480 |
}
|
|
481 |
return(KErrNone);
|
|
482 |
}
|
|
483 |
|
|
484 |
TInt DLddMmcCntrlInterface::DoControl(TInt aFunction,TAny* a1,TAny* /*a2*/)
|
|
485 |
//
|
|
486 |
// Mostly requests (but some kernel server async ones)
|
|
487 |
//
|
|
488 |
{
|
|
489 |
|
|
490 |
TInt r=KErrNotSupported;
|
|
491 |
switch (aFunction)
|
|
492 |
{
|
|
493 |
case RMmcCntrlIf::ESvReset:
|
|
494 |
{
|
|
495 |
Reset();
|
|
496 |
r=KErrNone;
|
|
497 |
break;
|
|
498 |
}
|
|
499 |
case RMmcCntrlIf::ESvPwrDown:
|
|
500 |
{
|
|
501 |
// iStack->PowerDown(); ???
|
|
502 |
// iMmcController->SetPowerEvent(0,EPEventPwrDownNormal,0);
|
|
503 |
r=KErrNone;
|
|
504 |
break;
|
|
505 |
}
|
|
506 |
case RMmcCntrlIf::EExecStackInfo:
|
|
507 |
{
|
|
508 |
// Determine the number of cards present
|
|
509 |
TUint cardsPresentMask=0x00000000;
|
|
510 |
TMMCard* card;
|
|
511 |
for (TInt i=0;i<KMaxMMCCardsPerStack;i++)
|
|
512 |
{
|
|
513 |
card=iStack->CardP(i);
|
|
514 |
if (card!=NULL && card->IsPresent())
|
|
515 |
cardsPresentMask|=(0x1<<i);
|
|
516 |
}
|
|
517 |
r = Kern::ThreadRawWrite(iClient,a1,&cardsPresentMask,sizeof(TUint));
|
|
518 |
break;
|
|
519 |
}
|
|
520 |
case RMmcCntrlIf::ESvRegisterEvent:
|
|
521 |
{
|
|
522 |
return(KErrNotSupported);
|
|
523 |
}
|
|
524 |
case RMmcCntrlIf::EExecSelectCard:
|
|
525 |
{
|
|
526 |
iCard=iStack->CardP((TUint)a1);
|
|
527 |
iSession->SetCard(iCard);
|
|
528 |
r=KErrNone;
|
|
529 |
break;
|
|
530 |
}
|
|
531 |
case RMmcCntrlIf::EExecCardInfo:
|
|
532 |
{
|
|
533 |
if (iCard)
|
|
534 |
{
|
|
535 |
TMmcCardInfo ci;
|
|
536 |
ci.iIsReady=iCard->IsPresent();
|
|
537 |
ci.iIsLocked=iCard->IsLocked();
|
|
538 |
TCID* cid=(TCID*)&(iCard->CID());
|
|
539 |
TInt i;
|
|
540 |
for (i=0;i<16;i++)
|
|
541 |
ci.iCID[i]=cid->At(i);
|
|
542 |
const TCSD& csd = iCard->CSD();
|
|
543 |
for (i=0;i<16;i++)
|
|
544 |
ci.iCSD[i]=csd.At(i);
|
|
545 |
ci.iRCA=TUint16(iCard->RCA());
|
|
546 |
ci.iMediaType=(TMmcMediaType)iCard->MediaType();
|
|
547 |
ci.iCardSizeInBytes=iCard->DeviceSize64();
|
|
548 |
ci.iReadBlLen=csd.ReadBlockLength();
|
|
549 |
ci.iWriteBlLen=csd.WriteBlockLength();
|
|
550 |
ci.iReadBlPartial=csd.ReadBlPartial();
|
|
551 |
ci.iWriteBlPartial=csd.WriteBlPartial();
|
|
552 |
ci.iReadBlkMisalign=csd.ReadBlkMisalign();
|
|
553 |
ci.iWriteBlkMisalign=csd.WriteBlkMisalign();
|
|
554 |
ci.iReadCurrentInMilliAmps=csd.MaxReadCurrentInMilliamps();
|
|
555 |
ci.iWriteCurrentInMilliAmps=csd.MaxWriteCurrentInMilliamps();
|
|
556 |
ci.iSpecVers=csd.SpecVers();
|
|
557 |
ci.iTAAC=csd.TAAC();
|
|
558 |
ci.iNSAC=csd.NSAC();
|
|
559 |
ci.iTransferSpeed=csd.TranSpeed();
|
|
560 |
ci.iCommandRegister=csd.CCC();
|
|
561 |
ci.iHighCapacity = iCard->IsHighCapacity();
|
|
562 |
r = Kern::ThreadRawWrite(iClient, a1/*TAny *aDest*/, &ci/*const TAny *aSrc*/, sizeof(TMmcCardInfo));
|
|
563 |
}
|
|
564 |
else
|
|
565 |
r=KErrGeneral;
|
|
566 |
break;
|
|
567 |
}
|
|
568 |
}
|
|
569 |
return(r);
|
|
570 |
}
|
|
571 |
|
|
572 |
void DLddMmcCntrlInterface::Reset()
|
|
573 |
//
|
|
574 |
// Release any resources
|
|
575 |
//
|
|
576 |
{
|
|
577 |
iSessionEndDfc.Cancel();
|
|
578 |
}
|
|
579 |
|
|
580 |
void DLddMmcCntrlInterface::SessionEndCallBack(TAny *aPtr)
|
|
581 |
//
|
|
582 |
// Session end callback
|
|
583 |
//
|
|
584 |
{
|
|
585 |
DLddMmcCntrlInterface &mci=*(DLddMmcCntrlInterface*)aPtr;
|
|
586 |
|
|
587 |
// Signal request complete using DFC
|
|
588 |
if (!mci.iSessionEndDfc.Queued())
|
|
589 |
mci.iSessionEndDfc.Enque();
|
|
590 |
}
|
|
591 |
|
|
592 |
void DLddMmcCntrlInterface::SessionEndDfc(TAny *aPtr)
|
|
593 |
//
|
|
594 |
// Session end dfc
|
|
595 |
//
|
|
596 |
{
|
|
597 |
DLddMmcCntrlInterface &mci=*(DLddMmcCntrlInterface*)aPtr;
|
|
598 |
TInt err=mci.iSession->EpocErrorCode();
|
|
599 |
switch (mci.iMmcSessionCmd)
|
|
600 |
{
|
|
601 |
case EMmcSesReadBlk:
|
|
602 |
{
|
|
603 |
TPtr8 ptr(&mci.iBuf[mci.iBlkOffet],KSectorSizeInBytes,KSectorSizeInBytes);
|
|
604 |
TPtrC8* srcDes = (TPtrC8*)mci.iClientDesPtr;
|
|
605 |
TInt r = Kern::ThreadDesWrite(mci.iClient,srcDes,ptr,0,mci.iClient);
|
|
606 |
|
|
607 |
Kern::RequestComplete(mci.iClient, mci.iReadWriteStatusP, (r == KErrNone) ? err : r);
|
|
608 |
break;
|
|
609 |
}
|
|
610 |
case EMmcSesWriteBlk:
|
|
611 |
{
|
|
612 |
Kern::Printf("EMmcSesWriteBlk Complete");
|
|
613 |
Kern::RequestComplete(mci.iClient, mci.iReadWriteStatusP, err);
|
|
614 |
break;
|
|
615 |
}
|
|
616 |
case EMmcSesReadExtCSD:
|
|
617 |
{
|
|
618 |
TPtr8 ptr((TUint8*) &mci.iExtendedCSD, KMMCExtendedCSDLength, KMMCExtendedCSDLength);
|
|
619 |
TPtrC8* dstDes = (TPtrC8*)mci.iClientDesPtr;
|
|
620 |
TInt r = Kern::ThreadDesWrite(mci.iClient, dstDes, ptr, 0,mci.iClient);
|
|
621 |
|
|
622 |
Kern::RequestComplete(mci.iClient, mci.iReadWriteStatusP, (r == KErrNone) ? err : r);
|
|
623 |
break;
|
|
624 |
}
|
|
625 |
default:
|
|
626 |
break;
|
|
627 |
}
|
|
628 |
mci.iMmcSessionCmd=EMmcSesNone;
|
|
629 |
}
|
|
630 |
|
|
631 |
void DLddMmcCntrlInterface::EventCallBack(TAny* aPtr, TInt aReason, TAny* a1, TAny* a2)
|
|
632 |
{
|
|
633 |
DLddMmcCntrlInterface &mci=*(DLddMmcCntrlInterface*)aPtr;
|
|
634 |
|
|
635 |
if(mci.iPowerUpStatusP)
|
|
636 |
{
|
|
637 |
TInt retCode = KErrCompletion;
|
|
638 |
|
|
639 |
switch(aReason)
|
|
640 |
{
|
|
641 |
case TPBusCallBack::EPBusStateChange:
|
|
642 |
{
|
|
643 |
TPBusState newState = (TPBusState)(TInt)a1;
|
|
644 |
TInt errorCode = (TInt)a2;
|
|
645 |
|
|
646 |
switch(newState)
|
|
647 |
{
|
|
648 |
case EPBusCardAbsent: retCode = KErrNotFound; break;
|
|
649 |
case EPBusOff: retCode = errorCode; break;
|
|
650 |
case EPBusPsuFault: retCode = KErrBadPower; break;
|
|
651 |
case EPBusOn: retCode = KErrNone; break;
|
|
652 |
case EPBusPowerUpPending:
|
|
653 |
case EPBusPoweringUp:
|
|
654 |
default:
|
|
655 |
break;
|
|
656 |
}
|
|
657 |
|
|
658 |
break;
|
|
659 |
}
|
|
660 |
}
|
|
661 |
|
|
662 |
if(retCode != KErrCompletion)
|
|
663 |
{
|
|
664 |
Kern::RequestComplete(mci.iClient, mci.iPowerUpStatusP, retCode);
|
|
665 |
mci.iPowerUpStatusP = NULL;
|
|
666 |
}
|
|
667 |
}
|
|
668 |
}
|
|
669 |
|
|
670 |
|