]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
MdeModulePkg/SdMmcPciHcDxe: allow HC capabilities to be overridden
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / SdMmcPciHcDxe / SdMmcPciHcDxe.c
index b7240f256c8d425e36fb1588e552a751dcb316b0..f923930bbae9b9189f0f660ef92f9b65845e9d52 100644 (file)
@@ -17,6 +17,8 @@
 \r
 #include "SdMmcPciHcDxe.h"\r
 \r
+EDKII_SD_MMC_OVERRIDE           *mOverride;\r
+\r
 //\r
 // Driver Global Variables\r
 //\r
@@ -51,8 +53,8 @@ SD_MMC_HC_PRIVATE_DATA gSdMmcPciHcTemplate = {
                                     // Queue\r
   INITIALIZE_LIST_HEAD_VARIABLE (gSdMmcPciHcTemplate.Queue),\r
   {                                 // Slot\r
-    {0, UnknownSlot, 0, 0}, {0, UnknownSlot, 0, 0}, {0, UnknownSlot, 0, 0},\r
-    {0, UnknownSlot, 0, 0}, {0, UnknownSlot, 0, 0}, {0, UnknownSlot, 0, 0}\r
+    {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0},\r
+    {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}, {0, UnknownSlot, 0, 0, 0}\r
   },\r
   {                                 // Capability\r
     {0},\r
@@ -197,7 +199,7 @@ Done:
       Trb->Packet->TransactionStatus = EFI_TIMEOUT;\r
       TrbEvent = Trb->Event;\r
       SdMmcFreeTrb (Trb);\r
-      DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT\n", TrbEvent));\r
+      DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT\n", TrbEvent));\r
       gBS->SignalEvent (TrbEvent);\r
       return;\r
     }\r
@@ -207,7 +209,7 @@ Done:
     Trb->Packet->TransactionStatus = Status;\r
     TrbEvent = Trb->Event;\r
     SdMmcFreeTrb (Trb);\r
-    DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p with %r\n", TrbEvent, Status));\r
+    DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p with %r\n", TrbEvent, Status));\r
     gBS->SignalEvent (TrbEvent);\r
   }\r
   return;\r
