\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
{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
//\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
Status = gBS->CreateEvent (\r
EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
TPL_CALLBACK,\r
- EhcMoniteAsyncRequests,\r
+ EhcMonitorAsyncRequests,\r
Ehc,\r
&Ehc->PollTimer\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
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