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
//\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
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
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
);\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
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
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
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