]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
Adding a segment code to make sure that the EHCI controller get attached to the EHCI...
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / EhciDxe / Ehci.c
index c8de7052bb9f1b90778e188004e1bb3dd5b0cbfa..aae39b0acbda79f6395bbc78010aca21fa887f32 100644 (file)
@@ -41,11 +41,17 @@ gEhciDriverBinding = {
   EhcDriverBindingSupported,\r
   EhcDriverBindingStart,\r
   EhcDriverBindingStop,\r
-  0x10,\r
+  0x30,\r
   NULL,\r
   NULL\r
 };\r
 \r
+///\r
+/// USB host controller Programming Interface.\r
+///\r
+#define  PCI_CLASSC_PI_UHCI               0x00\r
+#define  PCI_CLASSC_PI_EHCI               0x20\r
+\r
 /**\r
   Retrieves the capability of root hub ports.\r
 \r
@@ -1354,9 +1360,8 @@ EhcDriverBindingSupported (
   //\r
   // Test whether the controller belongs to Ehci type\r
   //\r
-  if ((UsbClassCReg.BaseCode     != PCI_CLASS_SERIAL) ||\r
-      (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
-      (UsbClassCReg.PI           != EHC_PCI_CLASSC_PI)) {\r
+  if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) || (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB)\r
+      || ((UsbClassCReg.PI != EHC_PCI_CLASSC_PI) && (UsbClassCReg.PI !=PCI_CLASSC_PI_UHCI))) {\r
 \r
     Status = EFI_UNSUPPORTED;\r
   }\r
@@ -1449,6 +1454,33 @@ EhcCreateUsb2Hc (
   return Ehc;\r
 }\r
 \r
+/**\r
+  One notified function to stop the Host Controller when gBS->ExitBootServices() called.\r
+\r
+  @param  Event                   Pointer to this event\r
+  @param  Context                 Event hanlder private data\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EhcExitBootService (\r
+  EFI_EVENT                      Event,\r
+  VOID                           *Context\r
+  )\r
+\r
+{\r
+  USB2_HC_DEV   *Ehc;\r
+\r
+  Ehc = (USB2_HC_DEV *) Context;\r
+\r
+  //\r
+  // Stop the Host Controller\r
+  //\r
+  EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);\r
+\r
+  return;\r
+}\r
+\r
 \r
 /**\r
   Starting the Usb EHCI Driver.\r
@@ -1474,9 +1506,22 @@ EhcDriverBindingStart (
   EFI_STATUS              Status;\r
   USB2_HC_DEV             *Ehc;\r
   EFI_PCI_IO_PROTOCOL     *PciIo;\r
+  EFI_PCI_IO_PROTOCOL     *Instance;\r
   UINT64                  Supports;\r
   UINT64                  OriginalPciAttributes;\r
   BOOLEAN                 PciAttributesSaved;\r
+  USB_CLASSC              UsbClassCReg;\r
+  EFI_HANDLE              *HandleBuffer;\r
+  UINTN                   NumberOfHandles;\r
+  UINTN                   Index;\r
+  UINTN                   UhciSegmentNumber;\r
+  UINTN                   UhciBusNumber;\r
+  UINTN                   UhciDeviceNumber;\r
+  UINTN                   UhciFunctionNumber;\r
+  UINTN                   EhciSegmentNumber;\r
+  UINTN                   EhciBusNumber;\r
+  UINTN                   EhciDeviceNumber;\r
+  UINTN                   EhciFunctionNumber;\r
 \r
   //\r
   // Open the PciIo Protocol, then enable the USB host controller\r
@@ -1491,8 +1536,7 @@ EhcDriverBindingStart (
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to open PCI_IO\n"));\r
-    return EFI_DEVICE_ERROR;\r
+    return Status;\r
   }\r
 \r
   PciAttributesSaved = FALSE;\r
@@ -1532,6 +1576,96 @@ EhcDriverBindingStart (
     goto CLOSE_PCIIO;\r
   }\r
 \r
+  Status = PciIo->Pci.Read (\r
+                        PciIo,\r
+                        EfiPciIoWidthUint8,\r
+                        EHC_PCI_CLASSC,\r
+                        sizeof (USB_CLASSC) / sizeof (UINT8),\r
+                        &UsbClassCReg\r
+                        );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto CLOSE_PCIIO;\r
+  }\r
+\r
+  if ((UsbClassCReg.PI == PCI_CLASSC_PI_UHCI) &&\r
+       (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) && \r
+       (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {\r
+    Status = PciIo->GetLocation (\r
+                    PciIo,\r
+                    &UhciSegmentNumber,\r
+                    &UhciBusNumber,\r
+                    &UhciDeviceNumber,\r
+                    &UhciFunctionNumber\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto CLOSE_PCIIO;\r
+    }\r
+\r
+    Status = gBS->LocateHandleBuffer (\r
+                    ByProtocol,\r
+                    &gEfiPciIoProtocolGuid,\r
+                    NULL,\r
+                    &NumberOfHandles,\r
+                    &HandleBuffer\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto CLOSE_PCIIO;\r
+    }\r
+\r
+    for (Index = 0; Index < NumberOfHandles; Index++) {\r
+      //\r
+      // Get the device path on this handle\r
+      //\r
+      Status = gBS->HandleProtocol (\r
+                    HandleBuffer[Index],\r
+                    &gEfiPciIoProtocolGuid,\r
+                    (VOID **)&Instance\r
+                    );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      Status = Instance->Pci.Read (\r
+                    Instance,\r
+                    EfiPciIoWidthUint8,\r
+                    EHC_PCI_CLASSC,\r
+                    sizeof (USB_CLASSC) / sizeof (UINT8),\r
+                    &UsbClassCReg\r
+                    );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        Status = EFI_UNSUPPORTED;\r
+        goto CLOSE_PCIIO;\r
+      }\r
+\r
+      if ((UsbClassCReg.PI == PCI_CLASSC_PI_EHCI) &&\r
+           (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) && \r
+           (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {\r
+        Status = Instance->GetLocation (\r
+                    Instance,\r
+                    &EhciSegmentNumber,\r
+                    &EhciBusNumber,\r
+                    &EhciDeviceNumber,\r
+                    &EhciFunctionNumber\r
+                    );\r
+        if (EFI_ERROR (Status)) {\r
+          goto CLOSE_PCIIO;\r
+        }\r
+        if (EhciBusNumber == UhciBusNumber) {\r
+          gBS->CloseProtocol (\r
+                    Controller,\r
+                    &gEfiPciIoProtocolGuid,\r
+                    This->DriverBindingHandle,\r
+                    Controller\r
+                    );\r
+          EhcDriverBindingStart(This, HandleBuffer[Index], NULL);\r
+        }\r
+      }\r
+    }\r
+    Status = EFI_NOT_FOUND;\r
+    goto CLOSE_PCIIO;\r
+  }\r
+\r
   //\r
   // Create then install USB2_HC_PROTOCOL\r
   //\r
@@ -1584,6 +1718,21 @@ EhcDriverBindingStart (
     goto UNINSTALL_USBHC;\r
   }\r
 \r
+  //\r
+  // Create event to stop the HC when exit boot service.\r
+  //\r
+  Status = gBS->CreateEventEx (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  EhcExitBootService,\r
+                  Ehc,\r
+                  &gEfiEventExitBootServicesGuid,\r
+                  &Ehc->ExitBootServiceEvent\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto UNINSTALL_USBHC;\r
+  }\r
+\r
   //\r
   // Install the component name protocol, don't fail the start\r
   // because of something for display.\r
@@ -1712,6 +1861,10 @@ EhcDriverBindingStop (
     gBS->CloseEvent (Ehc->PollTimer);\r
   }\r
 \r
+  if (Ehc->ExitBootServiceEvent != NULL) {\r
+    gBS->CloseEvent (Ehc->ExitBootServiceEvent);\r
+  }\r
+\r
   EhcFreeSched (Ehc);\r
 \r
   if (Ehc->ControllerNameTable != NULL) {\r