@@ -238,6 +240,7 @@ SdMmcPciHcEnumerateDevice (
   LIST_ENTRY                          *Link;\r
   LIST_ENTRY                          *NextLink;\r
   SD_MMC_HC_TRB                       *Trb;\r
+  EFI_TPL                             OldTpl;\r
 \r
   Private = (SD_MMC_HC_PRIVATE_DATA*)Context;\r
 \r
@@ -245,11 +248,13 @@ SdMmcPciHcEnumerateDevice (
     if ((Private->Slot[Slot].Enable) && (Private->Slot[Slot].SlotType == RemovableSlot)) {\r
       Status = SdMmcHcCardDetect (Private->PciIo, Slot, &MediaPresent);\r
       if ((Status == EFI_MEDIA_CHANGED) && !MediaPresent) {\r
-        DEBUG ((EFI_D_INFO, "SdMmcPciHcEnumerateDevice: device disconnected at slot %d of pci %p\n", Slot, Private->PciIo));\r
+        DEBUG ((DEBUG_INFO, "SdMmcPciHcEnumerateDevice: device disconnected at slot %d of pci %p\n", Slot, Private->PciIo));\r
         Private->Slot[Slot].MediaPresent = FALSE;\r
+        Private->Slot[Slot].Initialized  = FALSE;\r
         //\r
         // Signal all async task events at the slot with EFI_NO_MEDIA status.\r
         //\r
+        OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
         for (Link = GetFirstNode (&Private->Queue);\r
              !IsNull (&Private->Queue, Link);\r
              Link = NextLink) {\r
@@ -262,6 +267,7 @@ SdMmcPciHcEnumerateDevice (
             SdMmcFreeTrb (Trb);\r
           }\r
         }\r
+        gBS->RestoreTPL (OldTpl);\r
         //\r
         // Notify the upper layer the connect state change through ReinstallProtocolInterface.\r
         //\r
@@ -273,23 +279,24 @@ SdMmcPciHcEnumerateDevice (
               );\r
       }\r
       if ((Status == EFI_MEDIA_CHANGED) && MediaPresent) {\r
-        DEBUG ((EFI_D_INFO, "SdMmcPciHcEnumerateDevice: device connected at slot %d of pci %p\n", Slot, Private->PciIo));\r
+        DEBUG ((DEBUG_INFO, "SdMmcPciHcEnumerateDevice: device connected at slot %d of pci %p\n", Slot, Private->PciIo));\r
         //\r
         // Reset the specified slot of the SD/MMC Pci Host Controller\r
         //\r
-        Status = SdMmcHcReset (Private->PciIo, Slot);\r
+        Status = SdMmcHcReset (Private, Slot);\r
         if (EFI_ERROR (Status)) {\r
           continue;\r
         }\r
         //\r
         // Reinitialize slot and restart identification process for the new attached device\r
         //\r
-        Status = SdMmcHcInitHost (Private->PciIo, Slot, Private->Capability[Slot]);\r
+        Status = SdMmcHcInitHost (Private, Slot);\r
         if (EFI_ERROR (Status)) {\r
           continue;\r
         }\r
 \r
         Private->Slot[Slot].MediaPresent = TRUE;\r
+        Private->Slot[Slot].Initialized  = TRUE;\r
         RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE);\r
         for (Index = 0; Index < RoutineNum; Index++) {\r
           Routine = &mCardTypeDetectRoutineTable[Index];\r
@@ -300,6 +307,12 @@ SdMmcPciHcEnumerateDevice (
             }\r
           }\r
         }\r
+        //\r
+        // This card doesn't get initialized correctly.\r
+        //\r
+        if (Index == RoutineNum) {\r
+          Private->Slot[Slot].Initialized = FALSE;\r
+        }\r
 \r
         //\r
         // Notify the upper layer the connect state change through ReinstallProtocolInterface.\r
@@ -516,8 +529,9 @@ SdMmcPciHcDriverBindingStart (
   CARD_TYPE_DETECT_ROUTINE        *Routine;\r
   UINT32                          RoutineNum;\r
   BOOLEAN                         MediaPresent;\r
+  BOOLEAN                         Support64BitDma;\r
 \r
-  DEBUG ((EFI_D_INFO, "SdMmcPciHcDriverBindingStart: Start\n"));\r
+  DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: Start\n"));\r
 \r
   //\r
   // Open PCI I/O Protocol and save pointer to open protocol\r
@@ -589,6 +603,21 @@ SdMmcPciHcDriverBindingStart (
     goto Done;\r
   }\r
 \r
+  //\r
+  // Attempt to locate the singleton instance of the SD/MMC override protocol,\r
+  // which implements platform specific workarounds for non-standard SDHCI\r
+  // implementations.\r
+  //\r
+  if (mOverride == NULL) {\r
+    Status = gBS->LocateProtocol (&gEdkiiSdMmcOverrideProtocolGuid, NULL,\r
+                    (VOID **)&mOverride);\r
+    if (!EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_INFO, "%a: found SD/MMC override protocol\n",\r
+        __FUNCTION__));\r
+    }\r
+  }\r
+\r
+  Support64BitDma = TRUE;\r
   for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {\r
     Private->Slot[Slot].Enable = TRUE;\r
 \r
@@ -596,8 +625,21 @@ SdMmcPciHcDriverBindingStart (
     if (EFI_ERROR (Status)) {\r
       continue;\r
     }\r
+    if (mOverride != NULL && mOverride->Capability != NULL) {\r
+      Status = mOverride->Capability (\r
+                            Controller,\r
+                            Slot,\r
+                            &Private->Capability[Slot]);\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((DEBUG_WARN, "%a: Failed to override capability - %r\n",\r
+          __FUNCTION__, Status));\r
+        continue;\r
+      }\r
+    }\r
     DumpCapabilityReg (Slot, &Private->Capability[Slot]);\r
 \r
+    Support64BitDma &= Private->Capability[Slot].SysBus64;\r
+\r
     Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private->MaxCurrent[Slot]);\r
     if (EFI_ERROR (Status)) {\r
       continue;\r
@@ -605,14 +647,14 @@ SdMmcPciHcDriverBindingStart (
 \r
     Private->Slot[Slot].SlotType = Private->Capability[Slot].SlotType;\r
     if ((Private->Slot[Slot].SlotType != RemovableSlot) && (Private->Slot[Slot].SlotType != EmbeddedSlot)) {\r
-      DEBUG ((EFI_D_INFO, "SdMmcPciHcDxe doesn't support the slot type [%d]!!!\n", Private->Slot[Slot].SlotType));\r
+      DEBUG ((DEBUG_INFO, "SdMmcPciHcDxe doesn't support the slot type [%d]!!!\n", Private->Slot[Slot].SlotType));\r
       continue;\r
     }\r
 \r
     //\r
     // Reset the specified slot of the SD/MMC Pci Host Controller\r
     //\r
-    Status = SdMmcHcReset (PciIo, Slot);\r
+    Status = SdMmcHcReset (Private, Slot);\r
     if (EFI_ERROR (Status)) {\r
       continue;\r
     }\r
@@ -623,16 +665,17 @@ SdMmcPciHcDriverBindingStart (
     if (EFI_ERROR (Status) && (Status != EFI_MEDIA_CHANGED)) {\r
       continue;\r
     } else if (!MediaPresent) {\r
-      DEBUG ((EFI_D_ERROR, "SdMmcHcCardDetect: No device attached in Slot[%d]!!!\n", Slot));\r
+      DEBUG ((DEBUG_INFO, "SdMmcHcCardDetect: No device attached in Slot[%d]!!!\n", Slot));\r
       continue;\r
     }\r
 \r
-    Status = SdMmcHcInitHost (PciIo, Slot, Private->Capability[Slot]);\r
+    Status = SdMmcHcInitHost (Private, Slot);\r
     if (EFI_ERROR (Status)) {\r
       continue;\r
     }\r
 \r
     Private->Slot[Slot].MediaPresent = TRUE;\r
+    Private->Slot[Slot].Initialized  = TRUE;\r
     RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE);\r
     for (Index = 0; Index < RoutineNum; Index++) {\r
       Routine = &mCardTypeDetectRoutineTable[Index];\r
@@ -643,6 +686,28 @@ SdMmcPciHcDriverBindingStart (
         }\r
       }\r
     }\r
+    //\r
+    // This card doesn't get initialized correctly.\r
+    //\r
+    if (Index == RoutineNum) {\r
+      Private->Slot[Slot].Initialized = FALSE;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Enable 64-bit DMA support in the PCI layer if this controller\r
+  // supports it.\r
+  //\r
+  if (Support64BitDma) {\r
+    Status = PciIo->Attributes (\r
+                      PciIo,\r
+                      EfiPciIoAttributeOperationEnable,\r
+                      EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,\r
+                      NULL\r
+                      );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_WARN, "SdMmcPciHcDriverBindingStart: failed to enable 64-bit DMA (%r)\n", Status));\r
+    }\r
   }\r
 \r
   //\r
