TianoCore EDK2 master
Loading...
Searching...
No Matches
SdMmcPciHcDxe.c
Go to the documentation of this file.
1
15#include "SdMmcPciHcDxe.h"
16
17EDKII_SD_MMC_OVERRIDE *mOverride;
18
19//
20// Driver Global Variables
21//
22EFI_DRIVER_BINDING_PROTOCOL gSdMmcPciHcDriverBinding = {
26 0x10,
27 NULL,
28 NULL
29};
30
31#define SLOT_INIT_TEMPLATE {0, UnknownSlot, 0, 0, 0, 0,\
32 {EDKII_SD_MMC_BUS_WIDTH_IGNORE,\
33 EDKII_SD_MMC_CLOCK_FREQ_IGNORE,\
34 {EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE}}}
35
36//
37// Template for SD/MMC host controller private data.
38//
39SD_MMC_HC_PRIVATE_DATA gSdMmcPciHcTemplate = {
40 SD_MMC_HC_PRIVATE_SIGNATURE, // Signature
41 NULL, // ControllerHandle
42 NULL, // PciIo
43 { // PassThru
44 sizeof (UINT32),
50 },
51 0, // PciAttributes
52 0, // PreviousSlot
53 NULL, // TimerEvent
54 NULL, // ConnectEvent
55 // Queue
56 INITIALIZE_LIST_HEAD_VARIABLE (gSdMmcPciHcTemplate.Queue),
57 { // Slot
58 SLOT_INIT_TEMPLATE,
59 SLOT_INIT_TEMPLATE,
60 SLOT_INIT_TEMPLATE,
61 SLOT_INIT_TEMPLATE,
62 SLOT_INIT_TEMPLATE,
63 SLOT_INIT_TEMPLATE
64 },
65 { // Capability
66 { 0 },
67 },
68 { // MaxCurrent
69 0,
70 },
71 {
72 0 // ControllerVersion
73 }
74};
75
76SD_DEVICE_PATH mSdDpTemplate = {
77 {
80 {
81 (UINT8)(sizeof (SD_DEVICE_PATH)),
82 (UINT8)((sizeof (SD_DEVICE_PATH)) >> 8)
83 }
84 },
85 0
86};
87
88EMMC_DEVICE_PATH mEmmcDpTemplate = {
89 {
92 {
93 (UINT8)(sizeof (EMMC_DEVICE_PATH)),
94 (UINT8)((sizeof (EMMC_DEVICE_PATH)) >> 8)
95 }
96 },
97 0
98};
99
100//
101// Prioritized function list to detect card type.
102// User could add other card detection logic here.
103//
104CARD_TYPE_DETECT_ROUTINE mCardTypeDetectRoutineTable[] = {
107 NULL
108};
109
121EFIAPI
123 IN EFI_HANDLE ImageHandle,
124 IN EFI_SYSTEM_TABLE *SystemTable
125 )
126{
127 EFI_STATUS Status;
128
130 ImageHandle,
131 SystemTable,
132 &gSdMmcPciHcDriverBinding,
133 ImageHandle,
134 &gSdMmcPciHcComponentName,
135 &gSdMmcPciHcComponentName2
136 );
137 ASSERT_EFI_ERROR (Status);
138
139 return Status;
140}
141
150VOID
151EFIAPI
153 IN EFI_EVENT Event,
154 IN VOID *Context
155 )
156{
157 SD_MMC_HC_PRIVATE_DATA *Private;
158 LIST_ENTRY *Link;
159 SD_MMC_HC_TRB *Trb;
160 EFI_STATUS Status;
162 BOOLEAN InfiniteWait;
163 EFI_EVENT TrbEvent;
164
165 Private = (SD_MMC_HC_PRIVATE_DATA *)Context;
166
167 //
168 // Check if the first entry in the async I/O queue is done or not.
169 //
170 Status = EFI_SUCCESS;
171 Trb = NULL;
172 Link = GetFirstNode (&Private->Queue);
173 if (!IsNull (&Private->Queue, Link)) {
174 Trb = SD_MMC_HC_TRB_FROM_THIS (Link);
175 if (!Private->Slot[Trb->Slot].MediaPresent) {
176 Status = EFI_NO_MEDIA;
177 goto Done;
178 }
179
180 if (!Trb->Started) {
181 //
182 // Check whether the cmd/data line is ready for transfer.
183 //
184 Status = SdMmcCheckTrbEnv (Private, Trb);
185 if (!EFI_ERROR (Status)) {
186 Trb->Started = TRUE;
187 Status = SdMmcExecTrb (Private, Trb);
188 if (EFI_ERROR (Status)) {
189 goto Done;
190 }
191 } else {
192 goto Done;
193 }
194 }
195
196 Status = SdMmcCheckTrbResult (Private, Trb);
197 }
198
199Done:
200 if ((Trb != NULL) && (Status == EFI_NOT_READY)) {
201 Packet = Trb->Packet;
202 if (Packet->Timeout == 0) {
203 InfiniteWait = TRUE;
204 } else {
205 InfiniteWait = FALSE;
206 }
207
208 if ((!InfiniteWait) && (Trb->Timeout-- == 0)) {
209 RemoveEntryList (Link);
210 Trb->Packet->TransactionStatus = EFI_TIMEOUT;
211 TrbEvent = Trb->Event;
212 SdMmcFreeTrb (Trb);
213 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT\n", TrbEvent));
214 gBS->SignalEvent (TrbEvent);
215 return;
216 }
217 } else if ((Trb != NULL) && (Status == EFI_CRC_ERROR) && (Trb->Retries > 0)) {
218 Trb->Retries--;
219 Trb->Started = FALSE;
220 } else if ((Trb != NULL)) {
221 RemoveEntryList (Link);
222 Trb->Packet->TransactionStatus = Status;
223 TrbEvent = Trb->Event;
224 SdMmcFreeTrb (Trb);
225 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p with %r\n", TrbEvent, Status));
226 gBS->SignalEvent (TrbEvent);
227 }
228
229 return;
230}
231
240VOID
241EFIAPI
243 IN EFI_EVENT Event,
244 IN VOID *Context
245 )
246{
247 SD_MMC_HC_PRIVATE_DATA *Private;
248 EFI_STATUS Status;
249 UINT8 Slot;
250 BOOLEAN MediaPresent;
251 UINT32 RoutineNum;
253 UINTN Index;
254 LIST_ENTRY *Link;
255 LIST_ENTRY *NextLink;
256 SD_MMC_HC_TRB *Trb;
257 EFI_TPL OldTpl;
258
259 Private = (SD_MMC_HC_PRIVATE_DATA *)Context;
260
261 for (Slot = 0; Slot < SD_MMC_HC_MAX_SLOT; Slot++) {
262 if ((Private->Slot[Slot].Enable) && (Private->Slot[Slot].SlotType == RemovableSlot)) {
263 Status = SdMmcHcCardDetect (Private->PciIo, Slot, &MediaPresent);
264 if ((Status == EFI_MEDIA_CHANGED) && !MediaPresent) {
265 DEBUG ((DEBUG_INFO, "SdMmcPciHcEnumerateDevice: device disconnected at slot %d of pci %p\n", Slot, Private->PciIo));
266 Private->Slot[Slot].MediaPresent = FALSE;
267 Private->Slot[Slot].Initialized = FALSE;
268 //
269 // Signal all async task events at the slot with EFI_NO_MEDIA status.
270 //
271 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
272 for (Link = GetFirstNode (&Private->Queue);
273 !IsNull (&Private->Queue, Link);
274 Link = NextLink)
275 {
276 NextLink = GetNextNode (&Private->Queue, Link);
277 Trb = SD_MMC_HC_TRB_FROM_THIS (Link);
278 if (Trb->Slot == Slot) {
279 RemoveEntryList (Link);
280 Trb->Packet->TransactionStatus = EFI_NO_MEDIA;
281 gBS->SignalEvent (Trb->Event);
282 SdMmcFreeTrb (Trb);
283 }
284 }
285
286 gBS->RestoreTPL (OldTpl);
287 //
288 // Notify the upper layer the connect state change through ReinstallProtocolInterface.
289 //
290 gBS->ReinstallProtocolInterface (
291 Private->ControllerHandle,
292 &gEfiSdMmcPassThruProtocolGuid,
293 &Private->PassThru,
294 &Private->PassThru
295 );
296 }
297
298 if ((Status == EFI_MEDIA_CHANGED) && MediaPresent) {
299 DEBUG ((DEBUG_INFO, "SdMmcPciHcEnumerateDevice: device connected at slot %d of pci %p\n", Slot, Private->PciIo));
300 //
301 // Reset the specified slot of the SD/MMC Pci Host Controller
302 //
303 Status = SdMmcHcReset (Private, Slot);
304 if (EFI_ERROR (Status)) {
305 continue;
306 }
307
308 //
309 // Reinitialize slot and restart identification process for the new attached device
310 //
311 Status = SdMmcHcInitHost (Private, Slot);
312 if (EFI_ERROR (Status)) {
313 continue;
314 }
315
316 Private->Slot[Slot].MediaPresent = TRUE;
317 Private->Slot[Slot].Initialized = TRUE;
318 RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE);
319 for (Index = 0; Index < RoutineNum; Index++) {
320 Routine = &mCardTypeDetectRoutineTable[Index];
321 if (*Routine != NULL) {
322 Status = (*Routine)(Private, Slot);
323 if (!EFI_ERROR (Status)) {
324 break;
325 }
326 }
327 }
328
329 //
330 // This card doesn't get initialized correctly.
331 //
332 if (Index == RoutineNum) {
333 Private->Slot[Slot].Initialized = FALSE;
334 }
335
336 //
337 // Notify the upper layer the connect state change through ReinstallProtocolInterface.
338 //
339 gBS->ReinstallProtocolInterface (
340 Private->ControllerHandle,
341 &gEfiSdMmcPassThruProtocolGuid,
342 &Private->PassThru,
343 &Private->PassThru
344 );
345 }
346 }
347 }
348
349 return;
350}
351
395EFIAPI
398 IN EFI_HANDLE Controller,
399 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
400 )
401{
402 EFI_STATUS Status;
403 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
404 EFI_PCI_IO_PROTOCOL *PciIo;
405 PCI_TYPE00 PciData;
406
407 PciIo = NULL;
408 ParentDevicePath = NULL;
409
410 //
411 // SdPciHcDxe is a device driver, and should ingore the
412 // "RemainingDevicePath" according to EFI spec.
413 //
414 Status = gBS->OpenProtocol (
415 Controller,
416 &gEfiDevicePathProtocolGuid,
417 (VOID *)&ParentDevicePath,
418 This->DriverBindingHandle,
419 Controller,
420 EFI_OPEN_PROTOCOL_BY_DRIVER
421 );
422 if (EFI_ERROR (Status)) {
423 //
424 // EFI_ALREADY_STARTED is also an error.
425 //
426 return Status;
427 }
428
429 //
430 // Close the protocol because we don't use it here.
431 //
432 gBS->CloseProtocol (
433 Controller,
434 &gEfiDevicePathProtocolGuid,
435 This->DriverBindingHandle,
436 Controller
437 );
438
439 //
440 // Now test the EfiPciIoProtocol.
441 //
442 Status = gBS->OpenProtocol (
443 Controller,
444 &gEfiPciIoProtocolGuid,
445 (VOID **)&PciIo,
446 This->DriverBindingHandle,
447 Controller,
448 EFI_OPEN_PROTOCOL_BY_DRIVER
449 );
450 if (EFI_ERROR (Status)) {
451 return Status;
452 }
453
454 //
455 // Now further check the PCI header: Base class (offset 0x08) and
456 // Sub Class (offset 0x05). This controller should be an SD/MMC PCI
457 // Host Controller.
458 //
459 Status = PciIo->Pci.Read (
460 PciIo,
461 EfiPciIoWidthUint8,
462 0,
463 sizeof (PciData),
464 &PciData
465 );
466 if (EFI_ERROR (Status)) {
467 gBS->CloseProtocol (
468 Controller,
469 &gEfiPciIoProtocolGuid,
470 This->DriverBindingHandle,
471 Controller
472 );
473 return EFI_UNSUPPORTED;
474 }
475
476 //
477 // Since we already got the PciData, we can close protocol to avoid to carry it
478 // on for multiple exit points.
479 //
480 gBS->CloseProtocol (
481 Controller,
482 &gEfiPciIoProtocolGuid,
483 This->DriverBindingHandle,
484 Controller
485 );
486
487 //
488 // Examine SD PCI Host Controller PCI Configuration table fields.
489 //
490 if ((PciData.Hdr.ClassCode[2] == PCI_CLASS_SYSTEM_PERIPHERAL) &&
491 (PciData.Hdr.ClassCode[1] == PCI_SUBCLASS_SD_HOST_CONTROLLER) &&
492 ((PciData.Hdr.ClassCode[0] == 0x00) || (PciData.Hdr.ClassCode[0] == 0x01)))
493 {
494 return EFI_SUCCESS;
495 }
496
497 return EFI_UNSUPPORTED;
498}
499
536EFIAPI
539 IN EFI_HANDLE Controller,
540 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
541 )
542{
543 EFI_STATUS Status;
544 SD_MMC_HC_PRIVATE_DATA *Private;
545 EFI_PCI_IO_PROTOCOL *PciIo;
546 UINT64 Supports;
547 UINT64 PciAttributes;
548 UINT8 SlotNum;
549 UINT8 FirstBar;
550 UINT8 Slot;
551 UINT8 Index;
553 UINT32 RoutineNum;
554 BOOLEAN MediaPresent;
555 BOOLEAN Support64BitDma;
556
557 DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: Start\n"));
558
559 //
560 // Open PCI I/O Protocol and save pointer to open protocol
561 // in private data area.
562 //
563 PciIo = NULL;
564 Status = gBS->OpenProtocol (
565 Controller,
566 &gEfiPciIoProtocolGuid,
567 (VOID **)&PciIo,
568 This->DriverBindingHandle,
569 Controller,
570 EFI_OPEN_PROTOCOL_BY_DRIVER
571 );
572 if (EFI_ERROR (Status)) {
573 return Status;
574 }
575
576 //
577 // Enable the SD Host Controller MMIO space
578 //
579 Private = NULL;
580 Status = PciIo->Attributes (
581 PciIo,
583 0,
584 &PciAttributes
585 );
586
587 if (EFI_ERROR (Status)) {
588 goto Done;
589 }
590
591 Status = PciIo->Attributes (
592 PciIo,
594 0,
595 &Supports
596 );
597
598 if (!EFI_ERROR (Status)) {
599 Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
600 Status = PciIo->Attributes (
601 PciIo,
603 Supports,
604 NULL
605 );
606 } else {
607 goto Done;
608 }
609
610 Private = AllocateCopyPool (sizeof (SD_MMC_HC_PRIVATE_DATA), &gSdMmcPciHcTemplate);
611 if (Private == NULL) {
612 Status = EFI_OUT_OF_RESOURCES;
613 goto Done;
614 }
615
616 Private->ControllerHandle = Controller;
617 Private->PciIo = PciIo;
618 Private->PciAttributes = PciAttributes;
619 InitializeListHead (&Private->Queue);
620
621 //
622 // Get SD/MMC Pci Host Controller Slot info
623 //
624 Status = SdMmcHcGetSlotInfo (PciIo, &FirstBar, &SlotNum);
625 if (EFI_ERROR (Status)) {
626 goto Done;
627 }
628
629 //
630 // Attempt to locate the singleton instance of the SD/MMC override protocol,
631 // which implements platform specific workarounds for non-standard SDHCI
632 // implementations.
633 //
634 if (mOverride == NULL) {
635 Status = gBS->LocateProtocol (
636 &gEdkiiSdMmcOverrideProtocolGuid,
637 NULL,
638 (VOID **)&mOverride
639 );
640 if (!EFI_ERROR (Status)) {
641 DEBUG ((
642 DEBUG_INFO,
643 "%a: found SD/MMC override protocol\n",
644 __func__
645 ));
646 }
647 }
648
649 Support64BitDma = TRUE;
650 for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
651 Private->Slot[Slot].Enable = TRUE;
652 //
653 // Get SD/MMC Pci Host Controller Version
654 //
655 Status = SdMmcHcGetControllerVersion (PciIo, Slot, &Private->ControllerVersion[Slot]);
656 if (EFI_ERROR (Status)) {
657 continue;
658 }
659
660 Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);
661 if (EFI_ERROR (Status)) {
662 continue;
663 }
664
665 Private->BaseClkFreq[Slot] = Private->Capability[Slot].BaseClkFreq;
666
667 if (mOverride != NULL) {
668 if (mOverride->Capability != NULL) {
669 Status = mOverride->Capability (
670 Controller,
671 Slot,
672 &Private->Capability[Slot],
673 &Private->BaseClkFreq[Slot]
674 );
675 if (EFI_ERROR (Status)) {
676 DEBUG ((
677 DEBUG_WARN,
678 "%a: Failed to override capability - %r\n",
679 __func__,
680 Status
681 ));
682 continue;
683 }
684 }
685
686 if (mOverride->NotifyPhase != NULL) {
687 Status = mOverride->NotifyPhase (
688 Controller,
689 Slot,
690 EdkiiSdMmcGetOperatingParam,
691 (VOID *)&Private->Slot[Slot].OperatingParameters
692 );
693 if (EFI_ERROR (Status)) {
694 DEBUG ((DEBUG_WARN, "%a: Failed to get operating parameters, using defaults\n", __func__));
695 }
696 }
697 }
698
699 DumpCapabilityReg (Slot, &Private->Capability[Slot]);
700 DEBUG ((
701 DEBUG_INFO,
702 "Slot[%d] Base Clock Frequency: %dMHz\n",
703 Slot,
704 Private->BaseClkFreq[Slot]
705 ));
706
707 //
708 // If any of the slots does not support 64b system bus
709 // do not enable 64b DMA in the PCI layer.
710 //
711 if (((Private->ControllerVersion[Slot] == SD_MMC_HC_CTRL_VER_300) &&
712 (Private->Capability[Slot].SysBus64V3 == 0)) ||
713 ((Private->ControllerVersion[Slot] == SD_MMC_HC_CTRL_VER_400) &&
714 (Private->Capability[Slot].SysBus64V3 == 0)) ||
715 ((Private->ControllerVersion[Slot] >= SD_MMC_HC_CTRL_VER_410) &&
716 (Private->Capability[Slot].SysBus64V4 == 0)))
717 {
718 Support64BitDma = FALSE;
719 }
720
721 Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private->MaxCurrent[Slot]);
722 if (EFI_ERROR (Status)) {
723 continue;
724 }
725
726 Private->Slot[Slot].SlotType = Private->Capability[Slot].SlotType;
727 if ((Private->Slot[Slot].SlotType != RemovableSlot) && (Private->Slot[Slot].SlotType != EmbeddedSlot)) {
728 DEBUG ((DEBUG_INFO, "SdMmcPciHcDxe doesn't support the slot type [%d]!!!\n", Private->Slot[Slot].SlotType));
729 continue;
730 }
731
732 //
733 // Reset the specified slot of the SD/MMC Pci Host Controller
734 //
735 Status = SdMmcHcReset (Private, Slot);
736 if (EFI_ERROR (Status)) {
737 continue;
738 }
739
740 //
741 // Check whether there is a SD/MMC card attached
742 //
743 if (Private->Slot[Slot].SlotType == RemovableSlot) {
744 Status = SdMmcHcCardDetect (PciIo, Slot, &MediaPresent);
745 if (EFI_ERROR (Status) && (Status != EFI_MEDIA_CHANGED)) {
746 continue;
747 } else if (!MediaPresent) {
748 DEBUG ((
749 DEBUG_INFO,
750 "SdMmcHcCardDetect: No device attached in Slot[%d]!!!\n",
751 Slot
752 ));
753 continue;
754 }
755 }
756
757 Status = SdMmcHcInitHost (Private, Slot);
758 if (EFI_ERROR (Status)) {
759 continue;
760 }
761
762 Private->Slot[Slot].MediaPresent = TRUE;
763 Private->Slot[Slot].Initialized = TRUE;
764 RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE);
765 for (Index = 0; Index < RoutineNum; Index++) {
766 Routine = &mCardTypeDetectRoutineTable[Index];
767 if (*Routine != NULL) {
768 Status = (*Routine)(Private, Slot);
769 if (!EFI_ERROR (Status)) {
770 break;
771 }
772 }
773 }
774
775 //
776 // This card doesn't get initialized correctly.
777 //
778 if (Index == RoutineNum) {
779 Private->Slot[Slot].Initialized = FALSE;
780 }
781 }
782
783 //
784 // Enable 64-bit DMA support in the PCI layer if this controller
785 // supports it.
786 //
787 if (Support64BitDma) {
788 Status = PciIo->Attributes (
789 PciIo,
792 NULL
793 );
794 if (EFI_ERROR (Status)) {
795 DEBUG ((DEBUG_WARN, "SdMmcPciHcDriverBindingStart: failed to enable 64-bit DMA (%r)\n", Status));
796 }
797 }
798
799 //
800 // Start the asynchronous I/O monitor
801 //
802 Status = gBS->CreateEvent (
803 EVT_TIMER | EVT_NOTIFY_SIGNAL,
804 TPL_NOTIFY,
806 Private,
807 &Private->TimerEvent
808 );
809 if (EFI_ERROR (Status)) {
810 goto Done;
811 }
812
813 Status = gBS->SetTimer (Private->TimerEvent, TimerPeriodic, SD_MMC_HC_ASYNC_TIMER);
814 if (EFI_ERROR (Status)) {
815 goto Done;
816 }
817
818 //
819 // Start the Sd removable device connection enumeration
820 //
821 Status = gBS->CreateEvent (
822 EVT_TIMER | EVT_NOTIFY_SIGNAL,
823 TPL_CALLBACK,
825 Private,
826 &Private->ConnectEvent
827 );
828 if (EFI_ERROR (Status)) {
829 goto Done;
830 }
831
832 Status = gBS->SetTimer (Private->ConnectEvent, TimerPeriodic, SD_MMC_HC_ENUM_TIMER);
833 if (EFI_ERROR (Status)) {
834 goto Done;
835 }
836
837 Status = gBS->InstallMultipleProtocolInterfaces (
838 &Controller,
839 &gEfiSdMmcPassThruProtocolGuid,
840 &(Private->PassThru),
841 NULL
842 );
843
844 DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: %r End on %x\n", Status, Controller));
845
846Done:
847 if (EFI_ERROR (Status)) {
848 if ((Private != NULL) && (Private->PciAttributes != 0)) {
849 //
850 // Restore original PCI attributes
851 //
852 PciIo->Attributes (
853 PciIo,
855 Private->PciAttributes,
856 NULL
857 );
858 }
859
860 gBS->CloseProtocol (
861 Controller,
862 &gEfiPciIoProtocolGuid,
863 This->DriverBindingHandle,
864 Controller
865 );
866
867 if ((Private != NULL) && (Private->TimerEvent != NULL)) {
868 gBS->CloseEvent (Private->TimerEvent);
869 }
870
871 if ((Private != NULL) && (Private->ConnectEvent != NULL)) {
872 gBS->CloseEvent (Private->ConnectEvent);
873 }
874
875 if (Private != NULL) {
876 FreePool (Private);
877 }
878 }
879
880 return Status;
881}
882
910EFIAPI
913 IN EFI_HANDLE Controller,
914 IN UINTN NumberOfChildren,
915 IN EFI_HANDLE *ChildHandleBuffer
916 )
917{
918 EFI_STATUS Status;
920 SD_MMC_HC_PRIVATE_DATA *Private;
921 EFI_PCI_IO_PROTOCOL *PciIo;
922 LIST_ENTRY *Link;
923 LIST_ENTRY *NextLink;
924 SD_MMC_HC_TRB *Trb;
925
926 DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStop: Start\n"));
927
928 Status = gBS->OpenProtocol (
929 Controller,
930 &gEfiSdMmcPassThruProtocolGuid,
931 (VOID **)&PassThru,
932 This->DriverBindingHandle,
933 Controller,
934 EFI_OPEN_PROTOCOL_GET_PROTOCOL
935 );
936 if (EFI_ERROR (Status)) {
937 return Status;
938 }
939
940 Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
941 //
942 // Close Non-Blocking timer and free Task list.
943 //
944 if (Private->TimerEvent != NULL) {
945 gBS->CloseEvent (Private->TimerEvent);
946 Private->TimerEvent = NULL;
947 }
948
949 if (Private->ConnectEvent != NULL) {
950 gBS->CloseEvent (Private->ConnectEvent);
951 Private->ConnectEvent = NULL;
952 }
953
954 //
955 // As the timer is closed, there is no needs to use TPL lock to
956 // protect the critical region "queue".
957 //
958 for (Link = GetFirstNode (&Private->Queue);
959 !IsNull (&Private->Queue, Link);
960 Link = NextLink)
961 {
962 NextLink = GetNextNode (&Private->Queue, Link);
963 RemoveEntryList (Link);
964 Trb = SD_MMC_HC_TRB_FROM_THIS (Link);
965 Trb->Packet->TransactionStatus = EFI_ABORTED;
966 gBS->SignalEvent (Trb->Event);
967 SdMmcFreeTrb (Trb);
968 }
969
970 //
971 // Uninstall Block I/O protocol from the device handle
972 //
973 Status = gBS->UninstallProtocolInterface (
974 Controller,
975 &gEfiSdMmcPassThruProtocolGuid,
976 &(Private->PassThru)
977 );
978
979 if (EFI_ERROR (Status)) {
980 return Status;
981 }
982
983 gBS->CloseProtocol (
984 Controller,
985 &gEfiPciIoProtocolGuid,
986 This->DriverBindingHandle,
987 Controller
988 );
989 //
990 // Restore original PCI attributes
991 //
992 PciIo = Private->PciIo;
993 Status = PciIo->Attributes (
994 PciIo,
996 Private->PciAttributes,
997 NULL
998 );
999 ASSERT_EFI_ERROR (Status);
1000
1001 FreePool (Private);
1002
1003 DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStop: End with %r\n", Status));
1004
1005 return Status;
1006}
1007
1019 IN SD_MMC_HC_PRIVATE_DATA *Private,
1020 IN SD_MMC_HC_TRB *Trb
1021 )
1022{
1023 EFI_STATUS Status;
1024 EFI_TPL OldTpl;
1025
1026 //
1027 // Wait async I/O list is empty before execute sync I/O operation.
1028 //
1029 while (TRUE) {
1030 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1031 if (IsListEmpty (&Private->Queue)) {
1032 gBS->RestoreTPL (OldTpl);
1033 break;
1034 }
1035
1036 gBS->RestoreTPL (OldTpl);
1037 }
1038
1039 while (Trb->Retries) {
1040 Status = SdMmcWaitTrbEnv (Private, Trb);
1041 if (EFI_ERROR (Status)) {
1042 return Status;
1043 }
1044
1045 Status = SdMmcExecTrb (Private, Trb);
1046 if (EFI_ERROR (Status)) {
1047 return Status;
1048 }
1049
1050 Status = SdMmcWaitTrbResult (Private, Trb);
1051 if (Status == EFI_CRC_ERROR) {
1052 Trb->Retries--;
1053 } else {
1054 return Status;
1055 }
1056 }
1057
1058 return Status;
1059}
1060
1099EFIAPI
1102 IN UINT8 Slot,
1104 IN EFI_EVENT Event OPTIONAL
1105 )
1106{
1107 EFI_STATUS Status;
1108 SD_MMC_HC_PRIVATE_DATA *Private;
1109 SD_MMC_HC_TRB *Trb;
1110
1111 if ((This == NULL) || (Packet == NULL)) {
1112 return EFI_INVALID_PARAMETER;
1113 }
1114
1115 if ((Packet->SdMmcCmdBlk == NULL) || (Packet->SdMmcStatusBlk == NULL)) {
1116 return EFI_INVALID_PARAMETER;
1117 }
1118
1119 if ((Packet->OutDataBuffer == NULL) && (Packet->OutTransferLength != 0)) {
1120 return EFI_INVALID_PARAMETER;
1121 }
1122
1123 if ((Packet->InDataBuffer == NULL) && (Packet->InTransferLength != 0)) {
1124 return EFI_INVALID_PARAMETER;
1125 }
1126
1127 Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);
1128
1129 if (!Private->Slot[Slot].Enable) {
1130 return EFI_INVALID_PARAMETER;
1131 }
1132
1133 if (!Private->Slot[Slot].MediaPresent) {
1134 return EFI_NO_MEDIA;
1135 }
1136
1137 if (!Private->Slot[Slot].Initialized) {
1138 return EFI_DEVICE_ERROR;
1139 }
1140
1141 Trb = SdMmcCreateTrb (Private, Slot, Packet, Event);
1142 if (Trb == NULL) {
1143 return EFI_OUT_OF_RESOURCES;
1144 }
1145
1146 //
1147 // Immediately return for async I/O.
1148 //
1149 if (Event != NULL) {
1150 return EFI_SUCCESS;
1151 }
1152
1153 Status = SdMmcPassThruExecSyncTrb (Private, Trb);
1154
1155 SdMmcFreeTrb (Trb);
1156
1157 return Status;
1158}
1159
1190EFIAPI
1193 IN OUT UINT8 *Slot
1194 )
1195{
1196 SD_MMC_HC_PRIVATE_DATA *Private;
1197 UINT8 Index;
1198
1199 if ((This == NULL) || (Slot == NULL)) {
1200 return EFI_INVALID_PARAMETER;
1201 }
1202
1203 Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);
1204
1205 if (*Slot == 0xFF) {
1206 for (Index = 0; Index < SD_MMC_HC_MAX_SLOT; Index++) {
1207 if (Private->Slot[Index].Enable) {
1208 *Slot = Index;
1209 Private->PreviousSlot = Index;
1210 return EFI_SUCCESS;
1211 }
1212 }
1213
1214 return EFI_NOT_FOUND;
1215 } else if (*Slot == Private->PreviousSlot) {
1216 for (Index = *Slot + 1; Index < SD_MMC_HC_MAX_SLOT; Index++) {
1217 if (Private->Slot[Index].Enable) {
1218 *Slot = Index;
1219 Private->PreviousSlot = Index;
1220 return EFI_SUCCESS;
1221 }
1222 }
1223
1224 return EFI_NOT_FOUND;
1225 } else {
1226 return EFI_INVALID_PARAMETER;
1227 }
1228}
1229
1265EFIAPI
1268 IN UINT8 Slot,
1269 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
1270 )
1271{
1272 SD_MMC_HC_PRIVATE_DATA *Private;
1273 SD_DEVICE_PATH *SdNode;
1274 EMMC_DEVICE_PATH *EmmcNode;
1275
1276 if ((This == NULL) || (DevicePath == NULL) || (Slot >= SD_MMC_HC_MAX_SLOT)) {
1277 return EFI_INVALID_PARAMETER;
1278 }
1279
1280 Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);
1281
1282 if ((!Private->Slot[Slot].Enable) || (!Private->Slot[Slot].MediaPresent)) {
1283 return EFI_NOT_FOUND;
1284 }
1285
1286 if (Private->Slot[Slot].CardType == SdCardType) {
1287 SdNode = AllocateCopyPool (sizeof (SD_DEVICE_PATH), &mSdDpTemplate);
1288 if (SdNode == NULL) {
1289 return EFI_OUT_OF_RESOURCES;
1290 }
1291
1292 SdNode->SlotNumber = Slot;
1293
1294 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)SdNode;
1295 } else if (Private->Slot[Slot].CardType == EmmcCardType) {
1296 EmmcNode = AllocateCopyPool (sizeof (EMMC_DEVICE_PATH), &mEmmcDpTemplate);
1297 if (EmmcNode == NULL) {
1298 return EFI_OUT_OF_RESOURCES;
1299 }
1300
1301 EmmcNode->SlotNumber = Slot;
1302
1303 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)EmmcNode;
1304 } else {
1305 //
1306 // Currently we only support SD and EMMC two device nodes.
1307 //
1308 return EFI_NOT_FOUND;
1309 }
1310
1311 return EFI_SUCCESS;
1312}
1313
1336EFIAPI
1339 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1340 OUT UINT8 *Slot
1341 )
1342{
1343 SD_MMC_HC_PRIVATE_DATA *Private;
1344 SD_DEVICE_PATH *SdNode;
1345 EMMC_DEVICE_PATH *EmmcNode;
1346 UINT8 SlotNumber;
1347
1348 if ((This == NULL) || (DevicePath == NULL) || (Slot == NULL)) {
1349 return EFI_INVALID_PARAMETER;
1350 }
1351
1352 Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);
1353
1354 //
1355 // Check whether the DevicePath belongs to SD_DEVICE_PATH or EMMC_DEVICE_PATH
1356 //
1357 if ((DevicePath->Type != MESSAGING_DEVICE_PATH) ||
1358 ((DevicePath->SubType != MSG_SD_DP) &&
1359 (DevicePath->SubType != MSG_EMMC_DP)) ||
1360 (DevicePathNodeLength (DevicePath) != sizeof (SD_DEVICE_PATH)) ||
1361 (DevicePathNodeLength (DevicePath) != sizeof (EMMC_DEVICE_PATH)))
1362 {
1363 return EFI_UNSUPPORTED;
1364 }
1365
1366 if (DevicePath->SubType == MSG_SD_DP) {
1367 SdNode = (SD_DEVICE_PATH *)DevicePath;
1368 SlotNumber = SdNode->SlotNumber;
1369 } else {
1370 EmmcNode = (EMMC_DEVICE_PATH *)DevicePath;
1371 SlotNumber = EmmcNode->SlotNumber;
1372 }
1373
1374 if (SlotNumber >= SD_MMC_HC_MAX_SLOT) {
1375 return EFI_NOT_FOUND;
1376 }
1377
1378 if (Private->Slot[SlotNumber].Enable) {
1379 *Slot = SlotNumber;
1380 return EFI_SUCCESS;
1381 } else {
1382 return EFI_NOT_FOUND;
1383 }
1384}
1385
1410EFIAPI
1413 IN UINT8 Slot
1414 )
1415{
1416 SD_MMC_HC_PRIVATE_DATA *Private;
1417 LIST_ENTRY *Link;
1418 LIST_ENTRY *NextLink;
1419 SD_MMC_HC_TRB *Trb;
1420 EFI_TPL OldTpl;
1421
1422 if (This == NULL) {
1423 return EFI_INVALID_PARAMETER;
1424 }
1425
1426 Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);
1427
1428 if (!Private->Slot[Slot].Enable) {
1429 return EFI_INVALID_PARAMETER;
1430 }
1431
1432 if (!Private->Slot[Slot].MediaPresent) {
1433 return EFI_NO_MEDIA;
1434 }
1435
1436 if (!Private->Slot[Slot].Initialized) {
1437 return EFI_DEVICE_ERROR;
1438 }
1439
1440 //
1441 // Free all async I/O requests in the queue
1442 //
1443 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1444
1445 for (Link = GetFirstNode (&Private->Queue);
1446 !IsNull (&Private->Queue, Link);
1447 Link = NextLink)
1448 {
1449 NextLink = GetNextNode (&Private->Queue, Link);
1450 RemoveEntryList (Link);
1451 Trb = SD_MMC_HC_TRB_FROM_THIS (Link);
1452 Trb->Packet->TransactionStatus = EFI_ABORTED;
1453 gBS->SignalEvent (Trb->Event);
1454 SdMmcFreeTrb (Trb);
1455 }
1456
1457 gBS->RestoreTPL (OldTpl);
1458
1459 return EFI_SUCCESS;
1460}
UINT64 UINTN
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
#define INITIALIZE_LIST_HEAD_VARIABLE(ListHead)
Definition: BaseLib.h:2904
#define MSG_SD_DP
Definition: DevicePath.h:907
#define MSG_EMMC_DP
Definition: DevicePath.h:916
#define MESSAGING_DEVICE_PATH
Definition: DevicePath.h:321
UINTN EFIAPI DevicePathNodeLength(IN CONST VOID *Node)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STATUS EmmcIdentification(IN SD_MMC_HC_PRIVATE_DATA *Private, IN UINT8 Slot)
Definition: EmmcDevice.c:1318
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
Clear for PCI controllers that can not genrate a DAC.
Definition: PciIo.h:64
@ EfiPciIoAttributeOperationGet
Definition: PciIo.h:103
@ EfiPciIoAttributeOperationEnable
Definition: PciIo.h:111
@ EfiPciIoAttributeOperationSet
Definition: PciIo.h:107
@ EfiPciIoAttributeOperationSupported
Definition: PciIo.h:119
EFI_STATUS SdCardIdentification(IN SD_MMC_HC_PRIVATE_DATA *Private, IN UINT8 Slot)
Definition: SdDevice.c:1210
VOID EFIAPI SdMmcPciHcEnumerateDevice(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS EFIAPI InitializeSdMmcPciHcDxe(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
EFI_STATUS EFIAPI SdMmcPciHcDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
EFI_STATUS EFIAPI SdMmcPassThruPassThru(IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, IN UINT8 Slot, IN OUT EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet, IN EFI_EVENT Event OPTIONAL)
EFI_STATUS EFIAPI SdMmcPassThruResetDevice(IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, IN UINT8 Slot)
EFI_STATUS SdMmcPassThruExecSyncTrb(IN SD_MMC_HC_PRIVATE_DATA *Private, IN SD_MMC_HC_TRB *Trb)
EFI_STATUS EFIAPI SdMmcPassThruGetSlotNumber(IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT UINT8 *Slot)
VOID EFIAPI ProcessAsyncTaskList(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS EFIAPI SdMmcPassThruGetNextSlot(IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, IN OUT UINT8 *Slot)
EFI_STATUS EFIAPI SdMmcPciHcDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
EFI_STATUS EFIAPI SdMmcPciHcDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer)
EFI_STATUS EFIAPI SdMmcPassThruBuildDevicePath(IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, IN UINT8 Slot, IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath)
EFI_STATUS SdMmcHcReset(IN SD_MMC_HC_PRIVATE_DATA *Private, IN UINT8 Slot)
Definition: SdMmcPciHci.c:477
EFI_STATUS SdMmcWaitTrbEnv(IN SD_MMC_HC_PRIVATE_DATA *Private, IN SD_MMC_HC_TRB *Trb)
Definition: SdMmcPciHci.c:2075
EFI_STATUS SdMmcCheckTrbResult(IN SD_MMC_HC_PRIVATE_DATA *Private, IN SD_MMC_HC_TRB *Trb)
Definition: SdMmcPciHci.c:2798
SD_MMC_HC_TRB * SdMmcCreateTrb(IN SD_MMC_HC_PRIVATE_DATA *Private, IN UINT8 Slot, IN EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet, IN EFI_EVENT Event)
Definition: SdMmcPciHci.c:1848
EFI_STATUS(* CARD_TYPE_DETECT_ROUTINE)(IN SD_MMC_HC_PRIVATE_DATA *Private, IN UINT8 Slot)
EFI_STATUS SdMmcHcInitHost(IN SD_MMC_HC_PRIVATE_DATA *Private, IN UINT8 Slot)
Definition: SdMmcPciHci.c:1213
EFI_STATUS SdMmcCheckTrbEnv(IN SD_MMC_HC_PRIVATE_DATA *Private, IN SD_MMC_HC_TRB *Trb)
Definition: SdMmcPciHci.c:2021
EFI_STATUS SdMmcWaitTrbResult(IN SD_MMC_HC_PRIVATE_DATA *Private, IN SD_MMC_HC_TRB *Trb)
Definition: SdMmcPciHci.c:2888
VOID SdMmcFreeTrb(IN SD_MMC_HC_TRB *Trb)
Definition: SdMmcPciHci.c:1959
EFI_STATUS SdMmcExecTrb(IN SD_MMC_HC_PRIVATE_DATA *Private, IN SD_MMC_HC_TRB *Trb)
Definition: SdMmcPciHci.c:2127
EFI_STATUS SdMmcHcCardDetect(IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 Slot, OUT BOOLEAN *MediaPresent)
Definition: SdMmcPciHci.c:678
EFI_STATUS SdMmcHcGetMaxCurrent(IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 Slot, OUT UINT64 *MaxCurrent)
Definition: SdMmcPciHci.c:649
EFI_STATUS EFIAPI SdMmcHcGetSlotInfo(IN EFI_PCI_IO_PROTOCOL *PciIo, OUT UINT8 *FirstBar, OUT UINT8 *SlotNum)
Definition: SdMmcPciHci.c:92
EFI_STATUS SdMmcHcGetCapability(IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 Slot, OUT SD_MMC_HC_SLOT_CAP *Capability)
Definition: SdMmcPciHci.c:618
EFI_STATUS SdMmcHcGetControllerVersion(IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 Slot, OUT UINT16 *Version)
Definition: SdMmcPciHci.c:448
VOID DumpCapabilityReg(IN UINT8 Slot, IN SD_MMC_HC_SLOT_CAP *Capability)
Definition: SdMmcPciHci.c:25
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
UINTN EFI_TPL
Definition: UefiBaseType.h:41
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI EfiLibInstallDriverBindingComponentName2(IN CONST EFI_HANDLE ImageHandle, IN CONST EFI_SYSTEM_TABLE *SystemTable, IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, IN EFI_HANDLE DriverBindingHandle, IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName OPTIONAL, IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2 OPTIONAL)
@ TimerPeriodic
Definition: UefiSpec.h:535
EFI_PCI_IO_PROTOCOL_CONFIG Read
Definition: PciIo.h:232