]> 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 44405b73ce4b4562cc58b6624db5a20f9355df00..aae39b0acbda79f6395bbc78010aca21fa887f32 100644 (file)
@@ -2,7 +2,7 @@
   \r
   The Ehci controller driver.\r
 \r
-Copyright (c) 2006 - 2008, Intel Corporation\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
 All rights reserved. This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -36,9 +36,24 @@ USB_PORT_STATE_MAP  mUsbPortChangeMap[] = {
   {PORTSC_OVERCUR_CHANGE, USB_PORT_STAT_C_OVERCURRENT}\r
 };\r
 \r
+EFI_DRIVER_BINDING_PROTOCOL\r
+gEhciDriverBinding = {\r
+  EhcDriverBindingSupported,\r
+  EhcDriverBindingStart,\r
+  EhcDriverBindingStop,\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 capablility of root hub ports.\r
+  Retrieves the capability of root hub ports.\r
 \r
   @param  This                  This EFI_USB_HC_PROTOCOL instance.\r
   @param  MaxSpeed              Max speed supported by the controller.\r
@@ -1345,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
@@ -1427,7 +1441,7 @@ EhcCreateUsb2Hc (
   Status = gBS->CreateEvent (\r
                   EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
                   TPL_CALLBACK,\r
-                  EhcMoniteAsyncRequests,\r
+                  EhcMonitorAsyncRequests,\r
                   Ehc,\r
                   &Ehc->PollTimer\r
                   );\r
@@ -1440,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
@@ -1465,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
@@ -1482,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
@@ -1523,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
@@ -1575,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
@@ -1703,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
@@ -1731,12 +1893,3 @@ EhcDriverBindingStop (
   return EFI_SUCCESS;\r
 }\r
 \r
-EFI_DRIVER_BINDING_PROTOCOL\r
-gEhciDriverBinding = {\r
-  EhcDriverBindingSupported,\r
-  EhcDriverBindingStart,\r
-  EhcDriverBindingStop,\r
-  0x10,\r
-  NULL,\r
-  NULL\r
-};\r