First public contribution.
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
23 #include "d_mmcsdif.h"
27 const TInt KMajorVersionNumber=1;
28 const TInt KMinorVersionNumber=0;
29 const TInt KBuildVersionNumber=0;
32 TDynamicDfcQue* gDfcQ;
36 DECLARE_STANDARD_LDD()
38 return new DLddFactoryMmcCntrlInterface;
42 * DLddFactoryMmcCntrlInterface constructor
48 DLddFactoryMmcCntrlInterface::DLddFactoryMmcCntrlInterface()
50 iParseMask=KDeviceAllowUnit; // Pass stack number as unit
51 iUnitsMask=0xffffffff;
52 iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
56 * Create logical channel
58 * @param DLogicalChannelBase*& aChannel - logical channel
60 * @return TInt the error code
64 TInt DLddFactoryMmcCntrlInterface::Create(DLogicalChannelBase*& aChannel)
66 aChannel = new DLddMmcCntrlInterface;
67 return aChannel ? KErrNone : KErrNoMemory;
70 const TInt KDMmcThreadPriority = 27;
71 _LIT(KDMmcThread,"DMMCSDThread");
77 * @return TInt the error code
81 TInt DLddFactoryMmcCntrlInterface::Install()
83 // Allocate a kernel thread to run the DFC
84 TInt r = Kern::DynamicDfcQCreate(gDfcQ, KDMmcThreadPriority, KDMmcThread);
88 __KTRACE_OPT(KHARDWARE,MMCSDLOG("installing driver name from factory"));
89 return SetName(&KLddName);
93 * Get the Pc Card Contoller Interface ldd's version info
95 * @param TDes8 &aDes - Buffer to contain version info
101 void DLddFactoryMmcCntrlInterface::GetCaps(TDes8 &aDes) const
104 b.version=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
105 aDes.FillZ(aDes.MaxLength());
106 aDes.Copy((TUint8 *)&b,Min(aDes.MaxLength(),sizeof(b)));
116 DLddFactoryMmcCntrlInterface::~DLddFactoryMmcCntrlInterface()
123 * DLddMmcCntrlInterface constructor
129 DLddMmcCntrlInterface::DLddMmcCntrlInterface()
131 iClient = &Kern::CurrentThread();
132 ((DObject*)iClient)->Open(); // can't fail since thread is running
142 DLddMmcCntrlInterface::~DLddMmcCntrlInterface()
144 Kern::SafeClose((DObject*&)iClient,NULL);
145 iAsyncList.ResetAndDestroy();
149 * Create driver ojects
151 * @param TInt aUnit - Socket ID
152 * @param const TDesC8* aInfo - Buffer for logging
153 * @param const TVersion& aVer - Current version
155 * @return TInt the error code
159 TInt DLddMmcCntrlInterface::DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
161 if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer))
162 return(KErrNotSupported);
164 MMCSDLOG2("DLddMmcCntrlInterface::DoCreate called aInfo(%S)", aInfo);
166 // create the socket - there is only a DMMCSocket
167 iSocket = static_cast<DMMCSocket*>(DPBusSocket::SocketFromId(aUnit));
169 return(KErrNoMemory);
171 //Obtain the appropriate card from the stack
172 iStack = static_cast<DMMCStack*>(iSocket->Stack(KStackNo));
174 return(KErrNoMemory);
176 //Obtain the appropriate card power supply
177 iPsu=static_cast<DMMCPsu*>(iSocket->iVcc);
179 return(KErrNoMemory);
181 //Obtain the appropriate card Media change
182 iMediaChange=static_cast<DMMCMediaChange*>(iSocket->iMediaChange);
183 if (iMediaChange==NULL)
184 return(KErrNoMemory);
189 iUnit = aUnit; // save the unit - needed for regitering callbacks for subsequent bus events
195 * Request cancelled callback
197 * @param TInt sReqNo - Request Number
203 void DLddMmcCntrlInterface::DoCancel(TInt /*aReqNo*/)
208 * Handle kernel side message
210 * @param TMessageBase* aMsg - The kernel side message
216 void DLddMmcCntrlInterface::HandleMsg(TMessageBase* aMsg)
218 TThreadMessage& m=*(TThreadMessage*)aMsg;
221 if (id==(TInt)ECloseMsg)
223 m.Complete(KErrNone, EFalse);
226 else if (id==KMaxTInt)
229 m.Complete(KErrNone,ETrue);
236 TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
237 TInt r=DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
239 Kern::RequestComplete(iClient, pS, r);
240 m.Complete(KErrNone,ETrue);
245 TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
246 if(r != KErrCompletion)
254 * Do a kernel side request
256 * @param TInt aFunction - Request Function ID
257 * @param TRequestStatus* aStatus - Request Status
258 * @param TAny* a1 - Given parameter
259 * @param TAny* a2 - Given parameter
261 * @return TInt the error code
265 TInt DLddMmcCntrlInterface::DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny *a2)
268 TTCFunctionId fid = TTCFunctionId(aFunction);
269 switch(fid.TestType())
272 return SocketDoRequest(aStatus, a1, a2, aFunction);
276 case EMmcTestMediaChange:
277 case EMmcGeneralTest:
282 switch(fid.FunctionId())
284 case RMMCSDTestControllerInterface::EReadSector:
286 // read sector a1 is block number, a2 is client descriptor
287 // data will be written back to upon completion
288 MMCSDLOG3("RMMCSDTestControllerInterface::EReadSector a1(%d) a2(%x)", (TUint32)a1, a2);
291 MMCSDLOG("RMMCSDTestControllerInterface::EReadSector NULL card\n");
295 DMmcSessionAsyncRequest* request = CreateAsyncSessionRequest(EMmcSesReadBlk, aStatus);
297 TUint32 srcAddr=((TUint32)a1)<<KSectorSizeShift;
298 TUint readBlLen = 1 << iCard->MaxReadBlLen();
299 TUint readBlMask=(readBlLen-1);
300 request->iBlkOffet=srcAddr-(srcAddr&(~readBlMask));
301 request->iClientDesPtr = a2;
302 srcAddr &= (~readBlMask);
304 MMCSDLOG("RMMCSDTestControllerInterface::EReadSector #2");
305 TMMCArgument da(srcAddr);
307 request->Session().SetupCIMReadBlock(da,readBlLen,&(request->iBuf[0]));
308 request->Session().Engage();
310 MMCSDLOG("RMMCSDTestControllerInterface::EReadSector #3");
313 case RMMCSDTestControllerInterface::EWriteSector:
315 MMCSDLOG3("RMMCSDTestControllerInterface::EWriteSector a1(%d) a2(%x) #1", (TUint32)a1, a2);
318 MMCSDLOG("RMMCSDTestControllerInterface::EWriteSector NULL card\n");
322 TUint32 destAddr=((TUint32)a1)<<KSectorSizeShift;
323 TUint writeBlLen=1 << iCard->MaxWriteBlLen();
325 DMmcSessionAsyncRequest* request = CreateAsyncSessionRequest(EMmcSesWriteBlk, aStatus);
327 TUint writeBlMask=(writeBlLen-1);
328 request->iBlkOffet=destAddr-(destAddr&(~writeBlMask));
329 TPtr8* srcDes = (TPtr8*)a2;
330 TPtr8 ptr(&(request->iBuf[request->iBlkOffet]),KSectorSizeInBytes,KSectorSizeInBytes);
331 TInt r = Kern::ThreadDesRead(iClient, srcDes, ptr, 0, KChunkShiftBy0);
337 destAddr&=(~writeBlMask);
338 request->Session().SetupCIMWriteBlock(TMMCArgument(destAddr),writeBlLen,&(request->iBuf[0]));
339 request->Session().Engage();
341 MMCSDLOG("RMMCSDTestControllerInterface::EWriteSector #4");
349 * Do a kernel side control
351 * @param TInt aFunction - Request Function ID
352 * @param TAny* a1 - Given parameter
353 * @param TAny* a2 - Given parameter
355 * @return TInt the error code
359 TInt DLddMmcCntrlInterface::DoControl(TInt aFunction,TAny* a1,TAny* a2)
361 TInt r = KErrNotSupported;
362 TTCFunctionId fid = TTCFunctionId(aFunction);
363 MMCSDLOG4("DLddMmcCntrlInterface::DoControl aFunction(%d) \
364 fid.FunctionId()(%d) fid.TestType(%d)"
365 , aFunction, fid.FunctionId(), fid.TestType());
367 switch(fid.TestType())
370 return StackDoControl(aFunction, a1, a2);
372 return SocketDoControl(aFunction, a1, a2);
374 return PsuDoControl(aFunction, a1, a2);
375 case EMmcTestMediaChange:
376 return MediaChangeDoControl(aFunction, a1, a2);
377 case EMmcGeneralTest:
382 switch (fid.FunctionId())
384 case RMMCSDTestControllerInterface::EReadCSD:
388 TCSDInfo csdInfo(iCSD);
389 r = Kern::ThreadRawWrite(iClient, a1, &csdInfo, sizeof(csdInfo));
394 case RMMCSDTestControllerInterface::EReadExtCSD:
396 iExtendedCSD = iCard->ExtendedCSD();
397 TExtendedCSDInfo extendedCSDInfo(iExtendedCSD);
398 r = Kern::ThreadRawWrite(iClient, a1, &extendedCSDInfo, sizeof(extendedCSDInfo));
402 case RMMCSDTestControllerInterface::ECardInfo:
404 TMMCCardInfo cardInfo;
405 cardInfo.SetCardInfo(*iCard);
406 r = Kern::ThreadRawWrite(iClient, a1, &cardInfo, sizeof(cardInfo));
410 case RMMCSDTestControllerInterface::ECard:
412 r = Kern::ThreadRawWrite(iClient, a1, &iCard, sizeof(iCard));
416 case RMMCSDTestControllerInterface::ECardIsPresent:
418 TBool isPresent = iCard->IsPresent();
419 r = Kern::ThreadRawWrite(iClient, a1, &isPresent, sizeof(isPresent));
423 case RMMCSDTestControllerInterface::ECardIsReady:
425 TBool isReady = iCard->IsReady();
426 r = Kern::ThreadRawWrite(iClient, a1, &isReady, sizeof(isReady));
430 case RMMCSDTestControllerInterface::ECardIsLocked:
432 TBool isLocked = iCard->IsLocked();
433 r = Kern::ThreadRawWrite(iClient, a1, &isLocked, sizeof(isLocked));
439 MMCSDLOG2("DLddMmcCntrlInterface::DoControl - Invalid FunctionId()(%d)", fid.FunctionId());
449 * Check if a request status exists
451 * @param TRequestStatus* aStatus - Request Status
453 * @return TBool A request status exists
457 TBool DLddMmcCntrlInterface::RequestStatusExists(TRequestStatus* aStatus)
460 // check whether this request status already exists in the async request list
461 for(int i=0;i<iAsyncList.Count();i++)
463 MMCSDLOG3("Checking index(%d) iAsyncList[i]->Status(%x)", i, iAsyncList[i]->Status());
465 if(iAsyncList[i]->Status() == aStatus)
467 MMCSDLOG3("WaRNING - adding duplicate TRequestStatus index[%d] aStatus(%x)", i, aStatus);
476 * Create Asynchronous Session Request
478 * @param TMmcAsyncCmd aFunctionId - Request Function ID
479 * @param TRequestStatus* aStatus - Request Status
481 * @return DMmcSessionAsyncRequest* Poniter to the created session request object
485 DMmcSessionAsyncRequest* DLddMmcCntrlInterface::CreateAsyncSessionRequest(TMmcAsyncCmd aFunctionId, TRequestStatus* aStatus)
488 MMCSDLOG3("DLddMmcCntrlInterface::CreateAsyncRequest aStatus(%x) num requests in list (%d)",
489 aStatus, iAsyncList.Count());
491 // create an async request & append to async request list
492 DMmcSessionAsyncRequest* request = new DMmcSessionAsyncRequest(aFunctionId, aStatus, *this, gDfcQ, *iStack, *iCard);
493 iAsyncList.Append(request);
494 MMCSDLOG4("DLddMmcCntrlInterface::CreateAsyncSessionRequest created OK Status(%x) functionID(%d) aFunctionId(%d)",
495 request->Status(), request->FunctionId(), aFunctionId);
500 * Create Asynchronous Bus Event Request
502 * @param TMmcAsyncCmd aFunctionId - Request Function ID
503 * @param TRequestStatus* aStatus - Request Status
504 * @param TInt aUnit - Socket ID
506 * @return DBusEventRequest* Poniter to the created bus event request object
510 DBusEventRequest* DLddMmcCntrlInterface::CreateAsyncBusEventRequest(TMmcAsyncCmd aFunctionId, TRequestStatus* aStatus, TInt aUnit)
512 MMCSDLOG3("DLddMmcCntrlInterface::CreateAsyncBusEventRequest aStatus(%x) num requests in list (%d)",
513 aStatus, iAsyncList.Count());
515 MMCSDLOG4("gDfcQ(%x), iStack(%x), iCard(%x)", gDfcQ, iStack, iCard);
517 // create an async request & append toS async request list
518 DBusEventRequest* request = new DBusEventRequest(aFunctionId, aStatus, *this, aUnit, gDfcQ, *iStack, *iCard);
519 iAsyncList.Append(request);
520 MMCSDLOG4("DLddMmcCntrlInterface::CreateAsyncBusEventRequest created OK Status(%x) functionID(%d) aFunctionId(%d)",
521 request->Status(), request->FunctionId(), aFunctionId);
527 * Clears an asynchronous Request from list
529 * @param DLddAsyncRequest* aRequest - Pointer to the request
535 void DLddMmcCntrlInterface::ClearRequest(DLddAsyncRequest* aRequest)
539 MMCSDLOG("ERROR IN DLddMmcCntrlInterface::ClearRequest NULL request");
543 TInt i = iAsyncList.Find(aRequest);
546 iAsyncList.Remove(i);
550 MMCSDLOG2("ERROR IN DLddMmcCntrlInterface::ClearRequest err(%d)", i);
558 * Callback when request has completed
560 * @param DLddAsyncRequest& aRequest - The completed request
566 void DLddMmcCntrlInterface::Notify(DLddAsyncRequest& aRequest) // callback from DLddAsyncRequest
568 MMCSDLOG("DLddMmcCntrlInterface::Notify called");
569 TRequestStatus* status = aRequest.Status();
570 switch (aRequest.FunctionId())
572 case DLddMmcCntrlInterface::EMmcSesReadBlk:
574 DMmcSessionAsyncRequest& request = (DMmcSessionAsyncRequest&) aRequest;
575 MMCSDLOG("DLddMmcCntrlInterface::ReadBlockComplete");
577 if (request.iClientDesPtr) // have we supplied descriptor to hold returned data
579 TPtr8 ptr(&(request.iBuf[request.iBlkOffet]), KSectorSizeInBytes, KSectorSizeInBytes);
580 TPtrC8* srcDes = (TPtrC8*)request.iClientDesPtr;
581 r = Kern::ThreadDesWrite(iClient, srcDes, ptr, 0, iClient);
584 MMCSDLOG2("ERROR DLddMmcCntrlInterface::ReadBlockComplete Kern::ThreadDesWrite returned r(%d)", r);
589 MMCSDLOG("ERROR DLddMmcCntrlInterface::ReadExtCSDComplete - No pointer provided to hold returned data");
590 Kern::PanicCurrentThread(_L("PBUS-MMC"), 0);
592 Kern::RequestComplete(iClient, status, (r == KErrNone) ? aRequest.Error() : r);
596 case DLddMmcCntrlInterface::EMmcSesWriteBlk:
598 MMCSDLOG("DLddMmcCntrlInterface::WriteBlockComplete)");
599 TRequestStatus* status = aRequest.Status();
600 Kern::RequestComplete(iClient, status, aRequest.Error());
604 case DLddMmcCntrlInterface::EMmcSesReadCSD:
606 DMmcSessionAsyncRequest& request = (DMmcSessionAsyncRequest&) aRequest;
607 MMCSDLOG("DLddMmcCntrlInterface::ReadCSDComplete");
609 if (request.iClientDesPtr) // have we supplied pointer to hold returned data
612 TCSDInfo csdInfo(iCSD);
613 r = Kern::ThreadRawWrite(iClient, request.iClientDesPtr, &csdInfo, sizeof(csdInfo));
617 MMCSDLOG2("ERROR DLddMmcCntrlInterface::ReadCSDComplete Kern::ThreadRawWrite returned r(%d)", r);
622 MMCSDLOG("ERROR DLddMmcCntrlInterface::ReadExtCSDComplete - No pointer provided to hold returned data");
623 Kern::PanicCurrentThread(_L("PBUS-MMC"), 0);
625 Kern::RequestComplete(iClient, status, (r == KErrNone) ? aRequest.Error() : r);
629 case DLddMmcCntrlInterface::EMmcSesReadExtCSD:
631 DMmcSessionAsyncRequest& request = (DMmcSessionAsyncRequest&) aRequest;
632 MMCSDLOG("DLddMmcCntrlInterface::ReadExtCSDComplete");
634 if (request.iClientDesPtr) // have we supplied pointer to hold returned data
636 TExtendedCSDInfo extendedCSDInfo(iExtendedCSD);
637 r = Kern::ThreadRawWrite(iClient, request.iClientDesPtr, &extendedCSDInfo, sizeof(extendedCSDInfo));
640 MMCSDLOG2("ERROR DLddMmcCntrlInterface::ReadExtCSDComplete Kern::ThreadRawWrite returned r(%d)", r);
645 MMCSDLOG("ERROR DLddMmcCntrlInterface::ReadExtCSDComplete - No pointer provided to hold returned data");
646 Kern::PanicCurrentThread(_L("PBUS-MMC"), 0);
648 Kern::RequestComplete(iClient, status, (r == KErrNone) ? aRequest.Error() : r);
652 case DLddMmcCntrlInterface::EMMcSocketPowerUp:
654 DBusEventRequest& request = (DBusEventRequest&) aRequest;
655 TInt retCode = KErrNone;
657 MMCSDLOG2("DLddMmcCntrlInterface::EMMcSocketPowerUp ret code = %d", aRequest.Error());
658 MMCSDLOG2("DLddMmcCntrlInterface::EMMcSocketPowerUp request.BusState() = %d", request.BusState());
659 MMCSDLOG2("DLddMmcCntrlInterface::EMMcSocketPowerUp request.BusError() = %d", request.BusError());
661 switch(aRequest.Error())
663 case TPBusCallBack::EPBusStateChange:
665 TPBusState newState = request.BusState();
666 retCode = request.BusError();
668 if (retCode == KErrNone)
672 case EPBusCardAbsent: retCode = KErrNotFound; break;
673 case EPBusPsuFault: retCode = KErrBadPower; break;
676 case EPBusPowerUpPending:
677 case EPBusPoweringUp:
687 Kern::RequestComplete(iClient, status, retCode);
692 MMCSDLOG("#######################################################################");
693 MMCSDLOG("## UNHANDLED END DFC DLddAsyncRequest DLddMmcCntrlInterface::Notify ##");
694 MMCSDLOG2("## aRequest.FunctionId(%d) ##", aRequest.FunctionId());
695 MMCSDLOG("#######################################################################");
696 Kern::PanicCurrentThread(_L("PBUS-MMC"), 0);
700 ClearRequest(&aRequest);