@@ -650,7 +715,7 @@ SdMmcPciHcDriverBindingStart (
   //\r
   Status = gBS->CreateEvent (\r
                   EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
+                  TPL_NOTIFY,\r
                   ProcessAsyncTaskList,\r
                   Private,\r
                   &Private->TimerEvent\r
@@ -690,7 +755,7 @@ SdMmcPciHcDriverBindingStart (
                   NULL\r
                   );\r
 \r
-  DEBUG ((EFI_D_INFO, "SdMmcPciHcDriverBindingStart: %r End on %x\n", Status, Controller));\r
+  DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: %r End on %x\n", Status, Controller));\r
 \r
 Done:\r
   if (EFI_ERROR (Status)) {\r
@@ -771,7 +836,7 @@ SdMmcPciHcDriverBindingStop (
   LIST_ENTRY                          *NextLink;\r
   SD_MMC_HC_TRB                       *Trb;\r
 \r
-  DEBUG ((EFI_D_INFO, "SdMmcPciHcDriverBindingStop: Start\n"));\r
+  DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStop: Start\n"));\r
 \r
   Status = gBS->OpenProtocol (\r
                   Controller,\r
@@ -845,7 +910,7 @@ SdMmcPciHcDriverBindingStop (
 \r
   FreePool (Private);\r
 \r
-  DEBUG ((EFI_D_INFO, "SdMmcPciHcDriverBindingStop: End with %r\n", Status));\r
+  DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStop: End with %r\n", Status));\r
 \r
   return Status;\r
 }\r
@@ -927,6 +992,10 @@ SdMmcPassThruPassThru (
     return EFI_NO_MEDIA;\r
   }\r
 \r
+  if (!Private->Slot[Slot].Initialized) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
   Trb = SdMmcCreateTrb (Private, Slot, Packet, Event);\r
   if (Trb == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -942,7 +1011,7 @@ SdMmcPassThruPassThru (
   // Wait async I/O list is empty before execute sync I/O operation.\r
   //\r
   while (TRUE) {\r
-    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
     if (IsListEmpty (&Private->Queue)) {\r
       gBS->RestoreTPL (OldTpl);\r
       break;\r
@@ -966,13 +1035,7 @@ SdMmcPassThruPassThru (
   }\r
 \r
 Done:\r
-  if ((Trb != NULL) && (Trb->AdmaDesc != NULL)) {\r
-    FreePages (Trb->AdmaDesc, Trb->AdmaPages);\r
-  }\r
-\r
-  if (Trb != NULL) {\r
-    FreePool (Trb);\r
-  }\r
+  SdMmcFreeTrb (Trb);\r
 \r
   return Status;\r
 }\r
@@ -1244,13 +1307,17 @@ SdMmcPassThruResetDevice (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-    if (!Private->Slot[Slot].MediaPresent) {\r
-      return EFI_NO_MEDIA;\r
-    }\r
+  if (!Private->Slot[Slot].MediaPresent) {\r
+    return EFI_NO_MEDIA;\r
+  }\r
+\r
+  if (!Private->Slot[Slot].Initialized) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
   //\r
   // Free all async I/O requests in the queue\r
   //\r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
 \r
   for (Link = GetFirstNode (&Private->Queue);\r
        !IsNull (&Private->Queue, Link);\r