1 /** @file
2   This driver is used to manage SD/MMC PCI host controllers which are compliance
3   with SD Host Controller Simplified Specification version 3.00 plus the 64-bit
4   System Addressing support in SD Host Controller Simplified Specification version
5   4.20.
6 
7   It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.
8 
9   Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
10   Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
11   SPDX-License-Identifier: BSD-2-Clause-Patent
12 
13 **/
14 
15 #include "SdMmcPciHcDxe.h"
16 
17 EDKII_SD_MMC_OVERRIDE           *mOverride;
18 
19 //
20 // Driver Global Variables
21 //
22 EFI_DRIVER_BINDING_PROTOCOL gSdMmcPciHcDriverBinding = {
23   SdMmcPciHcDriverBindingSupported,
24   SdMmcPciHcDriverBindingStart,
25   SdMmcPciHcDriverBindingStop,
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 //
39 SD_MMC_HC_PRIVATE_DATA gSdMmcPciHcTemplate = {
40   SD_MMC_HC_PRIVATE_SIGNATURE,      // Signature
41   NULL,                             // ControllerHandle
42   NULL,                             // PciIo
43   {                                 // PassThru
44     sizeof (UINT32),
45     SdMmcPassThruPassThru,
46     SdMmcPassThruGetNextSlot,
47     SdMmcPassThruBuildDevicePath,
48     SdMmcPassThruGetSlotNumber,
49     SdMmcPassThruResetDevice
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 
76 SD_DEVICE_PATH    mSdDpTemplate = {
77   {
78     MESSAGING_DEVICE_PATH,
79     MSG_SD_DP,
80     {
81       (UINT8) (sizeof (SD_DEVICE_PATH)),
82       (UINT8) ((sizeof (SD_DEVICE_PATH)) >> 8)
83     }
84   },
85   0
86 };
87 
88 EMMC_DEVICE_PATH    mEmmcDpTemplate = {
89   {
90     MESSAGING_DEVICE_PATH,
91     MSG_EMMC_DP,
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 //
104 CARD_TYPE_DETECT_ROUTINE mCardTypeDetectRoutineTable[] = {
105   EmmcIdentification,
106   SdCardIdentification,
107   NULL
108 };
109 
110 /**
111   The entry point for SD host controller driver, used to install this driver on the ImageHandle.
112 
113   @param[in]  ImageHandle   The firmware allocated handle for this driver image.
114   @param[in]  SystemTable   Pointer to the EFI system table.
115 
116   @retval EFI_SUCCESS   Driver loaded.
117   @retval other         Driver not loaded.
118 
119 **/
120 EFI_STATUS
121 EFIAPI
InitializeSdMmcPciHcDxe(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)122 InitializeSdMmcPciHcDxe (
123   IN EFI_HANDLE        ImageHandle,
124   IN EFI_SYSTEM_TABLE  *SystemTable
125   )
126 {
127   EFI_STATUS           Status;
128 
129   Status = EfiLibInstallDriverBindingComponentName2 (
130              ImageHandle,
131              SystemTable,
132              &gSdMmcPciHcDriverBinding,
133              ImageHandle,
134              &gSdMmcPciHcComponentName,
135              &gSdMmcPciHcComponentName2
136              );
137   ASSERT_EFI_ERROR (Status);
138 
139   return Status;
140 }
141 
142 /**
143   Call back function when the timer event is signaled.
144 
145   @param[in]  Event     The Event this notify function registered to.
146   @param[in]  Context   Pointer to the context data registered to the
147                         Event.
148 
149 **/
150 VOID
151 EFIAPI
ProcessAsyncTaskList(IN EFI_EVENT Event,IN VOID * Context)152 ProcessAsyncTaskList (
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;
161   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
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     if (!Trb->Started) {
180       //
181       // Check whether the cmd/data line is ready for transfer.
182       //
183       Status = SdMmcCheckTrbEnv (Private, Trb);
184       if (!EFI_ERROR (Status)) {
185         Trb->Started = TRUE;
186         Status = SdMmcExecTrb (Private, Trb);
187         if (EFI_ERROR (Status)) {
188           goto Done;
189         }
190       } else {
191         goto Done;
192       }
193     }
194     Status = SdMmcCheckTrbResult (Private, Trb);
195   }
196 
197 Done:
198   if ((Trb != NULL) && (Status == EFI_NOT_READY)) {
199     Packet = Trb->Packet;
200     if (Packet->Timeout == 0) {
201       InfiniteWait = TRUE;
202     } else {
203       InfiniteWait = FALSE;
204     }
205     if ((!InfiniteWait) && (Trb->Timeout-- == 0)) {
206       RemoveEntryList (Link);
207       Trb->Packet->TransactionStatus = EFI_TIMEOUT;
208       TrbEvent = Trb->Event;
209       SdMmcFreeTrb (Trb);
210       DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT\n", TrbEvent));
211       gBS->SignalEvent (TrbEvent);
212       return;
213     }
214   } else if ((Trb != NULL) && (Status == EFI_CRC_ERROR) && (Trb->Retries > 0)) {
215     Trb->Retries--;
216     Trb->Started = FALSE;
217   } else if ((Trb != NULL)) {
218     RemoveEntryList (Link);
219     Trb->Packet->TransactionStatus = Status;
220     TrbEvent = Trb->Event;
221     SdMmcFreeTrb (Trb);
222     DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p with %r\n", TrbEvent, Status));
223     gBS->SignalEvent (TrbEvent);
224   }
225   return;
226 }
227 
228 /**
229   Sd removable device enumeration callback function when the timer event is signaled.
230 
231   @param[in]  Event     The Event this notify function registered to.
232   @param[in]  Context   Pointer to the context data registered to the
233                         Event.
234 
235 **/
236 VOID
237 EFIAPI
SdMmcPciHcEnumerateDevice(IN EFI_EVENT Event,IN VOID * Context)238 SdMmcPciHcEnumerateDevice (
239   IN EFI_EVENT          Event,
240   IN VOID*              Context
241   )
242 {
243   SD_MMC_HC_PRIVATE_DATA              *Private;
244   EFI_STATUS                          Status;
245   UINT8                               Slot;
246   BOOLEAN                             MediaPresent;
247   UINT32                              RoutineNum;
248   CARD_TYPE_DETECT_ROUTINE            *Routine;
249   UINTN                               Index;
250   LIST_ENTRY                          *Link;
251   LIST_ENTRY                          *NextLink;
252   SD_MMC_HC_TRB                       *Trb;
253   EFI_TPL                             OldTpl;
254 
255   Private = (SD_MMC_HC_PRIVATE_DATA*)Context;
256 
257   for (Slot = 0; Slot < SD_MMC_HC_MAX_SLOT; Slot++) {
258     if ((Private->Slot[Slot].Enable) && (Private->Slot[Slot].SlotType == RemovableSlot)) {
259       Status = SdMmcHcCardDetect (Private->PciIo, Slot, &MediaPresent);
260       if ((Status == EFI_MEDIA_CHANGED) && !MediaPresent) {
261         DEBUG ((DEBUG_INFO, "SdMmcPciHcEnumerateDevice: device disconnected at slot %d of pci %p\n", Slot, Private->PciIo));
262         Private->Slot[Slot].MediaPresent = FALSE;
263         Private->Slot[Slot].Initialized  = FALSE;
264         //
265         // Signal all async task events at the slot with EFI_NO_MEDIA status.
266         //
267         OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
268         for (Link = GetFirstNode (&Private->Queue);
269              !IsNull (&Private->Queue, Link);
270              Link = NextLink) {
271           NextLink = GetNextNode (&Private->Queue, Link);
272           Trb = SD_MMC_HC_TRB_FROM_THIS (Link);
273           if (Trb->Slot == Slot) {
274             RemoveEntryList (Link);
275             Trb->Packet->TransactionStatus = EFI_NO_MEDIA;
276             gBS->SignalEvent (Trb->Event);
277             SdMmcFreeTrb (Trb);
278           }
279         }
280         gBS->RestoreTPL (OldTpl);
281         //
282         // Notify the upper layer the connect state change through ReinstallProtocolInterface.
283         //
284         gBS->ReinstallProtocolInterface (
285               Private->ControllerHandle,
286               &gEfiSdMmcPassThruProtocolGuid,
287               &Private->PassThru,
288               &Private->PassThru
289               );
290       }
291       if ((Status == EFI_MEDIA_CHANGED) && MediaPresent) {
292         DEBUG ((DEBUG_INFO, "SdMmcPciHcEnumerateDevice: device connected at slot %d of pci %p\n", Slot, Private->PciIo));
293         //
294         // Reset the specified slot of the SD/MMC Pci Host Controller
295         //
296         Status = SdMmcHcReset (Private, Slot);
297         if (EFI_ERROR (Status)) {
298           continue;
299         }
300         //
301         // Reinitialize slot and restart identification process for the new attached device
302         //
303         Status = SdMmcHcInitHost (Private, Slot);
304         if (EFI_ERROR (Status)) {
305           continue;
306         }
307 
308         Private->Slot[Slot].MediaPresent = TRUE;
309         Private->Slot[Slot].Initialized  = TRUE;
310         RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE);
311         for (Index = 0; Index < RoutineNum; Index++) {
312           Routine = &mCardTypeDetectRoutineTable[Index];
313           if (*Routine != NULL) {
314             Status = (*Routine) (Private, Slot);
315             if (!EFI_ERROR (Status)) {
316               break;
317             }
318           }
319         }
320         //
321         // This card doesn't get initialized correctly.
322         //
323         if (Index == RoutineNum) {
324           Private->Slot[Slot].Initialized = FALSE;
325         }
326 
327         //
328         // Notify the upper layer the connect state change through ReinstallProtocolInterface.
329         //
330         gBS->ReinstallProtocolInterface (
331                Private->ControllerHandle,
332                &gEfiSdMmcPassThruProtocolGuid,
333                &Private->PassThru,
334                &Private->PassThru
335                );
336       }
337     }
338   }
339 
340   return;
341 }
342 
343 /**
344   Tests to see if this driver supports a given controller. If a child device is provided,
345   it further tests to see if this driver supports creating a handle for the specified child device.
346 
347   This function checks to see if the driver specified by This supports the device specified by
348   ControllerHandle. Drivers will typically use the device path attached to
349   ControllerHandle and/or the services from the bus I/O abstraction attached to
350   ControllerHandle to determine if the driver supports ControllerHandle. This function
351   may be called many times during platform initialization. In order to reduce boot times, the tests
352   performed by this function must be very small, and take as little time as possible to execute. This
353   function must not change the state of any hardware devices, and this function must be aware that the
354   device specified by ControllerHandle may already be managed by the same driver or a
355   different driver. This function must match its calls to AllocatePages() with FreePages(),
356   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
357   Since ControllerHandle may have been previously started by the same driver, if a protocol is
358   already in the opened state, then it must not be closed with CloseProtocol(). This is required
359   to guarantee the state of ControllerHandle is not modified by this function.
360 
361   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
362   @param[in]  ControllerHandle     The handle of the controller to test. This handle
363                                    must support a protocol interface that supplies
364                                    an I/O abstraction to the driver.
365   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
366                                    parameter is ignored by device drivers, and is optional for bus
367                                    drivers. For bus drivers, if this parameter is not NULL, then
368                                    the bus driver must determine if the bus controller specified
369                                    by ControllerHandle and the child controller specified
370                                    by RemainingDevicePath are both supported by this
371                                    bus driver.
372 
373   @retval EFI_SUCCESS              The device specified by ControllerHandle and
374                                    RemainingDevicePath is supported by the driver specified by This.
375   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
376                                    RemainingDevicePath is already being managed by the driver
377                                    specified by This.
378   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
379                                    RemainingDevicePath is already being managed by a different
380                                    driver or an application that requires exclusive access.
381                                    Currently not implemented.
382   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
383                                    RemainingDevicePath is not supported by the driver specified by This.
384 **/
385 EFI_STATUS
386 EFIAPI
SdMmcPciHcDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)387 SdMmcPciHcDriverBindingSupported (
388   IN EFI_DRIVER_BINDING_PROTOCOL *This,
389   IN EFI_HANDLE                  Controller,
390   IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
391   )
392 {
393   EFI_STATUS                Status;
394   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
395   EFI_PCI_IO_PROTOCOL       *PciIo;
396   PCI_TYPE00                PciData;
397 
398   PciIo            = NULL;
399   ParentDevicePath = NULL;
400 
401   //
402   // SdPciHcDxe is a device driver, and should ingore the
403   // "RemainingDevicePath" according to EFI spec.
404   //
405   Status = gBS->OpenProtocol (
406                   Controller,
407                   &gEfiDevicePathProtocolGuid,
408                   (VOID *) &ParentDevicePath,
409                   This->DriverBindingHandle,
410                   Controller,
411                   EFI_OPEN_PROTOCOL_BY_DRIVER
412                   );
413   if (EFI_ERROR (Status)) {
414     //
415     // EFI_ALREADY_STARTED is also an error.
416     //
417     return Status;
418   }
419   //
420   // Close the protocol because we don't use it here.
421   //
422   gBS->CloseProtocol (
423         Controller,
424         &gEfiDevicePathProtocolGuid,
425         This->DriverBindingHandle,
426         Controller
427         );
428 
429   //
430   // Now test the EfiPciIoProtocol.
431   //
432   Status = gBS->OpenProtocol (
433                   Controller,
434                   &gEfiPciIoProtocolGuid,
435                   (VOID **) &PciIo,
436                   This->DriverBindingHandle,
437                   Controller,
438                   EFI_OPEN_PROTOCOL_BY_DRIVER
439                   );
440   if (EFI_ERROR (Status)) {
441     return Status;
442   }
443 
444   //
445   // Now further check the PCI header: Base class (offset 0x08) and
446   // Sub Class (offset 0x05). This controller should be an SD/MMC PCI
447   // Host Controller.
448   //
449   Status = PciIo->Pci.Read (
450                         PciIo,
451                         EfiPciIoWidthUint8,
452                         0,
453                         sizeof (PciData),
454                         &PciData
455                         );
456   if (EFI_ERROR (Status)) {
457     gBS->CloseProtocol (
458           Controller,
459           &gEfiPciIoProtocolGuid,
460           This->DriverBindingHandle,
461           Controller
462           );
463     return EFI_UNSUPPORTED;
464   }
465   //
466   // Since we already got the PciData, we can close protocol to avoid to carry it
467   // on for multiple exit points.
468   //
469   gBS->CloseProtocol (
470         Controller,
471         &gEfiPciIoProtocolGuid,
472         This->DriverBindingHandle,
473         Controller
474         );
475 
476   //
477   // Examine SD PCI Host Controller PCI Configuration table fields.
478   //
479   if ((PciData.Hdr.ClassCode[2] == PCI_CLASS_SYSTEM_PERIPHERAL) &&
480       (PciData.Hdr.ClassCode[1] == PCI_SUBCLASS_SD_HOST_CONTROLLER) &&
481       ((PciData.Hdr.ClassCode[0] == 0x00) || (PciData.Hdr.ClassCode[0] == 0x01))) {
482     return EFI_SUCCESS;
483   }
484 
485   return EFI_UNSUPPORTED;
486 }
487 
488 /**
489   Starts a device controller or a bus controller.
490 
491   The Start() function is designed to be invoked from the EFI boot service ConnectController().
492   As a result, much of the error checking on the parameters to Start() has been moved into this
493   common boot service. It is legal to call Start() from other locations,
494   but the following calling restrictions must be followed or the system behavior will not be deterministic.
495   1. ControllerHandle must be a valid EFI_HANDLE.
496   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
497      EFI_DEVICE_PATH_PROTOCOL.
498   3. Prior to calling Start(), the Supported() function for the driver specified by This must
499      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
500 
501   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
502   @param[in]  ControllerHandle     The handle of the controller to start. This handle
503                                    must support a protocol interface that supplies
504                                    an I/O abstraction to the driver.
505   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
506                                    parameter is ignored by device drivers, and is optional for bus
507                                    drivers. For a bus driver, if this parameter is NULL, then handles
508                                    for all the children of Controller are created by this driver.
509                                    If this parameter is not NULL and the first Device Path Node is
510                                    not the End of Device Path Node, then only the handle for the
511                                    child device specified by the first Device Path Node of
512                                    RemainingDevicePath is created by this driver.
513                                    If the first Device Path Node of RemainingDevicePath is
514                                    the End of Device Path Node, no child handle is created by this
515                                    driver.
516 
517   @retval EFI_SUCCESS              The device was started.
518   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
519   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
520   @retval Others                   The driver failded to start the device.
521 
522 **/
523 EFI_STATUS
524 EFIAPI
SdMmcPciHcDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)525 SdMmcPciHcDriverBindingStart (
526   IN EFI_DRIVER_BINDING_PROTOCOL     *This,
527   IN EFI_HANDLE                      Controller,
528   IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
529   )
530 {
531   EFI_STATUS                      Status;
532   SD_MMC_HC_PRIVATE_DATA          *Private;
533   EFI_PCI_IO_PROTOCOL             *PciIo;
534   UINT64                          Supports;
535   UINT64                          PciAttributes;
536   UINT8                           SlotNum;
537   UINT8                           FirstBar;
538   UINT8                           Slot;
539   UINT8                           Index;
540   CARD_TYPE_DETECT_ROUTINE        *Routine;
541   UINT32                          RoutineNum;
542   BOOLEAN                         MediaPresent;
543   BOOLEAN                         Support64BitDma;
544 
545   DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: Start\n"));
546 
547   //
548   // Open PCI I/O Protocol and save pointer to open protocol
549   // in private data area.
550   //
551   PciIo  = NULL;
552   Status = gBS->OpenProtocol (
553                   Controller,
554                   &gEfiPciIoProtocolGuid,
555                   (VOID **) &PciIo,
556                   This->DriverBindingHandle,
557                   Controller,
558                   EFI_OPEN_PROTOCOL_BY_DRIVER
559                   );
560   if (EFI_ERROR (Status)) {
561     return Status;
562   }
563 
564   //
565   // Enable the SD Host Controller MMIO space
566   //
567   Private = NULL;
568   Status  = PciIo->Attributes (
569                      PciIo,
570                      EfiPciIoAttributeOperationGet,
571                      0,
572                      &PciAttributes
573                      );
574 
575   if (EFI_ERROR (Status)) {
576     goto Done;
577   }
578 
579   Status = PciIo->Attributes (
580                     PciIo,
581                     EfiPciIoAttributeOperationSupported,
582                     0,
583                     &Supports
584                     );
585 
586   if (!EFI_ERROR (Status)) {
587     Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
588     Status    = PciIo->Attributes (
589                          PciIo,
590                          EfiPciIoAttributeOperationEnable,
591                          Supports,
592                          NULL
593                          );
594   } else {
595     goto Done;
596   }
597 
598   Private = AllocateCopyPool (sizeof (SD_MMC_HC_PRIVATE_DATA), &gSdMmcPciHcTemplate);
599   if (Private == NULL) {
600     Status = EFI_OUT_OF_RESOURCES;
601     goto Done;
602   }
603 
604   Private->ControllerHandle = Controller;
605   Private->PciIo            = PciIo;
606   Private->PciAttributes    = PciAttributes;
607   InitializeListHead (&Private->Queue);
608 
609   //
610   // Get SD/MMC Pci Host Controller Slot info
611   //
612   Status = SdMmcHcGetSlotInfo (PciIo, &FirstBar, &SlotNum);
613   if (EFI_ERROR (Status)) {
614     goto Done;
615   }
616 
617   //
618   // Attempt to locate the singleton instance of the SD/MMC override protocol,
619   // which implements platform specific workarounds for non-standard SDHCI
620   // implementations.
621   //
622   if (mOverride == NULL) {
623     Status = gBS->LocateProtocol (&gEdkiiSdMmcOverrideProtocolGuid, NULL,
624                     (VOID **)&mOverride);
625     if (!EFI_ERROR (Status)) {
626       DEBUG ((DEBUG_INFO, "%a: found SD/MMC override protocol\n",
627         __FUNCTION__));
628     }
629   }
630 
631   Support64BitDma = TRUE;
632   for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
633     Private->Slot[Slot].Enable = TRUE;
634     //
635     // Get SD/MMC Pci Host Controller Version
636     //
637     Status = SdMmcHcGetControllerVersion (PciIo, Slot, &Private->ControllerVersion[Slot]);
638     if (EFI_ERROR (Status)) {
639       continue;
640     }
641 
642     Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);
643     if (EFI_ERROR (Status)) {
644       continue;
645     }
646 
647     Private->BaseClkFreq[Slot] = Private->Capability[Slot].BaseClkFreq;
648 
649     if (mOverride != NULL) {
650       if (mOverride->Capability != NULL) {
651         Status = mOverride->Capability (
652                               Controller,
653                               Slot,
654                               &Private->Capability[Slot],
655                               &Private->BaseClkFreq[Slot]
656                               );
657         if (EFI_ERROR (Status)) {
658           DEBUG ((DEBUG_WARN, "%a: Failed to override capability - %r\n",
659             __FUNCTION__, Status));
660           continue;
661         }
662       }
663 
664       if (mOverride->NotifyPhase != NULL) {
665         Status = mOverride->NotifyPhase (
666                               Controller,
667                               Slot,
668                               EdkiiSdMmcGetOperatingParam,
669                               (VOID*)&Private->Slot[Slot].OperatingParameters
670                               );
671         if (EFI_ERROR (Status)) {
672           DEBUG ((DEBUG_WARN, "%a: Failed to get operating parameters, using defaults\n", __FUNCTION__));
673         }
674       }
675     }
676 
677     DumpCapabilityReg (Slot, &Private->Capability[Slot]);
678     DEBUG ((
679       DEBUG_INFO,
680       "Slot[%d] Base Clock Frequency: %dMHz\n",
681       Slot,
682       Private->BaseClkFreq[Slot]
683       ));
684 
685     //
686     // If any of the slots does not support 64b system bus
687     // do not enable 64b DMA in the PCI layer.
688     //
689     if ((Private->ControllerVersion[Slot] == SD_MMC_HC_CTRL_VER_300 &&
690          Private->Capability[Slot].SysBus64V3 == 0) ||
691         (Private->ControllerVersion[Slot] == SD_MMC_HC_CTRL_VER_400 &&
692          Private->Capability[Slot].SysBus64V3 == 0) ||
693         (Private->ControllerVersion[Slot] >= SD_MMC_HC_CTRL_VER_410 &&
694          Private->Capability[Slot].SysBus64V4 == 0)) {
695       Support64BitDma = FALSE;
696     }
697 
698     Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private->MaxCurrent[Slot]);
699     if (EFI_ERROR (Status)) {
700       continue;
701     }
702 
703     Private->Slot[Slot].SlotType = Private->Capability[Slot].SlotType;
704     if ((Private->Slot[Slot].SlotType != RemovableSlot) && (Private->Slot[Slot].SlotType != EmbeddedSlot)) {
705       DEBUG ((DEBUG_INFO, "SdMmcPciHcDxe doesn't support the slot type [%d]!!!\n", Private->Slot[Slot].SlotType));
706       continue;
707     }
708 
709     //
710     // Reset the specified slot of the SD/MMC Pci Host Controller
711     //
712     Status = SdMmcHcReset (Private, Slot);
713     if (EFI_ERROR (Status)) {
714       continue;
715     }
716     //
717     // Check whether there is a SD/MMC card attached
718     //
719     if (Private->Slot[Slot].SlotType == RemovableSlot) {
720       Status = SdMmcHcCardDetect (PciIo, Slot, &MediaPresent);
721       if (EFI_ERROR (Status) && (Status != EFI_MEDIA_CHANGED)) {
722         continue;
723       } else if (!MediaPresent) {
724         DEBUG ((
725           DEBUG_INFO,
726           "SdMmcHcCardDetect: No device attached in Slot[%d]!!!\n",
727           Slot
728           ));
729         continue;
730       }
731     }
732 
733     Status = SdMmcHcInitHost (Private, Slot);
734     if (EFI_ERROR (Status)) {
735       continue;
736     }
737 
738     Private->Slot[Slot].MediaPresent = TRUE;
739     Private->Slot[Slot].Initialized  = TRUE;
740     RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE);
741     for (Index = 0; Index < RoutineNum; Index++) {
742       Routine = &mCardTypeDetectRoutineTable[Index];
743       if (*Routine != NULL) {
744         Status = (*Routine) (Private, Slot);
745         if (!EFI_ERROR (Status)) {
746           break;
747         }
748       }
749     }
750     //
751     // This card doesn't get initialized correctly.
752     //
753     if (Index == RoutineNum) {
754       Private->Slot[Slot].Initialized = FALSE;
755     }
756   }
757 
758   //
759   // Enable 64-bit DMA support in the PCI layer if this controller
760   // supports it.
761   //
762   if (Support64BitDma) {
763     Status = PciIo->Attributes (
764                       PciIo,
765                       EfiPciIoAttributeOperationEnable,
766                       EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
767                       NULL
768                       );
769     if (EFI_ERROR (Status)) {
770       DEBUG ((DEBUG_WARN, "SdMmcPciHcDriverBindingStart: failed to enable 64-bit DMA (%r)\n", Status));
771     }
772   }
773 
774   //
775   // Start the asynchronous I/O monitor
776   //
777   Status = gBS->CreateEvent (
778                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
779                   TPL_NOTIFY,
780                   ProcessAsyncTaskList,
781                   Private,
782                   &Private->TimerEvent
783                   );
784   if (EFI_ERROR (Status)) {
785     goto Done;
786   }
787 
788   Status = gBS->SetTimer (Private->TimerEvent, TimerPeriodic, SD_MMC_HC_ASYNC_TIMER);
789   if (EFI_ERROR (Status)) {
790     goto Done;
791   }
792 
793   //
794   // Start the Sd removable device connection enumeration
795   //
796   Status = gBS->CreateEvent (
797                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
798                   TPL_CALLBACK,
799                   SdMmcPciHcEnumerateDevice,
800                   Private,
801                   &Private->ConnectEvent
802                   );
803   if (EFI_ERROR (Status)) {
804     goto Done;
805   }
806 
807   Status = gBS->SetTimer (Private->ConnectEvent, TimerPeriodic, SD_MMC_HC_ENUM_TIMER);
808   if (EFI_ERROR (Status)) {
809     goto Done;
810   }
811 
812   Status = gBS->InstallMultipleProtocolInterfaces (
813                   &Controller,
814                   &gEfiSdMmcPassThruProtocolGuid,
815                   &(Private->PassThru),
816                   NULL
817                   );
818 
819   DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: %r End on %x\n", Status, Controller));
820 
821 Done:
822   if (EFI_ERROR (Status)) {
823     if ((Private != NULL) && (Private->PciAttributes != 0)) {
824       //
825       // Restore original PCI attributes
826       //
827       PciIo->Attributes (
828                PciIo,
829                EfiPciIoAttributeOperationSet,
830                Private->PciAttributes,
831                NULL
832                );
833     }
834     gBS->CloseProtocol (
835           Controller,
836           &gEfiPciIoProtocolGuid,
837           This->DriverBindingHandle,
838           Controller
839           );
840 
841     if ((Private != NULL) && (Private->TimerEvent != NULL)) {
842       gBS->CloseEvent (Private->TimerEvent);
843     }
844 
845     if ((Private != NULL) && (Private->ConnectEvent != NULL)) {
846       gBS->CloseEvent (Private->ConnectEvent);
847     }
848 
849     if (Private != NULL) {
850       FreePool (Private);
851     }
852   }
853 
854   return Status;
855 }
856 
857 /**
858   Stops a device controller or a bus controller.
859 
860   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
861   As a result, much of the error checking on the parameters to Stop() has been moved
862   into this common boot service. It is legal to call Stop() from other locations,
863   but the following calling restrictions must be followed or the system behavior will not be deterministic.
864   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
865      same driver's Start() function.
866   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
867      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
868      Start() function, and the Start() function must have called OpenProtocol() on
869      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
870 
871   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
872   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
873                                 support a bus specific I/O protocol for the driver
874                                 to use to stop the device.
875   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
876   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
877                                 if NumberOfChildren is 0.
878 
879   @retval EFI_SUCCESS           The device was stopped.
880   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
881 
882 **/
883 EFI_STATUS
884 EFIAPI
SdMmcPciHcDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)885 SdMmcPciHcDriverBindingStop (
886   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
887   IN  EFI_HANDLE                      Controller,
888   IN  UINTN                           NumberOfChildren,
889   IN  EFI_HANDLE                      *ChildHandleBuffer
890   )
891 {
892   EFI_STATUS                          Status;
893   EFI_SD_MMC_PASS_THRU_PROTOCOL       *PassThru;
894   SD_MMC_HC_PRIVATE_DATA              *Private;
895   EFI_PCI_IO_PROTOCOL                 *PciIo;
896   LIST_ENTRY                          *Link;
897   LIST_ENTRY                          *NextLink;
898   SD_MMC_HC_TRB                       *Trb;
899 
900   DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStop: Start\n"));
901 
902   Status = gBS->OpenProtocol (
903                   Controller,
904                   &gEfiSdMmcPassThruProtocolGuid,
905                   (VOID**) &PassThru,
906                   This->DriverBindingHandle,
907                   Controller,
908                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
909                   );
910   if (EFI_ERROR (Status)) {
911     return Status;
912   }
913 
914   Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
915   //
916   // Close Non-Blocking timer and free Task list.
917   //
918   if (Private->TimerEvent != NULL) {
919     gBS->CloseEvent (Private->TimerEvent);
920     Private->TimerEvent = NULL;
921   }
922   if (Private->ConnectEvent != NULL) {
923     gBS->CloseEvent (Private->ConnectEvent);
924     Private->ConnectEvent = NULL;
925   }
926   //
927   // As the timer is closed, there is no needs to use TPL lock to
928   // protect the critical region "queue".
929   //
930   for (Link = GetFirstNode (&Private->Queue);
931        !IsNull (&Private->Queue, Link);
932        Link = NextLink) {
933     NextLink = GetNextNode (&Private->Queue, Link);
934     RemoveEntryList (Link);
935     Trb = SD_MMC_HC_TRB_FROM_THIS (Link);
936     Trb->Packet->TransactionStatus = EFI_ABORTED;
937     gBS->SignalEvent (Trb->Event);
938     SdMmcFreeTrb (Trb);
939   }
940 
941   //
942   // Uninstall Block I/O protocol from the device handle
943   //
944   Status = gBS->UninstallProtocolInterface (
945                   Controller,
946                   &gEfiSdMmcPassThruProtocolGuid,
947                   &(Private->PassThru)
948                   );
949 
950   if (EFI_ERROR (Status)) {
951     return Status;
952   }
953 
954   gBS->CloseProtocol (
955          Controller,
956          &gEfiPciIoProtocolGuid,
957          This->DriverBindingHandle,
958          Controller
959          );
960   //
961   // Restore original PCI attributes
962   //
963   PciIo  = Private->PciIo;
964   Status = PciIo->Attributes (
965                     PciIo,
966                     EfiPciIoAttributeOperationSet,
967                     Private->PciAttributes,
968                     NULL
969                     );
970   ASSERT_EFI_ERROR (Status);
971 
972   FreePool (Private);
973 
974   DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStop: End with %r\n", Status));
975 
976   return Status;
977 }
978 
979 /**
980   Execute TRB synchronously.
981 
982   @param[in] Private  Pointer to driver private data.
983   @param[in] Trb      Pointer to TRB to execute.
984 
985   @retval EFI_SUCCESS  TRB executed successfully.
986   @retval Other        TRB failed.
987 **/
988 EFI_STATUS
SdMmcPassThruExecSyncTrb(IN SD_MMC_HC_PRIVATE_DATA * Private,IN SD_MMC_HC_TRB * Trb)989 SdMmcPassThruExecSyncTrb (
990   IN SD_MMC_HC_PRIVATE_DATA  *Private,
991   IN SD_MMC_HC_TRB           *Trb
992   )
993 {
994   EFI_STATUS  Status;
995   EFI_TPL     OldTpl;
996 
997   //
998   // Wait async I/O list is empty before execute sync I/O operation.
999   //
1000   while (TRUE) {
1001     OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1002     if (IsListEmpty (&Private->Queue)) {
1003       gBS->RestoreTPL (OldTpl);
1004       break;
1005     }
1006     gBS->RestoreTPL (OldTpl);
1007   }
1008 
1009   while (Trb->Retries) {
1010     Status = SdMmcWaitTrbEnv (Private, Trb);
1011     if (EFI_ERROR (Status)) {
1012       return Status;
1013     }
1014 
1015     Status = SdMmcExecTrb (Private, Trb);
1016     if (EFI_ERROR (Status)) {
1017       return Status;
1018     }
1019 
1020     Status = SdMmcWaitTrbResult (Private, Trb);
1021     if (Status == EFI_CRC_ERROR) {
1022       Trb->Retries--;
1023     } else {
1024       return Status;
1025     }
1026   }
1027 
1028   return Status;
1029 }
1030 
1031 /**
1032   Sends SD command to an SD card that is attached to the SD controller.
1033 
1034   The PassThru() function sends the SD command specified by Packet to the SD card
1035   specified by Slot.
1036 
1037   If Packet is successfully sent to the SD card, then EFI_SUCCESS is returned.
1038 
1039   If a device error occurs while sending the Packet, then EFI_DEVICE_ERROR is returned.
1040 
1041   If Slot is not in a valid range for the SD controller, then EFI_INVALID_PARAMETER
1042   is returned.
1043 
1044   If Packet defines a data command but both InDataBuffer and OutDataBuffer are NULL,
1045   EFI_INVALID_PARAMETER is returned.
1046 
1047   @param[in]     This           A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
1048   @param[in]     Slot           The slot number of the SD card to send the command to.
1049   @param[in,out] Packet         A pointer to the SD command data structure.
1050   @param[in]     Event          If Event is NULL, blocking I/O is performed. If Event is
1051                                 not NULL, then nonblocking I/O is performed, and Event
1052                                 will be signaled when the Packet completes.
1053 
1054   @retval EFI_SUCCESS           The SD Command Packet was sent by the host.
1055   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to send the SD
1056                                 command Packet.
1057   @retval EFI_INVALID_PARAMETER Packet, Slot, or the contents of the Packet is invalid.
1058   @retval EFI_INVALID_PARAMETER Packet defines a data command but both InDataBuffer and
1059                                 OutDataBuffer are NULL.
1060   @retval EFI_NO_MEDIA          SD Device not present in the Slot.
1061   @retval EFI_UNSUPPORTED       The command described by the SD Command Packet is not
1062                                 supported by the host controller.
1063   @retval EFI_BAD_BUFFER_SIZE   The InTransferLength or OutTransferLength exceeds the
1064                                 limit supported by SD card ( i.e. if the number of bytes
1065                                 exceed the Last LBA).
1066 
1067 **/
1068 EFI_STATUS
1069 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)1070 SdMmcPassThruPassThru (
1071   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL         *This,
1072   IN     UINT8                                 Slot,
1073   IN OUT EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   *Packet,
1074   IN     EFI_EVENT                             Event    OPTIONAL
1075   )
1076 {
1077   EFI_STATUS                      Status;
1078   SD_MMC_HC_PRIVATE_DATA          *Private;
1079   SD_MMC_HC_TRB                   *Trb;
1080 
1081   if ((This == NULL) || (Packet == NULL)) {
1082     return EFI_INVALID_PARAMETER;
1083   }
1084 
1085   if ((Packet->SdMmcCmdBlk == NULL) || (Packet->SdMmcStatusBlk == NULL)) {
1086     return EFI_INVALID_PARAMETER;
1087   }
1088 
1089   if ((Packet->OutDataBuffer == NULL) && (Packet->OutTransferLength != 0)) {
1090     return EFI_INVALID_PARAMETER;
1091   }
1092 
1093   if ((Packet->InDataBuffer == NULL) && (Packet->InTransferLength != 0)) {
1094     return EFI_INVALID_PARAMETER;
1095   }
1096 
1097   Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);
1098 
1099   if (!Private->Slot[Slot].Enable) {
1100     return EFI_INVALID_PARAMETER;
1101   }
1102 
1103   if (!Private->Slot[Slot].MediaPresent) {
1104     return EFI_NO_MEDIA;
1105   }
1106 
1107   if (!Private->Slot[Slot].Initialized) {
1108     return EFI_DEVICE_ERROR;
1109   }
1110 
1111   Trb = SdMmcCreateTrb (Private, Slot, Packet, Event);
1112   if (Trb == NULL) {
1113     return EFI_OUT_OF_RESOURCES;
1114   }
1115   //
1116   // Immediately return for async I/O.
1117   //
1118   if (Event != NULL) {
1119     return EFI_SUCCESS;
1120   }
1121 
1122   Status = SdMmcPassThruExecSyncTrb (Private, Trb);
1123 
1124   SdMmcFreeTrb (Trb);
1125 
1126   return Status;
1127 }
1128 
1129 /**
1130   Used to retrieve next slot numbers supported by the SD controller. The function
1131   returns information about all available slots (populated or not-populated).
1132 
1133   The GetNextSlot() function retrieves the next slot number on an SD controller.
1134   If on input Slot is 0xFF, then the slot number of the first slot on the SD controller
1135   is returned.
1136 
1137   If Slot is a slot number that was returned on a previous call to GetNextSlot(), then
1138   the slot number of the next slot on the SD controller is returned.
1139 
1140   If Slot is not 0xFF and Slot was not returned on a previous call to GetNextSlot(),
1141   EFI_INVALID_PARAMETER is returned.
1142 
1143   If Slot is the slot number of the last slot on the SD controller, then EFI_NOT_FOUND
1144   is returned.
1145 
1146   @param[in]     This           A pointer to the EFI_SD_MMMC_PASS_THRU_PROTOCOL instance.
1147   @param[in,out] Slot           On input, a pointer to a slot number on the SD controller.
1148                                 On output, a pointer to the next slot number on the SD controller.
1149                                 An input value of 0xFF retrieves the first slot number on the SD
1150                                 controller.
1151 
1152   @retval EFI_SUCCESS           The next slot number on the SD controller was returned in Slot.
1153   @retval EFI_NOT_FOUND         There are no more slots on this SD controller.
1154   @retval EFI_INVALID_PARAMETER Slot is not 0xFF and Slot was not returned on a previous call
1155                                 to GetNextSlot().
1156 
1157 **/
1158 EFI_STATUS
1159 EFIAPI
SdMmcPassThruGetNextSlot(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * This,IN OUT UINT8 * Slot)1160 SdMmcPassThruGetNextSlot (
1161   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL        *This,
1162   IN OUT UINT8                                *Slot
1163   )
1164 {
1165   SD_MMC_HC_PRIVATE_DATA          *Private;
1166   UINT8                           Index;
1167 
1168   if ((This == NULL) || (Slot == NULL)) {
1169     return EFI_INVALID_PARAMETER;
1170   }
1171 
1172   Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);
1173 
1174   if (*Slot == 0xFF) {
1175     for (Index = 0; Index < SD_MMC_HC_MAX_SLOT; Index++) {
1176       if (Private->Slot[Index].Enable) {
1177         *Slot = Index;
1178         Private->PreviousSlot = Index;
1179         return EFI_SUCCESS;
1180       }
1181     }
1182     return EFI_NOT_FOUND;
1183   } else if (*Slot == Private->PreviousSlot) {
1184     for (Index = *Slot + 1; Index < SD_MMC_HC_MAX_SLOT; Index++) {
1185       if (Private->Slot[Index].Enable) {
1186         *Slot = Index;
1187         Private->PreviousSlot = Index;
1188         return EFI_SUCCESS;
1189       }
1190     }
1191     return EFI_NOT_FOUND;
1192   } else {
1193     return EFI_INVALID_PARAMETER;
1194   }
1195 }
1196 
1197 /**
1198   Used to allocate and build a device path node for an SD card on the SD controller.
1199 
1200   The BuildDevicePath() function allocates and builds a single device node for the SD
1201   card specified by Slot.
1202 
1203   If the SD card specified by Slot is not present on the SD controller, then EFI_NOT_FOUND
1204   is returned.
1205 
1206   If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned.
1207 
1208   If there are not enough resources to allocate the device path node, then EFI_OUT_OF_RESOURCES
1209   is returned.
1210 
1211   Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of
1212   DevicePath are initialized to describe the SD card specified by Slot, and EFI_SUCCESS is
1213   returned.
1214 
1215   @param[in]     This           A pointer to the EFI_SD_MMMC_PASS_THRU_PROTOCOL instance.
1216   @param[in]     Slot           Specifies the slot number of the SD card for which a device
1217                                 path node is to be allocated and built.
1218   @param[in,out] DevicePath     A pointer to a single device path node that describes the SD
1219                                 card specified by Slot. This function is responsible for
1220                                 allocating the buffer DevicePath with the boot service
1221                                 AllocatePool(). It is the caller's responsibility to free
1222                                 DevicePath when the caller is finished with DevicePath.
1223 
1224   @retval EFI_SUCCESS           The device path node that describes the SD card specified by
1225                                 Slot was allocated and returned in DevicePath.
1226   @retval EFI_NOT_FOUND         The SD card specified by Slot does not exist on the SD controller.
1227   @retval EFI_INVALID_PARAMETER DevicePath is NULL.
1228   @retval EFI_OUT_OF_RESOURCES  There are not enough resources to allocate DevicePath.
1229 
1230 **/
1231 EFI_STATUS
1232 EFIAPI
SdMmcPassThruBuildDevicePath(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * This,IN UINT8 Slot,IN OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath)1233 SdMmcPassThruBuildDevicePath (
1234   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL       *This,
1235   IN     UINT8                               Slot,
1236   IN OUT EFI_DEVICE_PATH_PROTOCOL            **DevicePath
1237   )
1238 {
1239   SD_MMC_HC_PRIVATE_DATA          *Private;
1240   SD_DEVICE_PATH                  *SdNode;
1241   EMMC_DEVICE_PATH                *EmmcNode;
1242 
1243   if ((This == NULL) || (DevicePath == NULL) || (Slot >= SD_MMC_HC_MAX_SLOT)) {
1244     return EFI_INVALID_PARAMETER;
1245   }
1246 
1247   Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);
1248 
1249   if ((!Private->Slot[Slot].Enable) || (!Private->Slot[Slot].MediaPresent)) {
1250     return EFI_NOT_FOUND;
1251   }
1252 
1253   if (Private->Slot[Slot].CardType == SdCardType) {
1254     SdNode = AllocateCopyPool (sizeof (SD_DEVICE_PATH), &mSdDpTemplate);
1255     if (SdNode == NULL) {
1256       return EFI_OUT_OF_RESOURCES;
1257     }
1258     SdNode->SlotNumber = Slot;
1259 
1260     *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) SdNode;
1261   } else if (Private->Slot[Slot].CardType == EmmcCardType) {
1262     EmmcNode = AllocateCopyPool (sizeof (EMMC_DEVICE_PATH), &mEmmcDpTemplate);
1263     if (EmmcNode == NULL) {
1264       return EFI_OUT_OF_RESOURCES;
1265     }
1266     EmmcNode->SlotNumber = Slot;
1267 
1268     *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) EmmcNode;
1269   } else {
1270     //
1271     // Currently we only support SD and EMMC two device nodes.
1272     //
1273     return EFI_NOT_FOUND;
1274   }
1275 
1276   return EFI_SUCCESS;
1277 }
1278 
1279 /**
1280   This function retrieves an SD card slot number based on the input device path.
1281 
1282   The GetSlotNumber() function retrieves slot number for the SD card specified by
1283   the DevicePath node. If DevicePath is NULL, EFI_INVALID_PARAMETER is returned.
1284 
1285   If DevicePath is not a device path node type that the SD Pass Thru driver supports,
1286   EFI_UNSUPPORTED is returned.
1287 
1288   @param[in]  This              A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
1289   @param[in]  DevicePath        A pointer to the device path node that describes a SD
1290                                 card on the SD controller.
1291   @param[out] Slot              On return, points to the slot number of an SD card on
1292                                 the SD controller.
1293 
1294   @retval EFI_SUCCESS           SD card slot number is returned in Slot.
1295   @retval EFI_INVALID_PARAMETER Slot or DevicePath is NULL.
1296   @retval EFI_UNSUPPORTED       DevicePath is not a device path node type that the SD
1297                                 Pass Thru driver supports.
1298 
1299 **/
1300 EFI_STATUS
1301 EFIAPI
SdMmcPassThruGetSlotNumber(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * This,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,OUT UINT8 * Slot)1302 SdMmcPassThruGetSlotNumber (
1303   IN  EFI_SD_MMC_PASS_THRU_PROTOCOL          *This,
1304   IN  EFI_DEVICE_PATH_PROTOCOL               *DevicePath,
1305   OUT UINT8                                  *Slot
1306   )
1307 {
1308   SD_MMC_HC_PRIVATE_DATA          *Private;
1309   SD_DEVICE_PATH                  *SdNode;
1310   EMMC_DEVICE_PATH                *EmmcNode;
1311   UINT8                           SlotNumber;
1312 
1313   if ((This == NULL) || (DevicePath == NULL) || (Slot == NULL)) {
1314     return EFI_INVALID_PARAMETER;
1315   }
1316 
1317   Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);
1318 
1319   //
1320   // Check whether the DevicePath belongs to SD_DEVICE_PATH or EMMC_DEVICE_PATH
1321   //
1322   if ((DevicePath->Type != MESSAGING_DEVICE_PATH) ||
1323       ((DevicePath->SubType != MSG_SD_DP) &&
1324        (DevicePath->SubType != MSG_EMMC_DP)) ||
1325       (DevicePathNodeLength(DevicePath) != sizeof(SD_DEVICE_PATH)) ||
1326       (DevicePathNodeLength(DevicePath) != sizeof(EMMC_DEVICE_PATH))) {
1327     return EFI_UNSUPPORTED;
1328   }
1329 
1330   if (DevicePath->SubType == MSG_SD_DP) {
1331     SdNode = (SD_DEVICE_PATH *) DevicePath;
1332     SlotNumber = SdNode->SlotNumber;
1333   } else {
1334     EmmcNode = (EMMC_DEVICE_PATH *) DevicePath;
1335     SlotNumber = EmmcNode->SlotNumber;
1336   }
1337 
1338   if (SlotNumber >= SD_MMC_HC_MAX_SLOT) {
1339     return EFI_NOT_FOUND;
1340   }
1341 
1342   if (Private->Slot[SlotNumber].Enable) {
1343     *Slot = SlotNumber;
1344     return EFI_SUCCESS;
1345   } else {
1346     return EFI_NOT_FOUND;
1347   }
1348 }
1349 
1350 /**
1351   Resets an SD card that is connected to the SD controller.
1352 
1353   The ResetDevice() function resets the SD card specified by Slot.
1354 
1355   If this SD controller does not support a device reset operation, EFI_UNSUPPORTED is
1356   returned.
1357 
1358   If Slot is not in a valid slot number for this SD controller, EFI_INVALID_PARAMETER
1359   is returned.
1360 
1361   If the device reset operation is completed, EFI_SUCCESS is returned.
1362 
1363   @param[in]  This              A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
1364   @param[in]  Slot              Specifies the slot number of the SD card to be reset.
1365 
1366   @retval EFI_SUCCESS           The SD card specified by Slot was reset.
1367   @retval EFI_UNSUPPORTED       The SD controller does not support a device reset operation.
1368   @retval EFI_INVALID_PARAMETER Slot number is invalid.
1369   @retval EFI_NO_MEDIA          SD Device not present in the Slot.
1370   @retval EFI_DEVICE_ERROR      The reset command failed due to a device error
1371 
1372 **/
1373 EFI_STATUS
1374 EFIAPI
SdMmcPassThruResetDevice(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * This,IN UINT8 Slot)1375 SdMmcPassThruResetDevice (
1376   IN EFI_SD_MMC_PASS_THRU_PROTOCOL           *This,
1377   IN UINT8                                   Slot
1378   )
1379 {
1380   SD_MMC_HC_PRIVATE_DATA          *Private;
1381   LIST_ENTRY                      *Link;
1382   LIST_ENTRY                      *NextLink;
1383   SD_MMC_HC_TRB                   *Trb;
1384   EFI_TPL                         OldTpl;
1385 
1386   if (This == NULL) {
1387     return EFI_INVALID_PARAMETER;
1388   }
1389 
1390   Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);
1391 
1392   if (!Private->Slot[Slot].Enable) {
1393     return EFI_INVALID_PARAMETER;
1394   }
1395 
1396   if (!Private->Slot[Slot].MediaPresent) {
1397     return EFI_NO_MEDIA;
1398   }
1399 
1400   if (!Private->Slot[Slot].Initialized) {
1401     return EFI_DEVICE_ERROR;
1402   }
1403   //
1404   // Free all async I/O requests in the queue
1405   //
1406   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1407 
1408   for (Link = GetFirstNode (&Private->Queue);
1409        !IsNull (&Private->Queue, Link);
1410        Link = NextLink) {
1411     NextLink = GetNextNode (&Private->Queue, Link);
1412     RemoveEntryList (Link);
1413     Trb = SD_MMC_HC_TRB_FROM_THIS (Link);
1414     Trb->Packet->TransactionStatus = EFI_ABORTED;
1415     gBS->SignalEvent (Trb->Event);
1416     SdMmcFreeTrb (Trb);
1417   }
1418 
1419   gBS->RestoreTPL (OldTpl);
1420 
1421   return EFI_SUCCESS;
1422 }
1423 
1424