From 562d28495df348923812281161e64bc9514e15e6 Mon Sep 17 00:00:00 2001 From: ljin6 Date: Tue, 18 Jul 2006 04:13:40 +0000 Subject: [PATCH] Add DevicePathUtilities DevicePathToText DevciePathFromText USB2HostController protocols git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1037 6f19259b-4bc3-4df7-8a09-765794883524 --- EdkModulePkg/Bus/Pci/Ehci/Dxe/ComponentName.c | 189 + EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.c | 2821 +++++++++++++++ EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.h | 2689 +++++++++++++++ EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.msa | 87 + EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciMem.c | 761 ++++ EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciReg.c | 1539 +++++++++ EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciSched.c | 3072 +++++++++++++++++ EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa | 3 + EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c | 148 +- EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c | 1577 +++++++-- EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h | 1733 +++++++++- EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c | 2 +- EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa | 5 +- EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c | 2712 +++++++++++---- EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h | 913 ++++- EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c | 190 +- EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c | 18 +- EdkModulePkg/EdkModulePkg.spd | 2 + .../Universal/DevicePath/Dxe/DevicePath.c | 107 + .../Universal/DevicePath/Dxe/DevicePath.h | 422 +++ .../Universal/DevicePath/Dxe/DevicePath.msa | 109 + .../DevicePath/Dxe/DevicePathFromText.c | 2434 +++++++++++++ .../DevicePath/Dxe/DevicePathToText.c | 1526 ++++++++ .../DevicePath/Dxe/DevicePathUtilities.c | 421 +++ EdkNt32Pkg/Nt32.fpd | 159 + MdePkg/Include/Guid/PcAnsi.h | 10 + MdePkg/Include/IndustryStandard/Usb.h | 3 + MdePkg/Include/Protocol/DevicePathFromText.h | 4 +- MdePkg/Include/Protocol/Usb2HostController.h | 22 +- MdePkg/Include/Uefi/UefiSpec.h | 30 +- 30 files changed, 22444 insertions(+), 1264 deletions(-) create mode 100644 EdkModulePkg/Bus/Pci/Ehci/Dxe/ComponentName.c create mode 100644 EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.c create mode 100644 EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.h create mode 100644 EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.msa create mode 100644 EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciMem.c create mode 100644 EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciReg.c create mode 100644 EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciSched.c create mode 100644 EdkModulePkg/Universal/DevicePath/Dxe/DevicePath.c create mode 100644 EdkModulePkg/Universal/DevicePath/Dxe/DevicePath.h create mode 100644 EdkModulePkg/Universal/DevicePath/Dxe/DevicePath.msa create mode 100644 EdkModulePkg/Universal/DevicePath/Dxe/DevicePathFromText.c create mode 100644 EdkModulePkg/Universal/DevicePath/Dxe/DevicePathToText.c create mode 100644 EdkModulePkg/Universal/DevicePath/Dxe/DevicePathUtilities.c diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/ComponentName.c b/EdkModulePkg/Bus/Pci/Ehci/Dxe/ComponentName.c new file mode 100644 index 0000000000..e0d2010cd4 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Ehci/Dxe/ComponentName.c @@ -0,0 +1,189 @@ +/*++ + +Copyright 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "Ehci.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +EhciComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +EhciComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, OPTIONAL + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gEhciComponentName = { + EhciComponentNameGetDriverName, + EhciComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mEhciDriverNameTable[] = { + { "eng", L"UEFI Usb Ehci Driver" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +EhciComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gEhciComponentName.SupportedLanguages, + mEhciDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +EhciComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, OPTIONAL + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + USB2_HC_DEV *EhciDev; + EFI_USB2_HC_PROTOCOL *Usb2Hc; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsb2HcProtocolGuid, + (VOID **) &Usb2Hc, + gEhciDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + EhciDev = USB2_HC_DEV_FROM_THIS (Usb2Hc); + + return LookupUnicodeString ( + Language, + gEhciComponentName.SupportedLanguages, + EhciDev->ControllerNameTable, + ControllerName + ); + +} diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.c b/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.c new file mode 100644 index 0000000000..e7d359ee24 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.c @@ -0,0 +1,2821 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Ehci.c + +Abstract: + + +Revision History +--*/ + + +#include "Ehci.h" + +UINTN gEHCDebugLevel = EFI_D_INFO; +UINTN gEHCErrorLevel = EFI_D_ERROR; + +// +// Prototypes +// Driver model protocol interface +// + +EFI_STATUS +EFIAPI +EhciDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +EhciDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +EhciDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// Ehci protocol interface +// +EFI_STATUS +EFIAPI +EhciGetCapability ( + IN EFI_USB2_HC_PROTOCOL *This, + OUT UINT8 *MaxSpeed, + OUT UINT8 *PortNumber, + OUT UINT8 *Is64BitCapable + ); + +EFI_STATUS +EFIAPI +EhciReset ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT16 Attributes + ); + +EFI_STATUS +EFIAPI +EhciGetState ( + IN EFI_USB2_HC_PROTOCOL *This, + OUT EFI_USB_HC_STATE *State + ); + +EFI_STATUS +EFIAPI +EhciSetState ( + IN EFI_USB2_HC_PROTOCOL *This, + IN EFI_USB_HC_STATE State + ); + +EFI_STATUS +EFIAPI +EhciControlTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ); + +EFI_STATUS +EFIAPI +EhciBulkTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ); + +EFI_STATUS +EFIAPI +EhciAsyncInterruptTransfer ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaxiumPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle, + IN UINTN PollingInterval, + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, + IN VOID *Context OPTIONAL + ); + +EFI_STATUS +EFIAPI +EhciSyncInterruptTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ); + +EFI_STATUS +EFIAPI +EhciIsochronousTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ); + +EFI_STATUS +EFIAPI +EhciAsyncIsochronousTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context + ); + +EFI_STATUS +EFIAPI +EhciGetRootHubPortStatus ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus + ); + +EFI_STATUS +EFIAPI +EhciSetRootHubPortFeature ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ); + +EFI_STATUS +EFIAPI +EhciClearRootHubPortFeature ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ); + +// +// Ehci Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL gEhciDriverBinding = { + EhciDriverBindingSupported, + EhciDriverBindingStart, + EhciDriverBindingStop, + 0x10, + NULL, + NULL +}; + +UINT32 mUsbCapabilityLen; +UINT32 mDeviceSpeed[16]; + +EFI_STATUS +EFIAPI +EhciDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Test to see if this driver supports ControllerHandle. Any ControllerHandle + that has Usb2HcProtocol installed will be supported. + + Arguments: + + This - Protocol instance pointer. + Controlle - Handle of device to test + RemainingDevicePath - Not used + + Returns: + + EFI_SUCCESS This driver supports this device. + EFI_UNSUPPORTED This driver does not support this device. + +--*/ +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + USB_CLASSC UsbClassCReg; + + + // + // Test whether there is PCI IO Protocol attached on the controller handle. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto exit; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + CLASSC, + sizeof (USB_CLASSC) / sizeof (UINT8), + &UsbClassCReg + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + Status = EFI_UNSUPPORTED; + goto exit; + } + + // + // Test whether the controller belongs to Ehci type + // + if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) || + (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) || + (UsbClassCReg.PI != PCI_CLASSC_PI_EHCI) + ) { + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + Status = EFI_UNSUPPORTED; + goto exit; + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + +exit: + return Status; +} + +EFI_STATUS +EFIAPI +EhciDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Starting the Usb EHCI Driver + + Arguments: + + This - Protocol instance pointer. + Controller - Handle of device to test + RemainingDevicePath - Not used + + Returns: + + EFI_SUCCESS supports this device. + EFI_UNSUPPORTED do not support this device. + EFI_DEVICE_ERROR cannot be started due to device Error + EFI_OUT_OF_RESOURCES cannot allocate resources + +--*/ +{ + EFI_STATUS Status; + USB2_HC_DEV *HcDev; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 MaxSpeed; + UINT8 PortNumber; + UINT8 Is64BitCapable; + + // + // Open the PciIo Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + // + // Enable the USB Host Controller + // + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto close_pciio_protocol; + } + + // + // Allocate memory for EHC private data structure + // + HcDev = AllocateZeroPool (sizeof (USB2_HC_DEV)); + if (NULL == HcDev) { + Status = EFI_OUT_OF_RESOURCES; + goto close_pciio_protocol; + } + + // + // Init EFI_USB2_HC_PROTOCOL interface and private data structure + // + HcDev->Usb2Hc.GetCapability = EhciGetCapability; + HcDev->Usb2Hc.Reset = EhciReset; + HcDev->Usb2Hc.GetState = EhciGetState; + HcDev->Usb2Hc.SetState = EhciSetState; + HcDev->Usb2Hc.ControlTransfer = EhciControlTransfer; + HcDev->Usb2Hc.BulkTransfer = EhciBulkTransfer; + HcDev->Usb2Hc.AsyncInterruptTransfer = EhciAsyncInterruptTransfer; + HcDev->Usb2Hc.SyncInterruptTransfer = EhciSyncInterruptTransfer; + HcDev->Usb2Hc.IsochronousTransfer = EhciIsochronousTransfer; + HcDev->Usb2Hc.AsyncIsochronousTransfer = EhciAsyncIsochronousTransfer; + HcDev->Usb2Hc.GetRootHubPortStatus = EhciGetRootHubPortStatus; + HcDev->Usb2Hc.SetRootHubPortFeature = EhciSetRootHubPortFeature; + HcDev->Usb2Hc.ClearRootHubPortFeature = EhciClearRootHubPortFeature; + HcDev->Usb2Hc.MajorRevision = 0x1; + HcDev->Usb2Hc.MinorRevision = 0x1; + + HcDev->AsyncRequestList = NULL; + HcDev->ControllerNameTable = NULL; + HcDev->Signature = USB2_HC_DEV_SIGNATURE; + HcDev->PciIo = PciIo; + + // + // Install USB2_HC_PROTOCOL + // + Status = gBS->InstallProtocolInterface ( + &Controller, + &gEfiUsb2HcProtocolGuid, + EFI_NATIVE_INTERFACE, + &HcDev->Usb2Hc + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto free_pool; + } + + // + // Get Capability Register Length + // + Status = GetCapabilityLen (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto uninstall_usb2hc_protocol; + } + + // + // Create and Init Perodic Frame List + // + Status = EhciGetCapability ( + &HcDev->Usb2Hc, + &MaxSpeed, + &PortNumber, + &Is64BitCapable + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto uninstall_usb2hc_protocol; + } + HcDev->Is64BitCapable = Is64BitCapable; + + // + // Create and Init Perodic Frame List + // + Status = InitialPeriodicFrameList ( + HcDev, + EHCI_MAX_FRAME_LIST_LENGTH + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto uninstall_usb2hc_protocol; + } + + // + // Init memory pool management + // + Status = InitialMemoryManagement (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto deinit_perodic_frame_list; + } + + // + // Create AsyncRequest Polling Timer + // + Status = CreatePollingTimer (HcDev, AsyncRequestMoniter); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto deinit_memory_management; + } + + // + // Default Maxximum Interrupt Interval is 8, + // it means that 8 micro frame = 1ms + // + + // + // Start the Host Controller + // + if (IsEhcHalted (HcDev)) { + Status = StartScheduleExecution (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto deinit_timer; + } + } + + // + // Set all ports routing to EHC + // + Status = SetPortRoutingEhc (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto deinit_timer; + } + + // + // Component name protocol + // + Status = AddUnicodeString ( + "eng", + gEhciComponentName.SupportedLanguages, + &HcDev->ControllerNameTable, + L"Usb Enhanced Host Controller" + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto deinit_timer; + } + + goto exit; + + // + // Error handle process + // +deinit_timer: + DestoryPollingTimer (HcDev); +deinit_memory_management: + DeinitialMemoryManagement (HcDev); +deinit_perodic_frame_list: + DeinitialPeriodicFrameList (HcDev); +uninstall_usb2hc_protocol: + gBS->UninstallProtocolInterface ( + Controller, + &gEfiUsb2HcProtocolGuid, + &HcDev->Usb2Hc + ); +free_pool: + gBS->FreePool (HcDev); +close_pciio_protocol: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + +exit: + return Status; +} + +EFI_STATUS +EFIAPI +EhciDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + Arguments: + + This - Protocol instance pointer. + Controller - Handle of device to stop driver on + NumberOfChildren - Number of Children in the ChildHandleBuffer + ChildHandleBuffer - List of handles for the children we need to stop. + + Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail +--*/ +{ + EFI_STATUS Status; + EFI_USB2_HC_PROTOCOL *Usb2Hc; + USB2_HC_DEV *HcDev; + + // + // Test whether the Controller handler passed in is a valid + // Usb controller handle that should be supported, if not, + // return the error status directly + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiUsb2HcProtocolGuid, + (VOID **) &Usb2Hc, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + HcDev = USB2_HC_DEV_FROM_THIS (Usb2Hc); + + // + // free all the controller related memory and uninstall UHCI Protocol. + // + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiUsb2HcProtocolGuid, + Usb2Hc + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + // + // Set Host Controller state as halt + // + Status = Usb2Hc->SetState ( + Usb2Hc, + EfiUsbHcStateHalt + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + // + // Stop AsyncRequest Polling Timer + // + Status = StopPollingTimer (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + // + // Destroy Asynchronous Request Event + // + DestoryPollingTimer (HcDev); + + // + // Destroy Perodic Frame List + // + DeinitialPeriodicFrameList (HcDev); + + // + // Deinit Ehci pool memory management + // + DeinitialMemoryManagement (HcDev); + + // + // Denint Unicode String Table + // + FreeUnicodeStringTable (HcDev->ControllerNameTable); + + // + // Disable the USB Host Controller + // + Status = HcDev->PciIo->Attributes ( + HcDev->PciIo, + EfiPciIoAttributeOperationDisable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + gBS->FreePool (HcDev); + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + +exit: + return Status; +} + +EFI_STATUS +EFIAPI +EhciGetCapability ( + IN EFI_USB2_HC_PROTOCOL *This, + OUT UINT8 *MaxSpeed, + OUT UINT8 *PortNumber, + OUT UINT8 *Is64BitCapable + ) +/*++ + + Routine Description: + + Retrieves the capablility of root hub ports. + + Arguments: + + This - A pointer to the EFI_USB_HC_PROTOCOL instance. + MaxSpeed - A pointer to the number of the host controller. + PortNumber - A pointer to the number of the root hub ports. + Is64BitCapable - A pointer to the flag for whether controller supports + 64-bit memory addressing. + + Returns: + + EFI_SUCCESS host controller capability were retrieved successfully. + EFI_INVALID_PARAMETER MaxSpeed or PortNumber or Is64BitCapable is NULL. + EFI_DEVICE_ERROR An error was encountered while attempting to retrieve the capabilities. + +--*/ +{ + EFI_STATUS Status; + USB2_HC_DEV *HcDev; + UINT32 HcStructParamsAddr; + UINT32 HcStructParamsReg; + UINT32 HcCapParamsAddr; + UINT32 HcCapParamsReg; + + if (MaxSpeed == NULL || PortNumber == NULL || Is64BitCapable == NULL) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + HcStructParamsAddr = HCSPARAMS; + HcCapParamsAddr = HCCPARAMS; + HcDev = USB2_HC_DEV_FROM_THIS (This); + + Status = ReadEhcCapabiltiyReg ( + HcDev, + HcStructParamsAddr, + &HcStructParamsReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + Status = ReadEhcCapabiltiyReg ( + HcDev, + HcCapParamsAddr, + &HcCapParamsReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + *MaxSpeed = EFI_USB_SPEED_HIGH; + *PortNumber = (UINT8) (HcStructParamsReg & HCSP_NPORTS); + *Is64BitCapable = (UINT8) (HcCapParamsReg & HCCP_64BIT); + +exit: + return Status; +} + +EFI_STATUS +EFIAPI +EhciReset ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT16 Attributes + ) +/*++ + + Routine Description: + + Provides software reset for the USB host controller. + + Arguments: + + This - A pointer to the EFI_USB2_HC_PROTOCOL instance. + Attributes - A bit mask of the reset operation to perform. + See below for a list of the supported bit mask values. + + #define EFI_USB_HC_RESET_GLOBAL 0x0001 + #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002 + #define EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG 0x0004 + #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008 + + EFI_USB_HC_RESET_GLOBAL + If this bit is set, a global reset signal will be sent to the USB bus. + This resets all of the USB bus logic, including the USB host + controller hardware and all the devices attached on the USB bus. + EFI_USB_HC_RESET_HOST_CONTROLLER + If this bit is set, the USB host controller hardware will be reset. + No reset signal will be sent to the USB bus. + EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG + If this bit is set, a global reset signal will be sent to the USB bus. + This resets all of the USB bus logic, including the USB host + controller hardware and all the devices attached on the USB bus. + If this is an EHCI controller and the debug port has configured, then + this is will still reset the host controller. + EFI_USB_HC_RESET_HOST_WITH_DEBUG + If this bit is set, the USB host controller hardware will be reset. + If this is an EHCI controller and the debug port has been configured, + then this will still reset the host controller. + + Returns: + + EFI_SUCCESS + The reset operation succeeded. + EFI_INVALID_PARAMETER + Attributes is not valid. + EFI_UNSUPPOURTED + The type of reset specified by Attributes is not currently supported by + the host controller hardware. + EFI_ACCESS_DENIED + Reset operation is rejected due to the debug port being configured and + active; only EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG or + EFI_USB_HC_RESET_HOST_WITH_DEBUG reset Atrributes can be used to + perform reset operation for this host controller. + EFI_DEVICE_ERROR + An error was encountered while attempting to perform + the reset operation. + +--*/ +{ + EFI_STATUS Status; + USB2_HC_DEV *HcDev; + UINTN FrameIndex; + FRAME_LIST_ENTRY *FrameEntryPtr; + + HcDev = USB2_HC_DEV_FROM_THIS (This); + + switch (Attributes) { + + case EFI_USB_HC_RESET_GLOBAL: + + // + // Same behavior as Host Controller Reset + // + + case EFI_USB_HC_RESET_HOST_CONTROLLER: + + // + // Host Controller must be Halt when Reset it + // + if (IsEhcHalted (HcDev)) { + Status = ResetEhc (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + // + // Set to zero by Host Controller when reset process completes + // + Status = WaitForEhcReset (HcDev, EHCI_GENERIC_TIMEOUT); + if (EFI_ERROR (Status)) { + Status = EFI_TIMEOUT; + goto exit; + } + } else { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + // + // only asynchronous interrupt transfers are always alive on the bus, need to cleanup + // + CleanUpAllAsyncRequestTransfer (HcDev); + Status = ClearEhcAllStatus (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + // + // Set appropriate 4G Segment Selector + // + Status = SetCtrlDataStructSeg (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + // + // Init Perodic List Base Addr and Frame List + // + Status = SetFrameListBaseAddr ( + HcDev, + (UINT32) GET_0B_TO_31B (HcDev->PeriodicFrameListBuffer) + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer; + for (FrameIndex = 0; FrameIndex < HcDev->PeriodicFrameListLength; FrameIndex++) { + FrameEntryPtr->LinkTerminate = TRUE; + FrameEntryPtr++; + } + + // + // Start the Host Controller + // + if (IsEhcHalted (HcDev)) { + Status = StartScheduleExecution (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + } + + // + // Set all ports routing to EHC + // + Status = SetPortRoutingEhc (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + break; + + case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG: + + Status = EFI_UNSUPPORTED; + break; + + case EFI_USB_HC_RESET_HOST_WITH_DEBUG: + + Status = EFI_UNSUPPORTED; + break; + + default: + Status = EFI_INVALID_PARAMETER; + } + +exit: + return Status; +} + +EFI_STATUS +EFIAPI +EhciGetState ( + IN EFI_USB2_HC_PROTOCOL *This, + OUT EFI_USB_HC_STATE *State + ) +/*++ + + Routine Description: + + Retrieves current state of the USB host controller. + + Arguments: + + This A pointer to the EFI_USB2_HC_PROTOCOL instance. + State A pointer to the EFI_USB_HC_STATE data structure that + indicates current state of the USB host controller. + Type EFI_USB_HC_STATE is defined below. + + typedef enum { + EfiUsbHcStateHalt, + EfiUsbHcStateOperational, + EfiUsbHcStateSuspend, + EfiUsbHcStateMaximum + } EFI_USB_HC_STATE; + + Returns: + + EFI_SUCCESS + The state information of the host controller was returned in State. + EFI_INVALID_PARAMETER + State is NULL. + EFI_DEVICE_ERROR + An error was encountered while attempting to retrieve the + host controller's current state. +--*/ +{ + EFI_STATUS Status; + USB2_HC_DEV *HcDev; + UINT32 UsbStatusAddr; + UINT32 UsbStatusReg; + + if (State == NULL) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + UsbStatusAddr = USBSTS; + HcDev = USB2_HC_DEV_FROM_THIS (This); + + Status = ReadEhcOperationalReg ( + HcDev, + UsbStatusAddr, + &UsbStatusReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + if (UsbStatusReg & USBSTS_HCH) { + *State = EfiUsbHcStateHalt; + } else { + *State = EfiUsbHcStateOperational; + } + +exit: + return Status; +} + +EFI_STATUS +EFIAPI +EhciSetState ( + IN EFI_USB2_HC_PROTOCOL *This, + IN EFI_USB_HC_STATE State + ) +/*++ + + Routine Description: + + Sets the USB host controller to a specific state. + + Arguments: + + This - A pointer to the EFI_USB2_HC_PROTOCOL instance. + State - Indicates the state of the host controller that will be set. + + Returns: + + EFI_SUCCESS + The USB host controller was successfully placed in the state + specified by State. + EFI_INVALID_PARAMETER + State is invalid. + EFI_DEVICE_ERROR + Failed to set the state specified by State due to device error. + +--*/ +{ + EFI_STATUS Status; + USB2_HC_DEV *HcDev; + UINT32 UsbCommandAddr; + UINT32 UsbCommandReg; + EFI_USB_HC_STATE CurrentState; + + UsbCommandAddr = USBCMD; + HcDev = USB2_HC_DEV_FROM_THIS (This); + + Status = EhciGetState (This, &CurrentState); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + switch (State) { + + case EfiUsbHcStateHalt: + + if (EfiUsbHcStateHalt == CurrentState) { + Status = EFI_SUCCESS; + goto exit; + } else if (EfiUsbHcStateOperational == CurrentState) { + Status = ReadEhcOperationalReg ( + HcDev, + UsbCommandAddr, + &UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + UsbCommandReg &= ~USBCMD_RS; + Status = WriteEhcOperationalReg ( + HcDev, + UsbCommandAddr, + UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + // + // Ensure the HC is in halt status after send the stop command + // + Status = WaitForEhcHalt (HcDev, EHCI_GENERIC_TIMEOUT); + if (EFI_ERROR (Status)) { + Status = EFI_TIMEOUT; + goto exit; + } + } + break; + + case EfiUsbHcStateOperational: + + if (IsEhcSysError (HcDev)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + if (EfiUsbHcStateOperational == CurrentState) { + Status = EFI_SUCCESS; + goto exit; + } else if (EfiUsbHcStateHalt == CurrentState) { + // + // Set Host Controller Run + // + Status = ReadEhcOperationalReg ( + HcDev, + UsbCommandAddr, + &UsbCommandReg + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + UsbCommandReg |= USBCMD_RS; + Status = WriteEhcOperationalReg ( + HcDev, + UsbCommandAddr, + UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + } + break; + + case EfiUsbHcStateSuspend: + + Status = EFI_UNSUPPORTED; + break; + + default: + + Status = EFI_INVALID_PARAMETER; + } + +exit: + return Status; +} + +EFI_STATUS +EFIAPI +EhciGetRootHubPortStatus ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus + ) +/*++ + + Routine Description: + + Retrieves the current status of a USB root hub port. + + Arguments: + + This - A pointer to the EFI_USB2_HC_PROTOCOL. + PortNumber - Specifies the root hub port from which the status + is to be retrieved. This value is zero-based. For example, + if a root hub has two ports, then the first port is numbered 0, + and the second port is numbered 1. + PortStatus - A pointer to the current port status bits and + port status change bits. + + Returns: + + EFI_SUCCESS The status of the USB root hub port specified + by PortNumber was returned in PortStatus. + EFI_INVALID_PARAMETER PortNumber is invalid. + EFI_DEVICE_ERROR Can't read register + +--*/ +{ + EFI_STATUS Status; + USB2_HC_DEV *HcDev; + UINT32 PortStatusControlAddr; + UINT32 PortStatusControlReg; + UINT8 MaxSpeed; + UINT8 TotalPortNumber; + UINT8 Is64BitCapable; + + if (PortStatus == NULL) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + EhciGetCapability ( + This, + &MaxSpeed, + &TotalPortNumber, + &Is64BitCapable + ); + + if (PortNumber >= TotalPortNumber) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + HcDev = USB2_HC_DEV_FROM_THIS (This); + PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber)); + + // + // Clear port status + // + PortStatus->PortStatus = 0; + PortStatus->PortChangeStatus = 0; + + Status = ReadEhcOperationalReg ( + HcDev, + PortStatusControlAddr, + &PortStatusControlReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + // + // Fill Port Status bits + // + + // + // Current Connect Status + // + if (PORTSC_CCS & PortStatusControlReg) { + PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION; + } + // + // Port Enabled/Disabled + // + if (PORTSC_PED & PortStatusControlReg) { + PortStatus->PortStatus |= USB_PORT_STAT_ENABLE; + } + // + // Port Suspend + // + if (PORTSC_SUSP & PortStatusControlReg) { + PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND; + } + // + // Over-current Active + // + if (PORTSC_OCA & PortStatusControlReg) { + PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT; + } + // + // Port Reset + // + if (PORTSC_PR & PortStatusControlReg) { + PortStatus->PortStatus |= USB_PORT_STAT_RESET; + } + // + // Port Power + // + if (PORTSC_PP & PortStatusControlReg) { + PortStatus->PortStatus |= USB_PORT_STAT_POWER; + } + // + // Port Owner + // + if (PORTSC_PO & PortStatusControlReg) { + PortStatus->PortStatus |= USB_PORT_STAT_OWNER; + } + // + // Identify device speed + // + if (PORTSC_LS_KSTATE & PortStatusControlReg) { + // + // Low Speed Device Attached + // + PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED; + } else { + // + // Not Low Speed Device Attached + // + if ((PORTSC_CCS & PortStatusControlReg) && (PORTSC_CSC & PortStatusControlReg)) { + mDeviceSpeed[PortNumber] = IsHighSpeedDevice (This, PortNumber) ? USB_PORT_STAT_HIGH_SPEED : 0; + } + PortStatus->PortStatus |= mDeviceSpeed[PortNumber]; + } + // + // Fill Port Status Change bits + // + // + // Connect Status Change + // + if (PORTSC_CSC & PortStatusControlReg) { + PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION; + } + // + // Port Enabled/Disabled Change + // + if (PORTSC_PEDC & PortStatusControlReg) { + PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE; + } + // + // Port Over Current Change + // + if (PORTSC_OCC & PortStatusControlReg) { + PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT; + } + +exit: + return Status; +} + +EFI_STATUS +EFIAPI +EhciSetRootHubPortFeature ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +/*++ + + Routine Description: + + Sets a feature for the specified root hub port. + + Arguments: + + This - A pointer to the EFI_USB2_HC_PROTOCOL. + PortNumber - Specifies the root hub port whose feature + is requested to be set. + PortFeature - Indicates the feature selector associated + with the feature set request. + + Returns: + + EFI_SUCCESS + The feature specified by PortFeature was set for the + USB root hub port specified by PortNumber. + EFI_INVALID_PARAMETER + PortNumber is invalid or PortFeature is invalid. + EFI_DEVICE_ERROR + Can't read register + +--*/ +{ + EFI_STATUS Status; + USB2_HC_DEV *HcDev; + UINT32 PortStatusControlAddr; + UINT32 PortStatusControlReg; + UINT8 MaxSpeed; + UINT8 TotalPortNumber; + UINT8 Is64BitCapable; + + EhciGetCapability ( + This, + &MaxSpeed, + &TotalPortNumber, + &Is64BitCapable + ); + + if (PortNumber >= TotalPortNumber) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + HcDev = USB2_HC_DEV_FROM_THIS (This); + PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber)); + + Status = ReadEhcOperationalReg ( + HcDev, + PortStatusControlAddr, + &PortStatusControlReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + switch (PortFeature) { + + case EfiUsbPortEnable: + + // + // Sofeware can't set this bit, Port can only be enable by the Host Controller + // as a part of the reset and enable + // + PortStatusControlReg &= 0xffffffd5; + PortStatusControlReg |= PORTSC_PED; + break; + + case EfiUsbPortSuspend: + + PortStatusControlReg &= 0xffffffd5; + PortStatusControlReg |= PORTSC_SUSP; + break; + + case EfiUsbPortReset: + + // + // Make sure Host Controller not halt before reset it + // + if (IsEhcHalted (HcDev)) { + Status = StartScheduleExecution (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + Status = WaitForEhcNotHalt (HcDev, EHCI_GENERIC_TIMEOUT); + if (EFI_ERROR (Status)) { + DEBUG ((gEHCDebugLevel, "WaitForEhcNotHalt TimeOut\n")); + Status = EFI_DEVICE_ERROR; + goto exit; + } + } + PortStatusControlReg &= 0xffffffd5; + PortStatusControlReg |= PORTSC_PR; + // + // Set one to PortReset bit must also set zero to PortEnable bit + // + PortStatusControlReg &= ~PORTSC_PED; + break; + + case EfiUsbPortPower: + + // + // No support, no operation + // + goto exit; + + case EfiUsbPortOwner: + + PortStatusControlReg &= 0xffffffd5; + PortStatusControlReg |= PORTSC_PO; + break; + + default: + + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + Status = WriteEhcOperationalReg ( + HcDev, + PortStatusControlAddr, + PortStatusControlReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + } + +exit: + return Status; +} + +EFI_STATUS +EFIAPI +EhciClearRootHubPortFeature ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +/*++ + + Routine Description: + + Clears a feature for the specified root hub port. + + Arguments: + + This - A pointer to the EFI_USB2_HC_PROTOCOL instance. + PortNumber - Specifies the root hub port whose feature + is requested to be cleared. + PortFeature - Indicates the feature selector associated with the + feature clear request. + + Returns: + + EFI_SUCCESS + The feature specified by PortFeature was cleared for the + USB root hub port specified by PortNumber. + EFI_INVALID_PARAMETER + PortNumber is invalid or PortFeature is invalid. + EFI_DEVICE_ERROR + Can't read register + +--*/ +{ + EFI_STATUS Status; + USB2_HC_DEV *HcDev; + UINT32 PortStatusControlAddr; + UINT32 PortStatusControlReg; + UINT8 MaxSpeed; + UINT8 TotalPortNumber; + UINT8 Is64BitCapable; + + EhciGetCapability ( + This, + &MaxSpeed, + &TotalPortNumber, + &Is64BitCapable + ); + + if (PortNumber >= TotalPortNumber) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + HcDev = USB2_HC_DEV_FROM_THIS (This); + PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber)); + + Status = ReadEhcOperationalReg ( + HcDev, + PortStatusControlAddr, + &PortStatusControlReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + switch (PortFeature) { + + case EfiUsbPortEnable: + + // + // Clear PORT_ENABLE feature means disable port. + // + PortStatusControlReg &= 0xffffffd5; + PortStatusControlReg &= ~PORTSC_PED; + break; + + case EfiUsbPortSuspend: + + // + // A write of zero to this bit is ignored by the host controller. + // The host controller will unconditionally set this bit to a zero when: + // 1. software sets the Forct Port Resume bit to a zero from a one. + // 2. software sets the Port Reset bit to a one frome a zero. + // + PortStatusControlReg &= 0xffffffd5; + PortStatusControlReg &= ~PORTSC_FPR; + break; + + case EfiUsbPortReset: + + // + // Clear PORT_RESET means clear the reset signal. + // + PortStatusControlReg &= 0xffffffd5; + PortStatusControlReg &= ~PORTSC_PR; + break; + + case EfiUsbPortPower: + + // + // No support, no operation + // + goto exit; + + case EfiUsbPortOwner: + + // + // Clear port owner means this port owned by EHC + // + PortStatusControlReg &= 0xffffffd5; + PortStatusControlReg &= ~PORTSC_PO; + break; + + case EfiUsbPortConnectChange: + + // + // Clear connect status change + // + PortStatusControlReg &= 0xffffffd5; + PortStatusControlReg |= PORTSC_CSC; + break; + + case EfiUsbPortEnableChange: + + // + // Clear enable status change + // + PortStatusControlReg &= 0xffffffd5; + PortStatusControlReg |= PORTSC_PEDC; + break; + + case EfiUsbPortSuspendChange: + + // + // No related bit, no operation + // + goto exit; + + case EfiUsbPortOverCurrentChange: + + // + // Clear PortOverCurrent change + // + PortStatusControlReg &= 0xffffffd5; + PortStatusControlReg |= PORTSC_OCC; + break; + + case EfiUsbPortResetChange: + + // + // No related bit, no operation + // + goto exit; + + default: + + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + Status = WriteEhcOperationalReg ( + HcDev, + PortStatusControlAddr, + PortStatusControlReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + +exit: + return Status; +} + +EFI_STATUS +EFIAPI +EhciControlTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + + Submits control transfer to a target USB device. + + Arguments: + + This - A pointer to the EFI_USB2_HC_PROTOCOL instance. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + DeviceSpeed - Indicates target device speed. + MaximumPacketLength - Indicates the maximum packet size that the + default control transfer endpoint is capable of + sending or receiving. + Request - A pointer to the USB device request that will be sent + to the USB device. + TransferDirection - Specifies the data direction for the transfer. + There are three values available, DataIn, DataOut + and NoData. + Data - A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + DataLength - Indicates the size, in bytes, of the data buffer + specified by Data. + TimeOut - Indicates the maximum time, in microseconds, + which the transfer is allowed to complete. + Translator - A pointr to the transaction translator data. + TransferResult - A pointer to the detailed result information generated + by this control transfer. + + Returns: + + EFI_SUCCESS + The control transfer was completed successfully. + EFI_OUT_OF_RESOURCES + The control transfer could not be completed due to a lack of resources. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_TIMEOUT + The control transfer failed due to timeout. + EFI_DEVICE_ERROR + The control transfer failed due to host controller or device error. + Caller should check TranferResult for detailed error information. + +--*/ +{ + EFI_STATUS Status; + USB2_HC_DEV *HcDev; + UINT8 PktId; + EHCI_QH_ENTITY *QhPtr; + EHCI_QTD_ENTITY *ControlQtdsPtr; + UINT8 *DataCursor; + VOID *DataMap; + UINT8 *RequestCursor; + VOID *RequestMap; + + QhPtr = NULL; + ControlQtdsPtr = NULL; + DataCursor = NULL; + DataMap = NULL; + RequestCursor = NULL; + RequestMap = NULL; + HcDev = USB2_HC_DEV_FROM_THIS (This); + + // + // Parameters Checking + // + if (TransferDirection != EfiUsbDataIn && + TransferDirection != EfiUsbDataOut && + TransferDirection != EfiUsbNoData + ) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (EfiUsbNoData == TransferDirection) { + if (NULL != Data || 0 != *DataLength) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + } else { + if (NULL == Data || 0 == *DataLength) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + } + + if (Request == NULL || TransferResult == NULL) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (EFI_USB_SPEED_LOW == DeviceSpeed) { + if (MaximumPacketLength != 8) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + } else if (MaximumPacketLength != 8 && + MaximumPacketLength != 16 && + MaximumPacketLength != 32 && + MaximumPacketLength != 64 + ) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + // + // If errors exist that cause host controller halt, + // then return EFI_DEVICE_ERROR. + // + if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) { + ClearEhcAllStatus (HcDev); + *TransferResult = EFI_USB_ERR_SYSTEM; + Status = EFI_DEVICE_ERROR; + goto exit; + } + + // + // Map the Request for bus master access. + // BusMasterRead means cpu write + // + Status = MapRequestBuffer ( + HcDev, + Request, + &RequestCursor, + &RequestMap + ); + if (EFI_ERROR (Status)) { + *TransferResult = EFI_USB_ERR_SYSTEM; + Status = EFI_DEVICE_ERROR; + goto exit; + } + + // + // Map the source data buffer for bus master access. + // + Status = MapDataBuffer ( + HcDev, + TransferDirection, + Data, + DataLength, + &PktId, + &DataCursor, + &DataMap + ); + if (EFI_ERROR (Status)) { + *TransferResult = EFI_USB_ERR_SYSTEM; + Status = EFI_DEVICE_ERROR; + goto unmap_request; + } + + // + // Create and init control Qh + // + Status = CreateControlQh ( + HcDev, + DeviceAddress, + DeviceSpeed, + MaximumPacketLength, + Translator, + &QhPtr + ); + if (EFI_ERROR (Status)) { + *TransferResult = EFI_USB_ERR_SYSTEM; + Status = EFI_OUT_OF_RESOURCES; + goto unmap_data; + } + + // + // Create and init control Qtds + // + Status = CreateControlQtds ( + HcDev, + PktId, + RequestCursor, + DataCursor, + *DataLength, + Translator, + &ControlQtdsPtr + ); + if (EFI_ERROR (Status)) { + *TransferResult = EFI_USB_ERR_SYSTEM; + Status = EFI_OUT_OF_RESOURCES; + goto destory_qh; + } + + // + // Link Qtds to Qh + // + LinkQtdToQh (QhPtr, ControlQtdsPtr); + + ClearEhcAllStatus (HcDev); + + // + // Link Qh and Qtds to Async Schedule List + // + Status = LinkQhToAsyncList (HcDev, QhPtr); + if (EFI_ERROR (Status)) { + *TransferResult = EFI_USB_ERR_SYSTEM; + Status = EFI_DEVICE_ERROR; + goto destory_qtds; + } + + // + // Poll Qh-Qtds execution and get result. + // detail status is returned + // + Status = ExecuteTransfer ( + HcDev, + TRUE, + QhPtr, + DataLength, + 0, + TimeOut, + TransferResult + ); + if (EFI_ERROR (Status)) { + goto destory_qtds; + } + + // + // If has errors that cause host controller halt, + // then return EFI_DEVICE_ERROR directly. + // + if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) { + *TransferResult |= EFI_USB_ERR_SYSTEM; + } + + ClearEhcAllStatus (HcDev); + +destory_qtds: + UnlinkQhFromAsyncList (HcDev, QhPtr); + DestoryQtds (HcDev, ControlQtdsPtr); +destory_qh: + DestoryQh (HcDev, QhPtr); +unmap_data: + HcDev->PciIo->Unmap (HcDev->PciIo, DataMap); +unmap_request: + HcDev->PciIo->Unmap (HcDev->PciIo, RequestMap); +exit: + HcDev->PciIo->Flush (HcDev->PciIo); + return Status; +} + +EFI_STATUS +EFIAPI +EhciBulkTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + + Submits bulk transfer to a bulk endpoint of a USB device. + + Arguments: + + This - A pointer to the EFI_USB2_HC_PROTOCOL instance. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - The combination of an endpoint number and an + endpoint direction of the target USB device. + Each endpoint address supports data transfer in + one direction except the control endpoint + (whose default endpoint address is 0). + It is the caller's responsibility to make sure that + the EndPointAddress represents a bulk endpoint. + DeviceSpeed - Indicates device speed. The supported values are EFI_USB_SPEED_FULL + and EFI_USB_SPEED_HIGH. + MaximumPacketLength - Indicates the maximum packet size the target endpoint + is capable of sending or receiving. + DataBuffersNumber - Number of data buffers prepared for the transfer. + Data - Array of pointers to the buffers of data that will be transmitted + to USB device or received from USB device. + DataLength - When input, indicates the size, in bytes, of the data buffer + specified by Data. When output, indicates the actually + transferred data size. + DataToggle - A pointer to the data toggle value. On input, it indicates + the initial data toggle value the bulk transfer should adopt; + on output, it is updated to indicate the data toggle value + of the subsequent bulk transfer. + Translator - A pointr to the transaction translator data. + TimeOut - Indicates the maximum time, in microseconds, which the + transfer is allowed to complete. + TransferResult - A pointer to the detailed result information of the + bulk transfer. + + Returns: + + EFI_SUCCESS + The bulk transfer was completed successfully. + EFI_OUT_OF_RESOURCES + The bulk transfer could not be submitted due to lack of resource. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_TIMEOUT + The bulk transfer failed due to timeout. + EFI_DEVICE_ERROR + The bulk transfer failed due to host controller or device error. + Caller should check TranferResult for detailed error information. + +--*/ +{ + EFI_STATUS Status; + USB2_HC_DEV *HcDev; + UINT8 PktId; + EHCI_QH_ENTITY *QhPtr; + EHCI_QTD_ENTITY *BulkQtdsPtr; + UINT8 *DataCursor; + VOID *DataMap; + EFI_USB_DATA_DIRECTION TransferDirection; + + QhPtr = NULL; + BulkQtdsPtr = NULL; + DataCursor = NULL; + DataMap = NULL; + HcDev = USB2_HC_DEV_FROM_THIS (This); + + // + // Parameters Checking + // + if (NULL == DataLength || + NULL == Data || + NULL == Data[0] || + NULL == TransferResult + ) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (*DataLength == 0) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (1 != *DataToggle && 0 != *DataToggle) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (EFI_USB_SPEED_LOW == DeviceSpeed) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (EFI_USB_SPEED_FULL == DeviceSpeed) { + if (MaximumPacketLength > 64) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + } + + if (EFI_USB_SPEED_HIGH == DeviceSpeed) { + if (MaximumPacketLength > 512) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + } + + // + // if has errors that cause host controller halt, + // then return EFI_DEVICE_ERROR directly. + // + if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) { + ClearEhcAllStatus (HcDev); + *TransferResult = EFI_USB_ERR_SYSTEM; + Status = EFI_DEVICE_ERROR; + goto exit; + } + + Status = ClearEhcAllStatus (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + // + // construct QH and TD data structures, + // and link them together + // + if (EndPointAddress & 0x80) { + TransferDirection = EfiUsbDataIn; + } else { + TransferDirection = EfiUsbDataOut; + } + + Status = MapDataBuffer ( + HcDev, + TransferDirection, + Data[0], + DataLength, + &PktId, + &DataCursor, + &DataMap + ); + if (EFI_ERROR (Status)) { + *TransferResult = EFI_USB_ERR_SYSTEM; + Status = EFI_DEVICE_ERROR; + goto exit; + } + + // + // Create and init Bulk Qh + // + Status = CreateBulkQh ( + HcDev, + DeviceAddress, + EndPointAddress, + DeviceSpeed, + *DataToggle, + MaximumPacketLength, + Translator, + &QhPtr + ); + if (EFI_ERROR (Status)) { + *TransferResult = EFI_USB_ERR_SYSTEM; + Status = EFI_OUT_OF_RESOURCES; + goto unmap_data; + } + + // + // Create and init Bulk Qtds + // + Status = CreateBulkOrInterruptQtds ( + HcDev, + PktId, + DataCursor, + *DataLength, + Translator, + &BulkQtdsPtr + ); + if (EFI_ERROR (Status)) { + *TransferResult = EFI_USB_ERR_SYSTEM; + Status = EFI_OUT_OF_RESOURCES; + goto destory_qh; + } + + // + // Link Qtds to Qh + // + LinkQtdToQh (QhPtr, BulkQtdsPtr); + + ClearEhcAllStatus (HcDev); + + // + // Link Qh and qtds to Async Schedule List + // + Status = LinkQhToAsyncList (HcDev, QhPtr); + if (EFI_ERROR (Status)) { + *TransferResult = EFI_USB_ERR_SYSTEM; + Status = EFI_DEVICE_ERROR; + goto destory_qtds; + } + + // + // Poll QH-TDs execution and get result. + // detail status is returned + // + Status = ExecuteTransfer ( + HcDev, + FALSE, + QhPtr, + DataLength, + DataToggle, + TimeOut, + TransferResult + ); + if (EFI_ERROR (Status)) { + goto destory_qtds; + } + + // + // if has errors that cause host controller halt, + // then return EFI_DEVICE_ERROR directly. + // + if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) { + *TransferResult |= EFI_USB_ERR_SYSTEM; + } + + ClearEhcAllStatus (HcDev); + +destory_qtds: + UnlinkQhFromAsyncList (HcDev, QhPtr); + DestoryQtds (HcDev, BulkQtdsPtr); +destory_qh: + DestoryQh (HcDev, QhPtr); +unmap_data: + HcDev->PciIo->Unmap (HcDev->PciIo, DataMap); +exit: + HcDev->PciIo->Flush (HcDev->PciIo); + return Status; +} + +EFI_STATUS +EFIAPI +EhciAsyncInterruptTransfer ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle, + IN UINTN PollingInterval, + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, + IN VOID *Context OPTIONAL + ) +/*++ + + Routine Description: + + Submits an asynchronous interrupt transfer to an + interrupt endpoint of a USB device. + + Arguments: + + This - A pointer to the EFI_USB2_HC_PROTOCOL instance. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - The combination of an endpoint number and an endpoint + direction of the target USB device. Each endpoint address + supports data transfer in one direction except the + control endpoint (whose default endpoint address is 0). + It is the caller's responsibility to make sure that + the EndPointAddress represents an interrupt endpoint. + DeviceSpeed - Indicates device speed. + MaximumPacketLength - Indicates the maximum packet size the target endpoint + is capable of sending or receiving. + IsNewTransfer - If TRUE, an asynchronous interrupt pipe is built between + the host and the target interrupt endpoint. + If FALSE, the specified asynchronous interrupt pipe + is canceled. + DataToggle - A pointer to the data toggle value. On input, it is valid + when IsNewTransfer is TRUE, and it indicates the initial + data toggle value the asynchronous interrupt transfer + should adopt. + On output, it is valid when IsNewTransfer is FALSE, + and it is updated to indicate the data toggle value of + the subsequent asynchronous interrupt transfer. + PollingInterval - Indicates the interval, in milliseconds, that the + asynchronous interrupt transfer is polled. + This parameter is required when IsNewTransfer is TRUE. + DataLength - Indicates the length of data to be received at the + rate specified by PollingInterval from the target + asynchronous interrupt endpoint. This parameter + is only required when IsNewTransfer is TRUE. + Translator - A pointr to the transaction translator data. + CallBackFunction - The Callback function.This function is called at the + rate specified by PollingInterval.This parameter is + only required when IsNewTransfer is TRUE. + Context - The context that is passed to the CallBackFunction. + - This is an optional parameter and may be NULL. + + Returns: + + EFI_SUCCESS + The asynchronous interrupt transfer request has been successfully + submitted or canceled. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_OUT_OF_RESOURCES + The request could not be completed due to a lack of resources. + EFI_DEVICE_ERROR + Can't read register + +--*/ +{ + EFI_STATUS Status; + USB2_HC_DEV *HcDev; + UINT8 PktId; + EHCI_QH_ENTITY *QhPtr; + EHCI_QTD_ENTITY *InterruptQtdsPtr; + UINT8 *DataPtr; + UINT8 *DataCursor; + VOID *DataMap; + UINTN MappedLength; + EHCI_ASYNC_REQUEST *AsyncRequestPtr; + EFI_TPL OldTpl; + + QhPtr = NULL; + InterruptQtdsPtr = NULL; + DataPtr = NULL; + DataCursor = NULL; + DataMap = NULL; + AsyncRequestPtr = NULL; + HcDev = USB2_HC_DEV_FROM_THIS (This); + + // + // Parameters Checking + // + if (!IsDataInTransfer (EndPointAddress)) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (IsNewTransfer) { + if (0 == DataLength) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (*DataToggle != 1 && *DataToggle != 0) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (PollingInterval > 255 || PollingInterval < 1) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + } + + // + // if has errors that cause host controller halt, + // then return EFI_DEVICE_ERROR directly. + // + if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) { + ClearEhcAllStatus (HcDev); + Status = EFI_DEVICE_ERROR; + goto exit; + } + + Status = ClearEhcAllStatus (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + // + // Delete Async interrupt transfer request + // + if (!IsNewTransfer) { + + OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + Status = DeleteAsyncRequestTransfer ( + HcDev, + DeviceAddress, + EndPointAddress, + DataToggle + ); + + gBS->RestoreTPL (OldTpl); + + goto exit; + } + + Status = EhciAllocatePool ( + HcDev, + (UINT8 **) &AsyncRequestPtr, + sizeof (EHCI_ASYNC_REQUEST) + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + Status = EhciAllocatePool (HcDev, &DataPtr, DataLength); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto free_request; + } + + MappedLength = DataLength; + Status = MapDataBuffer ( + HcDev, + EfiUsbDataIn, + DataPtr, + &MappedLength, + &PktId, + &DataCursor, + &DataMap + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto free_data; + } + + // + // Create and init Interrupt Qh + // + Status = CreateInterruptQh ( + HcDev, + DeviceAddress, + EndPointAddress, + DeviceSpeed, + *DataToggle, + MaximumPacketLength, + PollingInterval, + Translator, + &QhPtr + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto unmap_data; + } + + // + // Create and init Interrupt Qtds + // + Status = CreateBulkOrInterruptQtds ( + HcDev, + PktId, + DataCursor, + MappedLength, + Translator, + &InterruptQtdsPtr + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto destory_qh; + } + + // + // Link Qtds to Qh + // + LinkQtdToQh (QhPtr, InterruptQtdsPtr); + + // + // Init AsyncRequest Entry + // + AsyncRequestPtr->Context = Context; + AsyncRequestPtr->CallBackFunc = CallBackFunction; + AsyncRequestPtr->TransferType = ASYNC_INTERRUPT_TRANSFER; + AsyncRequestPtr->QhPtr = QhPtr; + AsyncRequestPtr->Prev = NULL; + AsyncRequestPtr->Next = NULL; + + if (NULL == HcDev->AsyncRequestList) { + Status = StartPollingTimer (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + CleanUpAllAsyncRequestTransfer (HcDev); + goto exit; + } + } + + // + // Link Entry to AsyncRequest List + // + LinkToAsyncReqeust (HcDev, AsyncRequestPtr); + + ClearEhcAllStatus (HcDev); + + Status = DisablePeriodicSchedule (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT); + if (EFI_ERROR (Status)) { + Status = EFI_TIMEOUT; + goto exit; + } + + // + // Link Qh and Qtds to Periodic Schedule List + // + LinkQhToPeriodicList (HcDev, QhPtr); + + Status = EnablePeriodicSchedule (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT); + if (EFI_ERROR (Status)) { + Status = EFI_TIMEOUT; + goto exit; + } + + if (IsEhcHalted (HcDev)) { + Status = StartScheduleExecution (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + } + + HcDev->PciIo->Flush (HcDev->PciIo); + goto exit; + +destory_qh: + DestoryQh (HcDev, QhPtr); +free_data: + EhciFreePool (HcDev, DataPtr, DataLength); +free_request: + EhciFreePool ( + HcDev, + (UINT8 *) AsyncRequestPtr, + sizeof (EHCI_ASYNC_REQUEST) + ); +unmap_data: + HcDev->PciIo->Unmap (HcDev->PciIo, DataMap); +exit: + return Status; +} + +EFI_STATUS +EFIAPI +EhciSyncInterruptTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + + Submits synchronous interrupt transfer to an interrupt endpoint + of a USB device. + + Arguments: + + This - A pointer to the EFI_USB2_HC_PROTOCOL instance. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - The combination of an endpoint number and an endpoint + direction of the target USB device. Each endpoint + address supports data transfer in one direction + except the control endpoint (whose default + endpoint address is 0). It is the caller's responsibility + to make sure that the EndPointAddress represents + an interrupt endpoint. + DeviceSpeed - Indicates device speed. + MaximumPacketLength - Indicates the maximum packet size the target endpoint + is capable of sending or receiving. + Data - A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + DataLength - On input, the size, in bytes, of the data buffer specified + by Data. On output, the number of bytes transferred. + DataToggle - A pointer to the data toggle value. On input, it indicates + the initial data toggle value the synchronous interrupt + transfer should adopt; + on output, it is updated to indicate the data toggle value + of the subsequent synchronous interrupt transfer. + TimeOut - Indicates the maximum time, in microseconds, which the + transfer is allowed to complete. + Translator - A pointr to the transaction translator data. + TransferResult - A pointer to the detailed result information from + the synchronous interrupt transfer. + + Returns: + + EFI_SUCCESS + The synchronous interrupt transfer was completed successfully. + EFI_OUT_OF_RESOURCES + The synchronous interrupt transfer could not be submitted due + to lack of resource. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_TIMEOUT + The synchronous interrupt transfer failed due to timeout. + EFI_DEVICE_ERROR + The synchronous interrupt transfer failed due to host controller + or device error. Caller should check TranferResult for detailed + error information. + +--*/ +{ + EFI_STATUS Status; + USB2_HC_DEV *HcDev; + UINT8 PktId; + EHCI_QH_ENTITY *QhPtr; + EHCI_QTD_ENTITY *InterruptQtdsPtr; + UINT8 *DataCursor; + VOID *DataMap; + + QhPtr = NULL; + InterruptQtdsPtr = NULL; + DataCursor = NULL; + DataMap = NULL; + HcDev = USB2_HC_DEV_FROM_THIS (This); + + // + // Parameters Checking + // + if (DataLength == NULL || + Data == NULL || + TransferResult == NULL + ) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (!IsDataInTransfer (EndPointAddress)) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (0 == *DataLength) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (*DataToggle != 1 && *DataToggle != 0) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (EFI_USB_SPEED_LOW == DeviceSpeed && 8 != MaximumPacketLength) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (EFI_USB_SPEED_FULL == DeviceSpeed && MaximumPacketLength > 64) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (EFI_USB_SPEED_HIGH == DeviceSpeed && MaximumPacketLength > 3072) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + // + // if has errors that cause host controller halt, + // then return EFI_DEVICE_ERROR directly. + // + if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) { + ClearEhcAllStatus (HcDev); + *TransferResult = EFI_USB_ERR_SYSTEM; + Status = EFI_DEVICE_ERROR; + goto exit; + } + + Status = ClearEhcAllStatus (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + Status = MapDataBuffer ( + HcDev, + EfiUsbDataIn, + Data, + DataLength, + &PktId, + &DataCursor, + &DataMap + ); + if (EFI_ERROR (Status)) { + *TransferResult = EFI_USB_ERR_SYSTEM; + Status = EFI_DEVICE_ERROR; + goto exit; + } + + // + // Create and init Interrupt Qh + // + Status = CreateInterruptQh ( + HcDev, + DeviceAddress, + EndPointAddress, + DeviceSpeed, + *DataToggle, + MaximumPacketLength, + 0, + Translator, + &QhPtr + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto unmap_data; + } + + // + // Create and init Interrupt Qtds + // + Status = CreateBulkOrInterruptQtds ( + HcDev, + PktId, + DataCursor, + *DataLength, + Translator, + &InterruptQtdsPtr + ); + if (EFI_ERROR (Status)) { + *TransferResult = EFI_USB_ERR_SYSTEM; + Status = EFI_OUT_OF_RESOURCES; + goto destory_qh; + } + + // + // Link Qtds to Qh + // + LinkQtdToQh (QhPtr, InterruptQtdsPtr); + + ClearEhcAllStatus (HcDev); + + Status = DisablePeriodicSchedule (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT); + if (EFI_ERROR (Status)) { + Status = EFI_TIMEOUT; + goto exit; + } + + // + // Link Qh and Qtds to Periodic Schedule List + // + LinkQhToPeriodicList (HcDev, QhPtr); + + Status = EnablePeriodicSchedule (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT); + if (EFI_ERROR (Status)) { + Status = EFI_TIMEOUT; + goto exit; + } + + if (IsEhcHalted (HcDev)) { + Status = StartScheduleExecution (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + } + + // + // Poll QH-TDs execution and get result. + // detail status is returned + // + Status = ExecuteTransfer ( + HcDev, + FALSE, + QhPtr, + DataLength, + DataToggle, + TimeOut, + TransferResult + ); + if (EFI_ERROR (Status)) { + goto destory_qtds; + } + + // + // if has errors that cause host controller halt, + // then return EFI_DEVICE_ERROR directly. + // + if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) { + *TransferResult |= EFI_USB_ERR_SYSTEM; + } + + ClearEhcAllStatus (HcDev); + +destory_qtds: + UnlinkQhFromPeriodicList (HcDev, QhPtr, 0); + DestoryQtds (HcDev, InterruptQtdsPtr); +destory_qh: + DestoryQh (HcDev, QhPtr); +unmap_data: + HcDev->PciIo->Unmap (HcDev->PciIo, DataMap); +exit: + HcDev->PciIo->Flush (HcDev->PciIo); + return Status; +} + +EFI_STATUS +EFIAPI +EhciIsochronousTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + + Submits isochronous transfer to a target USB device. + + Arguments: + + This - A pointer to the EFI_USB2_HC_PROTOCOL instance. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - End point address + DeviceSpeed - Indicates device speed. + MaximumPacketLength - Indicates the maximum packet size that the + default control transfer endpoint is capable of + sending or receiving. + DataBuffersNumber - Number of data buffers prepared for the transfer. + Data - Array of pointers to the buffers of data that will be + transmitted to USB device or received from USB device. + DataLength - Indicates the size, in bytes, of the data buffer + specified by Data. + Translator - A pointr to the transaction translator data. + TransferResult - A pointer to the detailed result information generated + by this control transfer. + + Returns: + + EFI_UNSUPPORTED + +--*/ +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +EhciAsyncIsochronousTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context + ) +/*++ + + Routine Description: + + Submits Async isochronous transfer to a target USB device. + + Arguments: + + This - A pointer to the EFI_USB2_HC_PROTOCOL instance. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - End point address + DeviceSpeed - Indicates device speed. + MaximumPacketLength - Indicates the maximum packet size that the + default control transfer endpoint is capable of + sending or receiving. + DataBuffersNumber - Number of data buffers prepared for the transfer. + Data - Array of pointers to the buffers of data that will be transmitted + to USB device or received from USB device. + Translator - A pointr to the transaction translator data. + IsochronousCallBack - When the transfer complete, the call back function will be called + Context - Pass to the call back function as parameter + + Returns: + + EFI_UNSUPPORTED + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.h b/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.h new file mode 100644 index 0000000000..a5fa2be394 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.h @@ -0,0 +1,2689 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Ehci.h + +Abstract: + + +Revision History +--*/ + +#ifndef _EHCI_H +#define _EHCI_H + +// +// Universal Host Controller Interface data structures and defines +// +#include + +#ifdef EFI_DEBUG +extern UINTN gEHCDebugLevel; +extern UINTN gEHCErrorLevel; +#endif + +#define STALL_1_MACRO_SECOND 1 +#define STALL_1_MILLI_SECOND 1000 * STALL_1_MACRO_SECOND +#define STALL_1_SECOND 1000 * STALL_1_MILLI_SECOND + +#define SETUP_PACKET_PID_CODE 0x02 +#define INPUT_PACKET_PID_CODE 0x01 +#define OUTPUT_PACKET_PID_CODE 0x0 + +#define ITD_SELECT_TYPE 0x0 +#define QH_SELECT_TYPE 0x01 +#define SITD_SELECT_TYPE 0x02 +#define FSTN_SELECT_TYPE 0x03 + +#define EHCI_SET_PORT_RESET_RECOVERY_TIME 50 * STALL_1_MILLI_SECOND +#define EHCI_CLEAR_PORT_RESET_RECOVERY_TIME STALL_1_MILLI_SECOND +#define EHCI_GENERIC_TIMEOUT 50 * STALL_1_MILLI_SECOND +#define EHCI_GENERIC_RECOVERY_TIME 50 * STALL_1_MACRO_SECOND +#define EHCI_SYNC_REQUEST_POLLING_TIME 50 * STALL_1_MACRO_SECOND +#define EHCI_ASYNC_REQUEST_POLLING_TIME 50 * STALL_1_MILLI_SECOND + +#define USB_BAR_INDEX 0 /* how many bytes away from USB_BASE to 0x10 */ + +#define NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES 1 + +#define EHCI_MIN_PACKET_SIZE 8 +#define EHCI_MAX_PACKET_SIZE 1024 +#define EHCI_MAX_FRAME_LIST_LENGTH 1024 +#define EHCI_BLOCK_SIZE_WITH_TT 64 +#define EHCI_BLOCK_SIZE 512 +#define EHCI_MAX_QTD_CAPACITY (EFI_PAGE_SIZE * 5) + +#define NAK_COUNT_RELOAD 3 +#define QTD_ERROR_COUNTER 1 +#define HIGH_BANDWIDTH_PIPE_MULTIPLIER 1 + +#define QTD_STATUS_ACTIVE 0x80 +#define QTD_STATUS_HALTED 0x40 +#define QTD_STATUS_BUFFER_ERR 0x20 +#define QTD_STATUS_BABBLE_ERR 0x10 +#define QTD_STATUS_TRANSACTION_ERR 0x08 +#define QTD_STATUS_DO_STOP_SPLIT 0x02 +#define QTD_STATUS_DO_START_SPLIT 0 +#define QTD_STATUS_DO_PING 0x01 +#define QTD_STATUS_DO_OUT 0 + +#define DATA0 0 +#define DATA1 1 + +#define MICRO_FRAME_0_CHANNEL 0x01 +#define MICRO_FRAME_1_CHANNEL 0x02 +#define MICRO_FRAME_2_CHANNEL 0x04 +#define MICRO_FRAME_3_CHANNEL 0x08 +#define MICRO_FRAME_4_CHANNEL 0x10 +#define MICRO_FRAME_5_CHANNEL 0x20 +#define MICRO_FRAME_6_CHANNEL 0x40 +#define MICRO_FRAME_7_CHANNEL 0x80 + +#define CONTROL_TRANSFER 0x01 +#define BULK_TRANSFER 0x02 +#define SYNC_INTERRUPT_TRANSFER 0x04 +#define ASYNC_INTERRUPT_TRANSFER 0x08 +#define SYNC_ISOCHRONOUS_TRANSFER 0x10 +#define ASYNC_ISOCHRONOUS_TRANSFER 0x20 + + +// +// Enhanced Host Controller Registers definitions +// +extern UINT32 mUsbCapabilityLen; +extern EFI_DRIVER_BINDING_PROTOCOL gEhciDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gEhciComponentName; + +#define USBCMD 0x0 /* Command Register Offset 00-03h */ +#define USBCMD_RS 0x01 /* Run / Stop */ +#define USBCMD_HCRESET 0x02 /* Host controller reset */ +#define USBCMD_FLS_512 0x04 /* 512 elements (2048bytes) in Frame List */ +#define USBCMD_FLS_256 0x08 /* 256 elements (1024bytes) in Frame List */ +#define USBCMD_PSE 0x10 /* Periodic schedule enable */ +#define USBCMD_ASE 0x20 /* Asynchronous schedule enable */ +#define USBCMD_IAAD 0x40 /* Interrupt on async advance doorbell */ + +#define USBSTS 0x04 /* Statue Register Offset 04-07h */ +#define USBSTS_HSE 0x10 /* Host system error */ +#define USBSTS_IAA 0x20 /* Interrupt on async advance */ +#define USBSTS_HCH 0x1000 /* Host controller halted */ +#define USBSTS_PSS 0x4000 /* Periodic schedule status */ +#define USBSTS_ASS 0x8000 /* Asynchronous schedule status */ + +#define USBINTR 0x08 /* Command Register Offset 08-0bh */ + +#define FRINDEX 0x0c /* Frame Index Offset 0c-0fh */ + +#define CTRLDSSGMENT 0x10 /* 4G Segment Selector Offset 10-13h */ + +#define PERIODICLISTBASE 0x14 /* Frame List Base Address Offset 14-17h */ + +#define ASYNCLISTADDR 0x18 /* Next Asynchronous List Address Offset 18-1bh */ + +#define CONFIGFLAG 0x40 /* Configured Flag Register Offset 40-43h */ +#define CONFIGFLAG_CF 0x01 /* Configure Flag */ + +#define PORTSC 0x44 /* Port Status/Control Offset 44-47h */ +#define PORTSC_CCS 0x01 /* Current Connect Status*/ +#define PORTSC_CSC 0x02 /* Connect Status Change */ +#define PORTSC_PED 0x04 /* Port Enable / Disable */ +#define PORTSC_PEDC 0x08 /* Port Enable / Disable Change */ +#define PORTSC_OCA 0x10 /* Over current Active */ +#define PORTSC_OCC 0x20 /* Over current Change */ +#define PORTSC_FPR 0x40 /* Force Port Resume */ +#define PORTSC_SUSP 0x80 /* Port Suspend State */ +#define PORTSC_PR 0x100 /* Port Reset */ +#define PORTSC_LS_KSTATE 0x400 /* Line Status K-state */ +#define PORTSC_LS_JSTATE 0x800 /* Line Status J-state */ +#define PORTSC_PP 0x1000 /* Port Power */ +#define PORTSC_PO 0x2000 /* Port Owner */ + +#define CAPLENGTH 0 /* Capability Register Length 00h */ + +#define HCIVERSION 0x02 /* Interface Version Number 02-03h */ + +#define HCSPARAMS 0x04 /* Structural Parameters 04-07h */ +#define HCSP_NPORTS 0x0f /* Number of physical downstream ports on host controller */ + +#define HCCPARAMS 0x08 /* Capability Parameters 08-0bh */ +#define HCCP_64BIT 0x01 /* 64-bit Addressing Capability */ +#define HCCP_PFLF 0x02 /* Programmable Frame List Flag */ +#define HCCP_EECP 0xff00 /* EHCI Extemded Capabilities Pointer */ + +#define HCSPPORTROUTE 0x0c /* Companion Port Route Description 60b */ + +#define CLASSC 0x09 /* Class Code 09-0bh */ + +#define USBBASE 0x10 /* Base Address to Memory-mapped Host Controller Register Space 10-13h */ + +#define SBRN 0x60 /* Serial Bus Release Number 60h */ + +#define FLADJ 0x61 /* Frame Length Adjustment Register 61h */ + +#define PORTWAKECAP 0x62 /* Port wake capablilities register(OPIONAL) 61-62h */ + +// +// PCI Configuration Registers +// +#define EHCI_PCI_CLASSC 0x09 +#define EHCI_PCI_MEMORY_BASE 0x10 + +// +// Memory Offset Registers +// +#define EHCI_MEMORY_CAPLENGTH 0x0 +#define EHCI_MEMORY_CONFIGFLAG 0x40 + +// +// USB Base Class Code,Sub-Class Code and Programming Interface +// +#define PCI_CLASSC_PI_EHCI 0x20 + +#define SETUP_PACKET_ID 0x2D +#define INPUT_PACKET_ID 0x69 +#define OUTPUT_PACKET_ID 0xE1 +#define ERROR_PACKET_ID 0x55 + +#define bit(a) 1 << (a) + +#define GET_0B_TO_31B(Addr) (((UINTN) Addr) & (0xffffffff)) +#define GET_32B_TO_63B(Addr) ((((UINTN) Addr) >> 32) & (0xffffffff)) + + +// +// Ehci Data and Ctrl Structures +// +#pragma pack(1) + +typedef struct { + UINT8 PI; + UINT8 SubClassCode; + UINT8 BaseCode; +} USB_CLASSC; + +typedef struct { + UINT32 NextQtdTerminate : 1; + UINT32 Rsvd1 : 4; + UINT32 NextQtdPointer : 27; + + UINT32 AltNextQtdTerminate : 1; + UINT32 Rsvd2 : 4; + UINT32 AltNextQtdPointer : 27; + + UINT32 Status : 8; + UINT32 PidCode : 2; + UINT32 ErrorCount : 2; + UINT32 CurrentPage : 3; + UINT32 InterruptOnComplete : 1; + UINT32 TotalBytes : 15; + UINT32 DataToggle : 1; + + UINT32 CurrentOffset : 12; + UINT32 BufferPointer0 : 20; + + UINT32 Rsvd3 : 12; + UINT32 BufferPointer1 : 20; + + UINT32 Rsvd4 : 12; + UINT32 BufferPointer2 : 20; + + UINT32 Rsvd5 : 12; + UINT32 BufferPointer3 : 20; + + UINT32 Rsvd6 : 12; + UINT32 BufferPointer4 : 20; + + UINT32 ExtBufferPointer0; + UINT32 ExtBufferPointer1; + UINT32 ExtBufferPointer2; + UINT32 ExtBufferPointer3; + UINT32 ExtBufferPointer4; +} EHCI_QTD_HW; + +typedef struct { + UINT32 QhTerminate : 1; + UINT32 SelectType : 2; + UINT32 Rsvd1 : 2; + UINT32 QhHorizontalPointer : 27; + + UINT32 DeviceAddr : 7; + UINT32 Inactive : 1; + UINT32 EndpointNum : 4; + UINT32 EndpointSpeed : 2; + UINT32 DataToggleControl : 1; + UINT32 HeadReclamationFlag : 1; + UINT32 MaxPacketLen : 11; + UINT32 ControlEndpointFlag : 1; + UINT32 NakCountReload : 4; + + UINT32 InerruptScheduleMask : 8; + UINT32 SplitComletionMask : 8; + UINT32 HubAddr : 7; + UINT32 PortNum : 7; + UINT32 Multiplier : 2; + + UINT32 Rsvd2 : 5; + UINT32 CurrentQtdPointer : 27; + + UINT32 NextQtdTerminate : 1; + UINT32 Rsvd3 : 4; + UINT32 NextQtdPointer : 27; + + UINT32 AltNextQtdTerminate : 1; + UINT32 NakCount : 4; + UINT32 AltNextQtdPointer : 27; + + UINT32 Status : 8; + UINT32 PidCode : 2; + UINT32 ErrorCount : 2; + UINT32 CurrentPage : 3; + UINT32 InterruptOnComplete : 1; + UINT32 TotalBytes : 15; + UINT32 DataToggle : 1; + + UINT32 CurrentOffset : 12; + UINT32 BufferPointer0 : 20; + + UINT32 CompleteSplitMask : 8; + UINT32 Rsvd4 : 4; + UINT32 BufferPointer1 : 20; + + UINT32 FrameTag : 5; + UINT32 SplitBytes : 7; + UINT32 BufferPointer2 : 20; + + UINT32 Rsvd5 : 12; + UINT32 BufferPointer3 : 20; + + UINT32 Rsvd6 : 12; + UINT32 BufferPointer4 : 20; + + UINT32 ExtBufferPointer0; + UINT32 ExtBufferPointer1; + UINT32 ExtBufferPointer2; + UINT32 ExtBufferPointer3; + UINT32 ExtBufferPointer4; +} EHCI_QH_HW; + +typedef struct { + UINT32 LinkTerminate : 1; + UINT32 SelectType : 2; + UINT32 Rsvd : 2; + UINT32 LinkPointer : 27; +} FRAME_LIST_ENTRY; + +#pragma pack() + +typedef struct _EHCI_QTD_ENTITY EHCI_QTD_ENTITY; +typedef struct _EHCI_QH_ENTITY EHCI_QH_ENTITY; +typedef struct _EHCI_ASYNC_REQUEST EHCI_ASYNC_REQUEST; + +typedef struct _EHCI_QTD_ENTITY { + EHCI_QTD_HW Qtd; + UINT32 TotalBytes; + UINT32 StaticTotalBytes; + UINT32 StaticCurrentOffset; + EHCI_QTD_ENTITY *Prev; + EHCI_QTD_ENTITY *Next; + EHCI_QTD_ENTITY *AltNext; + EHCI_QH_ENTITY *SelfQh; +} EHCI_QTD_ENTITY; + +typedef struct _EHCI_QH_ENTITY { + EHCI_QH_HW Qh; + EHCI_QH_ENTITY *Next; + EHCI_QH_ENTITY *Prev; + EHCI_QTD_ENTITY *FirstQtdPtr; + EHCI_QTD_ENTITY *LastQtdPtr; + EHCI_QTD_ENTITY *AltQtdPtr; + UINTN Interval; + UINT8 TransferType; +} EHCI_QH_ENTITY; + +#define GET_QH_ENTITY_ADDR(a) ((EHCI_QH_ENTITY *) a) +#define GET_QTD_ENTITY_ADDR(a) ((EHCI_QTD_ENTITY *) a) + + +// +// Ehci Managment Structures +// +#define USB2_HC_DEV_FROM_THIS(a) CR (a, USB2_HC_DEV, Usb2Hc, USB2_HC_DEV_SIGNATURE) + +#define USB2_HC_DEV_SIGNATURE EFI_SIGNATURE_32 ('e', 'h', 'c', 'i') + +typedef struct _LIST_HEAD { + struct _LIST_HEAD *pre; + struct _LIST_HEAD *next; +} LIST_HEAD; + +typedef struct _EHCI_ASYNC_REQUEST { + UINT8 TransferType; + EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunc; + VOID *Context; + EHCI_ASYNC_REQUEST *Prev; + EHCI_ASYNC_REQUEST *Next; + EHCI_QH_ENTITY *QhPtr; +} EHCI_ASYNC_REQUEST; + +typedef struct _MEMORY_MANAGE_HEADER { + UINT8 *BitArrayPtr; + UINTN BitArraySizeInBytes; + UINT8 *MemoryBlockPtr; + UINTN MemoryBlockSizeInBytes; + VOID *Mapping; + struct _MEMORY_MANAGE_HEADER *Next; +} MEMORY_MANAGE_HEADER; + +typedef struct _USB2_HC_DEV { + UINTN Signature; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_USB2_HC_PROTOCOL Usb2Hc; + UINTN PeriodicFrameListLength; + VOID *PeriodicFrameListBuffer; + VOID *PeriodicFrameListMap; + VOID *AsyncList; + EHCI_ASYNC_REQUEST *AsyncRequestList; + EFI_EVENT AsyncRequestEvent; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + MEMORY_MANAGE_HEADER *MemoryHeader; + UINT8 Is64BitCapable; + UINT32 High32BitAddr; +} USB2_HC_DEV; + + +// +// Internal Functions Declaration +// + +// +// EhciMem Functions +// +EFI_STATUS +CreateMemoryBlock ( + IN USB2_HC_DEV *HcDev, + OUT MEMORY_MANAGE_HEADER **MemoryHeader, + IN UINTN MemoryBlockSizeInPages + ) +/*++ + +Routine Description: + + Use PciIo->AllocateBuffer to allocate common buffer for the memory block, + and use PciIo->Map to map the common buffer for Bus Master Read/Write. + +Arguments: + + HcDev - USB2_HC_DEV + MemoryHeader - MEMORY_MANAGE_HEADER to output + MemoryBlockSizeInPages - MemoryBlockSizeInPages + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Fail for no resources + EFI_UNSUPPORTED Unsupported currently + +--*/ +; + +EFI_STATUS +FreeMemoryHeader ( + IN USB2_HC_DEV *HcDev, + IN MEMORY_MANAGE_HEADER *MemoryHeader + ) +/*++ + +Routine Description: + + Free Memory Header + +Arguments: + + HcDev - USB2_HC_DEV + MemoryHeader - MemoryHeader to be freed + +Returns: + + EFI_SUCCESS Success + EFI_INVALID_PARAMETER Parameter is error + +--*/ +; + +VOID +InsertMemoryHeaderToList ( + IN MEMORY_MANAGE_HEADER *MemoryHeader, + IN MEMORY_MANAGE_HEADER *NewMemoryHeader + ) +/*++ + +Routine Description: + + Insert Memory Header To List + +Arguments: + + MemoryHeader - MEMORY_MANAGE_HEADER + NewMemoryHeader - MEMORY_MANAGE_HEADER + +Returns: + + VOID + +--*/ +; + +EFI_STATUS +AllocMemInMemoryBlock ( + IN MEMORY_MANAGE_HEADER *MemoryHeader, + OUT VOID **Pool, + IN UINTN NumberOfMemoryUnit + ) +/*++ + +Routine Description: + + Alloc Memory In MemoryBlock + +Arguments: + + MemoryHeader - MEMORY_MANAGE_HEADER + Pool - Place to store pointer to memory + NumberOfMemoryUnit - Number Of Memory Unit + +Returns: + + EFI_SUCCESS Success + EFI_NOT_FOUND Can't find the free memory + +--*/ +; + +BOOLEAN +IsMemoryBlockEmptied ( + IN MEMORY_MANAGE_HEADER *MemoryHeaderPtr + ) +/*++ + +Routine Description: + + Is Memory Block Emptied + +Arguments: + + MemoryHeaderPtr - MEMORY_MANAGE_HEADER + +Returns: + + TRUE Empty + FALSE Not Empty + +--*/ +; + +VOID +DelinkMemoryBlock ( + IN MEMORY_MANAGE_HEADER *FirstMemoryHeader, + IN MEMORY_MANAGE_HEADER *NeedFreeMemoryHeader + ) +/*++ + +Routine Description: + + Delink Memory Block + +Arguments: + + FirstMemoryHeader - MEMORY_MANAGE_HEADER + NeedFreeMemoryHeader - MEMORY_MANAGE_HEADER + +Returns: + + VOID + +--*/ +; + +EFI_STATUS +InitialMemoryManagement ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Initialize Memory Management + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +DeinitialMemoryManagement ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Deinitialize Memory Management + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +EhciAllocatePool ( + IN USB2_HC_DEV *HcDev, + OUT UINT8 **Pool, + IN UINTN AllocSize + ) +/*++ + +Routine Description: + + Ehci Allocate Pool + +Arguments: + + HcDev - USB2_HC_DEV + Pool - Place to store pointer to the memory buffer + AllocSize - Alloc Size + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +VOID +EhciFreePool ( + IN USB2_HC_DEV *HcDev, + IN UINT8 *Pool, + IN UINTN AllocSize + ) +/*++ + +Routine Description: + + Uhci Free Pool + +Arguments: + + HcDev - USB_HC_DEV + Pool - Pool to free + AllocSize - Pool size + +Returns: + + VOID + +--*/ +; + +// +// EhciReg Functions +// +EFI_STATUS +ReadEhcCapabiltiyReg ( + IN USB2_HC_DEV *HcDev, + IN UINT32 CapabiltiyRegAddr, + IN OUT UINT32 *Data + ) +/*++ + +Routine Description: + + Read Ehc Capabitlity register + +Arguments: + + HcDev - USB2_HC_DEV + CapabiltiyRegAddr - Ehc Capability register address + Data - A pointer to data read from register + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +ReadEhcOperationalReg ( + IN USB2_HC_DEV *HcDev, + IN UINT32 OperationalRegAddr, + IN OUT UINT32 *Data + ) +/*++ + +Routine Description: + + Read Ehc Operation register + +Arguments: + + HcDev - USB2_HC_DEV + OperationalRegAddr - Ehc Operation register address + Data - A pointer to data read from register + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +WriteEhcOperationalReg ( + IN USB2_HC_DEV *HcDev, + IN UINT32 OperationalRegAddr, + IN UINT32 Data + ) +/*++ + +Routine Description: + + Write Ehc Operation register + +Arguments: + + HcDev - USB2_HC_DEV + OperationalRegAddr - Ehc Operation register address + Data - 32bit write to register + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +SetEhcDoorbell ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Set Ehc door bell bit + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +SetFrameListLen ( + IN USB2_HC_DEV *HcDev, + IN UINTN Length + ) +/*++ + +Routine Description: + + Set the length of Frame List + +Arguments: + + HcDev - USB2_HC_DEV + Length - the required length of frame list + +Returns: + + EFI_SUCCESS Success + EFI_INVALID_PARAMETER Invalid parameter + EFI_DEVICE_ERROR Fail + +--*/ +; + +BOOLEAN +IsFrameListProgrammable ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Whether frame list is programmable + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE Programmable + FALSE Unprogrammable + +--*/ +; + +BOOLEAN +IsPeriodicScheduleEnabled ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Whether periodic schedule is enabled + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE Enabled + FALSE Disabled + +--*/ +; + +BOOLEAN +IsAsyncScheduleEnabled ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Whether asynchronous schedule is enabled + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE Enabled + FALSE Disabled + +--*/ +; + +BOOLEAN +IsEhcPortEnabled ( + IN USB2_HC_DEV *HcDev, + IN UINT8 PortNum + ) +/*++ + +Routine Description: + + Whether port is enabled + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE Enabled + FALSE Disabled + +--*/ +; + +BOOLEAN +IsEhcReseted ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Whether Ehc is halted + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE Reseted + FALSE Unreseted + +--*/ +; + +BOOLEAN +IsEhcHalted ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Whether Ehc is halted + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE Halted + FALSE Not halted + +--*/ +; + +BOOLEAN +IsEhcSysError ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Whether Ehc is system error + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE System error + FALSE No system error + +--*/ +; + +BOOLEAN +IsHighSpeedDevice ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNum + ) +/*++ + +Routine Description: + + Whether high speed device attached + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE High speed + FALSE Full speed + +--*/ +; + +EFI_STATUS +WaitForEhcReset ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + wait for Ehc reset or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +; + +EFI_STATUS +WaitForEhcHalt ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + wait for Ehc halt or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +; + +EFI_STATUS +WaitForEhcNotHalt ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + wait for Ehc not halt or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +; + +EFI_STATUS +WaitForEhcDoorbell ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + Wait for periodic schedule disable or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +; + +EFI_STATUS +WaitForAsyncScheduleEnable ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + Wait for Ehc asynchronous schedule enable or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +; + +EFI_STATUS +WaitForAsyncScheduleDisable ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + Wait for Ehc asynchronous schedule disable or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +; + +EFI_STATUS +WaitForPeriodicScheduleEnable ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + Wait for Ehc periodic schedule enable or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +; + +EFI_STATUS +WaitForPeriodicScheduleDisable ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + Wait for periodic schedule disable or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +; + +EFI_STATUS +GetCapabilityLen ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Get the length of capability register + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +SetFrameListBaseAddr ( + IN USB2_HC_DEV *HcDev, + IN UINT32 FrameBuffer + ) +/*++ + +Routine Description: + + Set base address of frame list first entry + +Arguments: + + HcDev - USB2_HC_DEV + FrameBuffer - base address of first entry of frame list + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +SetAsyncListAddr ( + IN USB2_HC_DEV *HcDev, + IN EHCI_QH_ENTITY *QhPtr + ) +/*++ + +Routine Description: + + Set address of first Async schedule Qh + +Arguments: + + HcDev - USB2_HC_DEV + QhPtr - A pointer to first Qh in the Async schedule + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +SetCtrlDataStructSeg ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Set address of first Async schedule Qh + +Arguments: + + HcDev - USB2_HC_DEV + QhPtr - A pointer to first Qh in the Async schedule + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +SetPortRoutingEhc ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Set Ehc port routing bit + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +EnablePeriodicSchedule ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Enable periodic schedule + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +DisablePeriodicSchedule ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Disable periodic schedule + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +EnableAsynchronousSchedule ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Enable asynchrounous schedule + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +DisableAsynchronousSchedule ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Disable asynchrounous schedule + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +StartScheduleExecution ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Start Ehc schedule execution + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +ResetEhc ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Reset Ehc + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +ClearEhcAllStatus ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Clear Ehc all status bits + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +// +// EhciSched Functions +// +EFI_STATUS +InitialPeriodicFrameList ( + IN USB2_HC_DEV *HcDev, + IN UINTN Length + ) +/*++ + +Routine Description: + + Initialize Periodic Schedule Frame List + +Arguments: + + HcDev - USB2_HC_DEV + Length - Frame List Length + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +VOID +DeinitialPeriodicFrameList ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Deinitialize Periodic Schedule Frame List + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + VOID + +--*/ +; + +EFI_STATUS +CreatePollingTimer ( + IN USB2_HC_DEV *HcDev, + IN EFI_EVENT_NOTIFY NotifyFunction + ) +/*++ + +Routine Description: + + Create Async Request Polling Timer + +Arguments: + + HcDev - USB2_HC_DEV + NotifyFunction - Timer Notify Function + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +DestoryPollingTimer ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Destory Async Request Polling Timer + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +StartPollingTimer ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Start Async Request Polling Timer + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +StopPollingTimer ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Stop Async Request Polling Timer + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +CreateQh ( + IN USB2_HC_DEV *HcDev, + IN UINT8 DeviceAddr, + IN UINT8 Endpoint, + IN UINT8 DeviceSpeed, + IN UINTN MaxPacketLen, + OUT EHCI_QH_ENTITY **QhPtrPtr + ) +/*++ + +Routine Description: + + Create Qh Structure and Pre-Initialize + +Arguments: + + HcDev - USB2_HC_DEV + DeviceAddr - Address of Device + Endpoint - Endpoint Number + DeviceSpeed - Device Speed + MaxPacketLen - Max Length of one Packet + QhPtrPtr - A pointer of pointer to Qh for return + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +CreateControlQh ( + IN USB2_HC_DEV *HcDev, + IN UINT8 DeviceAddr, + IN UINT8 DeviceSpeed, + IN UINTN MaxPacketLen, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT EHCI_QH_ENTITY **QhPtrPtr + ) +/*++ + +Routine Description: + + Create Qh for Control Transfer + +Arguments: + + HcDev - USB2_HC_DEV + DeviceAddr - Address of Device + DeviceSpeed - Device Speed + MaxPacketLen - Max Length of one Packet + Translator - Translator Transaction for SplitX + QhPtrPtr - A pointer of pointer to Qh for return + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +CreateBulkQh ( + IN USB2_HC_DEV *HcDev, + IN UINT8 DeviceAddr, + IN UINT8 EndPointAddr, + IN UINT8 DeviceSpeed, + IN UINT8 DataToggle, + IN UINTN MaxPacketLen, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT EHCI_QH_ENTITY **QhPtrPtr + ) +/*++ + +Routine Description: + + Create Qh for Bulk Transfer + +Arguments: + + HcDev - USB2_HC_DEV + DeviceAddr - Address of Device + EndPointAddr - Address of Endpoint + DeviceSpeed - Device Speed + MaxPacketLen - Max Length of one Packet + Translator - Translator Transaction for SplitX + QhPtrPtr - A pointer of pointer to Qh for return + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +CreateInterruptQh ( + IN USB2_HC_DEV *HcDev, + IN UINT8 DeviceAddr, + IN UINT8 EndPointAddr, + IN UINT8 DeviceSpeed, + IN UINT8 DataToggle, + IN UINTN MaxPacketLen, + IN UINTN Interval, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT EHCI_QH_ENTITY **QhPtrPtr + ) +/*++ + +Routine Description: + + Create Qh for Control Transfer + +Arguments: + + HcDev - USB2_HC_DEV + DeviceAddr - Address of Device + EndPointAddr - Address of Endpoint + DeviceSpeed - Device Speed + MaxPacketLen - Max Length of one Packet + Interval - value of interval + Translator - Translator Transaction for SplitX + QhPtrPtr - A pointer of pointer to Qh for return + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +VOID +DestoryQh ( + IN USB2_HC_DEV *HcDev, + IN EHCI_QH_ENTITY *QhPtr + ) +/*++ + +Routine Description: + + Destory Qh Structure + +Arguments: + + HcDev - USB2_HC_DEV + QhPtr - A pointer to Qh + +Returns: + + VOID + +--*/ +; + +EFI_STATUS +CreateQtd ( + IN USB2_HC_DEV *HcDev, + IN UINT8 *DataPtr, + IN UINTN DataLen, + IN UINT8 PktId, + IN UINT8 Toggle, + IN UINT8 QtdStatus, + OUT EHCI_QTD_ENTITY **QtdPtrPtr + ) +/*++ + +Routine Description: + + Create Qtd Structure and Pre-Initialize it + +Arguments: + + HcDev - USB2_HC_DEV + DataPtr - A pointer to user data buffer to transfer + DataLen - Length of user data to transfer + PktId - Packet Identification of this Qtd + Toggle - Data Toggle of this Qtd + QtdStatus - Default value of status of this Qtd + QtdPtrPtr - A pointer of pointer to Qtd for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +; + +EFI_STATUS +CreateSetupQtd ( + IN USB2_HC_DEV *HcDev, + IN UINT8 *DevReqPtr, + OUT EHCI_QTD_ENTITY **QtdPtrPtr + ) +/*++ + +Routine Description: + + Create Qtd Structure for Setup + +Arguments: + + HcDev - USB2_HC_DEV + DevReqPtr - A pointer to Device Request Data + QtdPtrPtr - A pointer of pointer to Qtd for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +; + +EFI_STATUS +CreateDataQtd ( + IN USB2_HC_DEV *HcDev, + IN UINT8 *DataPtr, + IN UINTN DataLen, + IN UINT8 PktId, + IN UINT8 Toggle, + OUT EHCI_QTD_ENTITY **QtdPtrPtr + ) +/*++ + +Routine Description: + + Create Qtd Structure for data + +Arguments: + + HcDev - USB2_HC_DEV + DataPtr - A pointer to user data buffer to transfer + DataLen - Length of user data to transfer + PktId - Packet Identification of this Qtd + Toggle - Data Toggle of this Qtd + QtdPtrPtr - A pointer of pointer to Qtd for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +; + +EFI_STATUS +CreateStatusQtd ( + IN USB2_HC_DEV *HcDev, + IN UINT8 PktId, + OUT EHCI_QTD_ENTITY **QtdPtrPtr + ) +/*++ + +Routine Description: + + Create Qtd Structure for status + +Arguments: + + HcDev - USB2_HC_DEV + PktId - Packet Identification of this Qtd + QtdPtrPtr - A pointer of pointer to Qtd for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +; + +EFI_STATUS +CreateAltQtd ( + IN USB2_HC_DEV *HcDev, + IN UINT8 PktId, + OUT EHCI_QTD_ENTITY **QtdPtrPtr + ) +/*++ + +Routine Description: + + Create Qtd Structure for Alternative + +Arguments: + + HcDev - USB2_HC_DEV + PktId - Packet Identification of this Qtd + QtdPtrPtr - A pointer of pointer to Qtd for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +; + +EFI_STATUS +CreateControlQtds ( + IN USB2_HC_DEV *HcDev, + IN UINT8 DataPktId, + IN UINT8 *RequestCursor, + IN UINT8 *DataCursor, + IN UINTN DataLen, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT EHCI_QTD_ENTITY **ControlQtdsHead + ) +/*++ + +Routine Description: + + Create Qtds list for Control Transfer + +Arguments: + + HcDev - USB2_HC_DEV + DataPktId - Packet Identification of Data Qtds + RequestCursor - A pointer to request structure buffer to transfer + DataCursor - A pointer to user data buffer to transfer + DataLen - Length of user data to transfer + ControlQtdsHead - A pointer of pointer to first Qtd for control tranfer for return + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +CreateBulkOrInterruptQtds ( + IN USB2_HC_DEV *HcDev, + IN UINT8 PktId, + IN UINT8 *DataCursor, + IN UINTN DataLen, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT EHCI_QTD_ENTITY **QtdsHead + ) +/*++ + +Routine Description: + + Create Qtds list for Bulk or Interrupt Transfer + +Arguments: + + HcDev - USB2_HC_DEV + PktId - Packet Identification of Qtds + DataCursor - A pointer to user data buffer to transfer + DataLen - Length of user data to transfer + DataToggle - Data Toggle to start + Translator - Translator Transaction for SplitX + QtdsHead - A pointer of pointer to first Qtd for control tranfer for return + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +VOID +DestoryQtds ( + IN USB2_HC_DEV *HcDev, + IN EHCI_QTD_ENTITY *FirstQtdPtr + ) +/*++ + +Routine Description: + + Destory all Qtds in the list + +Arguments: + + HcDev - USB2_HC_DEV + FirstQtdPtr - A pointer to first Qtd in the list + +Returns: + + VOID + +--*/ +; + +VOID +LinkQtdToQtd ( + IN EHCI_QTD_ENTITY *PreQtdPtr, + IN EHCI_QTD_ENTITY *QtdPtr + ) +/*++ + +Routine Description: + + Link Qtds together + +Arguments: + + PreQtdPtr - A pointer to pre Qtd + QtdPtr - A pointer to next Qtd + +Returns: + + VOID + +--*/ +; + +VOID +LinkQtdsToAltQtd ( + IN EHCI_QTD_ENTITY *FirstQtdPtr, + IN EHCI_QTD_ENTITY *AltQtdPtr + ) +/*++ + +Routine Description: + + Link AlterQtds together + +Arguments: + + FirstQtdPtr - A pointer to first Qtd in the list + AltQtdPtr - A pointer to alternative Qtd + +Returns: + VOID + +--*/ +; + +VOID +LinkQtdToQh ( + IN EHCI_QH_ENTITY *QhPtr, + IN EHCI_QTD_ENTITY *QtdEntryPtr + ) +/*++ + +Routine Description: + + Link Qtds list to Qh + +Arguments: + + QhPtr - A pointer to Qh + QtdPtr - A pointer to first Qtd in the list + +Returns: + + VOID + +--*/ +; + +EFI_STATUS +LinkQhToAsyncList ( + IN USB2_HC_DEV *HcDev, + IN EHCI_QH_ENTITY *QhPtr + ) +/*++ + +Routine Description: + + Link Qh to Async Schedule List + +Arguments: + + HcDev - USB2_HC_DEV + QhPtr - A pointer to Qh + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +UnlinkQhFromAsyncList ( + IN USB2_HC_DEV *HcDev, + IN EHCI_QH_ENTITY *QhPtr + ) +/*++ + +Routine Description: + + Unlink Qh from Async Schedule List + +Arguments: + + HcDev - USB2_HC_DEV + QhPtr - A pointer to Qh + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +VOID +LinkQhToPeriodicList ( + IN USB2_HC_DEV *HcDev, + IN EHCI_QH_ENTITY *QhPtr + ) +/*++ + +Routine Description: + + Link Qh to Periodic Schedule List + +Arguments: + + HcDev - USB2_HC_DEV + QhPtr - A pointer to Qh + +Returns: + + VOID + +--*/ +; + +VOID +UnlinkQhFromPeriodicList ( + IN USB2_HC_DEV *HcDev, + IN EHCI_QH_ENTITY *QhPtr, + IN UINTN Interval + ) +/*++ + +Routine Description: + + Unlink Qh from Periodic Schedule List + +Arguments: + + HcDev - USB2_HC_DEV + QhPtr - A pointer to Qh + Interval - Interval of this periodic transfer + +Returns: + + VOID + +--*/ +; + +VOID +LinkToAsyncReqeust ( + IN USB2_HC_DEV *HcDev, + IN EHCI_ASYNC_REQUEST *AsyncRequestPtr + ) +/*++ + +Routine Description: + + Llink AsyncRequest Entry to Async Request List + +Arguments: + + HcDev - USB2_HC_DEV + AsyncRequestPtr - A pointer to Async Request Entry + +Returns: + + VOID + +--*/ +; + +VOID +UnlinkFromAsyncReqeust ( + IN USB2_HC_DEV *HcDev, + IN EHCI_ASYNC_REQUEST *AsyncRequestPtr + ) +/*++ + +Routine Description: + + Unlink AsyncRequest Entry from Async Request List + +Arguments: + + HcDev - USB2_HC_DEV + AsyncRequestPtr - A pointer to Async Request Entry + +Returns: + + VOID + +--*/ +; + +UINTN +GetNumberOfQtd ( + IN EHCI_QTD_ENTITY *FirstQtdPtr + ) +/*++ + +Routine Description: + + Number of Qtds in the list + +Arguments: + + FirstQtdPtr - A pointer to first Qtd in the list + +Returns: + + Number of Qtds in the list + +--*/ +; + +UINTN +GetNumberOfTransaction ( + IN UINTN SizeOfData, + IN UINTN SizeOfTransaction + ) +/*++ + +Routine Description: + + Number of Transactions in one Qtd + +Arguments: + + SizeOfData - Size of one Qtd + SizeOfTransaction - Size of one Transaction + +Returns: + + Number of Transactions in this Qtd + +--*/ +; + +UINTN +GetCapacityOfQtd ( + IN UINT8 *BufferCursor + ) +/*++ + +Routine Description: + + Get Capacity of Qtd + +Arguments: + + BufferCursor - BufferCursor of the Qtd + +Returns: + + Capacity of Qtd + +--*/ +; + +UINTN +GetApproxiOfInterval ( + IN UINTN Interval + ) +/*++ + +Routine Description: + + Get the approximate value in the 2 index sequence + +Arguments: + + Interval - the value of interval + +Returns: + + approximate value of interval in the 2 index sequence + +--*/ +; + +EHCI_QTD_HW * +GetQtdNextPointer ( + IN EHCI_QTD_HW *HwQtdPtr + ) +/*++ + +Routine Description: + + Get Qtd next pointer field + +Arguments: + + HwQtdPtr - A pointer to hardware Qtd structure + +Returns: + + A pointer to next hardware Qtd structure + +--*/ +; + +BOOLEAN +IsQtdStatusActive ( + IN EHCI_QTD_HW *HwQtdPtr + ) +/*++ + +Routine Description: + + Whether Qtd status is active or not + +Arguments: + + HwQtdPtr - A pointer to hardware Qtd structure + +Returns: + + TRUE Active + FALSE Inactive + +--*/ +; + +BOOLEAN +IsQtdStatusHalted ( + IN EHCI_QTD_HW *HwQtdPtr + ) +/*++ + +Routine Description: + + Whether Qtd status is halted or not + +Arguments: + + HwQtdPtr - A pointer to hardware Qtd structure + +Returns: + + TRUE Halted + FALSE Not halted + +--*/ +; + +BOOLEAN +IsQtdStatusBufferError ( + IN EHCI_QTD_HW *HwQtdPtr + ) +/*++ + +Routine Description: + + Whether Qtd status is buffer error or not + +Arguments: + + HwQtdPtr - A pointer to hardware Qtd structure + +Returns: + + TRUE Buffer error + FALSE No buffer error + +--*/ +; + +BOOLEAN +IsQtdStatusBabbleError ( + IN EHCI_QTD_HW *HwQtdPtr + ) +/*++ + +Routine Description: + + Whether Qtd status is babble error or not + +Arguments: + + HwQtdPtr - A pointer to hardware Qtd structure + +Returns: + + TRUE Babble error + FALSE No babble error + +--*/ +; + +BOOLEAN +IsQtdStatusTransactionError ( + IN EHCI_QTD_HW *HwQtdPtr + ) +/*++ + +Routine Description: + + Whether Qtd status is transaction error or not + +Arguments: + + HwQtdPtr - A pointer to hardware Qtd structure + +Returns: + + TRUE Transaction error + FALSE No transaction error + +--*/ +; + +BOOLEAN +IsDataInTransfer ( + IN UINT8 EndPointAddress + ) +/*++ + +Routine Description: + + Whether is a DataIn direction transfer + +Arguments: + + EndPointAddress - address of the endpoint + +Returns: + + TRUE DataIn + FALSE DataOut + +--*/ +; + +EFI_STATUS +MapDataBuffer ( + IN USB2_HC_DEV *HcDev, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + OUT UINT8 *PktId, + OUT UINT8 **DataCursor, + OUT VOID **DataMap + ) +/*++ + +Routine Description: + + Map address of user data buffer + +Arguments: + + HcDev - USB2_HC_DEV + TransferDirection - direction of transfer + Data - A pointer to user data buffer + DataLength - length of user data + PktId - Packte Identificaion + DataCursor - mapped address to return + DataMap - identificaion of this mapping to return + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +EFI_STATUS +MapRequestBuffer ( + IN USB2_HC_DEV *HcDev, + IN OUT VOID *Request, + OUT UINT8 **RequestCursor, + OUT VOID **RequestMap + ) +/*++ + +Routine Description: + + Map address of request structure buffer + +Arguments: + + HcDev - USB2_HC_DEV + Request - A pointer to request structure + RequestCursor - Mapped address of request structure to return + RequestMap - Identificaion of this mapping to return + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +VOID +SetQtdBufferPointer ( + IN EHCI_QTD_HW *QtdHwPtr, + IN VOID *DataPtr, + IN UINTN DataLen + ) +/*++ + +Routine Description: + + Set data buffer pointers in Qtd + +Arguments: + + QtdHwPtr - A pointer to Qtd hardware structure + DataPtr - A pointer to user data buffer + DataLen - Length of the user data buffer + +Returns: + + VOID + +--*/ +; + +EHCI_QTD_HW * +GetQtdAlternateNextPointer ( + IN EHCI_QTD_HW *HwQtdPtr + ) +/*++ + +Routine Description: + + Get Qtd alternate next pointer field + +Arguments: + + HwQtdPtr - A pointer to hardware Qtd structure + +Returns: + + A pointer to hardware alternate Qtd + +--*/ +; + +VOID +ZeroOutQhOverlay ( + IN EHCI_QH_ENTITY *QhPtr + ) +/*++ + +Routine Description: + + Zero out the fields in Qh structure + +Arguments: + + QhPtr - A pointer to Qh structure + +Returns: + + VOID + +--*/ +; + +VOID +UpdateAsyncRequestTransfer ( + IN EHCI_ASYNC_REQUEST *AsyncRequestPtr, + IN UINT32 TransferResult, + IN UINTN ErrTDPos + ) +/*++ + +Routine Description: + + Update asynchronous request transfer + +Arguments: + + AsyncRequestPtr - A pointer to async request + TransferResult - transfer result + ErrQtdPos - postion of error Qtd + +Returns: + + VOID + +--*/ +; + + +EFI_STATUS +DeleteAsyncRequestTransfer ( + IN USB2_HC_DEV *HcDev, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + OUT UINT8 *DataToggle + ) +/*++ + +Routine Description: + + Delete all asynchronous request transfer + +Arguments: + + HcDev - USB2_HC_DEV + DeviceAddress - address of usb device + EndPointAddress - address of endpoint + DataToggle - stored data toggle + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +VOID +CleanUpAllAsyncRequestTransfer ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Clean up all asynchronous request transfer + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + VOID + +--*/ +; + +EFI_STATUS +ExecuteTransfer ( + IN USB2_HC_DEV *HcDev, + IN BOOLEAN IsControl, + IN EHCI_QH_ENTITY *QhPtr, + IN OUT UINTN *ActualLen, + OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ) +/*++ + +Routine Description: + + Execute Bulk or SyncInterrupt Transfer + +Arguments: + + HcDev - USB2_HC_DEV + IsControl - Is control transfer or not + QhPtr - A pointer to Qh + ActualLen - Actual transfered Len + DataToggle - Data Toggle + TimeOut - TimeOut threshold + TransferResult - Transfer result + +Returns: + + EFI_SUCCESS Sucess + EFI_DEVICE_ERROR Error + +--*/ +; + +BOOLEAN +CheckQtdsTransferResult ( + IN BOOLEAN IsControl, + IN EHCI_QH_ENTITY *QhPtr, + OUT UINT32 *Result, + OUT UINTN *ErrQtdPos, + OUT UINTN *ActualLen + ) +/*++ + +Routine Description: + + Check transfer result of Qtds + +Arguments: + + IsControl - Is control transfer or not + QhPtr - A pointer to Qh + Result - Transfer result + ErrQtdPos - Error TD Position + ActualLen - Actual Transfer Size + +Returns: + + TRUE Qtds finished + FALSE Not finish + +--*/ +; + +EFI_STATUS +AsyncRequestMoniter ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + Interrupt transfer periodic check handler + +Arguments: + + Event - Interrupt event + Context - Pointer to USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.msa b/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.msa new file mode 100644 index 0000000000..a44b5a4a75 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Ehci/Dxe/Ehci.msa @@ -0,0 +1,87 @@ + + + + + Ehci + UEFI_DRIVER + BDFE430E-8F2A-4db0-9991-6F856594777E + 1.0 + Component description file for Ehci module + This module provides USB2 Host Controller Protocol implementation for Enhanced Host Controller Interface + Copyright (c) 2006, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + Ehci + + + + DebugLib + + + UefiDriverModelLib + + + UefiDriverEntryPoint + + + BaseLib + + + UefiLib + + + BaseMemoryLib + + + MemoryAllocationLib + + + UefiBootServicesTableLib + + + + Ehci.c + EhciMem.c + EhciReg.c + EhciSched.c + ComponentName.c + Ehci.h + + + + + + + gEfiPciIoProtocolGuid + + + gEfiUsb2HcProtocolGuid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00020000 + + gEhciDriverBinding + + + gEhciComponentName + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciMem.c b/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciMem.c new file mode 100644 index 0000000000..2f35f77848 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciMem.c @@ -0,0 +1,761 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + EhciMem.c + +Abstract: + + +Revision History +--*/ + +#include "Ehci.h" + + +EFI_STATUS +CreateMemoryBlock ( + IN USB2_HC_DEV *HcDev, + OUT MEMORY_MANAGE_HEADER **MemoryHeader, + IN UINTN MemoryBlockSizeInPages + ) +/*++ + +Routine Description: + + Use PciIo->AllocateBuffer to allocate common buffer for the memory block, + and use PciIo->Map to map the common buffer for Bus Master Read/Write. + +Arguments: + + HcDev - USB2_HC_DEV + MemoryHeader - MEMORY_MANAGE_HEADER to output + MemoryBlockSizeInPages - MemoryBlockSizeInPages + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Fail for no resources + EFI_UNSUPPORTED Unsupported currently + +--*/ +{ + EFI_STATUS Status; + VOID *CommonBuffer; + EFI_PHYSICAL_ADDRESS MappedAddress; + UINTN MemoryBlockSizeInBytes; + VOID *Mapping; + + // + // Allocate memory for MemoryHeader + // + *MemoryHeader = AllocateZeroPool (sizeof (MEMORY_MANAGE_HEADER)); + if (*MemoryHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + (*MemoryHeader)->Next = NULL; + + // + // set Memory block size + // + (*MemoryHeader)->MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages); + + // + // each bit in Bit Array will manage 32 bytes memory in memory block + // + (*MemoryHeader)->BitArraySizeInBytes = ((*MemoryHeader)->MemoryBlockSizeInBytes / 32) / 8; + + // + // Allocate memory for BitArray + // + (*MemoryHeader)->BitArrayPtr = AllocateZeroPool ((*MemoryHeader)->BitArraySizeInBytes); + if ((*MemoryHeader)->BitArrayPtr == NULL) { + gBS->FreePool (*MemoryHeader); + return EFI_OUT_OF_RESOURCES; + } + + // + // Memory Block uses MemoryBlockSizeInPages pages, + // and it is allocated as common buffer use. + // + Status = HcDev->PciIo->AllocateBuffer ( + HcDev->PciIo, + AllocateAnyPages, + EfiBootServicesData, + MemoryBlockSizeInPages, + &CommonBuffer, + 0 + ); + if (EFI_ERROR (Status)) { + gBS->FreePool ((*MemoryHeader)->BitArrayPtr); + gBS->FreePool (*MemoryHeader); + return EFI_OUT_OF_RESOURCES; + } + + MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages); + Status = HcDev->PciIo->Map ( + HcDev->PciIo, + EfiPciIoOperationBusMasterCommonBuffer, + CommonBuffer, + &MemoryBlockSizeInBytes, + &MappedAddress, + &Mapping + ); + // + // If returned Mapped size is less than the size + // we request,do not support. + // + if (EFI_ERROR (Status) || (MemoryBlockSizeInBytes != EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages))) { + HcDev->PciIo->FreeBuffer (HcDev->PciIo, MemoryBlockSizeInPages, CommonBuffer); + gBS->FreePool ((*MemoryHeader)->BitArrayPtr); + gBS->FreePool (*MemoryHeader); + return EFI_UNSUPPORTED; + } + + // + // Data structure involved by host controller + // should be restricted into the same 4G + // + if (HcDev->Is64BitCapable != 0) { + if (HcDev->High32BitAddr != GET_32B_TO_63B (MappedAddress)) { + HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); + HcDev->PciIo->FreeBuffer (HcDev->PciIo, MemoryBlockSizeInPages, CommonBuffer); + gBS->FreePool ((*MemoryHeader)->BitArrayPtr); + gBS->FreePool (*MemoryHeader); + return EFI_UNSUPPORTED; + } + } + + // + // Set Memory block initial address + // + (*MemoryHeader)->MemoryBlockPtr = (UINT8 *) ((UINTN) MappedAddress); + (*MemoryHeader)->Mapping = Mapping; + + ZeroMem ( + (*MemoryHeader)->MemoryBlockPtr, + EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages) + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +FreeMemoryHeader ( + IN USB2_HC_DEV *HcDev, + IN MEMORY_MANAGE_HEADER *MemoryHeader + ) +/*++ + +Routine Description: + + Free Memory Header + +Arguments: + + HcDev - USB2_HC_DEV + MemoryHeader - MemoryHeader to be freed + +Returns: + + EFI_SUCCESS Success + EFI_INVALID_PARAMETER Parameter is error + +--*/ +{ + if ((MemoryHeader == NULL) || (HcDev == NULL)) { + return EFI_INVALID_PARAMETER; + } + // + // unmap the common buffer used by the memory block + // + HcDev->PciIo->Unmap (HcDev->PciIo, MemoryHeader->Mapping); + + // + // free common buffer + // + HcDev->PciIo->FreeBuffer ( + HcDev->PciIo, + EFI_SIZE_TO_PAGES (MemoryHeader->MemoryBlockSizeInBytes), + MemoryHeader->MemoryBlockPtr + ); + // + // free bit array + // + gBS->FreePool (MemoryHeader->BitArrayPtr); + // + // free memory header + // + gBS->FreePool (MemoryHeader); + + return EFI_SUCCESS; +} + +EFI_STATUS +EhciAllocatePool ( + IN USB2_HC_DEV *HcDev, + OUT UINT8 **Pool, + IN UINTN AllocSize + ) +/*++ + +Routine Description: + + Ehci Allocate Pool + +Arguments: + + HcDev - USB2_HC_DEV + Pool - Place to store pointer to the memory buffer + AllocSize - Alloc Size + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + MEMORY_MANAGE_HEADER *MemoryHeader; + MEMORY_MANAGE_HEADER *TempHeaderPtr; + MEMORY_MANAGE_HEADER *NewMemoryHeader; + UINTN RealAllocSize; + UINTN MemoryBlockSizeInPages; + EFI_STATUS Status; + EFI_TPL OldTpl; + + *Pool = NULL; + + MemoryHeader = HcDev->MemoryHeader; + ASSERT (MemoryHeader != NULL); + + OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1); + + // + // allocate unit is 32 bytes (align on 32 byte) + // + if (AllocSize & 0x1F) { + RealAllocSize = (AllocSize / 32 + 1) * 32; + } else { + RealAllocSize = AllocSize; + } + + // + // There may be linked MemoryHeaders. + // To allocate a free pool in Memory blocks, + // must search in the MemoryHeader link list + // until enough free pool is found. + // + Status = EFI_NOT_FOUND; + for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) { + + Status = AllocMemInMemoryBlock ( + TempHeaderPtr, + Pool, + RealAllocSize / 32 + ); + if (!EFI_ERROR (Status)) { + ZeroMem (*Pool, AllocSize); + gBS->RestoreTPL (OldTpl); + return EFI_SUCCESS; + } + } + + gBS->RestoreTPL (OldTpl); + + // + // There is no enough memory, + // Create a new Memory Block + // + + // + // if pool size is larger than NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES, + // just allocate a large enough memory block. + // + if (RealAllocSize > EFI_PAGES_TO_SIZE (NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES)) { + MemoryBlockSizeInPages = EFI_SIZE_TO_PAGES (RealAllocSize) + 1; + } else { + MemoryBlockSizeInPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES; + } + + Status = CreateMemoryBlock (HcDev, &NewMemoryHeader, MemoryBlockSizeInPages); + if (EFI_ERROR (Status)) { + return Status; + } + + OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1); + + // + // Link the new Memory Block to the Memory Header list + // + InsertMemoryHeaderToList (MemoryHeader, NewMemoryHeader); + + Status = AllocMemInMemoryBlock ( + NewMemoryHeader, + Pool, + RealAllocSize / 32 + ); + if (!EFI_ERROR (Status)) { + ZeroMem (*Pool, AllocSize); + } + + gBS->RestoreTPL (OldTpl); + return Status; +} + +VOID +EhciFreePool ( + IN USB2_HC_DEV *HcDev, + IN UINT8 *Pool, + IN UINTN AllocSize + ) +/*++ + +Routine Description: + + Uhci Free Pool + +Arguments: + + HcDev - USB_HC_DEV + Pool - Pool to free + AllocSize - Pool size + +Returns: + + VOID + +--*/ +{ + MEMORY_MANAGE_HEADER *MemoryHeader; + MEMORY_MANAGE_HEADER *TempHeaderPtr; + UINTN StartBytePos; + UINTN Index; + UINT8 StartBitPos; + UINT8 Index2; + UINTN Count; + UINTN RealAllocSize; + EFI_TPL OldTpl; + + OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1); + + MemoryHeader = HcDev->MemoryHeader; + + // + // allocate unit is 32 byte (align on 32 byte) + // + if (AllocSize & 0x1F) { + RealAllocSize = (AllocSize / 32 + 1) * 32; + } else { + RealAllocSize = AllocSize; + } + + // + // scan the memory header linked list for + // the asigned memory to free. + // + for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) { + + if ((Pool >= TempHeaderPtr->MemoryBlockPtr) && + ((Pool + RealAllocSize) <= (TempHeaderPtr->MemoryBlockPtr + TempHeaderPtr->MemoryBlockSizeInBytes)) + ) { + // + // Pool is in the Memory Block area, + // find the start byte and bit in the bit array + // + StartBytePos = ((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) / 8; + StartBitPos = (UINT8) (((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) & 0x7); + + // + // reset associated bits in bit arry + // + for (Index = StartBytePos, Index2 = StartBitPos, Count = 0; Count < (RealAllocSize / 32); Count++) { + TempHeaderPtr->BitArrayPtr[Index] ^= (UINT8) (bit (Index2)); + Index2++; + if (Index2 == 8) { + Index += 1; + Index2 = 0; + } + } + // + // break the loop + // + break; + } + } + + // + // Release emptied memory blocks (only if the memory block is not + // the first one in the memory header list + // + for (TempHeaderPtr = MemoryHeader->Next; TempHeaderPtr != NULL;) { + + ASSERT (MemoryHeader->Next != NULL); + + if (IsMemoryBlockEmptied (TempHeaderPtr)) { + + DelinkMemoryBlock (MemoryHeader, TempHeaderPtr); + // + // when the TempHeaderPtr is freed in FreeMemoryHeader(), + // the TempHeaderPtr is pointing to nonsense content. + // + gBS->RestoreTPL (OldTpl); + FreeMemoryHeader (HcDev, TempHeaderPtr); + OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1); + // + // reset the TempHeaderPtr, continue search for + // another empty memory block. + // + TempHeaderPtr = MemoryHeader->Next; + continue; + } + + TempHeaderPtr = TempHeaderPtr->Next; + } + + gBS->RestoreTPL (OldTpl); +} + +VOID +InsertMemoryHeaderToList ( + IN MEMORY_MANAGE_HEADER *MemoryHeader, + IN MEMORY_MANAGE_HEADER *NewMemoryHeader + ) +/*++ + +Routine Description: + + Insert Memory Header To List + +Arguments: + + MemoryHeader - MEMORY_MANAGE_HEADER + NewMemoryHeader - MEMORY_MANAGE_HEADER + +Returns: + + VOID + +--*/ +{ + MEMORY_MANAGE_HEADER *TempHeaderPtr; + + for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) { + if (TempHeaderPtr->Next == NULL) { + TempHeaderPtr->Next = NewMemoryHeader; + break; + } + } +} + +EFI_STATUS +AllocMemInMemoryBlock ( + IN MEMORY_MANAGE_HEADER *MemoryHeader, + OUT VOID **Pool, + IN UINTN NumberOfMemoryUnit + ) +/*++ + +Routine Description: + + Alloc Memory In MemoryBlock + +Arguments: + + MemoryHeader - MEMORY_MANAGE_HEADER + Pool - Place to store pointer to memory + NumberOfMemoryUnit - Number Of Memory Unit + +Returns: + + EFI_SUCCESS Success + EFI_NOT_FOUND Can't find the free memory + +--*/ +{ + UINTN TempBytePos; + UINTN FoundBytePos; + UINT8 Index; + UINT8 FoundBitPos; + UINT8 ByteValue; + UINT8 BitValue; + UINTN NumberOfZeros; + UINTN Count; + + FoundBytePos = 0; + FoundBitPos = 0; + ByteValue = MemoryHeader->BitArrayPtr[0]; + NumberOfZeros = 0; + Index = 0; + + for (TempBytePos = 0; TempBytePos < MemoryHeader->BitArraySizeInBytes;) { + + // + // Pop out BitValue from a byte in TempBytePos. + // + BitValue = (UINT8) (ByteValue & 0x1); + + // + // right shift the byte + // + ByteValue /= 2; + + if (BitValue == 0) { + // + // Found a free bit, the NumberOfZeros only record the number + // of those consecutive zeros + // + NumberOfZeros++; + // + // Found enough consecutive free space, break the loop + // + if (NumberOfZeros >= NumberOfMemoryUnit) { + break; + } + } else { + // + // Encountering a '1', meant the bit is ocupied. + // + if (NumberOfZeros >= NumberOfMemoryUnit) { + // + // Found enough consecutive free space,break the loop + // + break; + } else { + // + // the NumberOfZeros only record the number of those consecutive zeros, + // so reset the NumberOfZeros to 0 when encountering '1' before finding + // enough consecutive '0's + // + NumberOfZeros = 0; + // + // reset the (FoundBytePos,FoundBitPos) to the position of '1' + // + FoundBytePos = TempBytePos; + FoundBitPos = Index; + } + } + + // + // step forward a bit + // + Index++; + if (Index == 8) { + // + // step forward a byte, getting the byte value, + // and reset the bit pos. + // + TempBytePos += 1; + ByteValue = MemoryHeader->BitArrayPtr[TempBytePos]; + Index = 0; + } + } + + if (NumberOfZeros < NumberOfMemoryUnit) { + return EFI_NOT_FOUND; + } + + // + // Found enough free space. + // + + // + // The values recorded in (FoundBytePos,FoundBitPos) have two conditions: + // 1)(FoundBytePos,FoundBitPos) record the position + // of the last '1' before the consecutive '0's, it must + // be adjusted to the start position of the consecutive '0's. + // 2)the start address of the consecutive '0's is just the start of + // the bitarray. so no need to adjust the values of + // (FoundBytePos,FoundBitPos). + // + if ((MemoryHeader->BitArrayPtr[FoundBytePos] & bit (FoundBitPos)) != 0) { + FoundBitPos += 1; + } + + // + // Have the (FoundBytePos,FoundBitPos) make sense. + // + if (FoundBitPos > 7) { + FoundBytePos += 1; + FoundBitPos -= 8; + } + + // + // Set the memory as allocated + // + for (TempBytePos = FoundBytePos, Index = FoundBitPos, Count = 0; Count < NumberOfMemoryUnit; Count++) { + + MemoryHeader->BitArrayPtr[TempBytePos] |= bit (Index); + Index++; + if (Index == 8) { + TempBytePos += 1; + Index = 0; + } + } + + *Pool = MemoryHeader->MemoryBlockPtr + (FoundBytePos * 8 + FoundBitPos) * 32; + + return EFI_SUCCESS; +} + +BOOLEAN +IsMemoryBlockEmptied ( + IN MEMORY_MANAGE_HEADER *MemoryHeaderPtr + ) +/*++ + +Routine Description: + + Is Memory Block Emptied + +Arguments: + + MemoryHeaderPtr - MEMORY_MANAGE_HEADER + +Returns: + + TRUE Empty + FALSE Not Empty + +--*/ +{ + UINTN Index; + + for (Index = 0; Index < MemoryHeaderPtr->BitArraySizeInBytes; Index++) { + if (MemoryHeaderPtr->BitArrayPtr[Index] != 0) { + return FALSE; + } + } + + return TRUE; +} + +VOID +DelinkMemoryBlock ( + IN MEMORY_MANAGE_HEADER *FirstMemoryHeader, + IN MEMORY_MANAGE_HEADER *NeedFreeMemoryHeader + ) +/*++ + +Routine Description: + + Delink Memory Block + +Arguments: + + FirstMemoryHeader - MEMORY_MANAGE_HEADER + NeedFreeMemoryHeader - MEMORY_MANAGE_HEADER + +Returns: + + VOID + +--*/ +{ + MEMORY_MANAGE_HEADER *TempHeaderPtr; + + if ((FirstMemoryHeader == NULL) || (NeedFreeMemoryHeader == NULL)) { + return ; + } + + for (TempHeaderPtr = FirstMemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) { + + if (TempHeaderPtr->Next == NeedFreeMemoryHeader) { + // + // Link the before and after + // + TempHeaderPtr->Next = NeedFreeMemoryHeader->Next; + break; + } + } +} + +EFI_STATUS +InitialMemoryManagement ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Initialize Memory Management + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + MEMORY_MANAGE_HEADER *MemoryHeader; + UINTN MemPages; + + MemPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES; + Status = CreateMemoryBlock (HcDev, &MemoryHeader, MemPages); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + HcDev->MemoryHeader = MemoryHeader; + +exit: + return Status; +} + +EFI_STATUS +DeinitialMemoryManagement ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Deinitialize Memory Management + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + MEMORY_MANAGE_HEADER *TempHeaderPtr; + + for (TempHeaderPtr = HcDev->MemoryHeader->Next; TempHeaderPtr != NULL;) { + + DelinkMemoryBlock (HcDev->MemoryHeader, TempHeaderPtr); + // + // when the TempHeaderPtr is freed in FreeMemoryHeader(), + // the TempHeaderPtr is pointing to nonsense content. + // + FreeMemoryHeader (HcDev, TempHeaderPtr); + // + // reset the TempHeaderPtr,continue free another memory block. + // + TempHeaderPtr = HcDev->MemoryHeader->Next; + } + + FreeMemoryHeader (HcDev, HcDev->MemoryHeader); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciReg.c b/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciReg.c new file mode 100644 index 0000000000..9ce816ecc9 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciReg.c @@ -0,0 +1,1539 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Ehchlp.c + +Abstract: + + +Revision History +--*/ + +#include "Ehci.h" + + +EFI_STATUS +ReadEhcCapabiltiyReg ( + IN USB2_HC_DEV *HcDev, + IN UINT32 CapabiltiyRegAddr, + IN OUT UINT32 *Data + ) +/*++ + +Routine Description: + + Read Ehc Capabitlity register + +Arguments: + + HcDev - USB2_HC_DEV + CapabiltiyRegAddr - Ehc Capability register address + Data - A pointer to data read from register + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + return HcDev->PciIo->Mem.Read ( + HcDev->PciIo, + EfiPciIoWidthUint32, + USB_BAR_INDEX, + (UINT64) CapabiltiyRegAddr, + 1, + Data + ); +} + +EFI_STATUS +ReadEhcOperationalReg ( + IN USB2_HC_DEV *HcDev, + IN UINT32 OperationalRegAddr, + IN OUT UINT32 *Data + ) +/*++ + +Routine Description: + + Read Ehc Operation register + +Arguments: + + HcDev - USB2_HC_DEV + OperationalRegAddr - Ehc Operation register address + Data - A pointer to data read from register + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + ASSERT (mUsbCapabilityLen); + return HcDev->PciIo->Mem.Read ( + HcDev->PciIo, + EfiPciIoWidthUint32, + USB_BAR_INDEX, + (UINT64) (OperationalRegAddr + mUsbCapabilityLen), + 1, + Data + ); +} + +EFI_STATUS +WriteEhcOperationalReg ( + IN USB2_HC_DEV *HcDev, + IN UINT32 OperationalRegAddr, + IN UINT32 Data + ) +/*++ + +Routine Description: + + Write Ehc Operation register + +Arguments: + + HcDev - USB2_HC_DEV + OperationalRegAddr - Ehc Operation register address + Data - 32bit write to register + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + ASSERT (mUsbCapabilityLen); + return HcDev->PciIo->Mem.Write ( + HcDev->PciIo, + EfiPciIoWidthUint32, + USB_BAR_INDEX, + (UINT64) (OperationalRegAddr + mUsbCapabilityLen), + 1, + &Data + ); +} + +EFI_STATUS +GetCapabilityLen ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Get the length of capability register + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + UINT32 CapabilityLenAddr; + + CapabilityLenAddr = CAPLENGTH; + + Status = ReadEhcCapabiltiyReg ( + HcDev, + CapabilityLenAddr, + &mUsbCapabilityLen + ); + mUsbCapabilityLen = (UINT8) mUsbCapabilityLen; + + return Status; +} + +EFI_STATUS +SetFrameListLen ( + IN USB2_HC_DEV *HcDev, + IN UINTN Length + ) +/*++ + +Routine Description: + + Set the length of Frame List + +Arguments: + + HcDev - USB2_HC_DEV + Length - the required length of frame list + +Returns: + + EFI_SUCCESS Success + EFI_INVALID_PARAMETER Invalid parameter + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + UINT32 UsbCommandAddr; + UINT32 UsbCommandReg; + + UsbCommandAddr = USBCMD; + + if (256 != Length && 512 != Length) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + Status = ReadEhcOperationalReg ( + HcDev, + UsbCommandAddr, + &UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + if (256 == Length) { + UsbCommandReg |= USBCMD_FLS_256; + } else { + UsbCommandReg |= USBCMD_FLS_512; + } + + Status = WriteEhcOperationalReg ( + HcDev, + UsbCommandAddr, + UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + } + +exit: + return Status; +} + +EFI_STATUS +SetFrameListBaseAddr ( + IN USB2_HC_DEV *HcDev, + IN UINT32 FrameBuffer + ) +/*++ + +Routine Description: + + Set base address of frame list first entry + +Arguments: + + HcDev - USB2_HC_DEV + FrameBuffer - base address of first entry of frame list + +Returns: + +--*/ +{ + EFI_STATUS Status; + UINT32 PeriodicListBaseAddr; + UINT32 PeriodicListBaseReg; + + Status = EFI_SUCCESS; + PeriodicListBaseAddr = PERIODICLISTBASE; + PeriodicListBaseReg = FrameBuffer & 0xfffff000; + + if (IsEhcHalted (HcDev)) { + + Status = WriteEhcOperationalReg ( + HcDev, + PeriodicListBaseAddr, + PeriodicListBaseReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + } + +exit: + return Status; +} + +EFI_STATUS +SetAsyncListAddr ( + IN USB2_HC_DEV *HcDev, + IN EHCI_QH_ENTITY *QhPtr + ) +/*++ + +Routine Description: + + Set address of first Async schedule Qh + +Arguments: + + HcDev - USB2_HC_DEV + QhPtr - A pointer to first Qh in the Async schedule + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + UINT32 AsyncListAddr; + UINT32 AsyncListReg; + + AsyncListAddr = ASYNCLISTADDR; + AsyncListReg = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh)); + + Status = WriteEhcOperationalReg ( + HcDev, + AsyncListAddr, + AsyncListReg + ); + + return Status; +} + +EFI_STATUS +SetCtrlDataStructSeg ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Set register of control and data structure segment + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + + +--*/ +{ + EFI_STATUS Status; + UINT32 CtrlDsSegmentAddr; + UINT32 CtrlDsSegmentReg; + + CtrlDsSegmentAddr = CTRLDSSGMENT; + CtrlDsSegmentReg = HcDev->High32BitAddr; + + Status = WriteEhcOperationalReg ( + HcDev, + CtrlDsSegmentAddr, + CtrlDsSegmentReg + ); + + return Status; +} + +EFI_STATUS +SetPortRoutingEhc ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Set Ehc port routing bit + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + UINT32 ConfigFlagAddr; + UINT32 ConfigFlagReg; + + ConfigFlagAddr = CONFIGFLAG; + + Status = ReadEhcOperationalReg ( + HcDev, + ConfigFlagAddr, + &ConfigFlagReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + ConfigFlagReg |= CONFIGFLAG_CF; + Status = WriteEhcOperationalReg ( + HcDev, + ConfigFlagAddr, + ConfigFlagReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + } + +exit: + return Status; +} + +EFI_STATUS +SetEhcDoorbell ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Set Ehc door bell bit + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + UINT32 UsbCommandAddr; + UINT32 UsbCommandReg; + + UsbCommandAddr = USBCMD; + + Status = ReadEhcOperationalReg ( + HcDev, + UsbCommandAddr, + &UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + UsbCommandReg |= USBCMD_IAAD; + Status = WriteEhcOperationalReg ( + HcDev, + UsbCommandAddr, + UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + } + +exit: + return Status; +} + +EFI_STATUS +ClearEhcAllStatus ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Clear Ehc all status bits + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + UINT32 UsbStatusAddr; + + UsbStatusAddr = USBSTS; + + return WriteEhcOperationalReg ( + HcDev, + UsbStatusAddr, + 0x003F + ); +} + +EFI_STATUS +EnablePeriodicSchedule ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Enable periodic schedule + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + UINT32 UsbCommandAddr; + UINT32 UsbCommandReg; + + UsbCommandAddr = USBCMD; + + Status = ReadEhcOperationalReg ( + HcDev, + UsbCommandAddr, + &UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + UsbCommandReg |= USBCMD_PSE; + Status = WriteEhcOperationalReg ( + HcDev, + UsbCommandAddr, + UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + } + +exit: + return Status; +} + +EFI_STATUS +DisablePeriodicSchedule ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Disable periodic schedule + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + UINT32 UsbCommandAddr; + UINT32 UsbCommandReg; + + UsbCommandAddr = USBCMD; + + Status = ReadEhcOperationalReg ( + HcDev, + UsbCommandAddr, + &UsbCommandReg + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + UsbCommandReg &= ~USBCMD_PSE; + Status = WriteEhcOperationalReg ( + HcDev, + UsbCommandAddr, + UsbCommandReg + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return Status; +} + +EFI_STATUS +EnableAsynchronousSchedule ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Enable asynchrounous schedule + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + UINT32 UsbCommandAddr; + UINT32 UsbCommandReg; + + UsbCommandAddr = USBCMD; + + Status = ReadEhcOperationalReg ( + HcDev, + UsbCommandAddr, + &UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + UsbCommandReg |= USBCMD_ASE; + Status = WriteEhcOperationalReg ( + HcDev, + UsbCommandAddr, + UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + } + +exit: + return Status; +} + +EFI_STATUS +DisableAsynchronousSchedule ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Disable asynchrounous schedule + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + UINT32 UsbCommandAddr; + UINT32 UsbCommandReg; + + UsbCommandAddr = USBCMD; + + Status = ReadEhcOperationalReg ( + HcDev, + UsbCommandAddr, + &UsbCommandReg + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + UsbCommandReg &= ~USBCMD_ASE; + Status = WriteEhcOperationalReg ( + HcDev, + UsbCommandAddr, + UsbCommandReg + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return Status; +} + +EFI_STATUS +ResetEhc ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Reset Ehc + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + UINT32 UsbCommandAddr; + UINT32 UsbCommandReg; + + UsbCommandAddr = USBCMD; + + Status = ReadEhcOperationalReg ( + HcDev, + UsbCommandAddr, + &UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + UsbCommandReg |= USBCMD_HCRESET; + Status = WriteEhcOperationalReg ( + HcDev, + UsbCommandAddr, + UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + } + +exit: + return Status; +} + +EFI_STATUS +StartScheduleExecution ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Start Ehc schedule execution + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + UINT32 UsbCommandAddr; + UINT32 UsbCommandReg; + + UsbCommandAddr = USBCMD; + + Status = ReadEhcOperationalReg ( + HcDev, + UsbCommandAddr, + &UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + UsbCommandReg |= USBCMD_RS; + Status = WriteEhcOperationalReg ( + HcDev, + UsbCommandAddr, + UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + } + +exit: + return Status; +} + +BOOLEAN +IsFrameListProgrammable ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Whether frame list is programmable + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE Programmable + FALSE Unprogrammable + +--*/ +{ + BOOLEAN Value; + UINT32 HcCapParamsAddr; + UINT32 HcCapParamsReg; + + HcCapParamsAddr = HCCPARAMS; + + ReadEhcOperationalReg ( + HcDev, + HcCapParamsAddr, + &HcCapParamsReg + ); + + if (HcCapParamsReg & HCCP_PFLF) { + Value = TRUE; + } else { + Value = FALSE; + } + + return Value; +} + +BOOLEAN +IsPeriodicScheduleEnabled ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Whether periodic schedule is enabled + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE Enabled + FALSE Disabled + +--*/ +{ + BOOLEAN Value; + UINT32 UsbStatusAddr; + UINT32 UsbStatusReg; + + UsbStatusAddr = USBSTS; + + ReadEhcOperationalReg ( + HcDev, + UsbStatusAddr, + &UsbStatusReg + ); + + if (UsbStatusReg & USBSTS_PSS) { + Value = TRUE; + } else { + Value = FALSE; + } + + return Value; +} + +BOOLEAN +IsAsyncScheduleEnabled ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Whether asynchronous schedule is enabled + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE Enabled + FALSE Disabled + +--*/ +{ + BOOLEAN Value; + UINT32 UsbStatusAddr; + UINT32 UsbStatusReg; + + UsbStatusAddr = USBSTS; + + ReadEhcOperationalReg ( + HcDev, + UsbStatusAddr, + &UsbStatusReg + ); + + if (UsbStatusReg & USBSTS_ASS) { + Value = TRUE; + } else { + Value = FALSE; + } + + return Value; +} + +BOOLEAN +IsEhcPortEnabled ( + IN USB2_HC_DEV *HcDev, + IN UINT8 PortNum + ) +/*++ + +Routine Description: + + Whether port is enabled + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE Enabled + FALSE Disabled + +--*/ +{ + UINT32 PortStatusControlAddr; + UINT32 PortStatusControlReg; + + PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNum)); + + ReadEhcOperationalReg ( + HcDev, + PortStatusControlAddr, + &PortStatusControlReg + ); + + return ((PortStatusControlReg & PORTSC_PED) ? TRUE : FALSE); +} + +BOOLEAN +IsEhcReseted ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Whether Ehc is reseted + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE Reseted + FALSE Unreseted + +--*/ +{ + BOOLEAN Value; + UINT32 UsbCommandAddr; + UINT32 UsbCommandReg; + + UsbCommandAddr = USBCMD; + + ReadEhcOperationalReg ( + HcDev, + UsbCommandAddr, + &UsbCommandReg + ); + + if (UsbCommandReg & USBCMD_HCRESET) { + Value = FALSE; + } else { + Value = TRUE; + } + + return Value; +} + +BOOLEAN +IsEhcHalted ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Whether Ehc is halted + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE Halted + FALSE Not halted + +--*/ +{ + BOOLEAN Value; + UINT32 UsbStatusAddr; + UINT32 UsbStatusReg; + + UsbStatusAddr = USBSTS; + + ReadEhcOperationalReg ( + HcDev, + UsbStatusAddr, + &UsbStatusReg + ); + + if (UsbStatusReg & USBSTS_HCH) { + Value = TRUE; + } else { + Value = FALSE; + } + + return Value; +} + +BOOLEAN +IsEhcSysError ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Whether Ehc is system error + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE System error + FALSE No system error + +--*/ +{ + BOOLEAN Value; + UINT32 UsbStatusAddr; + UINT32 UsbStatusReg; + + UsbStatusAddr = USBSTS; + + ReadEhcOperationalReg ( + HcDev, + UsbStatusAddr, + &UsbStatusReg + ); + + if (UsbStatusReg & USBSTS_HSE) { + Value = TRUE; + } else { + Value = FALSE; + } + + return Value; +} + +BOOLEAN +IsHighSpeedDevice ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNum + ) +/*++ + +Routine Description: + + Whether high speed device attached + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + TRUE High speed + FALSE Full speed + +--*/ +{ + USB2_HC_DEV *HcDev; + UINT32 PortStatusControlAddr; + UINT32 PortStatusControlReg; + + HcDev = USB2_HC_DEV_FROM_THIS (This); + PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNum)); + + // + // Set port reset bit + // + ReadEhcOperationalReg ( + HcDev, + PortStatusControlAddr, + &PortStatusControlReg + ); + // + // Make sure Host Controller not halt before reset it + // + if (IsEhcHalted (HcDev)) { + StartScheduleExecution (HcDev); + WaitForEhcNotHalt (HcDev, EHCI_GENERIC_TIMEOUT); + } + PortStatusControlReg &= 0xffffffd5; + PortStatusControlReg |= PORTSC_PR; + // + // Set one to PortReset bit must also set zero to PortEnable bit + // + PortStatusControlReg &= ~PORTSC_PED; + WriteEhcOperationalReg ( + HcDev, + PortStatusControlAddr, + PortStatusControlReg + ); + + // + // Set Port reset recovery time + // + gBS->Stall (EHCI_SET_PORT_RESET_RECOVERY_TIME); + + // + // Clear port reset bit + // + ReadEhcOperationalReg ( + HcDev, + PortStatusControlAddr, + &PortStatusControlReg + ); + PortStatusControlReg &= 0xffffffd5; + PortStatusControlReg &= ~PORTSC_PR; + WriteEhcOperationalReg ( + HcDev, + PortStatusControlAddr, + PortStatusControlReg + ); + + // + // Clear port reset recovery time + // + gBS->Stall (EHCI_CLEAR_PORT_RESET_RECOVERY_TIME); + + return (IsEhcPortEnabled (HcDev, PortNum) ? TRUE : FALSE); +} + +EFI_STATUS +WaitForEhcReset ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + wait for Ehc reset or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +{ + EFI_STATUS Status; + UINTN Delay; + + // + // Timeout is in US unit + // + Delay = (Timeout / 50) + 1; + do { + + if (IsEhcReseted (HcDev)) { + Status = EFI_SUCCESS; + goto exit; + } + gBS->Stall (EHCI_GENERIC_RECOVERY_TIME); + + } while (Delay--); + + Status = EFI_TIMEOUT; + +exit: + return Status; +} + +EFI_STATUS +WaitForEhcHalt ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + wait for Ehc halt or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +{ + EFI_STATUS Status; + UINTN Delay; + + // + // Timeout is in US unit + // + Delay = (Timeout / 50) + 1; + do { + + if (IsEhcHalted (HcDev)) { + Status = EFI_SUCCESS; + goto exit; + } + gBS->Stall (EHCI_GENERIC_RECOVERY_TIME); + + } while (Delay--); + + Status = EFI_TIMEOUT; + +exit: + return Status; +} + +EFI_STATUS +WaitForEhcNotHalt ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + wait for Ehc not halt or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +{ + EFI_STATUS Status; + UINTN Delay; + + // + // Timeout is in US unit + // + Delay = (Timeout / 50) + 1; + do { + + if (!IsEhcHalted (HcDev)) { + Status = EFI_SUCCESS; + goto exit; + } + gBS->Stall (EHCI_GENERIC_RECOVERY_TIME); + + } while (Delay--); + + Status = EFI_TIMEOUT; + +exit: + return Status; +} + +EFI_STATUS +WaitForAsyncScheduleEnable ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + Wait for Ehc asynchronous schedule enable or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +{ + EFI_STATUS Status; + UINTN Delay; + + // + // Timeout is in US unit + // + Delay = (Timeout / 50) + 1; + do { + + if (IsAsyncScheduleEnabled (HcDev)) { + Status = EFI_SUCCESS; + goto exit; + } + gBS->Stall (EHCI_GENERIC_RECOVERY_TIME); + + } while (Delay--); + + Status = EFI_TIMEOUT; + +exit: + return Status; +} + +EFI_STATUS +WaitForAsyncScheduleDisable ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + Wait for Ehc asynchronous schedule disable or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +{ + EFI_STATUS Status; + UINTN Delay; + + // + // Timeout is in US unit + // + Delay = (Timeout / 50) + 1; + do { + + if (!IsAsyncScheduleEnabled (HcDev)) { + Status = EFI_SUCCESS; + goto exit; + } + gBS->Stall (EHCI_GENERIC_RECOVERY_TIME); + + } while (Delay--); + + Status = EFI_TIMEOUT; + +exit: + return Status; +} + +EFI_STATUS +WaitForPeriodicScheduleEnable ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + Wait for Ehc periodic schedule enable or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +{ + EFI_STATUS Status; + UINTN Delay; + + // + // Timeout is in US unit + // + Delay = (Timeout / 50) + 1; + do { + + if (IsPeriodicScheduleEnabled (HcDev)) { + Status = EFI_SUCCESS; + goto exit; + } + gBS->Stall (EHCI_GENERIC_RECOVERY_TIME); + + } while (Delay--); + + Status = EFI_TIMEOUT; + +exit: + return Status; +} + +EFI_STATUS +WaitForPeriodicScheduleDisable ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + Wait for periodic schedule disable or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +{ + EFI_STATUS Status; + UINTN Delay; + + // + // Timeout is in US unit + // + Delay = (Timeout / 50) + 1; + do { + + if (!IsPeriodicScheduleEnabled (HcDev)) { + Status = EFI_SUCCESS; + goto exit; + } + gBS->Stall (EHCI_GENERIC_RECOVERY_TIME); + + } while (Delay--); + + Status = EFI_TIMEOUT; + +exit: + return Status; +} + +EFI_STATUS +WaitForEhcDoorbell ( + IN USB2_HC_DEV *HcDev, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + Wait for periodic schedule disable or timeout + +Arguments: + + HcDev - USB2_HC_DEV + Timeout - timeout threshold + +Returns: + + EFI_SUCCESS Success + EFI_TIMEOUT Timeout + +--*/ +{ + EFI_STATUS Status; + UINT32 UsbCommandAddr; + UINT32 UsbCommandReg; + UINTN Delay; + + UsbCommandAddr = USBCMD; + Delay = (Timeout / 50) + 1; + + do { + Status = ReadEhcOperationalReg ( + HcDev, + UsbCommandAddr, + &UsbCommandReg + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + if (!(UsbCommandReg & USBCMD_IAAD)) { + break; + } + + } while (--Delay); + + if (0 == Delay) { + Status = EFI_TIMEOUT; + } + +exit: + return Status; +} diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciSched.c b/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciSched.c new file mode 100644 index 0000000000..3dc1ff74af --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciSched.c @@ -0,0 +1,3072 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + EhciSched.c + +Abstract: + + +Revision History +--*/ + +#include "Ehci.h" + +EFI_STATUS +InitialPeriodicFrameList ( + IN USB2_HC_DEV *HcDev, + IN UINTN Length + ) +/*++ + +Routine Description: + + Initialize Periodic Schedule Frame List + +Arguments: + + HcDev - USB2_HC_DEV + Length - Frame List Length + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + VOID *CommonBuffer; + EFI_PHYSICAL_ADDRESS FrameBuffer; + VOID *Map; + UINTN BufferSizeInPages; + UINTN BufferSizeInBytes; + UINTN FrameIndex; + FRAME_LIST_ENTRY *FrameEntryPtr; + + // + // The Frame List is a common buffer that will be + // accessed by both the cpu and the usb bus master + // at the same time. + // The Frame List ocupies 4K bytes, + // and must be aligned on 4-Kbyte boundaries. + // + if (EHCI_MAX_FRAME_LIST_LENGTH != Length && IsFrameListProgrammable (HcDev)) { + Status = SetFrameListLen (HcDev, Length); + if (EFI_ERROR (Status)) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + } + + BufferSizeInBytes = EFI_PAGE_SIZE; + BufferSizeInPages = EFI_SIZE_TO_PAGES (BufferSizeInBytes); + Status = HcDev->PciIo->AllocateBuffer ( + HcDev->PciIo, + AllocateAnyPages, + EfiBootServicesData, + BufferSizeInPages, + &CommonBuffer, + 0 + ); + if (EFI_ERROR (Status)) { + DEBUG ((gEHCErrorLevel, "PciIo->AllocateBuffer Failed\n")); + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + Status = HcDev->PciIo->Map ( + HcDev->PciIo, + EfiPciIoOperationBusMasterCommonBuffer, + CommonBuffer, + &BufferSizeInBytes, + &FrameBuffer, + &Map + ); + if (EFI_ERROR (Status) || (BufferSizeInBytes != EFI_PAGE_SIZE)) { + DEBUG ((gEHCErrorLevel, "PciIo->MapBuffer Failed\n")); + Status = EFI_OUT_OF_RESOURCES; + goto free_buffer; + } + + // + // Put high 32bit into CtrlDataStructSeg reg + // when 64bit addressing range capability + // + if (HcDev->Is64BitCapable != 0) { + HcDev->High32BitAddr = (UINT32) GET_32B_TO_63B (FrameBuffer); + + Status = SetCtrlDataStructSeg (HcDev); + if (EFI_ERROR (Status)) { + DEBUG ((gEHCErrorLevel, "SetCtrlDataStructSeg Failed\n")); + Status = EFI_DEVICE_ERROR; + goto unmap_buffer; + } + } + + // + // Tell the Host Controller where the Frame List lies, + // by set the Frame List Base Address Register. + // + Status = SetFrameListBaseAddr (HcDev, (UINT32) FrameBuffer); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto unmap_buffer; + } + + HcDev->PeriodicFrameListLength = Length; + HcDev->PeriodicFrameListBuffer = (VOID *) ((UINTN) FrameBuffer); + HcDev->PeriodicFrameListMap = Map; + + // + // Init Frame List Array fields + // + FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer; + for (FrameIndex = 0; FrameIndex < HcDev->PeriodicFrameListLength; FrameIndex++) { + FrameEntryPtr->LinkPointer = 0; + FrameEntryPtr->Rsvd = 0; + FrameEntryPtr->SelectType = 0; + FrameEntryPtr->LinkTerminate = TRUE; + FrameEntryPtr++; + } + + goto exit; + +unmap_buffer: + HcDev->PciIo->Unmap (HcDev->PciIo, Map); +free_buffer: + HcDev->PciIo->FreeBuffer (HcDev->PciIo, BufferSizeInPages, CommonBuffer); +exit: + return Status; +} + +VOID +DeinitialPeriodicFrameList ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Deinitialize Periodic Schedule Frame List + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + VOID + +--*/ +{ + HcDev->PciIo->Unmap (HcDev->PciIo, HcDev->PeriodicFrameListMap); + HcDev->PciIo->FreeBuffer (HcDev->PciIo, EFI_SIZE_TO_PAGES (EFI_PAGE_SIZE), HcDev->PeriodicFrameListBuffer); + return ; +} + +EFI_STATUS +CreatePollingTimer ( + IN USB2_HC_DEV *HcDev, + IN EFI_EVENT_NOTIFY NotifyFunction + ) +/*++ + +Routine Description: + + Create Async Request Polling Timer + +Arguments: + + HcDev - USB2_HC_DEV + NotifyFunction - Timer Notify Function + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + return gBS->CreateEvent ( + EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_NOTIFY, + NotifyFunction, + HcDev, + &HcDev->AsyncRequestEvent + ); +} + +EFI_STATUS +DestoryPollingTimer ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Destory Async Request Polling Timer + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + return gBS->CloseEvent (HcDev->AsyncRequestEvent); +} + +EFI_STATUS +StartPollingTimer ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Start Async Request Polling Timer + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + return gBS->SetTimer ( + HcDev->AsyncRequestEvent, + TimerPeriodic, + EHCI_ASYNC_REQUEST_POLLING_TIME + ); +} + +EFI_STATUS +StopPollingTimer ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Stop Async Request Polling Timer + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + return gBS->SetTimer ( + HcDev->AsyncRequestEvent, + TimerCancel, + EHCI_ASYNC_REQUEST_POLLING_TIME + ); +} + +EFI_STATUS +CreateQh ( + IN USB2_HC_DEV *HcDev, + IN UINT8 DeviceAddr, + IN UINT8 Endpoint, + IN UINT8 DeviceSpeed, + IN UINTN MaxPacketLen, + OUT EHCI_QH_ENTITY **QhPtrPtr + ) +/*++ + +Routine Description: + + Create Qh Structure and Pre-Initialize + +Arguments: + + HcDev - USB2_HC_DEV + DeviceAddr - Address of Device + Endpoint - Endpoint Number + DeviceSpeed - Device Speed + MaxPacketLen - Max Length of one Packet + QhPtrPtr - A pointer of pointer to Qh for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +{ + EFI_STATUS Status; + EHCI_QH_HW *QhHwPtr; + + ASSERT (HcDev); + ASSERT (QhPtrPtr); + + *QhPtrPtr = NULL; + + // + // Allocate memory for Qh structure + // + Status = EhciAllocatePool ( + HcDev, + (UINT8 **) QhPtrPtr, + sizeof (EHCI_QH_ENTITY) + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + // + // Init fields in Qh + // + gBS->SetMem (*QhPtrPtr, sizeof (EHCI_QH_ENTITY), 0); + + // + // Software field + // + (*QhPtrPtr)->Next = NULL; + (*QhPtrPtr)->Prev = NULL; + (*QhPtrPtr)->FirstQtdPtr = NULL; + (*QhPtrPtr)->AltQtdPtr = NULL; + (*QhPtrPtr)->LastQtdPtr = NULL; + + // + // Hardware field + // + QhHwPtr = &((*QhPtrPtr)->Qh); + QhHwPtr->QhHorizontalPointer = 0; + QhHwPtr->SelectType = 0; + QhHwPtr->MaxPacketLen = (UINT32) MaxPacketLen; + QhHwPtr->EndpointSpeed = (DeviceSpeed & 0x3); + QhHwPtr->EndpointNum = (Endpoint & 0x0f); + QhHwPtr->DeviceAddr = (DeviceAddr & 0x7f); + QhHwPtr->Multiplier = HIGH_BANDWIDTH_PIPE_MULTIPLIER; + QhHwPtr->Rsvd1 = 0; + QhHwPtr->Rsvd2 = 0; + QhHwPtr->Rsvd3 = 0; + QhHwPtr->Rsvd4 = 0; + QhHwPtr->Rsvd5 = 0; + QhHwPtr->Rsvd6 = 0; + +exit: + return Status; +} + +VOID +DestoryQh ( + IN USB2_HC_DEV *HcDev, + IN EHCI_QH_ENTITY *QhPtr + ) +/*++ + +Routine Description: + + Destory Qh Structure + +Arguments: + + HcDev - USB2_HC_DEV + QhPtr - A pointer to Qh + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + ASSERT (HcDev); + ASSERT (QhPtr); + + EhciFreePool (HcDev, (UINT8 *) QhPtr, sizeof (EHCI_QH_ENTITY)); + return ; +} + +EFI_STATUS +CreateControlQh ( + IN USB2_HC_DEV *HcDev, + IN UINT8 DeviceAddr, + IN UINT8 DeviceSpeed, + IN UINTN MaxPacketLen, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT EHCI_QH_ENTITY **QhPtrPtr + ) +/*++ + +Routine Description: + + Create Qh for Control Transfer + +Arguments: + + HcDev - USB2_HC_DEV + DeviceAddr - Address of Device + DeviceSpeed - Device Speed + MaxPacketLen - Max Length of one Packet + Translator - Translator Transaction for SplitX + QhPtrPtr - A pointer of pointer to Qh for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +{ + EFI_STATUS Status; + + // + // Create and init Control Qh + // + Status = CreateQh ( + HcDev, + DeviceAddr, + 0, + DeviceSpeed, + MaxPacketLen, + QhPtrPtr + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + // + // Software field + // + (*QhPtrPtr)->Next = (*QhPtrPtr); + (*QhPtrPtr)->Prev = (*QhPtrPtr); + (*QhPtrPtr)->TransferType = CONTROL_TRANSFER; + + // + // Hardware field + // + // Control Transfer use DataToggleControl + // + (*QhPtrPtr)->Qh.DataToggleControl = TRUE; + (*QhPtrPtr)->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&((*QhPtrPtr)->Qh)) >> 5); + (*QhPtrPtr)->Qh.SelectType = QH_SELECT_TYPE; + (*QhPtrPtr)->Qh.QhTerminate = FALSE; + (*QhPtrPtr)->Qh.ControlEndpointFlag = TRUE; + (*QhPtrPtr)->Qh.NakCountReload = NAK_COUNT_RELOAD; + if (NULL != Translator) { + (*QhPtrPtr)->Qh.PortNum = Translator->TranslatorPortNumber; + (*QhPtrPtr)->Qh.HubAddr = Translator->TranslatorHubAddress; + (*QhPtrPtr)->Qh.Status |= QTD_STATUS_DO_START_SPLIT; + } + +exit: + return Status; +} + +EFI_STATUS +CreateBulkQh ( + IN USB2_HC_DEV *HcDev, + IN UINT8 DeviceAddr, + IN UINT8 EndPointAddr, + IN UINT8 DeviceSpeed, + IN UINT8 DataToggle, + IN UINTN MaxPacketLen, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT EHCI_QH_ENTITY **QhPtrPtr + ) +/*++ + +Routine Description: + + Create Qh for Bulk Transfer + +Arguments: + + HcDev - USB2_HC_DEV + DeviceAddr - Address of Device + EndPointAddr - Address of Endpoint + DeviceSpeed - Device Speed + MaxPacketLen - Max Length of one Packet + Translator - Translator Transaction for SplitX + QhPtrPtr - A pointer of pointer to Qh for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +{ + EFI_STATUS Status; + + // + // Create and init Bulk Qh + // + Status = CreateQh ( + HcDev, + DeviceAddr, + EndPointAddr, + DeviceSpeed, + MaxPacketLen, + QhPtrPtr + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + // + // Software fields + // + (*QhPtrPtr)->Next = (*QhPtrPtr); + (*QhPtrPtr)->Prev = (*QhPtrPtr); + (*QhPtrPtr)->TransferType = BULK_TRANSFER; + + // + // Hardware fields + // + // BulkTransfer don't use DataToggleControl + // + (*QhPtrPtr)->Qh.DataToggleControl = FALSE; + (*QhPtrPtr)->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&((*QhPtrPtr)->Qh)) >> 5); + (*QhPtrPtr)->Qh.SelectType = QH_SELECT_TYPE; + (*QhPtrPtr)->Qh.QhTerminate = FALSE; + (*QhPtrPtr)->Qh.NakCountReload = NAK_COUNT_RELOAD; + (*QhPtrPtr)->Qh.DataToggle = DataToggle; + if (NULL != Translator) { + (*QhPtrPtr)->Qh.PortNum = Translator->TranslatorPortNumber; + (*QhPtrPtr)->Qh.HubAddr = Translator->TranslatorHubAddress; + (*QhPtrPtr)->Qh.Status |= QTD_STATUS_DO_START_SPLIT; + } + +exit: + return Status; +} + +EFI_STATUS +CreateInterruptQh ( + IN USB2_HC_DEV *HcDev, + IN UINT8 DeviceAddr, + IN UINT8 EndPointAddr, + IN UINT8 DeviceSpeed, + IN UINT8 DataToggle, + IN UINTN MaxPacketLen, + IN UINTN Interval, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT EHCI_QH_ENTITY **QhPtrPtr + ) +/*++ + +Routine Description: + + Create Qh for Control Transfer + +Arguments: + + HcDev - USB2_HC_DEV + DeviceAddr - Address of Device + EndPointAddr - Address of Endpoint + DeviceSpeed - Device Speed + MaxPacketLen - Max Length of one Packet + Interval - value of interval + Translator - Translator Transaction for SplitX + QhPtrPtr - A pointer of pointer to Qh for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +{ + EFI_STATUS Status; + + // + // Create and init InterruptQh + // + Status = CreateQh ( + HcDev, + DeviceAddr, + EndPointAddr, + DeviceSpeed, + MaxPacketLen, + QhPtrPtr + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + // + // Software fields + // + if (Interval == 0) { + (*QhPtrPtr)->TransferType = SYNC_INTERRUPT_TRANSFER; + } else { + (*QhPtrPtr)->TransferType = ASYNC_INTERRUPT_TRANSFER; + } + (*QhPtrPtr)->Interval = GetApproxiOfInterval (Interval); + + // + // Hardware fields + // + // InterruptTranfer don't use DataToggleControl + // + (*QhPtrPtr)->Qh.DataToggleControl = FALSE; + (*QhPtrPtr)->Qh.QhHorizontalPointer = 0; + (*QhPtrPtr)->Qh.QhTerminate = TRUE; + (*QhPtrPtr)->Qh.NakCountReload = 0; + (*QhPtrPtr)->Qh.InerruptScheduleMask = MICRO_FRAME_0_CHANNEL; + (*QhPtrPtr)->Qh.SplitComletionMask = (MICRO_FRAME_2_CHANNEL | MICRO_FRAME_3_CHANNEL | MICRO_FRAME_4_CHANNEL); + (*QhPtrPtr)->Qh.DataToggle = DataToggle; + if (NULL != Translator) { + (*QhPtrPtr)->Qh.PortNum = Translator->TranslatorPortNumber; + (*QhPtrPtr)->Qh.HubAddr = Translator->TranslatorHubAddress; + (*QhPtrPtr)->Qh.Status |= QTD_STATUS_DO_START_SPLIT; + } + +exit: + return Status; +} + +EFI_STATUS +CreateQtd ( + IN USB2_HC_DEV *HcDev, + IN UINT8 *DataPtr, + IN UINTN DataLen, + IN UINT8 PktId, + IN UINT8 Toggle, + IN UINT8 QtdStatus, + OUT EHCI_QTD_ENTITY **QtdPtrPtr + ) +/*++ + +Routine Description: + + Create Qtd Structure and Pre-Initialize it + +Arguments: + + HcDev - USB2_HC_DEV + DataPtr - A pointer to user data buffer to transfer + DataLen - Length of user data to transfer + PktId - Packet Identification of this Qtd + Toggle - Data Toggle of this Qtd + QtdStatus - Default value of status of this Qtd + QtdPtrPtr - A pointer of pointer to Qtd for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +{ + EFI_STATUS Status; + EHCI_QTD_HW *QtdHwPtr; + + ASSERT (HcDev); + ASSERT (QtdPtrPtr); + + // + // Create memory for Qtd structure + // + Status = EhciAllocatePool ( + HcDev, + (UINT8 **) QtdPtrPtr, + sizeof (EHCI_QTD_ENTITY) + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + // + // Init fields in Qtd + // + gBS->SetMem (*QtdPtrPtr, sizeof (EHCI_QTD_ENTITY), 0); + + // + // Software field + // + (*QtdPtrPtr)->TotalBytes = (UINT32) DataLen; + (*QtdPtrPtr)->StaticTotalBytes = (UINT32) DataLen; + (*QtdPtrPtr)->Prev = NULL; + (*QtdPtrPtr)->Next = NULL; + + // + // Hardware field + // + QtdHwPtr = &((*QtdPtrPtr)->Qtd); + QtdHwPtr->NextQtdPointer = 0; + QtdHwPtr->NextQtdTerminate = TRUE; + QtdHwPtr->AltNextQtdPointer = 0; + QtdHwPtr->AltNextQtdTerminate = TRUE; + QtdHwPtr->DataToggle = Toggle; + QtdHwPtr->TotalBytes = (UINT32) DataLen; + QtdHwPtr->CurrentPage = 0; + QtdHwPtr->ErrorCount = QTD_ERROR_COUNTER; + QtdHwPtr->Status = QtdStatus; + QtdHwPtr->Rsvd1 = 0; + QtdHwPtr->Rsvd2 = 0; + QtdHwPtr->Rsvd3 = 0; + QtdHwPtr->Rsvd4 = 0; + QtdHwPtr->Rsvd5 = 0; + QtdHwPtr->Rsvd6 = 0; + + // + // Set PacketID [Setup/Data/Status] + // + switch (PktId) { + case SETUP_PACKET_ID: + QtdHwPtr->PidCode = SETUP_PACKET_PID_CODE; + break; + + case INPUT_PACKET_ID: + QtdHwPtr->PidCode = INPUT_PACKET_PID_CODE; + break; + + case OUTPUT_PACKET_ID: + QtdHwPtr->PidCode = OUTPUT_PACKET_PID_CODE; + break; + + default: + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + // + // Set Data Buffer Pointers + // + if (NULL != DataPtr) { + SetQtdBufferPointer ( + QtdHwPtr, + DataPtr, + DataLen + ); + (*QtdPtrPtr)->StaticCurrentOffset = QtdHwPtr->CurrentOffset; + } + +exit: + return Status; +} + +EFI_STATUS +CreateSetupQtd ( + IN USB2_HC_DEV *HcDev, + IN UINT8 *DevReqPtr, + OUT EHCI_QTD_ENTITY **QtdPtrPtr + ) +/*++ + +Routine Description: + + Create Qtd Structure for Setup + +Arguments: + + HcDev - USB2_HC_DEV + DevReqPtr - A pointer to Device Request Data + QtdPtrPtr - A pointer of pointer to Qtd for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +{ + return CreateQtd ( + HcDev, + DevReqPtr, + sizeof (EFI_USB_DEVICE_REQUEST), + SETUP_PACKET_ID, + DATA0, + QTD_STATUS_ACTIVE, + QtdPtrPtr + ); +} + +EFI_STATUS +CreateDataQtd ( + IN USB2_HC_DEV *HcDev, + IN UINT8 *DataPtr, + IN UINTN DataLen, + IN UINT8 PktId, + IN UINT8 Toggle, + OUT EHCI_QTD_ENTITY **QtdPtrPtr + ) +/*++ + +Routine Description: + + Create Qtd Structure for data + +Arguments: + + HcDev - USB2_HC_DEV + DataPtr - A pointer to user data buffer to transfer + DataLen - Length of user data to transfer + PktId - Packet Identification of this Qtd + Toggle - Data Toggle of this Qtd + QtdPtrPtr - A pointer of pointer to Qtd for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +{ + return CreateQtd ( + HcDev, + DataPtr, + DataLen, + PktId, + Toggle, + QTD_STATUS_ACTIVE, + QtdPtrPtr + ); +} + +EFI_STATUS +CreateAltQtd ( + IN USB2_HC_DEV *HcDev, + IN UINT8 PktId, + OUT EHCI_QTD_ENTITY **QtdPtrPtr + ) +/*++ + +Routine Description: + + Create Qtd Structure for Alternative + +Arguments: + + HcDev - USB2_HC_DEV + PktId - Packet Identification of this Qtd + QtdPtrPtr - A pointer of pointer to Qtd for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +{ + return CreateQtd ( + HcDev, + NULL, + 0, + PktId, + 0, + QTD_STATUS_ACTIVE, + QtdPtrPtr + ); +} + +EFI_STATUS +CreateStatusQtd ( + IN USB2_HC_DEV *HcDev, + IN UINT8 PktId, + OUT EHCI_QTD_ENTITY **QtdPtrPtr + ) +/*++ + +Routine Description: + + Create Qtd Structure for status + +Arguments: + + HcDev - USB2_HC_DEV + PktId - Packet Identification of this Qtd + QtdPtrPtr - A pointer of pointer to Qtd for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +{ + return CreateQtd ( + HcDev, + NULL, + 0, + PktId, + DATA1, + QTD_STATUS_ACTIVE, + QtdPtrPtr + ); +} + +EFI_STATUS +CreateControlQtds ( + IN USB2_HC_DEV *HcDev, + IN UINT8 DataPktId, + IN UINT8 *RequestCursor, + IN UINT8 *DataCursor, + IN UINTN DataLen, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT EHCI_QTD_ENTITY **ControlQtdsHead + ) +/*++ + +Routine Description: + + Create Qtds list for Control Transfer + +Arguments: + + HcDev - USB2_HC_DEV + DataPktId - Packet Identification of Data Qtds + RequestCursor - A pointer to request structure buffer to transfer + DataCursor - A pointer to user data buffer to transfer + DataLen - Length of user data to transfer + ControlQtdsHead - A pointer of pointer to first Qtd for control tranfer for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +{ + EFI_STATUS Status; + EHCI_QTD_ENTITY *QtdPtr; + EHCI_QTD_ENTITY *PreQtdPtr; + EHCI_QTD_ENTITY *SetupQtdPtr; + EHCI_QTD_ENTITY *FirstDataQtdPtr; + EHCI_QTD_ENTITY *LastDataQtdPtr; + EHCI_QTD_ENTITY *StatusQtdPtr; + UINT8 DataToggle; + UINT8 StatusPktId; + UINTN CapacityOfQtd; + UINTN SizePerQtd; + UINTN DataCount; + UINTN Xnum; + + QtdPtr = NULL; + PreQtdPtr = NULL; + SetupQtdPtr = NULL; + FirstDataQtdPtr = NULL; + LastDataQtdPtr = NULL; + StatusQtdPtr = NULL; + CapacityOfQtd = 0; + + // + // Setup Stage of Control Transfer + // + Status = CreateSetupQtd ( + HcDev, + RequestCursor, + &SetupQtdPtr + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + // + // Data Stage of Control Transfer + // + DataToggle = 1; + DataCount = DataLen; + + // + // Create Qtd structure and link together + // + while (DataCount > 0) { + // + // PktSize is the data load size that each Qtd. + // + CapacityOfQtd = GetCapacityOfQtd (DataCursor); + SizePerQtd = DataCount; + if (DataCount > CapacityOfQtd) { + SizePerQtd = CapacityOfQtd; + } + + Status = CreateDataQtd ( + HcDev, + DataCursor, + SizePerQtd, + DataPktId, + DataToggle, + &QtdPtr + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + if (NULL == FirstDataQtdPtr) { + goto destory_setup_qtd; + } else { + goto destory_qtds; + } + } + + if (NULL == FirstDataQtdPtr) { + FirstDataQtdPtr = QtdPtr; + } else { + LinkQtdToQtd (PreQtdPtr, QtdPtr); + } + + // + // Reverse Data Toggle or not determined by parity of transactions of one qtd + // + Xnum = Translator ? GetNumberOfTransaction (SizePerQtd, EHCI_BLOCK_SIZE_WITH_TT) : GetNumberOfTransaction (SizePerQtd, EHCI_BLOCK_SIZE); + if (Xnum % 2 != 0) { + DataToggle ^= 1; + } + + PreQtdPtr = QtdPtr; + DataCursor += SizePerQtd; + DataCount -= SizePerQtd; + } + + LastDataQtdPtr = QtdPtr; + + // + // Status Stage of Control Transfer + // + if (OUTPUT_PACKET_ID == DataPktId) { + StatusPktId = INPUT_PACKET_ID; + } else { + StatusPktId = OUTPUT_PACKET_ID; + } + + Status = CreateStatusQtd ( + HcDev, + StatusPktId, + &StatusQtdPtr + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto destory_qtds; + } + + // + // Link setup Qtd -> data Qtds -> status Qtd + // + if (FirstDataQtdPtr != NULL) { + LinkQtdToQtd (SetupQtdPtr, FirstDataQtdPtr); + LinkQtdToQtd (LastDataQtdPtr, StatusQtdPtr); + } else { + LinkQtdToQtd (SetupQtdPtr, StatusQtdPtr); + } + + *ControlQtdsHead = SetupQtdPtr; + + goto exit; + +destory_qtds: + DestoryQtds (HcDev, FirstDataQtdPtr); +destory_setup_qtd: + DestoryQtds (HcDev, SetupQtdPtr); +exit: + return Status; +} + +EFI_STATUS +CreateBulkOrInterruptQtds ( + IN USB2_HC_DEV *HcDev, + IN UINT8 PktId, + IN UINT8 *DataCursor, + IN UINTN DataLen, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT EHCI_QTD_ENTITY **QtdsHead + ) +/*++ + +Routine Description: + + Create Qtds list for Bulk or Interrupt Transfer + +Arguments: + + HcDev - USB2_HC_DEV + PktId - Packet Identification of Qtds + DataCursor - A pointer to user data buffer to transfer + DataLen - Length of user data to transfer + DataToggle - Data Toggle to start + Translator - Translator Transaction for SplitX + QtdsHead - A pointer of pointer to first Qtd for control tranfer for return + +Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +{ + EFI_STATUS Status; + EHCI_QTD_ENTITY *QtdPtr; + EHCI_QTD_ENTITY *PreQtdPtr; + EHCI_QTD_ENTITY *FirstQtdPtr; + EHCI_QTD_ENTITY *AltQtdPtr; + UINTN DataCount; + UINTN CapacityOfQtd; + UINTN SizePerQtd; + + Status = EFI_SUCCESS; + QtdPtr = NULL; + PreQtdPtr = NULL; + FirstQtdPtr = NULL; + AltQtdPtr = NULL; + CapacityOfQtd = 0; + + DataCount = DataLen; + while (DataCount > 0) { + + CapacityOfQtd = GetCapacityOfQtd (DataCursor); + SizePerQtd = DataCount; + if (DataCount > CapacityOfQtd) { + SizePerQtd = CapacityOfQtd; + } + + Status = CreateDataQtd ( + HcDev, + DataCursor, + SizePerQtd, + PktId, + 0, + &QtdPtr + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + if (NULL == FirstQtdPtr) { + goto exit; + } else { + goto destory_qtds; + } + } + + if (NULL == FirstQtdPtr) { + FirstQtdPtr = QtdPtr; + } else { + LinkQtdToQtd (PreQtdPtr, QtdPtr); + } + + PreQtdPtr = QtdPtr; + DataCursor += SizePerQtd; + DataCount -= SizePerQtd; + } + + // + // Set Alternate Qtd + // + if (INPUT_PACKET_ID == PktId && 1 < GetNumberOfQtd (FirstQtdPtr)) { + Status = CreateAltQtd ( + HcDev, + PktId, + &AltQtdPtr + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto destory_qtds; + } + + LinkQtdsToAltQtd (FirstQtdPtr, AltQtdPtr); + } + + *QtdsHead = FirstQtdPtr; + goto exit; + +destory_qtds: + DestoryQtds (HcDev, FirstQtdPtr); +exit: + return Status; +} + +VOID +DestoryQtds ( + IN USB2_HC_DEV *HcDev, + IN EHCI_QTD_ENTITY *FirstQtdPtr + ) +/*++ + +Routine Description: + + Destory all Qtds in the list + +Arguments: + + HcDev - USB2_HC_DEV + FirstQtdPtr - A pointer to first Qtd in the list + +Returns: + + VOID + +--*/ +{ + EHCI_QTD_ENTITY *PrevQtd; + EHCI_QTD_ENTITY *NextQtd; + + if (!FirstQtdPtr) { + goto exit; + } + + PrevQtd = FirstQtdPtr; + + // + // Delete all the Qtds. + // + do { + NextQtd = PrevQtd->Next; + EhciFreePool (HcDev, (UINT8 *) PrevQtd, sizeof (EHCI_QTD_ENTITY)); + PrevQtd = NextQtd; + } while (NULL != PrevQtd); + +exit: + return ; +} + +UINTN +GetNumberOfQtd ( + IN EHCI_QTD_ENTITY *FirstQtdPtr + ) +/*++ + +Routine Description: + + Number of Qtds in the list + +Arguments: + + FirstQtdPtr - A pointer to first Qtd in the list + +Returns: + + Number of Qtds in the list + +--*/ +{ + UINTN Count; + EHCI_QTD_ENTITY *QtdPtr; + Count = 0; + QtdPtr = FirstQtdPtr; + + ; + + while (NULL != QtdPtr) { + Count++; + QtdPtr = QtdPtr->Next; + } + + return Count; +} + +UINTN +GetNumberOfTransaction ( + IN UINTN SizeOfData, + IN UINTN SizeOfTransaction + ) +/*++ + +Routine Description: + + Number of Transactions in one Qtd + +Arguments: + + SizeOfData - Size of one Qtd + SizeOfTransaction - Size of one Transaction + +Returns: + + Number of Transactions in this Qtd + +--*/ +{ + + return ((SizeOfData & (SizeOfTransaction - 1)) ? SizeOfData / SizeOfTransaction + 1 : SizeOfData / SizeOfTransaction); + +} + +UINTN +GetCapacityOfQtd ( + IN UINT8 *BufferCursor + ) +/*++ + +Routine Description: + + Get Size of First Qtd + +Arguments: + + BufferCursor - BufferCursor of the Qtd + +Returns: + + Size of First Qtd + +--*/ +{ + + return (EHCI_MAX_QTD_CAPACITY - (EHCI_BLOCK_SIZE * GetNumberOfTransaction (EFI_PAGE_MASK & GET_0B_TO_31B (BufferCursor), EHCI_BLOCK_SIZE))); + +} + +UINTN +GetApproxiOfInterval ( + IN UINTN Interval + ) +/*++ + +Routine Description: + + Get the approximate value in the 2 index sequence + +Arguments: + + Interval - the value of interval + +Returns: + + approximate value of interval in the 2 index sequence + +--*/ +{ + UINTN Orignate; + UINTN Approxi; + + Orignate = Interval; + Approxi = 1; + + while (Orignate != 1 && Orignate != 0) { + Orignate = Orignate >> 1; + Approxi = Approxi << 1; + } + + if (Interval & (Approxi >> 1)) { + Approxi = Approxi << 1; + } + + return Approxi; +} + +EHCI_QTD_HW * +GetQtdAlternateNextPointer ( + IN EHCI_QTD_HW *HwQtdPtr + ) +/*++ + +Routine Description: + + Get Qtd alternate next pointer field + +Arguments: + + HwQtdPtr - A pointer to hardware Qtd structure + +Returns: + + A pointer to hardware alternate Qtd + +--*/ +{ + EHCI_QTD_HW *Value; + + Value = NULL; + + if (!HwQtdPtr->AltNextQtdTerminate) { + Value = (EHCI_QTD_HW *) GET_0B_TO_31B (HwQtdPtr->AltNextQtdPointer << 5); + } + + return Value; +} + +EHCI_QTD_HW * +GetQtdNextPointer ( + IN EHCI_QTD_HW *HwQtdPtr + ) +/*++ + +Routine Description: + + Get Qtd next pointer field + +Arguments: + + HwQtdPtr - A pointer to hardware Qtd structure + +Returns: + + A pointer to next hardware Qtd structure + +--*/ +{ + EHCI_QTD_HW *Value; + + Value = NULL; + + if (!HwQtdPtr->NextQtdTerminate) { + Value = (EHCI_QTD_HW *) GET_0B_TO_31B (HwQtdPtr->NextQtdPointer << 5); + } + + return Value; +} + +VOID LinkQtdToQtd ( + IN EHCI_QTD_ENTITY * PreQtdPtr, + IN EHCI_QTD_ENTITY * QtdPtr + ) +/*++ + +Routine Description: + + Link Qtds together + +Arguments: + + PreQtdPtr - A pointer to pre Qtd + QtdPtr - A pointer to next Qtd + +Returns: + + VOID + +--*/ +{ + EHCI_QTD_HW *QtdHwPtr; + + ASSERT(PreQtdPtr); + ASSERT(QtdPtr); + + // + // Software link + // + PreQtdPtr->Next = QtdPtr; + QtdPtr->Prev = PreQtdPtr; + + // + // Hardware link + // + QtdHwPtr = &(QtdPtr->Qtd); + PreQtdPtr->Qtd.NextQtdPointer = (UINT32) (GET_0B_TO_31B(QtdHwPtr) >> 5); + PreQtdPtr->Qtd.NextQtdTerminate = FALSE; + + return ; +} + + +VOID LinkQtdsToAltQtd ( + IN EHCI_QTD_ENTITY * FirstQtdPtr, + IN EHCI_QTD_ENTITY * AltQtdPtr + ) +/*++ + +Routine Description: + + Link AlterQtds together + +Arguments: + + FirstQtdPtr - A pointer to first Qtd in the list + AltQtdPtr - A pointer to alternative Qtd + +Returns: + + VOID + +--*/ +{ + EHCI_QTD_ENTITY *QtdPtr; + EHCI_QTD_HW *AltQtdHwPtr; + + ASSERT(FirstQtdPtr); + ASSERT(AltQtdPtr); + + AltQtdHwPtr = &(AltQtdPtr->Qtd); + QtdPtr = FirstQtdPtr; + + while (NULL != QtdPtr) { + // + // Software link + // + QtdPtr->AltNext = AltQtdPtr; + // + // Hardware link + // + QtdPtr->Qtd.AltNextQtdPointer = (UINT32) (GET_0B_TO_31B(AltQtdHwPtr) >> 5); + QtdPtr->Qtd.AltNextQtdTerminate = FALSE; + QtdPtr = QtdPtr->Next; + } + + return ; +} + +VOID +LinkQtdToQh ( + IN EHCI_QH_ENTITY *QhPtr, + IN EHCI_QTD_ENTITY *QtdPtr + ) +/*++ + +Routine Description: + + Link Qtds list to Qh + +Arguments: + + QhPtr - A pointer to Qh + QtdPtr - A pointer to first Qtd in the list + +Returns: + + VOID + +--*/ +{ + EHCI_QTD_ENTITY *Cursor; + EHCI_QTD_HW *QtdHwPtr; + + ASSERT (QhPtr); + ASSERT (QtdPtr); + + QhPtr->FirstQtdPtr = QtdPtr; + if (NULL != QtdPtr->AltNext) { + QhPtr->AltQtdPtr = QtdPtr->AltNext; + } + + Cursor = QtdPtr; + while (NULL != Cursor) { + Cursor->SelfQh = QhPtr; + if (NULL == Cursor->Next) { + QhPtr->LastQtdPtr = Cursor; + } + + Cursor = Cursor->Next; + } + + QtdHwPtr = &(QtdPtr->Qtd); + QhPtr->Qh.NextQtdPointer = (UINT32) (GET_0B_TO_31B (QtdHwPtr) >> 5); + QhPtr->Qh.NextQtdTerminate = FALSE; + + return ; +} + +EFI_STATUS +LinkQhToAsyncList ( + IN USB2_HC_DEV *HcDev, + IN EHCI_QH_ENTITY *QhPtr + ) +/*++ + +Routine Description: + + Link Qh to Async Schedule List + +Arguments: + + HcDev - USB2_HC_DEV + QhPtr - A pointer to Qh + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + + ASSERT (HcDev); + ASSERT (QhPtr); + + QhPtr->Qh.HeadReclamationFlag = TRUE; + + Status = SetAsyncListAddr (HcDev, QhPtr); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + if (!IsAsyncScheduleEnabled (HcDev)) { + + Status = EnableAsynchronousSchedule (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + Status = WaitForAsyncScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT); + if (EFI_ERROR (Status)) { + DEBUG ((gEHCDebugLevel, "WaitForAsyncScheduleEnable TimeOut")); + Status = EFI_TIMEOUT; + goto exit; + } + + if (IsEhcHalted (HcDev)) { + Status = StartScheduleExecution (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + } + } + + } + +exit: + return Status; +} + +EFI_STATUS +UnlinkQhFromAsyncList ( + IN USB2_HC_DEV *HcDev, + IN EHCI_QH_ENTITY *QhPtr + ) +/*++ + +Routine Description: + + Unlink Qh from Async Schedule List + +Arguments: + + HcDev - USB2_HC_DEV + QhPtr - A pointer to Qh + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + ASSERT (HcDev); + ASSERT (QhPtr); + + if (QhPtr == QhPtr->Next) { + + Status = DisableAsynchronousSchedule (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + Status = WaitForAsyncScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT); + if (EFI_ERROR (Status)) { + DEBUG ((gEHCErrorLevel, "WaitForAsyncScheduleDisable TimeOut\n")); + Status = EFI_TIMEOUT; + goto exit; + } + + } + +exit: + return Status; +} + +VOID +LinkQhToPeriodicList ( + IN USB2_HC_DEV *HcDev, + IN EHCI_QH_ENTITY *QhPtr + ) +/*++ + +Routine Description: + + Link Qh to Periodic Schedule List + +Arguments: + + HcDev - USB2_HC_DEV + QhPtr - A pointer to Qh + +Returns: + + VOID + +--*/ +{ + FRAME_LIST_ENTRY *FrameEntryPtr; + EHCI_QH_ENTITY *FindQhPtr; + EHCI_QH_HW *FindQhHwPtr; + UINTN FrameIndex; + + ASSERT (HcDev); + ASSERT (QhPtr); + + FindQhPtr = NULL; + FindQhHwPtr = NULL; + FrameIndex = 0; + FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer; + + QhPtr->Qh.HeadReclamationFlag = FALSE; + + if (QhPtr->TransferType == ASYNC_INTERRUPT_TRANSFER) { + + // + // AsyncInterruptTransfer Qh + // + + // + // Link to Frame[0] List + // + if (!FrameEntryPtr->LinkTerminate) { + // + // Not Null FrameList + // + FindQhHwPtr = (EHCI_QH_HW *) GET_0B_TO_31B (FrameEntryPtr->LinkPointer << 5); + FindQhPtr = (EHCI_QH_ENTITY *) GET_QH_ENTITY_ADDR (FindQhHwPtr); + // + // FindQh is Left/Right to Qh + // + while ((NULL != FindQhPtr->Next) && (FindQhPtr->Interval > QhPtr->Interval)) { + FindQhPtr = FindQhPtr->Next; + } + + if (FindQhPtr->Interval == QhPtr->Interval) { + // + // Link Qh after FindQh + // + if (NULL != FindQhPtr->Next) { + FindQhPtr->Next->Prev = QhPtr; + QhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(FindQhPtr->Next->Qh) >> 5); + QhPtr->Qh.SelectType = QH_SELECT_TYPE; + QhPtr->Qh.QhTerminate = FALSE; + } + + FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5); + FindQhPtr->Qh.SelectType = QH_SELECT_TYPE; + FindQhPtr->Qh.QhTerminate = FALSE; + + QhPtr->Prev = FindQhPtr; + QhPtr->Next = FindQhPtr->Next; + FindQhPtr->Next = QhPtr; + } else if (FindQhPtr->Interval < QhPtr->Interval) { + // + // Link Qh before FindQh + // + if (NULL == FindQhPtr->Prev) { + // + // Qh is the First one in Frame[0] List + // + FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5); + FrameEntryPtr->SelectType = QH_SELECT_TYPE; + FrameEntryPtr->LinkTerminate = FALSE; + } else { + // + // Qh is not the First one in Frame[0] List + // + FindQhPtr->Prev->Next = QhPtr; + FindQhPtr->Prev->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5); + FindQhPtr->Prev->Qh.SelectType = QH_SELECT_TYPE; + FindQhPtr->Prev->Qh.QhTerminate = FALSE; + } + + QhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(FindQhPtr->Qh) >> 5); + QhPtr->Qh.SelectType = QH_SELECT_TYPE; + QhPtr->Qh.QhTerminate = FALSE; + + QhPtr->Next = FindQhPtr; + QhPtr->Prev = FindQhPtr->Prev; + FindQhPtr->Prev = QhPtr; + } else { + // + // Link Qh after FindQh, Qh is the Last one + // + FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5); + FindQhPtr->Prev->Qh.SelectType = QH_SELECT_TYPE; + FindQhPtr->Qh.QhTerminate = FALSE; + + QhPtr->Prev = FindQhPtr; + QhPtr->Next = NULL; + FindQhPtr->Next = QhPtr; + } + } else { + // + // Null FrameList + // + FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5); + FrameEntryPtr->SelectType = QH_SELECT_TYPE; + FrameEntryPtr->LinkTerminate = FALSE; + } + // + // Other Frame[X] + // + if (NULL == QhPtr->Prev) { + // + // Qh is the First one in Frame[0] List + // + FrameIndex += QhPtr->Interval; + while (FrameIndex < HcDev->PeriodicFrameListLength) { + FrameEntryPtr = (FRAME_LIST_ENTRY *) (FrameEntryPtr + QhPtr->Interval); + FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5); + FrameEntryPtr->SelectType = QH_SELECT_TYPE; + FrameEntryPtr->LinkTerminate = FALSE; + FrameIndex += QhPtr->Interval; + } + } else if (QhPtr->Interval < QhPtr->Prev->Interval) { + // + // Qh is not the First one in Frame[0] List, and Prev.interval > Qh.interval + // + FrameIndex += QhPtr->Interval; + while (FrameIndex < HcDev->PeriodicFrameListLength) { + FrameEntryPtr = (FRAME_LIST_ENTRY *) (FrameEntryPtr + QhPtr->Interval); + if ((FrameIndex % QhPtr->Prev->Interval) != 0) { + FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5); + FrameEntryPtr->SelectType = QH_SELECT_TYPE; + FrameEntryPtr->LinkTerminate = FALSE; + } + + FrameIndex += QhPtr->Interval; + } + } + } else { + + // + // SyncInterruptTransfer Qh + // + + if (!FrameEntryPtr->LinkTerminate) { + // + // Not Null FrameList + // + FindQhHwPtr = (EHCI_QH_HW *) GET_0B_TO_31B (FrameEntryPtr->LinkPointer << 5); + FindQhPtr = (EHCI_QH_ENTITY *) GET_QH_ENTITY_ADDR (FindQhHwPtr); + // + // FindQh is Last Qh in the Asynchronous List, Link Qh after FindQh + // + while (NULL != FindQhPtr->Next) { + FindQhPtr = FindQhPtr->Next; + } + + FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5); + FindQhPtr->Qh.SelectType = QH_SELECT_TYPE; + FindQhPtr->Qh.QhTerminate = FALSE; + + FindQhPtr->Next = QhPtr; + QhPtr->Prev = FindQhPtr; + } else { + // + // Null FrameList + // + FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5); + FrameEntryPtr->SelectType = QH_SELECT_TYPE; + FrameEntryPtr->LinkTerminate = FALSE; + } + } + + return ; +} + +VOID +UnlinkQhFromPeriodicList ( + IN USB2_HC_DEV *HcDev, + IN EHCI_QH_ENTITY *QhPtr, + IN UINTN Interval + ) +/*++ + +Routine Description: + + Unlink Qh from Periodic Schedule List + +Arguments: + + HcDev - USB2_HC_DEV + QhPtr - A pointer to Qh + Interval - Interval of this periodic transfer + +Returns: + + VOID + +--*/ +{ + FRAME_LIST_ENTRY *FrameEntryPtr; + UINTN FrameIndex; + + FrameIndex = 0; + + ASSERT (HcDev); + ASSERT (QhPtr); + + FrameIndex = 0; + FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer; + + if (QhPtr->TransferType == ASYNC_INTERRUPT_TRANSFER) { + + // + // AsyncInterruptTransfer Qh + // + + if (NULL == QhPtr->Prev) { + // + // Qh is the First one on Frame[0] List + // + if (NULL == QhPtr->Next) { + // + // Only one on Frame[0] List + // + while (FrameIndex < HcDev->PeriodicFrameListLength) { + FrameEntryPtr->LinkPointer = 0; + FrameEntryPtr->SelectType = 0; + FrameEntryPtr->LinkTerminate = TRUE; + FrameEntryPtr += Interval; + FrameIndex += Interval; + } + } else { + while (FrameIndex < HcDev->PeriodicFrameListLength) { + FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Next->Qh) >> 5); + FrameEntryPtr->SelectType = QH_SELECT_TYPE; + FrameEntryPtr->LinkTerminate = FALSE; + FrameEntryPtr += Interval; + FrameIndex += Interval; + } + } + } else { + + // + // Not First one on Frame[0] List + // + if (NULL == QhPtr->Next) { + // + // Qh is the Last one on Frame[0] List + // + QhPtr->Prev->Qh.QhHorizontalPointer = 0; + QhPtr->Prev->Qh.SelectType = 0; + QhPtr->Prev->Qh.QhTerminate = TRUE; + } else { + QhPtr->Prev->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Next->Qh) >> 5); + QhPtr->Prev->Qh.SelectType = QH_SELECT_TYPE; + QhPtr->Prev->Qh.QhTerminate = FALSE; + } + + if (Interval == QhPtr->Prev->Interval) { + // + // Interval is the same as Prev + // Not involed Frame[X] + // + } else { + // + // Other Frame[X] + // + while (FrameIndex < HcDev->PeriodicFrameListLength) { + if ((FrameIndex % QhPtr->Prev->Interval) != 0) { + FrameEntryPtr->LinkPointer = QhPtr->Prev->Qh.QhHorizontalPointer; + FrameEntryPtr->SelectType = QhPtr->Prev->Qh.SelectType; + FrameEntryPtr->LinkTerminate = QhPtr->Prev->Qh.QhTerminate; + } + FrameEntryPtr += Interval; + FrameIndex += Interval; + } + } + } + + if (NULL != QhPtr->Next) { + QhPtr->Next->Prev = QhPtr->Prev; + } + + if (NULL != QhPtr->Prev) { + QhPtr->Prev->Next = QhPtr->Next; + } + } else { + // + // SyncInterruptTransfer Qh + // + if (NULL == QhPtr->Prev) { + // + // Qh is the only one Qh on Frame[0] List + // + FrameEntryPtr->LinkPointer = 0; + FrameEntryPtr->SelectType = 0; + FrameEntryPtr->LinkTerminate = TRUE; + } else { + QhPtr->Prev->Qh.QhHorizontalPointer = 0; + QhPtr->Prev->Qh.SelectType = 0; + QhPtr->Prev->Qh.QhTerminate = TRUE; + } + + if (NULL != QhPtr->Prev) { + QhPtr->Prev->Next = NULL; + } + } + + return ; +} + +VOID +LinkToAsyncReqeust ( + IN USB2_HC_DEV *HcDev, + IN EHCI_ASYNC_REQUEST *AsyncRequestPtr + ) +/*++ + +Routine Description: + + Llink AsyncRequest Entry to Async Request List + +Arguments: + + HcDev - USB2_HC_DEV + AsyncRequestPtr - A pointer to Async Request Entry + +Returns: + + VOID + +--*/ +{ + EHCI_ASYNC_REQUEST *CurrentPtr; + + CurrentPtr = HcDev->AsyncRequestList; + HcDev->AsyncRequestList = AsyncRequestPtr; + AsyncRequestPtr->Prev = NULL; + AsyncRequestPtr->Next = CurrentPtr; + + if (NULL != CurrentPtr) { + CurrentPtr->Prev = AsyncRequestPtr; + } + + return ; +} + +VOID +UnlinkFromAsyncReqeust ( + IN USB2_HC_DEV *HcDev, + IN EHCI_ASYNC_REQUEST *AsyncRequestPtr + ) +/*++ + +Routine Description: + + Unlink AsyncRequest Entry from Async Request List + +Arguments: + + HcDev - USB2_HC_DEV + AsyncRequestPtr - A pointer to Async Request Entry + +Returns: + + VOID + +--*/ +{ + if (NULL == AsyncRequestPtr->Prev) { + HcDev->AsyncRequestList = AsyncRequestPtr->Next; + if (NULL != AsyncRequestPtr->Next) { + AsyncRequestPtr->Next->Prev = NULL; + } + } else { + AsyncRequestPtr->Prev->Next = AsyncRequestPtr->Next; + if (NULL != AsyncRequestPtr->Next) { + AsyncRequestPtr->Next->Prev = AsyncRequestPtr->Prev; + } + } + + return ; +} + +VOID +SetQtdBufferPointer ( + IN EHCI_QTD_HW *QtdHwPtr, + IN VOID *DataPtr, + IN UINTN DataLen + ) +/*++ + +Routine Description: + + Set data buffer pointers in Qtd + +Arguments: + + QtdHwPtr - A pointer to Qtd hardware structure + DataPtr - A pointer to user data buffer + DataLen - Length of the user data buffer + +Returns: + + VOID + +--*/ +{ + UINTN RemainLen; + + RemainLen = DataLen; + ASSERT (QtdHwPtr); + + // + // Set BufferPointer0, ExtBufferPointer0 and Offset + // + QtdHwPtr->BufferPointer0 = (UINT32) (GET_0B_TO_31B (DataPtr) >> 12); + QtdHwPtr->CurrentOffset = (UINT32) (GET_0B_TO_31B (DataPtr) & EFI_PAGE_MASK); + QtdHwPtr->ExtBufferPointer0 = (UINT32) GET_32B_TO_63B (DataPtr); + + // + // Set BufferPointer1 and ExtBufferPointer1 + // + RemainLen = RemainLen > (EFI_PAGE_SIZE - QtdHwPtr->CurrentOffset) ? (RemainLen - (EFI_PAGE_SIZE - QtdHwPtr->CurrentOffset)) : 0; + if (RemainLen == 0) { + goto exit; + } + + QtdHwPtr->BufferPointer1 = QtdHwPtr->BufferPointer0 + 1; + QtdHwPtr->ExtBufferPointer1 = QtdHwPtr->ExtBufferPointer0; + + // + // Set BufferPointer2 and ExtBufferPointer2 + // + RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0; + if (RemainLen == 0) { + goto exit; + } + + QtdHwPtr->BufferPointer2 = QtdHwPtr->BufferPointer1 + 1; + QtdHwPtr->ExtBufferPointer2 = QtdHwPtr->ExtBufferPointer0; + + // + // Set BufferPointer3 and ExtBufferPointer3 + // + RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0; + if (RemainLen == 0) { + goto exit; + } + + QtdHwPtr->BufferPointer3 = QtdHwPtr->BufferPointer2 + 1; + QtdHwPtr->ExtBufferPointer3 = QtdHwPtr->ExtBufferPointer0; + + // + // Set BufferPointer4 and ExtBufferPointer4 + // + RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0; + if (RemainLen == 0) { + goto exit; + } + + QtdHwPtr->BufferPointer4 = QtdHwPtr->BufferPointer3 + 1; + QtdHwPtr->ExtBufferPointer4 = QtdHwPtr->ExtBufferPointer0; + +exit: + return ; +} + +BOOLEAN +IsQtdStatusActive ( + IN EHCI_QTD_HW *HwQtdPtr + ) +/*++ + +Routine Description: + + Whether Qtd status is active or not + +Arguments: + + HwQtdPtr - A pointer to hardware Qtd structure + +Returns: + + TRUE Active + FALSE Inactive + +--*/ +{ + UINT8 QtdStatus; + BOOLEAN Value; + + QtdStatus = (UINT8) (HwQtdPtr->Status); + Value = (BOOLEAN) (QtdStatus & QTD_STATUS_ACTIVE); + + return Value; +} + +BOOLEAN +IsQtdStatusHalted ( + IN EHCI_QTD_HW *HwQtdPtr + ) +/*++ + +Routine Description: + + Whether Qtd status is halted or not + +Arguments: + + HwQtdPtr - A pointer to hardware Qtd structure + +Returns: + + TRUE Halted + FALSE Not halted + +--*/ +{ + UINT8 QtdStatus; + BOOLEAN Value; + + QtdStatus = (UINT8) (HwQtdPtr->Status); + Value = (BOOLEAN) (QtdStatus & QTD_STATUS_HALTED); + + return Value; +} + +BOOLEAN +IsQtdStatusBufferError ( + IN EHCI_QTD_HW *HwQtdPtr + ) +/*++ + +Routine Description: + + Whether Qtd status is buffer error or not + +Arguments: + + HwQtdPtr - A pointer to hardware Qtd structure + +Returns: + + TRUE Buffer error + FALSE No buffer error + +--*/ +{ + UINT8 QtdStatus; + BOOLEAN Value; + + QtdStatus = (UINT8) (HwQtdPtr->Status); + Value = (BOOLEAN) (QtdStatus & QTD_STATUS_BUFFER_ERR); + + return Value; +} + +BOOLEAN +IsQtdStatusBabbleError ( + IN EHCI_QTD_HW *HwQtdPtr + ) +/*++ + +Routine Description: + + Whether Qtd status is babble error or not + +Arguments: + + HwQtdPtr - A pointer to hardware Qtd structure + +Returns: + + TRUE Babble error + FALSE No babble error + +--*/ +{ + UINT8 QtdStatus; + BOOLEAN Value; + + QtdStatus = (UINT8) (HwQtdPtr->Status); + Value = (BOOLEAN) (QtdStatus & QTD_STATUS_BABBLE_ERR); + + return Value; +} + +BOOLEAN +IsQtdStatusTransactionError ( + IN EHCI_QTD_HW *HwQtdPtr + ) +/*++ + +Routine Description: + + Whether Qtd status is transaction error or not + +Arguments: + + HwQtdPtr - A pointer to hardware Qtd structure + +Returns: + + TRUE Transaction error + FALSE No transaction error + +--*/ +{ + UINT8 QtdStatus; + BOOLEAN Value; + + QtdStatus = (UINT8) (HwQtdPtr->Status); + Value = (BOOLEAN) (QtdStatus & QTD_STATUS_TRANSACTION_ERR); + + return Value; +} + +BOOLEAN +IsDataInTransfer ( + IN UINT8 EndPointAddress + ) +/*++ + +Routine Description: + + Whether is a DataIn direction transfer + +Arguments: + + EndPointAddress - address of the endpoint + +Returns: + + TRUE DataIn + FALSE DataOut + +--*/ +{ + BOOLEAN Value; + + if (EndPointAddress & 0x80) { + Value = TRUE; + } else { + Value = FALSE; + } + + return Value; +} + +EFI_STATUS +MapDataBuffer ( + IN USB2_HC_DEV *HcDev, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN VOID *Data, + IN OUT UINTN *DataLength, + OUT UINT8 *PktId, + OUT UINT8 **DataCursor, + OUT VOID **DataMap + ) +/*++ + +Routine Description: + + Map address of user data buffer + +Arguments: + + HcDev - USB2_HC_DEV + TransferDirection - direction of transfer + Data - A pointer to user data buffer + DataLength - length of user data + PktId - Packte Identificaion + DataCursor - mapped address to return + DataMap - identificaion of this mapping to return + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS TempPhysicalAddr; + + Status = EFI_SUCCESS; + + switch (TransferDirection) { + + case EfiUsbDataIn: + + *PktId = INPUT_PACKET_ID; + // + // BusMasterWrite means cpu read + // + Status = HcDev->PciIo->Map ( + HcDev->PciIo, + EfiPciIoOperationBusMasterWrite, + Data, + DataLength, + &TempPhysicalAddr, + DataMap + ); + if (EFI_ERROR (Status)) { + DEBUG ((gEHCDebugLevel, "MapDataBuffer Failed\n")); + Status = EFI_DEVICE_ERROR; + goto exit; + } + + *DataCursor = (UINT8 *) ((UINTN) TempPhysicalAddr); + break; + + case EfiUsbDataOut: + + *PktId = OUTPUT_PACKET_ID; + // + // BusMasterRead means cpu write + // + Status = HcDev->PciIo->Map ( + HcDev->PciIo, + EfiPciIoOperationBusMasterRead, + Data, + DataLength, + &TempPhysicalAddr, + DataMap + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + *DataCursor = (UINT8 *) ((UINTN) TempPhysicalAddr); + break; + + case EfiUsbNoData: + + *PktId = OUTPUT_PACKET_ID; + Data = NULL; + *DataLength = 0; + *DataCursor = NULL; + *DataMap = NULL; + break; + + default: + + Status = EFI_INVALID_PARAMETER; + } + +exit: + return Status; +} + +EFI_STATUS +MapRequestBuffer ( + IN USB2_HC_DEV *HcDev, + IN OUT VOID *Request, + OUT UINT8 **RequestCursor, + OUT VOID **RequestMap + ) +/*++ + +Routine Description: + + Map address of request structure buffer + +Arguments: + + HcDev - USB2_HC_DEV + Request - A pointer to request structure + RequestCursor - Mapped address of request structure to return + RequestMap - Identificaion of this mapping to return + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + UINTN RequestLen; + EFI_PHYSICAL_ADDRESS TempPhysicalAddr; + + RequestLen = sizeof (EFI_USB_DEVICE_REQUEST); + Status = HcDev->PciIo->Map ( + HcDev->PciIo, + EfiPciIoOperationBusMasterRead, + (UINT8 *) Request, + (UINTN *) &RequestLen, + &TempPhysicalAddr, + RequestMap + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + *RequestCursor = (UINT8 *) ((UINTN) TempPhysicalAddr); + +exit: + return Status; +} + +EFI_STATUS +DeleteAsyncRequestTransfer ( + IN USB2_HC_DEV *HcDev, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + OUT UINT8 *DataToggle + ) +/*++ + +Routine Description: + + Delete all asynchronous request transfer + +Arguments: + + HcDev - USB2_HC_DEV + DeviceAddress - address of usb device + EndPointAddress - address of endpoint + DataToggle - stored data toggle + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + EHCI_ASYNC_REQUEST *AsyncRequestPtr; + EHCI_ASYNC_REQUEST *MatchPtr; + EHCI_QH_HW *QhHwPtr; + UINT8 EndPointNum; + + if (NULL == HcDev->AsyncRequestList) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + MatchPtr = NULL; + QhHwPtr = NULL; + EndPointNum = EndPointAddress & 0x0f; + AsyncRequestPtr = HcDev->AsyncRequestList; + + // + // Find QH of AsyncRequest by DeviceAddress and EndPointNum + // + do { + + QhHwPtr = &(AsyncRequestPtr->QhPtr->Qh); + if (QhHwPtr->DeviceAddr == DeviceAddress && QhHwPtr->EndpointNum == EndPointNum) { + MatchPtr = AsyncRequestPtr; + break; + } + + AsyncRequestPtr = AsyncRequestPtr->Next; + + } while (NULL != AsyncRequestPtr); + + if (NULL == MatchPtr) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + Status = DisablePeriodicSchedule (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT); + if (EFI_ERROR (Status)) { + DEBUG ((gEHCErrorLevel, "WaitForPeriodicScheduleDisable TimeOut\n")); + Status = EFI_TIMEOUT; + goto exit; + } + + *DataToggle = (UINT8) MatchPtr->QhPtr->Qh.DataToggle; + UnlinkQhFromPeriodicList (HcDev, MatchPtr->QhPtr, MatchPtr->QhPtr->Interval); + UnlinkFromAsyncReqeust (HcDev, MatchPtr); + + if (NULL == HcDev->AsyncRequestList) { + + Status = StopPollingTimer (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + } else { + + Status = EnablePeriodicSchedule (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + + Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT); + if (EFI_ERROR (Status)) { + DEBUG ((gEHCErrorLevel, "WaitForPeriodicScheduleEnable TimeOut\n")); + Status = EFI_TIMEOUT; + goto exit; + } + + if (IsEhcHalted (HcDev)) { + Status = StartScheduleExecution (HcDev); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto exit; + } + } + + } + + DestoryQtds (HcDev, MatchPtr->QhPtr->FirstQtdPtr); + DestoryQh (HcDev, MatchPtr->QhPtr); + EhciFreePool (HcDev, (UINT8 *) MatchPtr, sizeof (EHCI_ASYNC_REQUEST)); + +exit: + return Status; +} + +VOID +CleanUpAllAsyncRequestTransfer ( + IN USB2_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Clean up all asynchronous request transfer + +Arguments: + + HcDev - USB2_HC_DEV + +Returns: + + VOID + +--*/ +{ + EHCI_ASYNC_REQUEST *AsyncRequestPtr; + EHCI_ASYNC_REQUEST *FreePtr; + + AsyncRequestPtr = NULL; + FreePtr = NULL; + + StopPollingTimer (HcDev); + + AsyncRequestPtr = HcDev->AsyncRequestList; + while (NULL != AsyncRequestPtr) { + + FreePtr = AsyncRequestPtr; + AsyncRequestPtr = AsyncRequestPtr->Next; + UnlinkFromAsyncReqeust (HcDev, FreePtr); + UnlinkQhFromPeriodicList (HcDev, FreePtr->QhPtr, FreePtr->QhPtr->Interval); + DestoryQtds (HcDev, FreePtr->QhPtr->FirstQtdPtr); + DestoryQh (HcDev, FreePtr->QhPtr); + EhciFreePool (HcDev, (UINT8 *) FreePtr, sizeof (EHCI_ASYNC_REQUEST)); + + } + + return ; +} + +VOID +ZeroOutQhOverlay ( + IN EHCI_QH_ENTITY *QhPtr + ) +/*++ + +Routine Description: + + Zero out the fields in Qh structure + +Arguments: + + QhPtr - A pointer to Qh structure + +Returns: + + VOID + +--*/ +{ + QhPtr->Qh.CurrentQtdPointer = 0; + QhPtr->Qh.AltNextQtdPointer = 0; + QhPtr->Qh.NakCount = 0; + QhPtr->Qh.AltNextQtdTerminate = 0; + QhPtr->Qh.TotalBytes = 0; + QhPtr->Qh.InterruptOnComplete = 0; + QhPtr->Qh.CurrentPage = 0; + QhPtr->Qh.ErrorCount = 0; + QhPtr->Qh.PidCode = 0; + QhPtr->Qh.Status = 0; + QhPtr->Qh.BufferPointer0 = 0; + QhPtr->Qh.CurrentOffset = 0; + QhPtr->Qh.BufferPointer1 = 0; + QhPtr->Qh.CompleteSplitMask = 0; + QhPtr->Qh.BufferPointer2 = 0; + QhPtr->Qh.SplitBytes = 0; + QhPtr->Qh.FrameTag = 0; + QhPtr->Qh.BufferPointer3 = 0; + QhPtr->Qh.BufferPointer4 = 0; + QhPtr->Qh.ExtBufferPointer0 = 0; + QhPtr->Qh.ExtBufferPointer1 = 0; + QhPtr->Qh.ExtBufferPointer2 = 0; + QhPtr->Qh.ExtBufferPointer3 = 0; + QhPtr->Qh.ExtBufferPointer4 = 0; +} + +VOID +UpdateAsyncRequestTransfer ( + IN EHCI_ASYNC_REQUEST *AsyncRequestPtr, + IN UINT32 TransferResult, + IN UINTN ErrQtdPos + ) +/*++ + +Routine Description: + + Update asynchronous request transfer + +Arguments: + + AsyncRequestPtr - A pointer to async request + TransferResult - transfer result + ErrQtdPos - postion of error Qtd + +Returns: + + VOID + +--*/ +{ + EHCI_QTD_ENTITY *QtdPtr; + + QtdPtr = NULL; + + if (EFI_USB_NOERROR == TransferResult) { + + // + // Update Qh for next trigger + // + + QtdPtr = AsyncRequestPtr->QhPtr->FirstQtdPtr; + + // + // Update fields in Qh + // + + // + // Get DataToggle from Overlay in Qh + // + // ZeroOut Overlay in Qh except DataToggle, HostController will update this field + // + ZeroOutQhOverlay (AsyncRequestPtr->QhPtr); + AsyncRequestPtr->QhPtr->Qh.NextQtdPointer = (UINT32) (GET_0B_TO_31B (&(QtdPtr->Qtd)) >> 5); + AsyncRequestPtr->QhPtr->Qh.NextQtdTerminate = FALSE; + + // + // Update fields in Qtd + // + while (NULL != QtdPtr) { + QtdPtr->Qtd.TotalBytes = QtdPtr->StaticTotalBytes; + QtdPtr->Qtd.CurrentOffset = QtdPtr->StaticCurrentOffset; + QtdPtr->Qtd.CurrentPage = 0; + QtdPtr->Qtd.ErrorCount = QTD_ERROR_COUNTER; + QtdPtr->Qtd.Status = QTD_STATUS_ACTIVE; + + QtdPtr->TotalBytes = QtdPtr->StaticTotalBytes; + QtdPtr = QtdPtr->Next; + } + } + + return ; +} + +BOOLEAN +CheckQtdsTransferResult ( + IN BOOLEAN IsControl, + IN EHCI_QH_ENTITY *QhPtr, + OUT UINT32 *Result, + OUT UINTN *ErrQtdPos, + OUT UINTN *ActualLen + ) +/*++ + +Routine Description: + + Check transfer result of Qtds + +Arguments: + + IsControl - Is control transfer or not + QhPtr - A pointer to Qh + Result - Transfer result + ErrQtdPos - Error TD Position + ActualLen - Actual Transfer Size + +Returns: + + TRUE Qtds finished + FALSE Not finish + +--*/ +{ + UINTN ActualLenPerQtd; + EHCI_QTD_ENTITY *QtdPtr; + EHCI_QTD_HW *QtdHwPtr; + BOOLEAN Value; + + ASSERT (QhPtr); + ASSERT (Result); + ASSERT (ErrQtdPos); + ASSERT (ActualLen); + + Value = TRUE; + QtdPtr = QhPtr->FirstQtdPtr; + QtdHwPtr = &(QtdPtr->Qtd); + + while (NULL != QtdHwPtr) { + + if (IsQtdStatusActive (QtdHwPtr)) { + *Result |= EFI_USB_ERR_NOTEXECUTE; + } + + if (IsQtdStatusHalted (QtdHwPtr)) { + *Result |= EFI_USB_ERR_STALL; + } + + if (IsQtdStatusBufferError (QtdHwPtr)) { + *Result |= EFI_USB_ERR_BUFFER; + } + + if (IsQtdStatusBabbleError (QtdHwPtr)) { + *Result |= EFI_USB_ERR_BABBLE; + } + + if (IsQtdStatusTransactionError (QtdHwPtr)) { + *Result |= EFI_USB_ERR_TIMEOUT; + } + + ActualLenPerQtd = QtdPtr->TotalBytes - QtdHwPtr->TotalBytes; + QtdPtr->TotalBytes = QtdHwPtr->TotalBytes; + // + // Accumulate actual transferred data length in each DataQtd. + // + if (SETUP_PACKET_PID_CODE != QtdHwPtr->PidCode) { + *ActualLen += ActualLenPerQtd; + } + + if (*Result) { + Value = FALSE; + break; + } + + if ((!IsControl) && (QtdPtr->TotalBytes > 0)) { + // + // Did something, but isn't full workload + // + break; + } + + (*ErrQtdPos)++; + QtdHwPtr = GetQtdNextPointer (QtdHwPtr); + QtdPtr = (EHCI_QTD_ENTITY *) GET_QTD_ENTITY_ADDR (QtdHwPtr); + + } + + return Value; +} + +EFI_STATUS +ExecuteTransfer ( + IN USB2_HC_DEV *HcDev, + IN BOOLEAN IsControl, + IN EHCI_QH_ENTITY *QhPtr, + IN OUT UINTN *ActualLen, + OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ) +/*++ + +Routine Description: + + Execute Bulk or SyncInterrupt Transfer + +Arguments: + + HcDev - USB2_HC_DEV + IsControl - Is control transfer or not + QhPtr - A pointer to Qh + ActualLen - Actual transfered Len + DataToggle - Data Toggle + TimeOut - TimeOut threshold + TransferResult - Transfer result + +Returns: + + EFI_SUCCESS Sucess + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + UINTN ErrQtdPos; + UINTN Delay; + UINTN RequireLen; + BOOLEAN Finished; + + Status = EFI_SUCCESS; + ErrQtdPos = 0; + *TransferResult = EFI_USB_NOERROR; + RequireLen = *ActualLen; + *ActualLen = 0; + Finished = FALSE; + + Delay = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1; + + do { + *TransferResult = 0; + Finished = CheckQtdsTransferResult ( + IsControl, + QhPtr, + TransferResult, + &ErrQtdPos, + ActualLen + ); + if (Finished) { + break; + } + // + // Qtd is inactive, which means bulk or interrupt transfer's end. + // + if (!(*TransferResult & EFI_USB_ERR_NOTEXECUTE)) { + break; + } + + gBS->Stall (EHCI_SYNC_REQUEST_POLLING_TIME); + + } while (--Delay); + + if (EFI_USB_NOERROR != *TransferResult) { + if (0 == Delay) { + Status = EFI_TIMEOUT; + } else { + Status = EFI_DEVICE_ERROR; + } + } + + // + // Special for Bulk and Interrupt Transfer + // + *DataToggle = (UINT8) QhPtr->Qh.DataToggle; + + return Status; +} + +EFI_STATUS +AsyncRequestMoniter ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ +Routine Description: + + Interrupt transfer periodic check handler + +Arguments: + Event - Interrupt event + Context - Pointer to USB2_HC_DEV + +Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + USB2_HC_DEV *HcDev; + EHCI_ASYNC_REQUEST *AsyncRequestPtr; + EHCI_QTD_HW *QtdHwPtr; + UINTN ErrQtdPos; + UINTN ActualLen; + UINT32 TransferResult; + UINT8 *ReceiveBuffer; + UINT8 *ProcessBuffer; + + Status = EFI_SUCCESS; + QtdHwPtr = NULL; + ReceiveBuffer = NULL; + ProcessBuffer = NULL; + HcDev = (USB2_HC_DEV *) Context; + AsyncRequestPtr = HcDev->AsyncRequestList; + + while (NULL != AsyncRequestPtr) { + + TransferResult = 0; + ErrQtdPos = 0; + ActualLen = 0; + + CheckQtdsTransferResult ( + FALSE, + AsyncRequestPtr->QhPtr, + &TransferResult, + &ErrQtdPos, + &ActualLen + ); + + if ((TransferResult & EFI_USB_ERR_NAK) || (TransferResult & EFI_USB_ERR_NOTEXECUTE)) { + AsyncRequestPtr = AsyncRequestPtr->Next; + continue; + } + // + // Allocate memory for EHC private data structure + // + ProcessBuffer = AllocateZeroPool (ActualLen); + if (NULL == ProcessBuffer) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + QtdHwPtr = &(AsyncRequestPtr->QhPtr->FirstQtdPtr->Qtd); + ReceiveBuffer = (UINT8 *) GET_0B_TO_31B ((QtdHwPtr->BufferPointer0 << 12) | AsyncRequestPtr->QhPtr->FirstQtdPtr->StaticCurrentOffset); + CopyMem ( + ProcessBuffer, + ReceiveBuffer, + ActualLen + ); + + UpdateAsyncRequestTransfer (AsyncRequestPtr, TransferResult, ErrQtdPos); + + if (EFI_USB_NOERROR == TransferResult) { + + if (AsyncRequestPtr->CallBackFunc != NULL) { + (AsyncRequestPtr->CallBackFunc) (ProcessBuffer, ActualLen, AsyncRequestPtr->Context, TransferResult); + } + + } else { + + // + // leave error recovery to its related device driver. A common case of + // the error recovery is to re-submit the interrupt transfer. + // When an interrupt transfer is re-submitted, its position in the linked + // list is changed. It is inserted to the head of the linked list, while + // this function scans the whole list from head to tail. Thus, the + // re-submitted interrupt transfer's callback function will not be called + // again in this round. + // + if (AsyncRequestPtr->CallBackFunc != NULL) { + (AsyncRequestPtr->CallBackFunc) (NULL, 0, AsyncRequestPtr->Context, TransferResult); + } + + } + + if (NULL != ProcessBuffer) { + gBS->FreePool (ProcessBuffer); + } + + AsyncRequestPtr = AsyncRequestPtr->Next; + + } + +exit: + return Status; +} + diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa b/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa index 66a41d9319..3d24744f12 100644 --- a/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa +++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa @@ -71,6 +71,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.--> gEfiUsbHcProtocolGuid + + gEfiUsb2HcProtocolGuid + EFI_SPECIFICATION_VERSION 0x00020000 diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c index 62d58eed78..74ddc6bb12 100644 --- a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c +++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c @@ -49,13 +49,13 @@ Returns: // Perform 16bit Read in PCI IO Space // return PciIo->Io.Read ( - PciIo, - EfiPciIoWidthUint16, - USB_BAR_INDEX, - (UINT64) PortOffset, - 1, - Data - ); + PciIo, + EfiPciIoWidthUint16, + USB_BAR_INDEX, + (UINT64) PortOffset, + 1, + Data + ); } EFI_STATUS @@ -86,13 +86,13 @@ Returns: // Perform 32bit Read in PCI IO Space // return PciIo->Io.Read ( - PciIo, - EfiPciIoWidthUint32, - USB_BAR_INDEX, - (UINT64) PortOffset, - 1, - Data - ); + PciIo, + EfiPciIoWidthUint32, + USB_BAR_INDEX, + (UINT64) PortOffset, + 1, + Data + ); } EFI_STATUS @@ -123,13 +123,13 @@ Returns: // Perform 16bit Write in PCI IO Space // return PciIo->Io.Write ( - PciIo, - EfiPciIoWidthUint16, - USB_BAR_INDEX, - (UINT64) PortOffset, - 1, - &Data - ); + PciIo, + EfiPciIoWidthUint16, + USB_BAR_INDEX, + (UINT64) PortOffset, + 1, + &Data + ); } EFI_STATUS @@ -160,13 +160,13 @@ Returns: // Perform 32bit Write in PCI IO Space // return PciIo->Io.Write ( - PciIo, - EfiPciIoWidthUint32, - USB_BAR_INDEX, - (UINT64) PortOffset, - 1, - &Data - ); + PciIo, + EfiPciIoWidthUint32, + USB_BAR_INDEX, + (UINT64) PortOffset, + 1, + &Data + ); } // // USB register-base helper functions @@ -657,10 +657,10 @@ Returns: EFI_STATUS Status; Status = ReadUHCCommandReg ( - HcDev->PciIo, - (UINT32) (USBCMD), - &CommandContent - ); + HcDev->PciIo, + (UINT32) (USBCMD), + &CommandContent + ); if ((CommandContent & USBCMD_MAXP) != USBCMD_MAXP) { CommandContent |= USBCMD_MAXP; @@ -715,25 +715,25 @@ Returns: BufferSizeInBytes = 4096; BufferSizeInPages = EFI_SIZE_TO_PAGES (BufferSizeInBytes); Status = HcDev->PciIo->AllocateBuffer ( - HcDev->PciIo, - AllocateAnyPages, - EfiBootServicesData, - BufferSizeInPages, - &CommonBuffer, - 0 - ); + HcDev->PciIo, + AllocateAnyPages, + EfiBootServicesData, + BufferSizeInPages, + &CommonBuffer, + 0 + ); if (EFI_ERROR (Status)) { return EFI_OUT_OF_RESOURCES; } Status = HcDev->PciIo->Map ( - HcDev->PciIo, - EfiPciIoOperationBusMasterCommonBuffer, - CommonBuffer, - &BufferSizeInBytes, - &MappedAddress, - &Mapping - ); + HcDev->PciIo, + EfiPciIoOperationBusMasterCommonBuffer, + CommonBuffer, + &BufferSizeInBytes, + &MappedAddress, + &Mapping + ); if (EFI_ERROR (Status) || (BufferSizeInBytes != 4096)) { HcDev->PciIo->FreeBuffer (HcDev->PciIo, BufferSizeInPages, CommonBuffer); return EFI_UNSUPPORTED; @@ -3589,13 +3589,13 @@ Returns: // and it is allocated as common buffer use. // Status = HcDev->PciIo->AllocateBuffer ( - HcDev->PciIo, - AllocateAnyPages, - EfiBootServicesData, - MemoryBlockSizeInPages, - &CommonBuffer, - 0 - ); + HcDev->PciIo, + AllocateAnyPages, + EfiBootServicesData, + MemoryBlockSizeInPages, + &CommonBuffer, + 0 + ); if (EFI_ERROR (Status)) { gBS->FreePool ((*MemoryHeader)->BitArrayPtr); gBS->FreePool (*MemoryHeader); @@ -3604,13 +3604,13 @@ Returns: MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages); Status = HcDev->PciIo->Map ( - HcDev->PciIo, - EfiPciIoOperationBusMasterCommonBuffer, - CommonBuffer, - &MemoryBlockSizeInBytes, - &MappedAddress, - &Mapping - ); + HcDev->PciIo, + EfiPciIoOperationBusMasterCommonBuffer, + CommonBuffer, + &MemoryBlockSizeInBytes, + &MappedAddress, + &Mapping + ); // // if returned Mapped size is less than the size we request,do not support. // @@ -3741,10 +3741,10 @@ Returns: TempHeaderPtr = TempHeaderPtr->Next) { Status = AllocMemInMemoryBlock ( - TempHeaderPtr, - (VOID **) Pool, - RealAllocSize / 32 - ); + TempHeaderPtr, + (VOID **) Pool, + RealAllocSize / 32 + ); if (!EFI_ERROR (Status)) { ZeroMem (*Pool, AllocSize); return EFI_SUCCESS; @@ -3777,10 +3777,10 @@ Returns: InsertMemoryHeaderToList (MemoryHeader, NewMemoryHeader); Status = AllocMemInMemoryBlock ( - NewMemoryHeader, - (VOID **) Pool, - RealAllocSize / 32 - ); + NewMemoryHeader, + (VOID **) Pool, + RealAllocSize / 32 + ); if (!EFI_ERROR (Status)) { ZeroMem (*Pool, AllocSize); @@ -4226,12 +4226,12 @@ TurnOffUSBEmulation ( // Command = 0; PciIo->Pci.Write ( - PciIo, - EfiPciIoWidthUint16, - USB_EMULATION, - 1, - &Command - ); + PciIo, + EfiPciIoWidthUint16, + USB_EMULATION, + 1, + &Command + ); return ; } diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c index 1eba8bed5b..14f8bf2790 100644 --- a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c +++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c @@ -26,13 +26,6 @@ Revision History // Driver model protocol interface // -EFI_STATUS -EFIAPI -UHCIDriverEntryPoint ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ); - EFI_STATUS EFIAPI UHCIDriverBindingSupported ( @@ -119,7 +112,7 @@ UHCIAsyncInterruptTransfer ( IN UINT8 DeviceAddress, IN UINT8 EndPointAddress, IN BOOLEAN IsSlowDevice, - IN UINT8 MaxiumPacketLength, + IN UINT8 MaximumPacketLength, IN BOOLEAN IsNewTransfer, IN OUT UINT8 *DataToggle, IN UINTN PollingInterval, OPTIONAL @@ -199,6 +192,161 @@ UHCIClearRootHubPortFeature ( IN EFI_USB_PORT_FEATURE PortFeature ); +// +// UEFI 2.0 Protocol +// + +EFI_STATUS +EFIAPI +UHCI2GetCapability( + IN EFI_USB2_HC_PROTOCOL * This, + OUT UINT8 *MaxSpeed, + OUT UINT8 *PortNumber, + OUT UINT8 *Is64BitCapable + ); + +EFI_STATUS +EFIAPI +UHCI2Reset ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT16 Attributes + ); + +EFI_STATUS +EFIAPI +UHCI2GetState ( + IN EFI_USB2_HC_PROTOCOL * This, + OUT EFI_USB_HC_STATE * State + ); + +EFI_STATUS +EFIAPI +UHCI2SetState ( + IN EFI_USB2_HC_PROTOCOL * This, + IN EFI_USB_HC_STATE State + ); + +EFI_STATUS +EFIAPI +UHCI2ControlTransfer ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN EFI_USB_DEVICE_REQUEST * Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data, OPTIONAL + IN OUT UINTN *DataLength, OPTIONAL + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ); + +EFI_STATUS +EFIAPI +UHCI2BulkTransfer ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ); + +EFI_STATUS +EFIAPI +UHCI2AsyncInterruptTransfer ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle, + IN UINTN PollingInterval, OPTIONAL + IN UINTN DataLength, OPTIONAL + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, OPTIONAL + IN VOID *Context OPTIONAL + ); + +EFI_STATUS +EFIAPI +UHCI2SyncInterruptTransfer ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ); + +EFI_STATUS +EFIAPI +UHCI2IsochronousTransfer ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ); + +EFI_STATUS +EFIAPI +UHCI2AsyncIsochronousTransfer ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context OPTIONAL + ); + +EFI_STATUS +EFIAPI +UHCI2GetRootHubPortStatus ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS * PortStatus + ); + +EFI_STATUS +EFIAPI +UHCI2SetRootHubPortFeature ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ); + +EFI_STATUS +EFIAPI +UHCI2ClearRootHubPortFeature ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ); + // // Asynchronous interrupt transfer monitor function // @@ -236,7 +384,7 @@ UHCIDriverBindingSupported ( Arguments: This - Protocol instance pointer. - Controller, - Handle of device to test + Controller - Handle of device to test RemainingDevicePath - Not used Returns: @@ -289,20 +437,20 @@ UHCIDriverBindingSupported ( (UsbClassCReg.PI != PCI_CLASSC_PI_UHCI)) { gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); return EFI_UNSUPPORTED; } gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); return EFI_SUCCESS; } @@ -351,6 +499,7 @@ UHCIDriverBindingStart ( if (EFI_ERROR (Status)) { return Status; } + // // Turn off USB emulation // @@ -367,11 +516,11 @@ UHCIDriverBindingStart ( ); if (EFI_ERROR (Status)) { gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); return EFI_UNSUPPORTED; } @@ -381,14 +530,14 @@ UHCIDriverBindingStart ( HcDev = AllocateZeroPool (sizeof (USB_HC_DEV)); if (HcDev == NULL) { gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); return EFI_OUT_OF_RESOURCES; } - + // // init EFI_USB_HC_PROTOCOL protocol interface and install the protocol // @@ -409,6 +558,27 @@ UHCIDriverBindingStart ( HcDev->UsbHc.MajorRevision = 0x1; HcDev->UsbHc.MinorRevision = 0x1; + // + // + // init EFI_USB2_HC_PROTOCOL protocol interface and install the protocol + // + HcDev->Usb2Hc.GetCapability = UHCI2GetCapability; + HcDev->Usb2Hc.Reset = UHCI2Reset; + HcDev->Usb2Hc.GetState = UHCI2GetState; + HcDev->Usb2Hc.SetState = UHCI2SetState; + HcDev->Usb2Hc.ControlTransfer = UHCI2ControlTransfer; + HcDev->Usb2Hc.BulkTransfer = UHCI2BulkTransfer; + HcDev->Usb2Hc.AsyncInterruptTransfer = UHCI2AsyncInterruptTransfer; + HcDev->Usb2Hc.SyncInterruptTransfer = UHCI2SyncInterruptTransfer; + HcDev->Usb2Hc.IsochronousTransfer = UHCI2IsochronousTransfer; + HcDev->Usb2Hc.AsyncIsochronousTransfer = UHCI2AsyncIsochronousTransfer; + HcDev->Usb2Hc.GetRootHubPortStatus = UHCI2GetRootHubPortStatus; + HcDev->Usb2Hc.SetRootHubPortFeature = UHCI2SetRootHubPortFeature; + HcDev->Usb2Hc.ClearRootHubPortFeature = UHCI2ClearRootHubPortFeature; + + HcDev->Usb2Hc.MajorRevision = 0x1; + HcDev->Usb2Hc.MinorRevision = 0x1; + // // Init UHCI private data structures // @@ -428,14 +598,14 @@ UHCIDriverBindingStart ( } gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); return EFI_OUT_OF_RESOURCES; } - + // // Init interrupt list head in the HcDev structure. // @@ -460,11 +630,11 @@ UHCIDriverBindingStart ( } gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); return EFI_UNSUPPORTED; } @@ -486,11 +656,11 @@ UHCIDriverBindingStart ( } gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); return EFI_UNSUPPORTED; } @@ -518,7 +688,7 @@ UHCIDriverBindingStart ( ); return Status; } - + // // Install Host Controller Protocol // @@ -538,17 +708,46 @@ UHCIDriverBindingStart ( } gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + + // + // Install USB2.0 Host Controller Protocol + // + Status = gBS->InstallProtocolInterface ( + &Controller, + &gEfiUsb2HcProtocolGuid, + EFI_NATIVE_INTERFACE, + &HcDev->Usb2Hc + ); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (HcDev->InterruptTransTimer); + FreeFrameListEntry (HcDev); + DelMemoryManagement (HcDev); + + if (HcDev != NULL) { + gBS->FreePool (HcDev); + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; } // // component name protocol. // + HcDev->ControllerNameTable = NULL; AddUnicodeString ( "eng", @@ -582,12 +781,17 @@ UnInstallUHCInterface ( HcDev = USB_HC_DEV_FROM_THIS (This); gBS->UninstallProtocolInterface ( - Controller, - &gEfiUsbHcProtocolGuid, - &HcDev->UsbHc - ); - - // + Controller, + &gEfiUsbHcProtocolGuid, + &HcDev->UsbHc + ); + + gBS->UninstallProtocolInterface ( + Controller, + &gEfiUsb2HcProtocolGuid, + &HcDev->Usb2Hc + ); + // // first stop USB Host Controller // This->SetState (This, EfiUsbHcStateHalt); @@ -659,12 +863,31 @@ UHCIDriverBindingStop ( --*/ { EFI_USB_HC_PROTOCOL *UsbHc; + EFI_USB2_HC_PROTOCOL *Usb2Hc; EFI_STATUS OpenStatus; OpenStatus = gBS->OpenProtocol ( Controller, &gEfiUsbHcProtocolGuid, - (VOID **) &UsbHc, + (VOID **)&UsbHc, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + // + // Test whether the Controller handler passed in is a valid + // Usb controller handle that should be supported, if not, + // return the error status directly + // + if (EFI_ERROR (OpenStatus)) { + return OpenStatus; + } + + OpenStatus = gBS->OpenProtocol ( + Controller, + &gEfiUsb2HcProtocolGuid, + (VOID **) &Usb2Hc, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL @@ -684,11 +907,11 @@ UHCIDriverBindingStop ( UnInstallUHCInterface (Controller, UsbHc); gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); return EFI_SUCCESS; @@ -753,20 +976,20 @@ UHCIReset ( // set the Global Reset bit in the command register // Status = ReadUHCCommandReg ( - HcDev->PciIo, - CommandRegAddr, - &Command - ); + HcDev->PciIo, + CommandRegAddr, + &Command + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } Command |= USBCMD_GRESET; Status = WriteUHCCommandReg ( - HcDev->PciIo, - CommandRegAddr, - Command - ); + HcDev->PciIo, + CommandRegAddr, + Command + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -782,10 +1005,10 @@ UHCIReset ( // Command &= ~USBCMD_GRESET; Status = WriteUHCCommandReg ( - HcDev->PciIo, - CommandRegAddr, - Command - ); + HcDev->PciIo, + CommandRegAddr, + Command + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -801,20 +1024,20 @@ UHCIReset ( // set Host Controller Reset bit to 1 // Status = ReadUHCCommandReg ( - HcDev->PciIo, - CommandRegAddr, - &Command - ); + HcDev->PciIo, + CommandRegAddr, + &Command + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } Command |= USBCMD_HCRESET; Status = WriteUHCCommandReg ( - HcDev->PciIo, - CommandRegAddr, - Command - ); + HcDev->PciIo, + CommandRegAddr, + Command + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -905,20 +1128,20 @@ UHCIGetState ( StatusRegAddr = (UINT32) (USBSTS); Status = ReadUHCCommandReg ( - HcDev->PciIo, - CommandRegAddr, - &UhcCommand - ); + HcDev->PciIo, + CommandRegAddr, + &UhcCommand + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } Status = ReadUHCCommandReg ( - HcDev->PciIo, - StatusRegAddr, - &UhcStatus - ); + HcDev->PciIo, + StatusRegAddr, + &UhcStatus + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -990,10 +1213,10 @@ UHCISetState ( } Status = ReadUHCCommandReg ( - HcDev->PciIo, - CommandRegAddr, - &Command - ); + HcDev->PciIo, + CommandRegAddr, + &Command + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -1001,10 +1224,10 @@ UHCISetState ( Command &= ~USBCMD_RS; Status = WriteUHCCommandReg ( - HcDev->PciIo, - CommandRegAddr, - Command - ); + HcDev->PciIo, + CommandRegAddr, + Command + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -1033,20 +1256,20 @@ UHCISetState ( // Set Run/Stop bit to 1. // Status = ReadUHCCommandReg ( - HcDev->PciIo, - CommandRegAddr, - &Command - ); + HcDev->PciIo, + CommandRegAddr, + &Command + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } Command |= USBCMD_RS | USBCMD_MAXP; Status = WriteUHCCommandReg ( - HcDev->PciIo, - CommandRegAddr, - Command - ); + HcDev->PciIo, + CommandRegAddr, + Command + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -1055,10 +1278,10 @@ UHCISetState ( case EfiUsbHcStateSuspend: Status = ReadUHCCommandReg ( - HcDev->PciIo, - CommandRegAddr, - &Command - ); + HcDev->PciIo, + CommandRegAddr, + &Command + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -1115,20 +1338,20 @@ UHCISetState ( // Set Enter Global Suspend Mode bit to 1. // Status = ReadUHCCommandReg ( - HcDev->PciIo, - CommandRegAddr, - &Command - ); + HcDev->PciIo, + CommandRegAddr, + &Command + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } Command |= USBCMD_EGSM; Status = WriteUHCCommandReg ( - HcDev->PciIo, - CommandRegAddr, - Command - ); + HcDev->PciIo, + CommandRegAddr, + Command + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -1185,10 +1408,10 @@ UHCIGetRootHubPortNumber ( for (Index = 0; Index < 2; Index++) { PSAddr = (UINT32) (USBPORTSC1 + Index * 2); Status = ReadRootPortReg ( - HcDev->PciIo, - PSAddr, - &RHPortControl - ); + HcDev->PciIo, + PSAddr, + &RHPortControl + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -1261,10 +1484,10 @@ UHCIGetRootHubPortStatus ( PortStatus->PortChangeStatus = 0; Status = ReadRootPortReg ( - HcDev->PciIo, - PSAddr, - &RHPortStatus - ); + HcDev->PciIo, + PSAddr, + &RHPortStatus + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; @@ -1307,6 +1530,10 @@ UHCIGetRootHubPortStatus ( PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED; } // + // CHC will always return one in this bit + // + PortStatus->PortStatus |= USB_PORT_STAT_OWNER; + // // Fill Port Status Change bits // @@ -1393,10 +1620,10 @@ UHCISetRootHubPortFeature ( case EfiUsbPortSuspend: Status = ReadUHCCommandReg ( - HcDev->PciIo, - CommandRegAddr, - &Command - ); + HcDev->PciIo, + CommandRegAddr, + &Command + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -1487,10 +1714,10 @@ UHCIClearRootHubPortFeature ( PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2); Status = ReadRootPortReg ( - HcDev->PciIo, - PSAddr, - &RHPortControl - ); + HcDev->PciIo, + PSAddr, + &RHPortControl + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -1733,13 +1960,13 @@ UHCIControlTransfer ( // BusMasterWrite means cpu read // Status = HcDev->PciIo->Map ( - HcDev->PciIo, - EfiPciIoOperationBusMasterWrite, - PtrDataSource, - &DataLen, - &TempPtr, - &Mapping - ); + HcDev->PciIo, + EfiPciIoOperationBusMasterWrite, + PtrDataSource, + &DataLen, + &TempPtr, + &Mapping + ); if (EFI_ERROR (Status)) { return Status; } @@ -1757,13 +1984,13 @@ UHCIControlTransfer ( // BusMasterRead means cpu write // Status = HcDev->PciIo->Map ( - HcDev->PciIo, - EfiPciIoOperationBusMasterRead, - PtrDataSource, - &DataLen, - &TempPtr, - &Mapping - ); + HcDev->PciIo, + EfiPciIoOperationBusMasterRead, + PtrDataSource, + &DataLen, + &TempPtr, + &Mapping + ); if (EFI_ERROR (Status)) { return Status; } @@ -1809,13 +2036,13 @@ UHCIControlTransfer ( // RequestLen = sizeof (EFI_USB_DEVICE_REQUEST); Status = HcDev->PciIo->Map ( - HcDev->PciIo, - EfiPciIoOperationBusMasterRead, - (UINT8 *) Request, - &RequestLen, - &TempPtr, - &RequestMapping - ); + HcDev->PciIo, + EfiPciIoOperationBusMasterRead, + (UINT8 *) Request, + &RequestLen, + &TempPtr, + &RequestMapping + ); if (EFI_ERROR (Status)) { HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); @@ -1829,14 +2056,14 @@ UHCIControlTransfer ( // generate Setup Stage TD // Status = GenSetupStageTD ( - HcDev, - DeviceAddress, - 0, - IsSlowDevice, - (UINT8 *) RequestMappedAddress, - sizeof (EFI_USB_DEVICE_REQUEST), - &PtrSetupTD - ); + HcDev, + DeviceAddress, + 0, + IsSlowDevice, + (UINT8 *) RequestMappedAddress, + sizeof (EFI_USB_DEVICE_REQUEST), + &PtrSetupTD + ); if (EFI_ERROR (Status)) { HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); @@ -1864,16 +2091,16 @@ UHCIControlTransfer ( } Status = GenDataTD ( - HcDev, - DeviceAddress, - 0, - Ptr, - PktSize, - PktID, - DataToggle, - IsSlowDevice, - &PtrTD - ); + HcDev, + DeviceAddress, + 0, + Ptr, + PktSize, + PktID, + DataToggle, + IsSlowDevice, + &PtrTD + ); if (EFI_ERROR (Status)) { // @@ -1920,13 +2147,13 @@ UHCIControlTransfer ( // create Status Stage TD structure // Status = CreateStatusTD ( - HcDev, - DeviceAddress, - 0, - PktID, - IsSlowDevice, - &PtrStatusTD - ); + HcDev, + DeviceAddress, + 0, + PktID, + IsSlowDevice, + &PtrStatusTD + ); if (EFI_ERROR (Status)) { HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); @@ -2009,13 +2236,13 @@ UHCIControlTransfer ( } Status = ExecuteControlTransfer ( - HcDev, - PtrFirstDataTD, - LoadFrameListIndex, - DataLength, - TimeOut, - TransferResult - ); + HcDev, + PtrFirstDataTD, + LoadFrameListIndex, + DataLength, + TimeOut, + TransferResult + ); for (Index = 0; Index < 500; Index++) { DelLinkSingleQH ( @@ -2060,13 +2287,13 @@ UHCIControlTransfer ( // detail status is returned // Status = ExecuteControlTransfer ( - HcDev, - PtrStatusTD, - LoadFrameListIndex, - DataLength, - TimeOut, - TransferResult - ); + HcDev, + PtrStatusTD, + LoadFrameListIndex, + DataLength, + TimeOut, + TransferResult + ); // // Delete Control Transfer QH-TDs structure @@ -2123,13 +2350,13 @@ UHCIControlTransfer ( // detail status is returned // Status = ExecuteControlTransfer ( - HcDev, - PtrSetupTD, - LoadFrameListIndex, - DataLength, - TimeOut, - TransferResult - ); + HcDev, + PtrSetupTD, + LoadFrameListIndex, + DataLength, + TimeOut, + TransferResult + ); // // Remove Control Transfer QH-TDs structure from the frame list // and update the pointers in the Frame List @@ -2354,13 +2581,13 @@ UHCIBulkTransfer ( // BusMasterWrite means cpu read // Status = HcDev->PciIo->Map ( - HcDev->PciIo, - EfiPciIoOperationBusMasterWrite, - PtrDataSource, - &DataLen, - &TempPtr, - &Mapping - ); + HcDev->PciIo, + EfiPciIoOperationBusMasterWrite, + PtrDataSource, + &DataLen, + &TempPtr, + &Mapping + ); if (EFI_ERROR (Status)) { return Status; } @@ -2377,13 +2604,13 @@ UHCIBulkTransfer ( // BusMasterRead means cpu write // Status = HcDev->PciIo->Map ( - HcDev->PciIo, - EfiPciIoOperationBusMasterRead, - PtrDataSource, - &DataLen, - &TempPtr, - &Mapping - ); + HcDev->PciIo, + EfiPciIoOperationBusMasterRead, + PtrDataSource, + &DataLen, + &TempPtr, + &Mapping + ); if (EFI_ERROR (Status)) { return Status; } @@ -2422,16 +2649,16 @@ UHCIBulkTransfer ( } Status = GenDataTD ( - HcDev, - DeviceAddress, - EndPointAddress, - Ptr, - PktSize, - PktID, - *DataToggle, - FALSE, - &PtrTD - ); + HcDev, + DeviceAddress, + EndPointAddress, + Ptr, + PktSize, + PktID, + *DataToggle, + FALSE, + &PtrTD + ); if (EFI_ERROR (Status)) { HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); @@ -2526,14 +2753,14 @@ UHCIBulkTransfer ( // of the last successful TD // Status = ExecBulkorSyncInterruptTransfer ( - HcDev, - PtrFirstTD, - LoadFrameListIndex, - DataLength, - DataToggle, - TimeOut, - TransferResult - ); + HcDev, + PtrFirstTD, + LoadFrameListIndex, + DataLength, + DataToggle, + TimeOut, + TransferResult + ); // // Delete Bulk transfer QH-TD structure @@ -2587,7 +2814,7 @@ UHCIAsyncInterruptTransfer ( IN UINT8 DeviceAddress, IN UINT8 EndPointAddress, IN BOOLEAN IsSlowDevice, - IN UINT8 MaxiumPacketLength, + IN UINT8 MaximumPacketLength, IN BOOLEAN IsNewTransfer, IN OUT UINT8 *DataToggle, IN UINTN PollingInterval, OPTIONAL @@ -2618,7 +2845,7 @@ UHCIAsyncInterruptTransfer ( IsSlowDevice Indicates whether the target device is slow device or full-speed device. - MaxiumPacketLength Indicates the maximum packet size the target endpoint + MaximumPacketLength Indicates the maximum packet size the target endpoint is capable of sending or receiving. IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between @@ -2715,11 +2942,11 @@ UHCIAsyncInterruptTransfer ( OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); Status = DeleteAsyncINTQHTDs ( - HcDev, - DeviceAddress, - EndPointAddress, - DataToggle - ); + HcDev, + DeviceAddress, + EndPointAddress, + DataToggle + ); gBS->RestoreTPL (OldTpl); @@ -2764,13 +2991,13 @@ UHCIAsyncInterruptTransfer ( // BusMasterWrite means cpu read // Status = HcDev->PciIo->Map ( - HcDev->PciIo, - EfiPciIoOperationBusMasterWrite, - Ptr, - &DataLen, - &TempPtr, - &Mapping - ); + HcDev->PciIo, + EfiPciIoOperationBusMasterWrite, + Ptr, + &DataLen, + &TempPtr, + &Mapping + ); if (EFI_ERROR (Status)) { gBS->FreePool (Ptr); return Status; @@ -2788,21 +3015,21 @@ UHCIAsyncInterruptTransfer ( // PktSize = (UINT8) DataLen; - if (DataLen > MaxiumPacketLength) { - PktSize = MaxiumPacketLength; + if (DataLen > MaximumPacketLength) { + PktSize = MaximumPacketLength; } Status = GenDataTD ( - HcDev, - DeviceAddress, - EndPointAddress, - MappedPtr, - PktSize, - PktID, - CurrentDataToggle, - IsSlowDevice, - &PtrTD - ); + HcDev, + DeviceAddress, + EndPointAddress, + MappedPtr, + PktSize, + PktID, + CurrentDataToggle, + IsSlowDevice, + &PtrTD + ); if (EFI_ERROR (Status)) { gBS->FreePool (Ptr); HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); @@ -3084,6 +3311,10 @@ UHCISyncInterruptTransfer ( return EFI_INVALID_PARAMETER; } + if (TransferResult == NULL) { + return EFI_INVALID_PARAMETER; + } + ClearStatusReg (HcDev->PciIo, StatusReg); // @@ -3357,6 +3588,830 @@ UHCIAsyncIsochronousTransfer ( return EFI_UNSUPPORTED; } +// +// UEFI 2.0 Protocol +// +EFI_STATUS +EFIAPI +UHCI2GetCapability( + IN EFI_USB2_HC_PROTOCOL * This, + OUT UINT8 *MaxSpeed, + OUT UINT8 *PortNumber, + OUT UINT8 *Is64BitCapable + ) +/*++ + + Routine Description: + Retrieves capabilities of USB host controller according to UEFI 2.0 spec. + + Arguments: + This - A pointer to the EFI_USB2_HC_PROTOCOL instance. + + MaxSpeed - A pointer to the max speed USB host controller supports. + + PortNumber - A pointer to the number of root hub ports. + + Is64BitCapable - A pointer to an integer to show whether USB host controller + supports 64-bit memory addressing. + Returns: + EFI_SUCCESS + The host controller capabilities were retrieved successfully. + EFI_INVALID_PARAMETER + MaxSpeed or PortNumber or Is64BitCapable is NULL. + EFI_DEVICE_ERROR + An error was encountered while attempting to retrieve the capabilities. + +--*/ +{ + USB_HC_DEV *HcDev; + + HcDev = USB2_HC_DEV_FROM_THIS (This); + + if ((NULL == MaxSpeed) + ||(NULL == PortNumber) + || (NULL == Is64BitCapable)) + { + return EFI_INVALID_PARAMETER; + } + + *MaxSpeed = EFI_USB_SPEED_FULL; + *Is64BitCapable = (UINT8)FALSE; + return UHCIGetRootHubPortNumber(&HcDev->UsbHc, PortNumber); +} + +EFI_STATUS +EFIAPI +UHCI2Reset ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT16 Attributes + ) +/*++ + + Routine Description: + Provides software reset for the USB host controller according to UEFI 2.0 spec. + + Arguments: + This - A pointer to the EFI_USB2_HC_PROTOCOL instance. + + Attributes - A bit mask of the reset operation to perform. + See below for a list of the supported bit mask values. + + #define EFI_USB_HC_RESET_GLOBAL 0x0001 + #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002 + #define EFI_USB_HC_RESET_GLOBAL _WITH_DEBUG 0x0004 + #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008 + + EFI_USB_HC_RESET_GLOBAL + If this bit is set, a global reset signal will be sent to the USB bus. + This resets all of the USB bus logic, including the USB host + controller hardware and all the devices attached on the USB bus. + EFI_USB_HC_RESET_HOST_CONTROLLER + If this bit is set, the USB host controller hardware will be reset. + No reset signal will be sent to the USB bus. + + Returns: + EFI_SUCCESS + The reset operation succeeded. + EFI_INVALID_PARAMETER + Attributes is not valid. + EFI_UNSUPPORTED + The type of reset specified by Attributes is not currently supported by the host controller hardware. + EFI_ACCESS_DENIED + Reset operation is rejected due to the debug port being configured and active. + EFI_DEVICE_ERROR + An error was encountered while attempting to perform + the reset operation. +--*/ +{ + USB_HC_DEV *HcDev; + + HcDev = USB2_HC_DEV_FROM_THIS (This); + + if (Attributes==EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG || Attributes==EFI_USB_HC_RESET_HOST_WITH_DEBUG) + return EFI_UNSUPPORTED; + + return UHCIReset( + &HcDev->UsbHc, + Attributes + ); +} + +EFI_STATUS +EFIAPI +UHCI2GetState ( + IN EFI_USB2_HC_PROTOCOL * This, + OUT EFI_USB_HC_STATE * State + ) +/*++ + + Routine Description: + Retrieves current state of the USB host controller according to UEFI 2.0 spec. + + Arguments: + + This - A pointer to the EFI_USB_HC_PROTOCOL instance. + + State - A pointer to the EFI_USB_HC_STATE data structure that + indicates current state of the USB host controller. + Type EFI_USB_HC_STATE is defined below. + + typedef enum { + EfiUsbHcStateHalt, + EfiUsbHcStateOperational, + EfiUsbHcStateSuspend, + EfiUsbHcStateMaximum + } EFI_USB_HC_STATE; + + Returns: + EFI_SUCCESS + The state information of the host controller was returned in State. + EFI_INVALID_PARAMETER + State is NULL. + EFI_DEVICE_ERROR + An error was encountered while attempting to retrieve the + host controller's current state. +--*/ +{ + USB_HC_DEV *HcDev; + + HcDev = USB2_HC_DEV_FROM_THIS (This); + return UHCIGetState( + &HcDev->UsbHc, + State + ); +} + +EFI_STATUS +EFIAPI +UHCI2SetState ( + IN EFI_USB2_HC_PROTOCOL * This, + IN EFI_USB_HC_STATE State + ) +/*++ + + Routine Description: + Sets the USB host controller to a specific state according to UEFI 2.0 spec. + + Arguments: + + This - A pointer to the EFI_USB_HC_PROTOCOL instance. + + State - Indicates the state of the host controller that will be set. + + Returns: + EFI_SUCCESS + The USB host controller was successfully placed in the state + specified by State. + EFI_INVALID_PARAMETER + State is invalid. + EFI_DEVICE_ERROR + Failed to set the state specified by State due to device error. +--*/ +{ + USB_HC_DEV *HcDev; + + HcDev = USB2_HC_DEV_FROM_THIS (This); + return UHCISetState( + &HcDev->UsbHc, + State + ); +} + +EFI_STATUS +EFIAPI +UHCI2ControlTransfer ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN EFI_USB_DEVICE_REQUEST * Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + Submits control transfer to a target USB device accroding to UEFI 2.0 spec.. + + Arguments: + + This - A pointer to the EFI_USB_HC_PROTOCOL instance. + + DeviceAddress -Represents the address of the target device on the USB, + which is assigned during USB enumeration. + + DeviceSpeed - Indicates transfer speed of device. + + MaximumPacketLength - Indicates the maximum packet size that the + default control transfer endpoint is capable of + sending or receiving. + + Request - A pointer to the USB device request that will be sent + to the USB device. + + TransferDirection - Specifies the data direction for the transfer. + There are three values available, DataIn, DataOut + and NoData. + + Data -A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + + DataLength - Indicates the size, in bytes, of the data buffer + specified by Data. + + TimeOut - Indicates the maximum time, in microseconds, + which the transfer is allowed to complete. + + TransferResult - A pointer to the detailed result information generated + by this control transfer. + + Returns: + EFI_SUCCESS + The control transfer was completed successfully. + EFI_OUT_OF_RESOURCES + The control transfer could not be completed due to a lack of resources. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_TIMEOUT + The control transfer failed due to timeout. + EFI_DEVICE_ERROR + The control transfer failed due to host controller or device error. + Caller should check TranferResult for detailed error information. + +--*/ +{ + USB_HC_DEV *HcDev; + BOOLEAN IsSlowDevice = (EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE; + + HcDev = USB2_HC_DEV_FROM_THIS (This); + + return UHCIControlTransfer( + &HcDev->UsbHc, + DeviceAddress, + IsSlowDevice, + (UINT8) MaximumPacketLength, + Request, + TransferDirection, + Data, + DataLength, + TimeOut, + TransferResult + ); +} + +EFI_STATUS +EFIAPI +UHCI2BulkTransfer ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + Submits bulk transfer to a bulk endpoint of a USB device according to UEFI 2.0 spec. + + Arguments: + + This A pointer to the EFI_USB2_HC_PROTOCOL instance. + + DeviceAddress Represents the address of the target device on the USB, + which is assigned during USB enumeration. + + EndPointAddress The combination of an endpoint number and an + endpoint direction of the target USB device. + Each endpoint address supports data transfer in + one direction except the control endpoint + (whose default endpoint address is 0). + It is the caller's responsibility to make sure that + the EndPointAddress represents a bulk endpoint. + + DeviceSpeed Indicates device speed. The supported values are EFI_USB_SPEED_FULL + and EFI_USB_SPEED_HIGH. + + MaximumPacketLength Indicates the maximum packet size the target endpoint + is capable of sending or receiving. + + DataBuffersNumber Number of data buffers prepared for the transfer. + + Data Array of pointers to the buffers of data that will be transmitted + to USB device or received from USB device. + + DataLength When input, indicates the size, in bytes, of the data buffer + specified by Data. When output, indicates the actually + transferred data size. + + DataToggle A pointer to the data toggle value. On input, it indicates + the initial data toggle value the bulk transfer should adopt; + on output, it is updated to indicate the data toggle value + of the subsequent bulk transfer. + + Translator A pointr to the transaction translator data. + + TimeOut Indicates the maximum time, in microseconds, which the + transfer is allowed to complete. + + TransferResult A pointer to the detailed result information of the + bulk transfer. + + Returns: + EFI_SUCCESS + The bulk transfer was completed successfully. + + EFI_OUT_OF_RESOURCES + The bulk transfer could not be submitted due to lack of resource. + + EFI_INVALID_PARAMETER + Some parameters are invalid. + + EFI_TIMEOUT + The bulk transfer failed due to timeout. + + EFI_DEVICE_ERROR + The bulk transfer failed due to host controller or device error. + Caller should check TranferResult for detailed error information. + +--*/ +{ + USB_HC_DEV *HcDev; + + HcDev = USB2_HC_DEV_FROM_THIS (This); + + if( Data == NULL || DeviceSpeed==EFI_USB_SPEED_LOW) + return EFI_INVALID_PARAMETER; + /* For full-speed bulk transfers only the data pointed by Data[0] shall be used */ + + return UHCIBulkTransfer ( + &HcDev->UsbHc, + DeviceAddress, + EndPointAddress, + (UINT8) MaximumPacketLength, + *Data, + DataLength, + DataToggle, + TimeOut, + TransferResult + ); +} + +EFI_STATUS +EFIAPI +UHCI2AsyncInterruptTransfer ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle, + IN UINTN PollingInterval, + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, + IN VOID *Context + ) +/*++ + + Routine Description: + Submits an asynchronous interrupt transfer to an + interrupt endpoint of a USB device according to UEFI 2.0 spec. + + Arguments: + + This A pointer to the EFI_USB2_HC_PROTOCOL instance. + + DeviceAddress Represents the address of the target device on the USB, + which is assigned during USB enumeration. + + EndPointAddress The combination of an endpoint number and an endpoint + direction of the target USB device. Each endpoint address + supports data transfer in one direction except the + control endpoint (whose default endpoint address is 0). + It is the caller's responsibility to make sure that + the EndPointAddress represents an interrupt endpoint. + + DeviceSpeed Indicates device speed. + + MaximumPacketLength Indicates the maximum packet size the target endpoint + is capable of sending or receiving. + + IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between + the host and the target interrupt endpoint. + If FALSE, the specified asynchronous interrupt pipe + is canceled. + + DataToggle A pointer to the data toggle value. On input, it is valid + when IsNewTransfer is TRUE, and it indicates the initial + data toggle value the asynchronous interrupt transfer + should adopt. + On output, it is valid when IsNewTransfer is FALSE, + and it is updated to indicate the data toggle value of + the subsequent asynchronous interrupt transfer. + + PollingInterval Indicates the interval, in milliseconds, that the + asynchronous interrupt transfer is polled. + This parameter is required when IsNewTransfer is TRUE. + + DataLength Indicates the length of data to be received at the + rate specified by PollingInterval from the target + asynchronous interrupt endpoint. This parameter + is only required when IsNewTransfer is TRUE. + + Translator A pointr to the transaction translator data. + + CallBackFunction The Callback function.This function is called at the + rate specified by PollingInterval.This parameter is + only required when IsNewTransfer is TRUE. + + Context The context that is passed to the CallBackFunction. + This is an optional parameter and may be NULL. + + Returns: + + EFI_SUCCESS + The asynchronous interrupt transfer request has been successfully + submitted or canceled. + + EFI_INVALID_PARAMETER + Some parameters are invalid. + + EFI_OUT_OF_RESOURCES + The request could not be completed due to a lack of resources. + + EFI_DEVICE_ERROR + Can't read register +--*/ +{ + USB_HC_DEV *HcDev; + BOOLEAN IsSlowDevice = (EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE; + + HcDev = USB2_HC_DEV_FROM_THIS (This); + return UHCIAsyncInterruptTransfer( + &HcDev->UsbHc, + DeviceAddress, + EndPointAddress, + IsSlowDevice, + (UINT8) MaximumPacketLength, + IsNewTransfer, + DataToggle, + PollingInterval, + DataLength, + CallBackFunction, + Context + ); +} + +EFI_STATUS +EFIAPI +UHCI2SyncInterruptTransfer ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + Submits synchronous interrupt transfer to an interrupt endpoint + of a USB device according to UEFI 2.0 spec. + + Arguments: + + This A pointer to the EFI_USB2_HC_PROTOCOL instance. + + DeviceAddress Represents the address of the target device on the USB, + which is assigned during USB enumeration. + + EndPointAddress The combination of an endpoint number and an endpoint + direction of the target USB device. Each endpoint + address supports data transfer in one direction + except the control endpoint (whose default + endpoint address is 0). It is the caller's responsibility + to make sure that the EndPointAddress represents + an interrupt endpoint. + + DeviceSpeed Indicates device speed. + + MaximumPacketLength Indicates the maximum packet size the target endpoint + is capable of sending or receiving. + + Data A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + + DataLength On input, the size, in bytes, of the data buffer specified + by Data. On output, the number of bytes transferred. + + DataToggle A pointer to the data toggle value. On input, it indicates + the initial data toggle value the synchronous interrupt + transfer should adopt; + on output, it is updated to indicate the data toggle value + of the subsequent synchronous interrupt transfer. + + TimeOut Indicates the maximum time, in microseconds, which the + transfer is allowed to complete. + Translator A pointr to the transaction translator data. + TransferResult A pointer to the detailed result information from + the synchronous interrupt transfer. + + Returns: + EFI_SUCCESS + The synchronous interrupt transfer was completed successfully. + EFI_OUT_OF_RESOURCES + The synchronous interrupt transfer could not be submitted due + to lack of resource. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_TIMEOUT + The synchronous interrupt transfer failed due to timeout. + EFI_DEVICE_ERROR + The synchronous interrupt transfer failed due to host controller + or device error. Caller should check TranferResult for detailed + error information. +--*/ +{ + USB_HC_DEV *HcDev; + BOOLEAN IsSlowDevice; + + if(DeviceSpeed==EFI_USB_SPEED_HIGH) + return EFI_INVALID_PARAMETER; + + IsSlowDevice = (EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE; + HcDev = USB2_HC_DEV_FROM_THIS (This); + + return UHCISyncInterruptTransfer( + &HcDev->UsbHc, + DeviceAddress, + EndPointAddress, + IsSlowDevice, + (UINT8) MaximumPacketLength, + Data, + DataLength, + DataToggle, + TimeOut, + TransferResult + ); +} + +EFI_STATUS +EFIAPI +UHCI2IsochronousTransfer ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + + Submits isochronous transfer to a target USB device according to UEFI 2.0 spec. + + Arguments: + + This A pointer to the EFI_USB2_HC_PROTOCOL instance. + + DeviceAddress Represents the address of the target device on the USB, + which is assigned during USB enumeration. + + EndPointAddress End point address + + DeviceSpeed Indicates device speed. + + MaximumPacketLength Indicates the maximum packet size that the + default control transfer endpoint is capable of + sending or receiving. + + DataBuffersNumber Number of data buffers prepared for the transfer. + + Data Array of pointers to the buffers of data that will be + transmitted to USB device or received from USB device. + + DataLength Indicates the size, in bytes, of the data buffer + specified by Data. + + Translator A pointr to the transaction translator data. + + TransferResult A pointer to the detailed result information generated + by this control transfer. + Returns: + + EFI_UNSUPPORTED + +--*/ +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +UHCI2AsyncIsochronousTransfer ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context + ) +/*++ + + Routine Description: + + Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec. + + Arguments: + + This A pointer to the EFI_USB2_HC_PROTOCOL instance. + + DeviceAddress Represents the address of the target device on the USB, + which is assigned during USB enumeration. + + EndPointAddress End point address + + DeviceSpeed Indicates device speed. + + MaximumPacketLength Indicates the maximum packet size that the + default control transfer endpoint is capable of + sending or receiving. + + DataBuffersNumber Number of data buffers prepared for the transfer. + + Data Array of pointers to the buffers of data that will be transmitted + to USB device or received from USB device. + + Translator A pointr to the transaction translator data. + + IsochronousCallBack When the transfer complete, the call back function will be called + + Context Pass to the call back function as parameter + + Returns: + + EFI_UNSUPPORTED + +--*/ +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +UHCI2GetRootHubPortStatus ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS * PortStatus + ) +/*++ + + Routine Description: + Retrieves the current status of a USB root hub port according to UEFI 2.0 spec. + + Arguments: + + This A pointer to the EFI_USB2_HC_PROTOCOL. + + PortNumber Specifies the root hub port from which the status + is to be retrieved. This value is zero-based. For example, + if a root hub has two ports, then the first port is numbered 0, + and the second port is numbered 1. + + PortStatus A pointer to the current port status bits and + port status change bits. + + Returns: + EFI_SUCCESS + The status of the USB root hub port specified by PortNumber + was returned in PortStatus. + EFI_INVALID_PARAMETER + PortNumber is invalid. + EFI_DEVICE_ERROR - Can't read register +--*/ +{ + USB_HC_DEV *HcDev; + + HcDev = USB2_HC_DEV_FROM_THIS (This); + + return UHCIGetRootHubPortStatus( + &HcDev->UsbHc, + PortNumber, + PortStatus + ); +} + +EFI_STATUS +EFIAPI +UHCI2SetRootHubPortFeature ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +/*++ + + Routine Description: + Sets a feature for the specified root hub port according to UEFI 2.0 spec. + + Arguments: + + This A pointer to the EFI_USB2_HC_PROTOCOL. + + PortNumber Specifies the root hub port whose feature + is requested to be set. + + PortFeature Indicates the feature selector associated + with the feature set request. + + Returns: + EFI_SUCCESS + The feature specified by PortFeature was set for the + USB root hub port specified by PortNumber. + EFI_INVALID_PARAMETER + PortNumber is invalid or PortFeature is invalid. + EFI_DEVICE_ERROR + Can't read register +--*/ +{ + USB_HC_DEV *HcDev; + + HcDev = USB2_HC_DEV_FROM_THIS (This); + return UHCISetRootHubPortFeature( + &HcDev->UsbHc, + PortNumber, + PortFeature + ); +} + +EFI_STATUS +EFIAPI +UHCI2ClearRootHubPortFeature ( + IN EFI_USB2_HC_PROTOCOL * This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +/*++ + + Routine Description: + Clears a feature for the specified root hub port according to Uefi 2.0 spec. + + Arguments: + + This A pointer to the EFI_USB2_HC_PROTOCOL instance. + + PortNumber Specifies the root hub port whose feature + is requested to be cleared. + + PortFeature Indicates the feature selector associated with the + feature clear request. + + Returns: + EFI_SUCCESS + The feature specified by PortFeature was cleared for the + USB root hub port specified by PortNumber. + EFI_INVALID_PARAMETER + PortNumber is invalid or PortFeature is invalid. + EFI_DEVICE_ERROR + Can't read register +--*/ +{ + USB_HC_DEV *HcDev; + + HcDev = USB2_HC_DEV_FROM_THIS (This); + return UHCIClearRootHubPortFeature( + &HcDev->UsbHc, + PortNumber, + PortFeature + ); +} + VOID EFIAPI MonitorInterruptTrans ( diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h index d6f841bf40..c5ae155f90 100644 --- a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h +++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h @@ -28,7 +28,7 @@ Revision History #include -#define EFI_D_UHCI EFI_D_INFO +#define EFI_D_UHCI EFI_D_INFO // // stall time @@ -45,21 +45,20 @@ Revision History // // 50 ms // -#define INTERRUPT_POLLING_TIME 50 * 1000 * 10 +#define INTERRUPT_POLLING_TIME 50 * 1000 * 10 // // UHCI IO Space Address Register Register locates at // offset 20 ~ 23h of PCI Configuration Space (UHCI spec, Revision 1.1), // so, its BAR Index is 4. // -#define USB_BAR_INDEX 4 +#define USB_BAR_INDEX 4 // // One memory block uses 1 page (common buffer for QH,TD use.) // #define NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES 1 - #define bit(a) 1 << (a) // @@ -82,13 +81,13 @@ extern UINT16 USBBaseAddr; #define USBCMD_MAXP bit (7) /* Max Packet (0 = 32, 1 = 64) */ /* Status register */ -#define USBSTS 2 /* Status Register Offset 02-03h */ -#define USBSTS_USBINT bit (0) /* Interrupt due to IOC */ -#define USBSTS_ERROR bit (1) /* Interrupt due to error */ -#define USBSTS_RD bit (2) /* Resume Detect */ -#define USBSTS_HSE bit (3) /* Host System Error*/ -#define USBSTS_HCPE bit (4) /* Host Controller Process Error*/ -#define USBSTS_HCH bit (5) /* HC Halted */ +#define USBSTS 2 /* Status Register Offset 02-03h */ +#define USBSTS_USBINT bit (0) /* Interrupt due to IOC */ +#define USBSTS_ERROR bit (1) /* Interrupt due to error */ +#define USBSTS_RD bit (2) /* Resume Detect */ +#define USBSTS_HSE bit (3) /* Host System Error*/ +#define USBSTS_HCPE bit (4) /* Host Controller Process Error*/ +#define USBSTS_HCH bit (5) /* HC Halted */ /* Interrupt enable register */ #define USBINTR 4 /* Interrupt Enable Register 04-05h */ @@ -98,13 +97,13 @@ extern UINT16 USBBaseAddr; #define USBINTR_SP bit (3) /* Short packet interrupt enable */ /* Frame Number Register Offset 06-08h */ -#define USBFRNUM 6 +#define USBFRNUM 6 /* Frame List Base Address Register Offset 08-0Bh */ -#define USBFLBASEADD 8 +#define USBFLBASEADD 8 /* Start of Frame Modify Register Offset 0Ch */ -#define USBSOF 0x0c +#define USBSOF 0x0c /* USB port status and control registers */ #define USBPORTSC1 0x10 /*Port 1 offset 10-11h */ @@ -126,16 +125,16 @@ extern UINT16 USBBaseAddr; // // Class Code Register offset // -#define CLASSC 0x09 +#define CLASSC 0x09 // // USB IO Space Base Address Register offset // -#define USBBASE 0x20 +#define USBBASE 0x20 // // USB legacy Support // -#define USB_EMULATION 0xc0 +#define USB_EMULATION 0xc0 // // USB Base Class Code,Sub-Class Code and Programming Interface. @@ -224,6 +223,7 @@ typedef struct { // ////////////////////////////////////////////////////////////////////////// #define USB_HC_DEV_FROM_THIS(a) CR (a, USB_HC_DEV, UsbHc, USB_HC_DEV_SIGNATURE) +#define USB2_HC_DEV_FROM_THIS(a) CR (a, USB_HC_DEV, Usb2Hc, USB_HC_DEV_SIGNATURE) #define USB_HC_DEV_SIGNATURE EFI_SIGNATURE_32 ('u', 'h', 'c', 'i') #define INTERRUPT_LIST_SIGNATURE EFI_SIGNATURE_32 ('i', 'n', 't', 's') @@ -267,6 +267,7 @@ typedef struct _MEMORY_MANAGE_HEADER { typedef struct { UINTN Signature; EFI_USB_HC_PROTOCOL UsbHc; + EFI_USB2_HC_PROTOCOL Usb2Hc; EFI_PCI_IO_PROTOCOL *PciIo; // @@ -289,196 +290,683 @@ WriteUHCCommandReg ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT32 CmdAddrOffset, IN UINT16 UsbCmd - ); + ) +/*++ + +Routine Description: + + Write UHCI Command Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + CmdAddrOffset - Command address offset + UsbCmd - Data to write + +Returns: + + EFI_SUCCESS + +--*/ +; EFI_STATUS ReadUHCCommandReg ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT32 CmdAddrOffset, IN OUT UINT16 *Data - ); + ) +/*++ + +Routine Description: + + Read UHCI Command Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + CmdAddrOffset - Command address offset + Data - Data to return + +Returns: + + EFI_SUCCESS + +--*/ +; EFI_STATUS WriteUHCStatusReg ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT32 StatusAddrOffset, IN UINT16 UsbSts - ); + ) +/*++ + +Routine Description: + + Write UHCI Staus Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + StatusAddrOffset - Status address offset + UsbSts - Data to write + +Returns: + + EFI_SUCCESS + +--*/ +; EFI_STATUS ReadUHCStatusReg ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT32 StatusAddrOffset, IN OUT UINT16 *Data - ); + ) +/*++ + +Routine Description: + + Read UHCI Staus Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + StatusAddrOffset - Status address offset + UsbSts - Data to return + +Returns: + + EFI_SUCCESS + +--*/ +; EFI_STATUS ClearStatusReg ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT32 StatusAddrOffset - ); + ) +/*++ + +Routine Description: + + Clear the content of UHC's Status Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + StatusAddrOffset - Status address offset + +Returns: + + EFI_SUCCESS + +--*/ +; EFI_STATUS ReadUHCFrameNumberReg ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT32 FrameNumAddrOffset, IN OUT UINT16 *Data - ); + ) +/*++ + +Routine Description: + + Read from UHC's Frame Number Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + FrameNumAddrOffset - Frame number register offset + Data - Data to return +Returns: + + EFI_SUCCESS + +--*/ +; EFI_STATUS WriteUHCFrameListBaseReg ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT32 FlBaseAddrOffset, IN UINT32 UsbFrameListBaseAddr - ); + ) +/*++ + +Routine Description: + + Write to UHC's Frame List Base Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + FlBaseAddrOffset - Frame Base address register + UsbFrameListBaseAddr - Address to write + +Returns: + + EFI_SUCCESS + +--*/ +; EFI_STATUS ReadRootPortReg ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT32 PortAddrOffset, IN OUT UINT16 *Data - ); + ) +/*++ + +Routine Description: + + Read from UHC's Root Port Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + PortAddrOffset - Port Addrress Offset, + Data - Data to return +Returns: + + EFI_SUCCESS + +--*/ +; EFI_STATUS WriteRootPortReg ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT32 PortAddrOffset, IN UINT16 ControlBits - ); + ) +/*++ + +Routine Description: + + Write to UHC's Root Port Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + PortAddrOffset - Port Addrress Offset, + ControlBits - Data to write +Returns: + + EFI_SUCCESS + +--*/ +; EFI_STATUS WaitForUHCHalt ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT32 StatusRegAddr, IN UINTN Timeout - ); + ) +/*++ + +Routine Description: + + Wait until UHCI halt or timeout + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + StatusRegAddr - Status Register Address + Timeout - Time out value in us + +Returns: + + EFI_DEVICE_ERROR - Unable to read the status register + EFI_TIMEOUT - Time out + EFI_SUCCESS - Success + +--*/ +; BOOLEAN IsStatusOK ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT32 StatusRegAddr - ); + ) +/*++ + +Routine Description: + + Judge whether the host controller operates well + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + StatusRegAddr - Status register address + +Returns: + + TRUE - Status is good + FALSE - Status is bad + +--*/ +; BOOLEAN IsHostSysOrProcessErr ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT32 StatusRegAddr - ); + ) +/*++ -// -// This routine programs the USB frame number register. We assume that the -// HC schedule execution is stopped. -// -EFI_STATUS -SetFrameNumberReg ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT32 FRNUMAddr, - IN UINT16 Index - ); +Routine Description: + + Judge the status is HostSys,ProcessErr error or good + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + StatusRegAddr - Status register address + +Returns: + + TRUE - Status is good + FALSE - Status is bad + +--*/ +; UINT16 GetCurrentFrameNumber ( IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT32 FRNUMAddr - ); + IN UINT32 FrameNumAddrOffset + ) +/*++ + +Routine Description: + + Get Current Frame Number + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + FrameNumAddrOffset - FrameNum register AddrOffset + +Returns: + + Frame number + +--*/ +; EFI_STATUS SetFrameListBaseAddress ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT32 FLBASEADDRReg, IN UINT32 Addr - ); + ) +/*++ + +Routine Description: + + Set FrameListBase Address + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + FlBaseAddrReg - FrameListBase register + Addr - Address to set + +Returns: + + EFI_SUCCESS + +--*/ +; UINT32 GetFrameListBaseAddress ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT32 FLBAddr - ); + ) +/*++ + +Routine Description: + + Get Current Frame Number + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + FrameNumAddrOffset - FrameNum register AddrOffset + +Returns: + + Frame number + +--*/ +; EFI_STATUS CreateFrameList ( IN USB_HC_DEV *HcDev, IN UINT32 FLBASEADDRReg - ); + ) +/*++ + +Routine Description: + + CreateFrameList + +Arguments: + + HcDev - USB_HC_DEV + FlBaseAddrReg - Frame List register + +Returns: + + EFI_OUT_OF_RESOURCES - Can't allocate memory resources + EFI_UNSUPPORTED - Map memory fail + EFI_SUCCESS - Success + +--*/ +; EFI_STATUS FreeFrameListEntry ( IN USB_HC_DEV *UhcDev - ); + ) +/*++ + +Routine Description: + + Free FrameList buffer + +Arguments: + + HcDev - USB_HC_DEV + +Returns: + + EFI_SUCCESS - success + +--*/ +; VOID InitFrameList ( IN USB_HC_DEV *HcDev - ); + ) +/*++ +Routine Description: + + Initialize FrameList + +Arguments: + + HcDev - USB_HC_DEV + +Returns: + VOID + +--*/ +; EFI_STATUS CreateQH ( IN USB_HC_DEV *HcDev, OUT QH_STRUCT **pptrQH - ); + ) +/*++ + +Routine Description: + + CreateQH + +Arguments: + + HcDev - USB_HC_DEV + pptrQH - QH_STRUCT content to return +Returns: + + EFI_SUCCESS - Success + EFI_OUT_OF_RESOURCES - Can't allocate memory + +--*/ +; VOID SetQHHorizontalLinkPtr ( IN QH_STRUCT *ptrQH, IN VOID *ptrNext - ); + ) +/*++ -VOID * +Routine Description: + + Set QH Horizontal Link Pointer + +Arguments: + + PtrQH - QH_STRUCT + ptrNext - Data to write + +Returns: + + VOID + +--*/ +; + +VOID * GetQHHorizontalLinkPtr ( IN QH_STRUCT *ptrQH - ); + ) +/*++ + +Routine Description: + + Get QH Horizontal Link Pointer + +Arguments: + + PtrQH - QH_STRUCT + + +Returns: + + Data to return + +--*/ +; VOID SetQHHorizontalQHorTDSelect ( IN QH_STRUCT *ptrQH, IN BOOLEAN bQH - ); + ) +/*++ + +Routine Description: + + Set QH Horizontal QH or TD + +Arguments: + + PtrQH - QH_STRUCT + bQH - TRUE is QH FALSE is TD + +Returns: + VOID + +--*/ +; VOID SetQHHorizontalValidorInvalid ( IN QH_STRUCT *ptrQH, IN BOOLEAN bValid - ); + ) +/*++ + +Routine Description: + + Set QH Horizontal Valid or Invalid + +Arguments: + + PtrQH - QH_STRUCT + bValid - TRUE is Valid FALSE is Invalid + +Returns: + VOID + +--*/ +; VOID SetQHVerticalLinkPtr ( IN QH_STRUCT *ptrQH, IN VOID *ptrNext - ); + ) +/*++ -VOID * +Routine Description: + + Set QH Vertical Link Pointer + +Arguments: + + PtrQH - QH_STRUCT + ptrNext - Data to write +Returns: + + VOID + +--*/ +; + +VOID * GetQHVerticalLinkPtr ( IN QH_STRUCT *ptrQH - ); + ) +/*++ + +Routine Description: + + Get QH Vertical Link Pointer + +Arguments: + + PtrQH - QH_STRUCT + +Returns: + + Data to return + +--*/ +; VOID SetQHVerticalQHorTDSelect ( IN QH_STRUCT *ptrQH, IN BOOLEAN bQH - ); + ) +/*++ + +Routine Description: + + Set QH Vertical QH or TD + +Arguments: + + PtrQH - QH_STRUCT + bQH - TRUE is QH FALSE is TD + +Returns: + + VOID + +--*/ +; BOOLEAN IsQHHorizontalQHSelect ( IN QH_STRUCT *ptrQH - ); + ) +/*++ + +Routine Description: + + Is QH Horizontal QH Select + +Arguments: + + PtrQH - QH_STRUCT + +Returns: + + TRUE - QH + FALSE - TD + +--*/ +; VOID SetQHVerticalValidorInvalid ( IN QH_STRUCT *ptrQH, IN BOOLEAN bValid - ); + ) +/*++ + +Routine Description: + + Set QH Vertical Valid or Invalid + +Arguments: + + PtrQH - QH_STRUCT + IsValid - TRUE is valid FALSE is invalid + +Returns: + + VOID + +--*/ +; BOOLEAN GetQHVerticalValidorInvalid ( IN QH_STRUCT *ptrQH - ); + ) +/*++ + +Routine Description: + + Get QH Vertical Valid or Invalid + +Arguments: + + PtrQH - QH_STRUCT + +Returns: + + TRUE - Valid + FALSE - Invalid + +--*/ +; EFI_STATUS AllocateTDStruct ( IN USB_HC_DEV *HcDev, OUT TD_STRUCT **ppTDStruct - ); + ) /*++ Routine Description: @@ -494,12 +982,13 @@ Returns: EFI_SUCCESS --*/ +; EFI_STATUS CreateTD ( IN USB_HC_DEV *HcDev, OUT TD_STRUCT **pptrTD - ); + ) /*++ Routine Description: @@ -517,6 +1006,7 @@ Returns: EFI_SUCCESS - Success --*/ +; EFI_STATUS @@ -528,7 +1018,7 @@ GenSetupStageTD ( IN UINT8 *pDevReq, IN UINT8 RequestLen, OUT TD_STRUCT **ppTD - ); + ) /*++ Routine Description: @@ -550,6 +1040,7 @@ Returns: EFI_SUCCESS - Success --*/ +; EFI_STATUS GenDataTD ( @@ -562,7 +1053,7 @@ GenDataTD ( IN UINT8 Toggle, IN BOOLEAN bSlow, OUT TD_STRUCT **ppTD - ); + ) /*++ Routine Description: @@ -586,6 +1077,7 @@ Returns: EFI_SUCCESS - Success --*/ +; EFI_STATUS CreateStatusTD ( @@ -595,7 +1087,7 @@ CreateStatusTD ( IN UINT8 PktID, IN BOOLEAN bSlow, OUT TD_STRUCT **ppTD - ); + ) /*++ Routine Description: @@ -617,237 +1109,918 @@ Returns: EFI_SUCCESS - Success --*/ +; VOID SetTDLinkPtrValidorInvalid ( IN TD_STRUCT *ptrTDStruct, IN BOOLEAN bValid - ); + ) +/*++ + +Routine Description: + + Set TD Link Pointer Valid or Invalid + +Arguments: + + ptrTDStruct - TD_STRUCT + bValid - TRUE is valid FALSE is invalid + +Returns: + + VOID + +--*/ +; VOID SetTDLinkPtrQHorTDSelect ( IN TD_STRUCT *ptrTDStruct, IN BOOLEAN bQH - ); + ) +/*++ + +Routine Description: + + Set TD Link Pointer QH or TD Select + +Arguments: + + ptrTDStruct - TD_STRUCT + bQH - TRUE is QH FALSE is TD + +Returns: + + VOID + +--*/ +; VOID SetTDLinkPtrDepthorBreadth ( IN TD_STRUCT *ptrTDStruct, IN BOOLEAN bDepth - ); + ) +/*++ + +Routine Description: + + Set TD Link Pointer depth or bread priority + +Arguments: + + ptrTDStruct - TD_STRUCT + bDepth - TRUE is Depth FALSE is Breadth + +Returns: + + VOID + +--*/ +; VOID SetTDLinkPtr ( IN TD_STRUCT *ptrTDStruct, IN VOID *ptrNext - ); + ) +/*++ -VOID * +Routine Description: + + Set TD Link Pointer + +Arguments: + + ptrTDStruct - TD_STRUCT + ptrNext - Pointer to set + +Returns: + + VOID + +--*/ +; + +VOID * GetTDLinkPtr ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Get TD Link Pointer + +Arguments: + + ptrTDStruct - TD_STRUCT + +Returns: + + Pointer to get + +--*/ +; VOID EnableorDisableTDShortPacket ( IN TD_STRUCT *ptrTDStruct, IN BOOLEAN bEnable - ); + ) +/*++ + +Routine Description: + + Enable or Disable TD ShortPacket + +Arguments: + + ptrTDStruct - TD_STRUCT + bEnable - TRUE is Enanble FALSE is Disable + +Returns: + + VOID + +--*/ +; VOID SetTDControlErrorCounter ( IN TD_STRUCT *ptrTDStruct, IN UINT8 nMaxErrors - ); + ) +/*++ + +Routine Description: + + Set TD Control ErrorCounter + +Arguments: + + ptrTDStruct - TD_STRUCT + nMaxErrors - Error counter number + +Returns: + + VOID + +--*/ +; VOID SetTDLoworFullSpeedDevice ( IN TD_STRUCT *ptrTDStruct, IN BOOLEAN bLowSpeedDevice - ); + ) +/*++ + +Routine Description: + + Set TD status low speed or full speed + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + bLowSpeedDevice - Show low speed or full speed + +Returns: + + VOID + +--*/ +; VOID SetTDControlIsochronousorNot ( IN TD_STRUCT *ptrTDStruct, IN BOOLEAN bIsochronous - ); + ) +/*++ + +Routine Description: + + Set TD status Isochronous or not + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + IsIsochronous - Show Isochronous or not + +Returns: + + VOID + +--*/ +; VOID SetorClearTDControlIOC ( IN TD_STRUCT *ptrTDStruct, IN BOOLEAN bSet - ); + ) +/*++ + +Routine Description: + + Set TD status IOC IsSet + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + IsSet - Show IOC set or not + +Returns: + + VOID + +--*/ +; VOID SetTDStatusActiveorInactive ( IN TD_STRUCT *ptrTDStruct, IN BOOLEAN bActive - ); + ) +/*++ + +Routine Description: + + Set TD status active or not +Arguments: + + ptrTDStruct - A point to TD_STRUCT + IsActive - Active or not + +Returns: + + VOID + +--*/ +; UINT16 SetTDTokenMaxLength ( IN TD_STRUCT *ptrTDStruct, IN UINT16 nMaxLen - ); + ) +/*++ + +Routine Description: + + Set TD Token maxlength + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + MaximumLength - Maximum length of TD Token + +Returns: + + Real maximum length set to TD Token + +--*/ +; VOID SetTDTokenDataToggle1 ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Set TD Token data toggle1 + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + VOID + +--*/ +; VOID SetTDTokenDataToggle0 ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Set TD Token data toggle0 + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + VOID + +--*/ +; UINT8 GetTDTokenDataToggle ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Get TD Token data toggle + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + data toggle value + +--*/ +; VOID SetTDTokenEndPoint ( IN TD_STRUCT *ptrTDStruct, IN UINTN nEndPoint - ); + ) +/*++ + +Routine Description: + + Set Data Token endpoint number + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + EndPoint - End point number + +Returns: + + VOID + +--*/ +; VOID SetTDTokenDeviceAddress ( IN TD_STRUCT *ptrTDStruct, IN UINTN nDevAddr - ); + ) +/*++ + +Routine Description: + + Set TD Token device address + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + DeviceAddress - Device address + +Returns: + + VOID + +--*/ +; VOID SetTDTokenPacketID ( IN TD_STRUCT *ptrTDStruct, IN UINT8 nPID - ); + ) +/*++ + +Routine Description: + + Set TD Token packet ID + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + PID - Packet ID + +Returns: + + VOID + +--*/ +; VOID SetTDDataBuffer ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Set TD data buffer + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + VOID + +--*/ +; BOOLEAN IsTDStatusActive ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Indicate whether TD status active or not + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + TRUE - Active + FALSE - Inactive + +--*/ +; BOOLEAN IsTDStatusStalled ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Indicate whether TD status stalled or not + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + TRUE - Stalled + FALSE - not stalled + +--*/ +; BOOLEAN IsTDStatusBufferError ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Indicate whether TD status buffer error or not + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + TRUE - Buffer error + FALSE - No error + +--*/ +; BOOLEAN IsTDStatusBabbleError ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Indicate whether TD status babble error or not + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + TRUE - Babble error + FALSE - No error + +--*/ +; BOOLEAN IsTDStatusNAKReceived ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Indicate whether TD status NAK received +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + TRUE - NAK received + FALSE - NAK not received + +--*/ +; BOOLEAN IsTDStatusCRCTimeOutError ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Indicate whether TD status CRC timeout error or not + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + TRUE - CRC timeout error + FALSE - CRC timeout no error + +--*/ +; BOOLEAN IsTDStatusBitStuffError ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Indicate whether TD status bit stuff error or not + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + TRUE - Bit stuff error + FALSE - Bit stuff no error + +--*/ +; UINT16 GetTDStatusActualLength ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Get TD status length + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + Return Td status length + +--*/ +; UINT16 GetTDTokenMaxLength ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Get TD Token maximum length + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + Return TD token maximum length + +--*/ +; UINT8 GetTDTokenEndPoint ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Get TD Token endpoint number + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + Return TD Token endpoint number + +--*/ +; UINT8 GetTDTokenDeviceAddress ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Get TD Token device address + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + Return TD Token device address + +--*/ +; UINT8 GetTDTokenPacketID ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ -UINT8 * +Routine Description: + + Get TD Token packet ID + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + Return TD Token packet ID + +--*/ +; + +UINT8 * GetTDDataBuffer ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Get the point to TD data buffer + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + Return a point to TD data buffer + +--*/ +; BOOLEAN GetTDLinkPtrValidorInvalid ( IN TD_STRUCT *ptrTDStruct - ); + ) +/*++ + +Routine Description: + + Get TD LinkPtr valid or not + +Arguments: + + ptrTDStruct - A point to TD_STRUCT + +Returns: + + TRUE - Invalid + FALSE - Valid + +--*/ +; UINTN CountTDsNumber ( IN TD_STRUCT *ptrFirstTD - ); + ) +/*++ + +Routine Description: + + Get the number of TDs + +Arguments: + + PtrFirstTD - A point to the first TD_STRUCT + +Returns: + + Return the number of TDs + +--*/ +; VOID LinkTDToQH ( IN QH_STRUCT *ptrQH, IN TD_STRUCT *ptrTD - ); + ) +/*++ + +Routine Description: + + Link TD To QH + +Arguments: + + PtrQH - QH_STRUCT + PtrTD - TD_STRUCT +Returns: + + VOID + +--*/ +; VOID LinkTDToTD ( IN TD_STRUCT *ptrPreTD, IN TD_STRUCT *ptrTD - ); + ) +/*++ + +Routine Description: + + Link TD To TD + +Arguments: + + ptrPreTD - Previous TD_STRUCT to be linked + PtrTD - TD_STRUCT to link +Returns: + + VOID + +--*/ +; VOID SetorClearCurFrameListTerminate ( IN FRAMELIST_ENTRY *pCurEntry, IN BOOLEAN bSet - ); + ) +/*++ + +Routine Description: + + Set or clear current framelist terminate + +Arguments: + + pCurEntry - A point to FRAMELIST_ENTITY + IsSet - TRUE to empty the frame and indicate the Pointer field is valid + +Returns: + + VOID + +--*/ +; VOID SetCurFrameListQHorTD ( IN FRAMELIST_ENTRY *pCurEntry, IN BOOLEAN bQH - ); + ) +/*++ + +Routine Description: + + Set current framelist QH or TD + +Arguments: + + pCurEntry - A point to FRAMELIST_ENTITY + IsQH - TRUE to set QH and FALSE to set TD + +Returns: + + VOID + +--*/ +; BOOLEAN GetCurFrameListTerminate ( IN FRAMELIST_ENTRY *pCurEntry - ); + ) +/*++ + +Routine Description: + + Get current framelist terminate + +Arguments: + + pCurEntry - A point to FRAMELIST_ENTITY + +Returns: + + TRUE - Terminate + FALSE - Not terminate + +--*/ +; VOID SetCurFrameListPointer ( IN FRAMELIST_ENTRY *pCurEntry, IN UINT8 *ptr - ); + ) +/*++ -VOID * +Routine Description: + + Set current framelist pointer + +Arguments: + + pCurEntry - A point to FRAMELIST_ENTITY + ptr - A point to FrameListPtr point to + +Returns: + + VOID + +--*/ +; + +VOID * GetCurFrameListPointer ( IN FRAMELIST_ENTRY *pCurEntry - ); + ) +/*++ + +Routine Description: + + Get current framelist pointer + +Arguments: + + pCurEntry - A point to FRAMELIST_ENTITY + +Returns: + + A point FrameListPtr point to + +--*/ +; VOID LinkQHToFrameList ( IN FRAMELIST_ENTRY *pEntry, IN UINT16 FrameListIndex, IN QH_STRUCT *ptrQH - ); + ) /*++ Routine Description: @@ -864,14 +2037,7 @@ Returns: VOID --*/ -VOID -DeleteQHTDs ( - IN FRAMELIST_ENTRY *pEntry, - IN QH_STRUCT *ptrQH, - IN TD_STRUCT *ptrFirstTD, - IN UINT16 FrameListIndex, - IN BOOLEAN SearchOther - ); +; VOID DelLinkSingleQH ( @@ -880,13 +2046,50 @@ DelLinkSingleQH ( IN UINT16 FrameListIndex, IN BOOLEAN SearchOther, IN BOOLEAN Delete - ); + ) +/*++ + +Routine Description: + + Unlink from frame list and delete single QH + +Arguments: + + HcDev - USB_HC_DEV + PtrQH - QH_STRUCT + FrameListIndex - Frame List Index + SearchOther - Search Other QH + Delete - TRUE is to delete the QH + +Returns: + + VOID + +--*/ +; VOID DeleteQueuedTDs ( IN USB_HC_DEV *HcDev, IN TD_STRUCT *ptrFirstTD - ); + ) +/*++ + +Routine Description: + + Delete Queued TDs + +Arguments: + + HcDev - USB_HC_DEV + PtrFirstTD - TD link list head + +Returns: + + VOID + +--*/ +; VOID InsertQHTDToINTList ( @@ -902,10 +2105,12 @@ InsertQHTDToINTList ( IN UINT8 *DataBuffer, IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, IN VOID *Context - ); + ) /*++ Routine Description: + Insert QH and TD To Interrupt List + Arguments: HcDev - USB_HC_DEV @@ -920,11 +2125,14 @@ Arguments: DataBuffer - Data buffer CallBackFunction- CallBackFunction after interrupt transfeer Context - CallBackFunction Context passed as function parameter + Returns: + EFI_SUCCESS - Sucess EFI_INVALID_PARAMETER - Paremeter is error --*/ +; EFI_STATUS DeleteAsyncINTQHTDs ( @@ -932,11 +2140,12 @@ DeleteAsyncINTQHTDs ( IN UINT8 DeviceAddress, IN UINT8 EndPointAddress, OUT UINT8 *DataToggle - ); + ) /*++ Routine Description: Delete Async INT QH and TDs + Arguments: HcDev - USB_HC_DEV @@ -945,10 +2154,13 @@ Arguments: DataToggle - Data Toggle Returns: + EFI_SUCCESS - Sucess EFI_INVALID_PARAMETER - Paremeter is error --*/ +; + BOOLEAN CheckTDsResults ( IN TD_STRUCT *ptrTD, @@ -956,7 +2168,7 @@ CheckTDsResults ( OUT UINT32 *Result, OUT UINTN *ErrTDPos, OUT UINTN *ActualTransferSize - ); + ) /*++ Routine Description: @@ -977,6 +2189,8 @@ Returns: FALSE - Fail --*/ +; + VOID ExecuteAsyncINTTDs ( IN USB_HC_DEV *HcDev, @@ -984,7 +2198,7 @@ ExecuteAsyncINTTDs ( OUT UINT32 *Result, OUT UINTN *ErrTDPos, OUT UINTN *ActualLen - ) ; + ) /*++ Routine Description: @@ -1004,12 +2218,14 @@ Returns: VOID --*/ +; + VOID UpdateAsyncINTQHTDs ( IN INTERRUPT_LIST *ptrList, IN UINT32 Result, IN UINT32 ErrTDPos - ); + ) /*++ Routine Description: @@ -1027,16 +2243,19 @@ Returns: VOID --*/ +; + VOID ReleaseInterruptList ( IN USB_HC_DEV *HcDev, IN LIST_ENTRY *ListHead - ); + ) /*++ Routine Description: Release Interrupt List + Arguments: HcDev - USB_HC_DEV @@ -1047,6 +2266,8 @@ Returns: VOID --*/ +; + EFI_STATUS ExecuteControlTransfer ( IN USB_HC_DEV *HcDev, @@ -1055,7 +2276,7 @@ ExecuteControlTransfer ( OUT UINTN *ActualLen, IN UINTN TimeOut, OUT UINT32 *TransferResult - ); + ) /*++ Routine Description: @@ -1077,6 +2298,8 @@ Returns: --*/ +; + EFI_STATUS ExecBulkorSyncInterruptTransfer ( IN USB_HC_DEV *HcDev, @@ -1086,7 +2309,7 @@ ExecBulkorSyncInterruptTransfer ( OUT UINT8 *DataToggle, IN UINTN TimeOut, OUT UINT32 *TransferResult - ); + ) /*++ Routine Description: @@ -1107,81 +2330,311 @@ Returns: EFI_SUCCESS - Sucess EFI_DEVICE_ERROR - Error --*/ +; EFI_STATUS InitializeMemoryManagement ( IN USB_HC_DEV *HcDev - ); + ) +/*++ + +Routine Description: + + Initialize Memory Management + +Arguments: + + HcDev - USB_HC_DEV + +Returns: + + EFI_SUCCESS - Success + +--*/ +; EFI_STATUS CreateMemoryBlock ( IN USB_HC_DEV *HcDev, IN MEMORY_MANAGE_HEADER **MemoryHeader, IN UINTN MemoryBlockSizeInPages - ); + ) +/*++ + +Routine Description: + + Use PciIo->AllocateBuffer to allocate common buffer for the memory block, + and use PciIo->Map to map the common buffer for Bus Master Read/Write. + + +Arguments: + + HcDev - USB_HC_DEV + MemoryHeader - MEMORY_MANAGE_HEADER to output + MemoryBlockSizeInPages - MemoryBlockSizeInPages + +Returns: + + EFI_SUCCESS - Success + EFI_OUT_OF_RESOURCES - Out of resources + EFI_UNSUPPORTED - Unsupported + +--*/ +; EFI_STATUS FreeMemoryHeader ( IN USB_HC_DEV *HcDev, IN MEMORY_MANAGE_HEADER *MemoryHeader - ); + ) +/*++ + +Routine Description: + + Free Memory Header + +Arguments: + + HcDev - USB_HC_DEV + MemoryHeader - MemoryHeader to be freed + +Returns: + + EFI_INVALID_PARAMETER - Parameter is error + EFI_SUCCESS - Success + +--*/ +; EFI_STATUS UhciAllocatePool ( IN USB_HC_DEV *UhcDev, IN UINT8 **Pool, IN UINTN AllocSize - ); + ) +/*++ + +Routine Description: + + Uhci Allocate Pool + +Arguments: + + HcDev - USB_HC_DEV + Pool - Place to store pointer to the memory buffer + AllocSize - Alloc Size + +Returns: + + EFI_SUCCESS - Success + +--*/ +; VOID UhciFreePool ( IN USB_HC_DEV *HcDev, IN UINT8 *Pool, IN UINTN AllocSize - ); + ) +/*++ + +Routine Description: + + Uhci Free Pool + +Arguments: + + HcDev - USB_HC_DEV + Pool - Pool to free + AllocSize - Pool size + +Returns: + + VOID + +--*/ +; VOID InsertMemoryHeaderToList ( IN MEMORY_MANAGE_HEADER *MemoryHeader, IN MEMORY_MANAGE_HEADER *NewMemoryHeader - ); + ) +/*++ + +Routine Description: + + Insert Memory Header To List + +Arguments: + + MemoryHeader - MEMORY_MANAGE_HEADER + NewMemoryHeader - MEMORY_MANAGE_HEADER + +Returns: + + VOID + +--*/ +; EFI_STATUS AllocMemInMemoryBlock ( IN MEMORY_MANAGE_HEADER *MemoryHeader, IN VOID **Pool, IN UINTN NumberOfMemoryUnit - ); + ) +/*++ + +Routine Description: + + Alloc Memory In MemoryBlock + +Arguments: + + MemoryHeader - MEMORY_MANAGE_HEADER + Pool - Place to store pointer to memory + NumberOfMemoryUnit - Number Of Memory Unit + +Returns: + + EFI_NOT_FOUND - Can't find the free memory + EFI_SUCCESS - Success + +--*/ +; BOOLEAN IsMemoryBlockEmptied ( IN MEMORY_MANAGE_HEADER *MemoryHeaderPtr - ); + ) +/*++ + +/*++ + +Routine Description: + + Is Memory Block Emptied + +Arguments: + + MemoryHeaderPtr - MEMORY_MANAGE_HEADER + +Returns: + + TRUE - Empty + FALSE - Not Empty + +--*/ +; VOID DelinkMemoryBlock ( IN MEMORY_MANAGE_HEADER *FirstMemoryHeader, IN MEMORY_MANAGE_HEADER *FreeMemoryHeader - ); + ) +/*++ + +Routine Description: + + Delink Memory Block + +Arguments: + + FirstMemoryHeader - MEMORY_MANAGE_HEADER + NeedFreeMemoryHeader - MEMORY_MANAGE_HEADER + +Returns: + + VOID + +--*/ +; EFI_STATUS DelMemoryManagement ( IN USB_HC_DEV *HcDev - ); + ) +/*++ + +Routine Description: + + Delete Memory Management + +Arguments: + + HcDev - USB_HC_DEV + +Returns: + + EFI_SUCCESS - Success + +--*/ +; VOID EnableMaxPacketSize ( IN USB_HC_DEV *HcDev - ); + ) +/*++ + +Routine Description: + + Enable Max Packet Size + +Arguments: + + HcDev - USB_HC_DEV + +Returns: + + VOID + +--*/ +; VOID CleanUsbTransactions ( IN USB_HC_DEV *HcDev - ); + ) +/*++ + +Routine Description: + + Clean USB Transactions + +Arguments: + + HcDev - A point to USB_HC_DEV + +Returns: + + VOID + +--*/ +; VOID TurnOffUSBEmulation ( IN EFI_PCI_IO_PROTOCOL *PciIo - ); + ) +/*++ + +Routine Description: + + Set current framelist QH or TD + +Arguments: + + pCurEntry - A point to FRAMELIST_ENTITY + IsQH - TRUE to set QH and FALSE to set TD + +Returns: + + VOID + +--*/ +; #endif diff --git a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c index 0aa0507c2a..8cd6b8e6f6 100644 --- a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c +++ b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c @@ -710,7 +710,7 @@ BotDataPhase ( BufferPtr = (UINT8 *) DataBuffer; TransferredSize = 0; MaxRetry = 10; - PackageNum = 15; + PackageNum = 128; // // retrieve the the max packet length of the given endpoint diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa index 54a79ecd9a..d7101dce0e 100644 --- a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa @@ -83,7 +83,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.--> gEfiUsbIoProtocolGuid - + + gEfiUsb2HcProtocolGuid + + gEfiUsbHcProtocolGuid diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c index f4ac69e13f..1d1f44d638 100644 --- a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c @@ -23,10 +23,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "usbbus.h" -//#ifdef EFI_DEBUG -UINTN gUSBDebugLevel = EFI_D_ERROR; +UINTN gUSBDebugLevel = EFI_D_INFO; UINTN gUSBErrorLevel = EFI_D_ERROR; -//#endif + // // The UsbBusProtocol is just used to locate USB_BUS_CONTROLLER // structure in the UsbBusDriverControllerDriverStop(). Then we can @@ -121,17 +120,52 @@ UsbDeviceConfiguration ( // STATIC VOID -EFIAPI -UsbEnumeration ( +RootHubEnumeration ( IN EFI_EVENT Event, IN VOID *Context ); +STATIC +VOID +HubEnumeration ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +STATIC +EFI_STATUS +UsbSetTransactionTranslator ( + IN USB_IO_CONTROLLER_DEVICE *ParentHubController, + IN UINT8 ParentPort, + IN OUT USB_IO_DEVICE *Device + ); + +STATIC +EFI_STATUS +UsbUnsetTransactionTranslator ( + USB_IO_DEVICE *Device + ); + +STATIC +EFI_STATUS +IdentifyDeviceSpeed ( + USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + USB_IO_DEVICE *NewDevice, + UINT8 Index + ); + +STATIC +EFI_STATUS +ReleasePortToCHC ( + USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + UINT8 PortNum + ); + EFI_STATUS ResetRootPort ( - IN EFI_USB_HC_PROTOCOL *UsbHCInterface, - IN UINT8 PortNum, - IN UINT8 RetryTimes + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 PortNum, + IN UINT8 RetryTimes ); EFI_STATUS @@ -140,12 +174,6 @@ ResetHubPort ( IN UINT8 PortIndex ); -EFI_STATUS -ClearRootPortConnectionChangeStatus ( - IN UINT8 PortNum, - IN EFI_USB_HC_PROTOCOL *UsbHCInterface - ); - STATIC EFI_STATUS ParentPortReset ( @@ -162,6 +190,18 @@ UINT8 UsbAllocateAddress ( IN UINT8 *AddressPool ) +/*++ + + Routine Description: + Allocate address for usb device + + Arguments: + AddressPool - Pool of usb device address + + Returns: + Usb device address + +--*/ { UINT8 ByteIndex; UINT8 BitIndex; @@ -188,6 +228,19 @@ UsbFreeAddress ( IN UINT8 DevAddress, IN UINT8 *AddressPool ) +/*++ + + Routine Description: + Free address for usb device + + Arguments: + DevAddress - Usb device address + AddressPool - Pool of usb device address + + Returns: + VOID + +--*/ { UINT8 WhichByte; UINT8 WhichBit; @@ -215,8 +268,8 @@ UsbBusControllerDriverSupported ( Arguments: This - Protocol instance pointer. - Controller - Handle of device to test - RemainingDevicePath - Not used + Controller - Handle of device to test + RemainingDevicePath - Device Path Protocol instance pointer Returns: EFI_SUCCESS - This driver supports this device. @@ -224,30 +277,103 @@ UsbBusControllerDriverSupported ( --*/ { - EFI_STATUS OpenStatus; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_USB2_HC_PROTOCOL *Usb2Hc; + EFI_USB_HC_PROTOCOL *UsbHc; + EFI_DEV_PATH_PTR Node; + // + // Check Device Path + // + if (RemainingDevicePath != NULL) { + Node.DevPath = RemainingDevicePath; + if (Node.DevPath->Type != MESSAGING_DEVICE_PATH || + Node.DevPath->SubType != MSG_USB_DP || + DevicePathNodeLength(Node.DevPath) != sizeof(USB_DEVICE_PATH)) { + return EFI_UNSUPPORTED; + } + } + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + // // Check whether USB Host Controller Protocol is already // installed on this handle. If it is installed, we can start // USB Bus Driver now. // - OpenStatus = gBS->OpenProtocol ( - Controller, - &gEfiUsbHcProtocolGuid, - NULL, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_TEST_PROTOCOL - ); - - if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) { - return EFI_UNSUPPORTED; + Status = gBS->OpenProtocol ( + Controller, + &gEfiUsb2HcProtocolGuid, + (VOID **) &Usb2Hc, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; } + + if (EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + (VOID **) &UsbHc, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } - return OpenStatus; + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_SUCCESS; + } + + gBS->CloseProtocol ( + Controller, + &gEfiUsb2HcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; } - EFI_STATUS EFIAPI UsbBusControllerDriverStart ( @@ -270,11 +396,8 @@ UsbBusControllerDriverStart ( Returns: EFI_SUCCESS - This driver supports this device. - EFI_UNSUPPORTED - This driver does not support this device. EFI_DEVICE_ERROR - This driver cannot be started due to device - Error EFI_OUT_OF_RESOURCES- Can't allocate memory resources - EFI_ALREADY_STARTED - This driver has been started --*/ { @@ -283,7 +406,9 @@ UsbBusControllerDriverStart ( USB_BUS_CONTROLLER_DEVICE *UsbBusDev; USB_IO_DEVICE *RootHub; USB_IO_CONTROLLER_DEVICE *RootHubController; - EFI_USB_HC_PROTOCOL *UsbHCInterface; + UINT8 MaxSpeed; + UINT8 PortNumber; + UINT8 Is64BitCapable; // // Allocate USB_BUS_CONTROLLER_DEVICE structure @@ -311,54 +436,56 @@ UsbBusControllerDriverStart ( if (EFI_ERROR (OpenStatus)) { gBS->FreePool (UsbBusDev); - return EFI_UNSUPPORTED; + return OpenStatus; } // // Locate the Host Controller Interface // OpenStatus = gBS->OpenProtocol ( Controller, - &gEfiUsbHcProtocolGuid, - (VOID **) &UsbHCInterface, + &gEfiUsb2HcProtocolGuid, + (VOID **) &(UsbBusDev->Usb2HCInterface), This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); + if (EFI_ERROR (OpenStatus)) { - if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) { - - // - // Report Status Code here since we will reset the host controller - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - EFI_IO_BUS_USB | EFI_IOB_EC_CONTROLLER_ERROR, - UsbBusDev->DevicePath - ); + UsbBusDev->Hc2ProtocolSupported = FALSE; + OpenStatus = gBS->OpenProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + (VOID **) &(UsbBusDev->UsbHCInterface), + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (OpenStatus)) { + // + // Report Status Code here since we will reset the host controller + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_USB | EFI_IOB_EC_CONTROLLER_ERROR, + UsbBusDev->DevicePath + ); - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - gBS->FreePool (UsbBusDev); - return EFI_UNSUPPORTED; + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->FreePool (UsbBusDev); + return OpenStatus; + } + + DEBUG ((gUSBDebugLevel, "UsbHcProtocol Opened.\n")); + } else { + DEBUG ((gUSBDebugLevel, "Usb2HcProtocol Opened.\n")); + UsbBusDev->Hc2ProtocolSupported = TRUE; } - if (OpenStatus == EFI_ALREADY_STARTED) { - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - gBS->FreePool (UsbBusDev); - return EFI_ALREADY_STARTED; - } - - UsbBusDev->UsbHCInterface = UsbHCInterface; - // // Attach EFI_USB_BUS_PROTOCOL to controller handle, // for locate UsbBusDev later @@ -378,12 +505,22 @@ UsbBusControllerDriverStart ( This->DriverBindingHandle, Controller ); - gBS->CloseProtocol ( - Controller, - &gEfiUsbHcProtocolGuid, - This->DriverBindingHandle, - Controller - ); + if (UsbBusDev->Hc2ProtocolSupported) { + gBS->CloseProtocol ( + Controller, + &gEfiUsb2HcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } else { + gBS->CloseProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + gBS->FreePool (UsbBusDev); return Status; } @@ -404,12 +541,22 @@ UsbBusControllerDriverStart ( This->DriverBindingHandle, Controller ); - gBS->CloseProtocol ( - Controller, - &gEfiUsbHcProtocolGuid, - This->DriverBindingHandle, - Controller - ); + if (UsbBusDev->Hc2ProtocolSupported) { + gBS->CloseProtocol ( + Controller, + &gEfiUsb2HcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } else { + gBS->CloseProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + gBS->FreePool (UsbBusDev); return EFI_OUT_OF_RESOURCES; } @@ -435,28 +582,41 @@ UsbBusControllerDriverStart ( This->DriverBindingHandle, Controller ); - gBS->CloseProtocol ( - Controller, - &gEfiUsbHcProtocolGuid, - This->DriverBindingHandle, - Controller - ); + if (UsbBusDev->Hc2ProtocolSupported) { + gBS->CloseProtocol ( + Controller, + &gEfiUsb2HcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } else { + gBS->CloseProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } gBS->FreePool (UsbBusDev); gBS->FreePool (RootHub); return EFI_OUT_OF_RESOURCES; } - UsbHCInterface->GetRootHubPortNumber ( - UsbHCInterface, - &RootHubController->DownstreamPorts - ); - RootHubController->UsbDevice = RootHub; - RootHubController->IsUsbHub = TRUE; - RootHubController->DevicePath = UsbBusDev->DevicePath; - RootHubController->HostController = Controller; + UsbVirtualHcGetCapability ( + UsbBusDev, + &MaxSpeed, + &PortNumber, + &Is64BitCapable + ); + RootHubController->DownstreamPorts = PortNumber; + RootHubController->UsbDevice = RootHub; + RootHubController->IsUsbHub = TRUE; + RootHubController->DevicePath = UsbBusDev->DevicePath; + RootHubController->HostController = Controller; - RootHub->NumOfControllers = 1; - RootHub->UsbController[0] = RootHubController; + RootHub->NumOfControllers = 1; + RootHub->UsbController[0] = RootHubController; + RootHub->DeviceSpeed = MaxSpeed; // // Report Status Code here since we will reset the host controller @@ -470,10 +630,10 @@ UsbBusControllerDriverStart ( // // Reset USB Host Controller // - UsbHCInterface->Reset ( - UsbHCInterface, - EFI_USB_HC_RESET_GLOBAL - ); + UsbVirtualHcReset ( + UsbBusDev, + EFI_USB_HC_RESET_GLOBAL + ); // // Report Status Code while we are going to bring up the Host Controller @@ -488,10 +648,10 @@ UsbBusControllerDriverStart ( // // Start USB Host Controller // - UsbHCInterface->SetState ( - UsbHCInterface, - EfiUsbHcStateOperational - ); + UsbVirtualHcSetState ( + UsbBusDev, + EfiUsbHcStateOperational + ); // // Create a timer to query root ports periodically @@ -499,7 +659,7 @@ UsbBusControllerDriverStart ( Status = gBS->CreateEvent ( EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, EFI_TPL_CALLBACK, - UsbEnumeration, + RootHubEnumeration, RootHubController, &RootHubController->HubNotify ); @@ -517,17 +677,26 @@ UsbBusControllerDriverStart ( Controller ); - gBS->CloseProtocol ( - Controller, - &gEfiUsbHcProtocolGuid, - This->DriverBindingHandle, - Controller - ); + if (UsbBusDev->Hc2ProtocolSupported) { + gBS->CloseProtocol ( + Controller, + &gEfiUsb2HcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } else { + gBS->CloseProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } gBS->FreePool (RootHubController); gBS->FreePool (RootHub); gBS->FreePool (UsbBusDev); - return EFI_UNSUPPORTED; + return EFI_OUT_OF_RESOURCES; } // @@ -556,22 +725,32 @@ UsbBusControllerDriverStart ( Controller ); - gBS->CloseProtocol ( - Controller, - &gEfiUsbHcProtocolGuid, - This->DriverBindingHandle, - Controller - ); + if (UsbBusDev->Hc2ProtocolSupported) { + gBS->CloseProtocol ( + Controller, + &gEfiUsb2HcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } else { + gBS->CloseProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } gBS->CloseEvent (RootHubController->HubNotify); gBS->FreePool (RootHubController); gBS->FreePool (RootHub); gBS->FreePool (UsbBusDev); - return EFI_UNSUPPORTED; + return EFI_DEVICE_ERROR; } return EFI_SUCCESS; } + // // Stop the bus controller // @@ -608,7 +787,6 @@ UsbBusControllerDriverStop ( USB_BUS_CONTROLLER_DEVICE *UsbBusController; EFI_USB_BUS_PROTOCOL *UsbIdentifier; UINT8 Index2; - EFI_USB_HC_PROTOCOL *UsbHCInterface; USB_IO_CONTROLLER_DEVICE *UsbController; USB_IO_DEVICE *UsbIoDevice; USB_IO_CONTROLLER_DEVICE *HubController; @@ -678,7 +856,6 @@ UsbBusControllerDriverStop ( // // Stop USB Host Controller // - UsbHCInterface = UsbBusController->UsbHCInterface; // // Report Status Code here since we will reset the host controller @@ -689,10 +866,10 @@ UsbBusControllerDriverStop ( EFI_IO_BUS_USB | EFI_IOB_PC_RESET ); - UsbHCInterface->SetState ( - UsbHCInterface, - EfiUsbHcStateHalt - ); + UsbVirtualHcSetState ( + UsbBusController, + EfiUsbHcStateHalt + ); // // Deconfiguration all its devices @@ -725,12 +902,21 @@ UsbBusControllerDriverStop ( // Close USB_HC_PROTOCOL & DEVICE_PATH_PROTOCOL // Opened by this Controller // - gBS->CloseProtocol ( - Controller, - &gEfiUsbHcProtocolGuid, - This->DriverBindingHandle, - Controller - ); + if (UsbBusController->Hc2ProtocolSupported) { + gBS->CloseProtocol ( + Controller, + &gEfiUsb2HcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } else { + gBS->CloseProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } gBS->CloseProtocol ( Controller, @@ -786,6 +972,13 @@ UsbDeviceConfiguration ( USB_IO_CONTROLLER_DEVICE *UsbIoController; UsbBusDev = UsbIoDevice->BusController; + + UsbSetTransactionTranslator ( + ParentHubController, + ParentPort, + UsbIoDevice + ); + // // Since a USB device must have at least on interface, // so create this instance first @@ -807,6 +1000,8 @@ UsbDeviceConfiguration ( // UsbIo = &FirstController->UsbIo; + ParentPortReset (FirstController, FALSE, 0); + // // First retrieve the 1st 8 bytes of // in order to get the MaxPacketSize for Endpoint 0 @@ -815,7 +1010,7 @@ UsbDeviceConfiguration ( UsbIoDevice->DeviceDescriptor.MaxPacketSize0 = 8; - ParentPortReset (FirstController, FALSE, Index); + gBS->Stall (100 * 1000); Result = UsbGetDescriptor ( UsbIo, @@ -826,7 +1021,8 @@ UsbDeviceConfiguration ( &Status ); if (!EFI_ERROR (Result)) { - DEBUG ((gUSBDebugLevel, + DEBUG ( + (gUSBDebugLevel, "Get Device Descriptor Success, MaxPacketSize0 = 0x%x\n", UsbIoDevice->DeviceDescriptor.MaxPacketSize0) ); @@ -874,6 +1070,11 @@ UsbDeviceConfiguration ( UsbIoDevice->DeviceAddress = DevAddress; + // + // SetAddress Complete Time by Spec, Max 50ms + // + gBS->Stall (10 * 1000); + // // Get the whole device descriptor // @@ -1049,7 +1250,6 @@ UsbDeviceConfiguration ( // // USB Device DeConfiguration // - EFI_STATUS UsbDeviceDeConfiguration ( IN USB_IO_DEVICE *UsbIoDevice @@ -1074,8 +1274,6 @@ UsbDeviceDeConfiguration ( UINT8 Index; EFI_USB_IO_PROTOCOL *UsbIo; - DEBUG ((gUSBDebugLevel, "Enter Usb Device Deconfiguration\n")); - // // Double check UsbIoDevice exists // @@ -1083,6 +1281,8 @@ UsbDeviceDeConfiguration ( return EFI_SUCCESS; } + UsbUnsetTransactionTranslator (UsbIoDevice); + for (index = 0; index < UsbIoDevice->NumOfControllers; index++) { // // Check if it is a hub, if so, de configuration all its @@ -1143,13 +1343,21 @@ UsbDeviceDeConfiguration ( // // remove child handle reference to the USB_HC_PROTOCOL // - gBS->CloseProtocol ( - UsbController->HostController, - &gEfiUsbHcProtocolGuid, - gUsbBusDriverBinding.DriverBindingHandle, - UsbController->Handle - ); - + if (UsbIoDevice->BusController->Hc2ProtocolSupported) { + gBS->CloseProtocol ( + UsbController->HostController, + &gEfiUsb2HcProtocolGuid, + gUsbBusDriverBinding.DriverBindingHandle, + UsbController->Handle + ); + } else { + gBS->CloseProtocol ( + UsbController->HostController, + &gEfiUsbHcProtocolGuid, + gUsbBusDriverBinding.DriverBindingHandle, + UsbController->Handle + ); + } // // Uninstall EFI_USB_IO_PROTOCOL & DEVICE_PATH_PROTOCOL // installed on this handle @@ -1314,30 +1522,31 @@ OnHubInterruptComplete ( STATIC VOID EFIAPI -UsbEnumeration ( +RootHubEnumeration ( IN EFI_EVENT Event, IN VOID *Context ) /*++ Routine Description: - This is USB enumerator + + This is USB RootHub enumerator Arguments: + Event - Indicating which event is signaled Context - actually it is a USB_IO_DEVICE Returns: - EFI_SUCCESS - Others - + + VOID + --*/ { USB_IO_CONTROLLER_DEVICE *HubController; EFI_USB_PORT_STATUS HubPortStatus; EFI_STATUS Status; UINT8 Index; - EFI_USB_HC_PROTOCOL *UsbHCInterface; USB_IO_DEVICE *UsbIoDev; USB_BUS_CONTROLLER_DEVICE *UsbBusDev; EFI_HANDLE HostController; @@ -1346,476 +1555,561 @@ UsbEnumeration ( USB_IO_CONTROLLER_DEVICE *NewController; UINT8 Index2; EFI_USB_IO_PROTOCOL *UsbIo; - UINT8 StatusChangePort; HubController = (USB_IO_CONTROLLER_DEVICE *) Context; HostController = HubController->HostController; UsbBusDev = HubController->UsbDevice->BusController; - if (HubController->UsbDevice->DeviceAddress == 1) { - // - // Root hub has the address 1 - // - UsbIoDev = HubController->UsbDevice; - UsbHCInterface = UsbIoDev->BusController->UsbHCInterface; + // + // Root hub has the address 1 + // + UsbIoDev = HubController->UsbDevice; - for (Index = 0; Index < HubController->DownstreamPorts; Index++) { - UsbHCInterface->GetRootHubPortStatus ( - UsbHCInterface, - Index, - (EFI_USB_PORT_STATUS *) &HubPortStatus - ); + for (Index = 0; Index < HubController->DownstreamPorts; Index++) { - if (!IsPortConnectChange (HubPortStatus.PortChangeStatus)) { + UsbVirtualHcGetRootHubPortStatus ( + UsbBusDev, + Index, + (EFI_USB_PORT_STATUS *) &HubPortStatus + ); + + if (!IsPortConnectChange (HubPortStatus.PortChangeStatus)) { + continue; + } + // + // Clear root hub status change status + // + UsbVirtualHcClearRootHubPortFeature ( + UsbBusDev, + Index, + EfiUsbPortConnectChange + ); + + gBS->Stall (100 * 1000); + + UsbVirtualHcGetRootHubPortStatus ( + UsbBusDev, + Index, + (EFI_USB_PORT_STATUS *) &HubPortStatus + ); + + if (IsPortConnect (HubPortStatus.PortStatus)) { + + // + // There is something connected to this port + // + DEBUG ((gUSBDebugLevel, "Something connected to Root Hub at Port0x%x\n", Index)); + + ReportUsbStatusCode ( + UsbBusDev, + EFI_PROGRESS_CODE, + EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG + ); + // + // if there is something physically detached, but still logically + // attached... + // + OldUsbIoDevice = HubController->Children[Index]; + + if (NULL != OldUsbIoDevice) { + UsbDeviceDeConfiguration (OldUsbIoDevice); + HubController->Children[Index] = NULL; + } + + NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE)); + if (NewDevice == NULL) { + return ; + } + // + // Initialize some fields by copying data from + // its parents + // + NewDevice->DeviceDescriptor.MaxPacketSize0 = 8; + NewDevice->BusController = UsbIoDev->BusController; + + // + // Process of identify device speed + // + Status = IdentifyDeviceSpeed ( + UsbBusDev, + NewDevice, + Index + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (NewDevice); continue; } + // - // Clear root hub status change status + // Configure that device // - ClearRootPortConnectionChangeStatus ( - Index, - UsbHCInterface - ); - - gBS->Stall (100 * 1000); - - UsbHCInterface->GetRootHubPortStatus ( - UsbHCInterface, - Index, - (EFI_USB_PORT_STATUS *) &HubPortStatus - ); - - if (IsPortConnect (HubPortStatus.PortStatus)) { - - // - // There is something connected to this port - // - DEBUG ((gUSBDebugLevel, "Something attached from Root Hub in 0x%x\n", Index)); - - ReportUsbStatusCode ( - UsbBusDev, - EFI_PROGRESS_CODE, - EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG - ); - // - // if there is something physically detached, but still logically - // attached... - // - OldUsbIoDevice = HubController->Children[Index]; - - if (NULL != OldUsbIoDevice) { - UsbDeviceDeConfiguration (OldUsbIoDevice); - HubController->Children[Index] = NULL; - } - - NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE)); - if (NewDevice == NULL) { - return ; - } - // - // Initialize some fields by copying data from - // its parents - // - NewDevice->IsSlowDevice = IsPortLowSpeedDeviceAttached (HubPortStatus.PortStatus); - - DEBUG ((gUSBDebugLevel, "DeviceSpeed 0x%x\n", NewDevice->IsSlowDevice)); - - NewDevice->BusController = UsbIoDev->BusController; - - // - // Configure that device - // - Status = UsbDeviceConfiguration ( - HubController, - HostController, - Index, - NewDevice - ); - if (EFI_ERROR (Status)) { - gBS->FreePool (NewDevice); - return ; - } - // - // Add this device to the usb bus tree - // - HubController->Children[Index] = NewDevice; - - for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) { - // - // If this device is hub, add to the hub index - // - NewController = NewDevice->UsbController[Index2]; - - Status = gBS->ConnectController ( - NewController->Handle, - NULL, - NULL, - TRUE - ); - // - // If connect success, we need to disconnect when - // stop the controller, otherwise we need not call - // gBS->DisconnectController () - // This is used by those usb devices we don't plan - // to support. We can allocate - // controller handles for them, but we don't have - // device drivers to manage them. - // - NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status)); - - if (IsHub (NewController)) { - - NewController->IsUsbHub = TRUE; - - // - // Configure Hub Controller - // - Status = DoHubConfig (NewController); - if (EFI_ERROR (Status)) { - continue; - } - // - // Create an event to do hub enumeration - // - gBS->CreateEvent ( - EFI_EVENT_NOTIFY_SIGNAL, - EFI_TPL_CALLBACK, - UsbEnumeration, - NewController, - &NewController->HubNotify - ); - - // - // Add request to do query hub status - // change endpoint - // Hub ports < 7 - // - UsbIo = &NewController->UsbIo; - UsbIo->UsbAsyncInterruptTransfer ( - UsbIo, - NewController->HubEndpointAddress, - TRUE, - 100, - 1, - OnHubInterruptComplete, - NewController - ); - - } - } - } else { - // - // Something disconnected from USB root hub - // - DEBUG ((gUSBDebugLevel, "Something deteached from Root Hub\n")); - - OldUsbIoDevice = HubController->Children[Index]; - - UsbDeviceDeConfiguration (OldUsbIoDevice); - - HubController->Children[Index] = NULL; - - UsbHCInterface->ClearRootHubPortFeature ( - UsbHCInterface, - Index, - EfiUsbPortEnableChange - ); - - UsbHCInterface->GetRootHubPortStatus ( - UsbHCInterface, - Index, - (EFI_USB_PORT_STATUS *) &HubPortStatus - ); - + Status = UsbDeviceConfiguration ( + HubController, + HostController, + Index, + NewDevice + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (NewDevice); + return ; } - } - - return ; - } else { - // - // Event from Hub, Get the hub controller handle - // - // - // Get the status change endpoint - // - StatusChangePort = HubController->StatusChangePort; - - // - // Clear HubController Status Change Bit - // - HubController->StatusChangePort = 0; - - if (StatusChangePort == 0) { // - // Hub changes, we don't handle here + // Add this device to the usb bus tree // - return ; - } - // - // Check which event took place at that port - // - UsbIo = &HubController->UsbIo; - Status = HubGetPortStatus ( - UsbIo, - StatusChangePort, - (UINT32 *) &HubPortStatus - ); + HubController->Children[Index] = NewDevice; - if (EFI_ERROR (Status)) { - return ; - } - // - // Clear some change status - // - if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) { + for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) { + // + // If this device is hub, add to the hub index + // + NewController = NewDevice->UsbController[Index2]; + + Status = gBS->ConnectController ( + NewController->Handle, + NULL, + NULL, + TRUE + ); + // + // If connect success, we need to disconnect when + // stop the controller, otherwise we need not call + // gBS->DisconnectController () + // This is used by those usb devices we don't plan + // to support. We can allocate + // controller handles for them, but we don't have + // device drivers to manage them. + // + NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status)); + + if (IsHub (NewController)) { + + NewController->IsUsbHub = TRUE; + + // + // Configure Hub Controller + // + Status = DoHubConfig (NewController); + if (EFI_ERROR (Status)) { + continue; + } + // + // Create an event to do hub enumeration + // + gBS->CreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + HubEnumeration, + NewController, + &NewController->HubNotify + ); + + // + // Add request to do query hub status + // change endpoint + // Hub ports < 7 + // + UsbIo = &NewController->UsbIo; + UsbIo->UsbAsyncInterruptTransfer ( + UsbIo, + NewController->HubEndpointAddress, + TRUE, + 100, + 1, + OnHubInterruptComplete, + NewController + ); + + } + } + } else { // - // Clear Hub port enable change + // Something disconnected from USB root hub // - DEBUG ((gUSBDebugLevel, "Port Enable Change\n")); - HubClearPortFeature ( - UsbIo, - StatusChangePort, + DEBUG ((gUSBDebugLevel, "Something disconnected from Root Hub at Port0x%x\n", Index)); + + OldUsbIoDevice = HubController->Children[Index]; + + UsbDeviceDeConfiguration (OldUsbIoDevice); + + HubController->Children[Index] = NULL; + + UsbVirtualHcClearRootHubPortFeature ( + UsbBusDev, + Index, EfiUsbPortEnableChange ); - - HubGetPortStatus ( - UsbIo, - StatusChangePort, - (UINT32 *) &HubPortStatus - ); } + } + + return ; +} +// +// USB Root Hub Enumerator +// +STATIC +VOID +EFIAPI +HubEnumeration ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + + Routine Description: + + This is Usb Hub enumerator + + Arguments: + + Event - Indicating which event is signaled + Context - actually it is a USB_IO_DEVICE + + Returns: + + VOID + +--*/ +{ + USB_IO_CONTROLLER_DEVICE *HubController; + EFI_USB_PORT_STATUS HubPortStatus; + EFI_STATUS Status; + USB_BUS_CONTROLLER_DEVICE *UsbBusDev; + EFI_HANDLE HostController; + USB_IO_DEVICE *OldUsbIoDevice; + USB_IO_DEVICE *NewDevice; + USB_IO_CONTROLLER_DEVICE *NewController; + UINT8 Index2; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 StatusChangePort; + UINT8 Number; + + HubController = (USB_IO_CONTROLLER_DEVICE *) Context; + HostController = HubController->HostController; + UsbBusDev = HubController->UsbDevice->BusController; + + // + // Event from Hub, Get the hub controller handle + // + // + // Get the status change endpoint + // + StatusChangePort = HubController->StatusChangePort; + + // + // Clear HubController Status Change Bit + // + HubController->StatusChangePort = 0; + + if (StatusChangePort == 0) { + // + // Hub changes, we don't handle here + // + return ; + } + // + // Check which event took place at that port + // + UsbIo = &HubController->UsbIo; + Status = HubGetPortStatus ( + UsbIo, + StatusChangePort, + (UINT32 *) &HubPortStatus + ); + + if (EFI_ERROR (Status)) { + return ; + } + // + // Clear some change status + // + if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) { + // + // Clear Hub port enable change + // + DEBUG ((gUSBDebugLevel, "Port Enable Change\n")); + HubClearPortFeature ( + UsbIo, + StatusChangePort, + EfiUsbPortEnableChange + ); + + HubGetPortStatus ( + UsbIo, + StatusChangePort, + (UINT32 *) &HubPortStatus + ); + } + + if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) { + // + // Clear Hub reset change + // + DEBUG ((gUSBDebugLevel, "Port Reset Change\n")); + HubClearPortFeature ( + UsbIo, + StatusChangePort, + EfiUsbPortResetChange + ); + + HubGetPortStatus ( + UsbIo, + StatusChangePort, + (UINT32 *) &HubPortStatus + ); + } + + if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_OVERCURRENT) { + // + // Clear Hub overcurrent change + // + DEBUG ((gUSBDebugLevel, "Port Overcurrent Change\n")); + HubClearPortFeature ( + UsbIo, + StatusChangePort, + EfiUsbPortOverCurrentChange + ); + + HubGetPortStatus ( + UsbIo, + StatusChangePort, + (UINT32 *) &HubPortStatus + ); + } + + if (IsPortConnectChange (HubPortStatus.PortChangeStatus)) { + // + // First clear port connection change + // + DEBUG ((gUSBDebugLevel, "Port Connection Change\n")); + HubClearPortFeature ( + UsbIo, + StatusChangePort, + EfiUsbPortConnectChange + ); + + HubGetPortStatus ( + UsbIo, + StatusChangePort, + (UINT32 *) &HubPortStatus + ); + + if (IsPortConnect (HubPortStatus.PortStatus)) { + + DEBUG ((gUSBDebugLevel, "New Device Connect on Hub port \n")); + + ReportUsbStatusCode ( + UsbBusDev, + EFI_PROGRESS_CODE, + EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG + ); - if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) { // - // Clear Hub reset change + // if there is something physically detached, but still logically + // attached... + // + OldUsbIoDevice = HubController->Children[StatusChangePort - 1]; + + if (NULL != OldUsbIoDevice) { + UsbDeviceDeConfiguration (OldUsbIoDevice); + HubController->Children[StatusChangePort - 1] = NULL; + } + + NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE)); + if (NewDevice == NULL) { + return ; + } + // + // Initialize some fields + // + NewDevice->DeviceDescriptor.MaxPacketSize0 = 8; + NewDevice->BusController = HubController->UsbDevice->BusController; + + // + // There is something connected to this port, + // reset that port + // + // Disable the enable bit in port status // - DEBUG ((gUSBDebugLevel, "Port Reset Change\n")); HubClearPortFeature ( UsbIo, StatusChangePort, - EfiUsbPortResetChange + EfiUsbPortEnable ); - HubGetPortStatus ( - UsbIo, - StatusChangePort, - (UINT32 *) &HubPortStatus - ); - } + gBS->Stall (50 * 1000); - if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_OVERCURRENT) { // - // Clear Hub overcurrent change + // Wait for bit change // - DEBUG ((gUSBDebugLevel, "Port Overcurrent Change\n")); - HubClearPortFeature ( - UsbIo, - StatusChangePort, - EfiUsbPortOverCurrentChange - ); - - HubGetPortStatus ( - UsbIo, - StatusChangePort, - (UINT32 *) &HubPortStatus - ); - } - - if (IsPortConnectChange (HubPortStatus.PortChangeStatus)) { - // - // First clear port connection change - // - DEBUG ((gUSBDebugLevel, "Port Connection Change\n")); - HubClearPortFeature ( - UsbIo, - StatusChangePort, - EfiUsbPortConnectChange - ); - - HubGetPortStatus ( - UsbIo, - StatusChangePort, - (UINT32 *) &HubPortStatus - ); - - if (IsPortConnect (HubPortStatus.PortStatus)) { - - DEBUG ((gUSBDebugLevel, "New Device Connect on Hub port \n")); - - ReportUsbStatusCode ( - UsbBusDev, - EFI_PROGRESS_CODE, - EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG - ); - - // - // if there is something physically detached, but still logically - // attached... - // - OldUsbIoDevice = HubController->Children[StatusChangePort - 1]; - - if (NULL != OldUsbIoDevice) { - UsbDeviceDeConfiguration (OldUsbIoDevice); - HubController->Children[StatusChangePort - 1] = NULL; - } - - NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE)); - if (NewDevice == NULL) { - return ; - } - - ResetHubPort (HubController, StatusChangePort); - + Number = 10; + do { HubGetPortStatus ( UsbIo, StatusChangePort, (UINT32 *) &HubPortStatus ); + gBS->Stall (10 * 1000); + Number -= 1; + } while ((HubPortStatus.PortStatus & USB_PORT_STAT_ENABLE) == 1 && Number > 0); + if (Number == 0) { // - // Initialize some fields + // Cannot disable port, return error // - NewDevice->IsSlowDevice = IsPortLowSpeedDeviceAttached (HubPortStatus.PortStatus); - - NewDevice->BusController = HubController->UsbDevice->BusController; - - // - // Configure that device - // - Status = UsbDeviceConfiguration ( - HubController, - HostController, - (UINT8) (StatusChangePort - 1), - NewDevice - ); - - if (EFI_ERROR (Status)) { - gBS->FreePool (NewDevice); - return ; - } - // - // Add this device to the usb bus tree - // StatusChangePort is begin from 1, - // - HubController->Children[StatusChangePort - 1] = NewDevice; - - for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) { - // - // If this device is hub, add to the hub index - // - NewController = NewDevice->UsbController[Index2]; - - // - // Connect the controller to the driver image - // - Status = gBS->ConnectController ( - NewController->Handle, - NULL, - NULL, - TRUE - ); - // - // If connect success, we need to disconnect when - // stop the controller, otherwise we need not call - // gBS->DisconnectController () - // This is used by those usb devices we don't plan - // to support. We can allocate - // controller handles for them, but we don't have - // device drivers to manage them. - // - NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status)); - - // - // If this device is hub, add to the hub index - // - if (IsHub (NewController)) { - - NewController->IsUsbHub = TRUE; - - // - // Configure Hub - // - Status = DoHubConfig (NewController); - - if (EFI_ERROR (Status)) { - continue; - } - // - // Create an event to do hub enumeration - // - gBS->CreateEvent ( - EFI_EVENT_NOTIFY_SIGNAL, - EFI_TPL_CALLBACK, - UsbEnumeration, - NewController, - &NewController->HubNotify - ); - - // - // Add request to do query hub status - // change endpoint - // - UsbIo = &NewController->UsbIo; - UsbIo->UsbAsyncInterruptTransfer ( - UsbIo, - NewController->HubEndpointAddress, // Hub endpoint address - TRUE, - 100, - 1, // Hub ports < 7 - OnHubInterruptComplete, - NewController - ); - } - } - } else { - // - // Something disconnected from USB hub - // - DEBUG ((gUSBDebugLevel, "Something Device Detached on Hub port\n")); - - OldUsbIoDevice = HubController->Children[StatusChangePort - 1]; - - UsbDeviceDeConfiguration (OldUsbIoDevice); - - HubController->Children[StatusChangePort - 1] = NULL; - + DEBUG ((gUSBErrorLevel, "Disable Port Failed\n")); + gBS->FreePool (NewDevice); + return ; } - return ; + HubSetPortFeature ( + UsbIo, + StatusChangePort, + EfiUsbPortReset + ); + + gBS->Stall (50 * 1000); + + // + // Wait for port reset complete + // + Number = 10; + do { + HubGetPortStatus ( + UsbIo, + StatusChangePort, + (UINT32 *) &HubPortStatus + ); + gBS->Stall (10 * 1000); + Number -= 1; + } while ((HubPortStatus.PortStatus & USB_PORT_STAT_RESET) == 1 && Number > 0); + + if (Number == 0) { + // + // Cannot reset port, return error + // + DEBUG ((gUSBErrorLevel, "Reset Port Failed\n")); + gBS->FreePool (NewDevice); + return ; + } + // + // Check high speed or full speed device + // + if (HubPortStatus.PortStatus & USB_PORT_STAT_LOW_SPEED) { + DEBUG ((gUSBDebugLevel, "Low Speed Device Attached to Hub\n")); + NewDevice->DeviceSpeed = EFI_USB_SPEED_LOW; + } else if (HubPortStatus.PortStatus & USB_PORT_STAT_HIGH_SPEED) { + DEBUG ((gUSBDebugLevel, "High Speed Device Attached to Hub\n")); + NewDevice->DeviceSpeed = EFI_USB_SPEED_HIGH; + } else { + DEBUG ((gUSBDebugLevel, "Full Speed Device Attached to Hub\n")); + NewDevice->DeviceSpeed = EFI_USB_SPEED_FULL; + } + // + // Configure that device + // + Status = UsbDeviceConfiguration ( + HubController, + HostController, + (UINT8) (StatusChangePort - 1), + NewDevice + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (NewDevice); + return ; + } + // + // Add this device to the usb bus tree + // StatusChangePort is begin from 1, + // + HubController->Children[StatusChangePort - 1] = NewDevice; + + for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) { + // + // If this device is hub, add to the hub index + // + NewController = NewDevice->UsbController[Index2]; + + // + // Connect the controller to the driver image + // + Status = gBS->ConnectController ( + NewController->Handle, + NULL, + NULL, + TRUE + ); + // + // If connect success, we need to disconnect when + // stop the controller, otherwise we need not call + // gBS->DisconnectController () + // This is used by those usb devices we don't plan + // to support. We can allocate + // controller handles for them, but we don't have + // device drivers to manage them. + // + NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status)); + + // + // If this device is hub, add to the hub index + // + if (IsHub (NewController)) { + + NewController->IsUsbHub = TRUE; + + // + // Configure Hub + // + Status = DoHubConfig (NewController); + + if (EFI_ERROR (Status)) { + continue; + } + // + // Create an event to do hub enumeration + // + gBS->CreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + HubEnumeration, + NewController, + &NewController->HubNotify + ); + + // + // Add request to do query hub status + // change endpoint + // + UsbIo = &NewController->UsbIo; + UsbIo->UsbAsyncInterruptTransfer ( + UsbIo, + NewController->HubEndpointAddress, // Hub endpoint address + TRUE, + 100, + 1, // Hub ports < 7 + OnHubInterruptComplete, + NewController + ); + } + } + } else { + // + // Something disconnected from USB hub + // + DEBUG ((gUSBDebugLevel, "Something Device Detached on Hub port\n")); + + OldUsbIoDevice = HubController->Children[StatusChangePort - 1]; + + UsbDeviceDeConfiguration (OldUsbIoDevice); + + HubController->Children[StatusChangePort - 1] = NULL; + } return ; } -} -// -// Clear port connection change status over a given root hub port -// -EFI_STATUS -ClearRootPortConnectionChangeStatus ( - UINT8 PortNum, - EFI_USB_HC_PROTOCOL *UsbHCInterface - ) -/*++ - Routine Description: - Clear port connection change status over a given root hub port - - Arguments: - PortNum - The given port. - UsbHCInterface - The EFI_USB_HC_PROTOCOL instance. - - Returns: - EFI_SUCCESS - ---*/ -{ - EFI_STATUS Status; - Status = UsbHCInterface->ClearRootHubPortFeature ( - UsbHCInterface, - PortNum, - EfiUsbPortConnectChange - ); - return Status; + return ; } STATIC @@ -1877,6 +2171,7 @@ InitUsbIoController ( EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; EFI_USB_HC_PROTOCOL *UsbHcProtocol; + EFI_USB2_HC_PROTOCOL *Usb2HcProtocol; // // Build the child device path for each new USB_IO device @@ -1908,14 +2203,25 @@ InitUsbIoController ( return Status; } - Status = gBS->OpenProtocol ( - UsbIoController->HostController, - &gEfiUsbHcProtocolGuid, - (VOID **) &UsbHcProtocol, - gUsbBusDriverBinding.DriverBindingHandle, - UsbIoController->Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); + if (UsbIoController->UsbDevice->BusController->Hc2ProtocolSupported) { + Status = gBS->OpenProtocol ( + UsbIoController->HostController, + &gEfiUsb2HcProtocolGuid, + (VOID **)&Usb2HcProtocol, + gUsbBusDriverBinding.DriverBindingHandle, + UsbIoController->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + Status = gBS->OpenProtocol ( + UsbIoController->HostController, + &gEfiUsbHcProtocolGuid, + (VOID **)&UsbHcProtocol, + gUsbBusDriverBinding.DriverBindingHandle, + UsbIoController->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } return Status; } @@ -1934,8 +2240,9 @@ ParentPortReset ( Arguments: UsbIoController - Indicating the Usb Controller Device. - Reconfigure - Do we need to reconfigure it. + ReConfigure - Do we need to reconfigure it. RetryTimes - Retry Times when failed + Returns: EFI_SUCCESS EFI_DEVICE_ERROR @@ -1960,7 +2267,7 @@ ParentPortReset ( if (ParentIoDev->DeviceAddress == 1) { DEBUG ((gUSBDebugLevel, "Reset from Root Hub 0x%x\n", HubPort)); - ResetRootPort (ParentIoDev->BusController->UsbHCInterface, HubPort, RetryTimes); + ResetRootPort (ParentIoDev->BusController, HubPort, RetryTimes); } else { DEBUG ((gUSBDebugLevel, "Reset from Hub, Addr 0x%x\n", ParentIoDev->DeviceAddress)); ResetHubPort (ParentController, HubPort + 1); @@ -2036,9 +2343,9 @@ UsbPortReset ( EFI_STATUS ResetRootPort ( - IN EFI_USB_HC_PROTOCOL *UsbHCInterface, - IN UINT8 PortNum, - IN UINT8 RetryTimes + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 PortNum, + IN UINT8 RetryTimes ) /*++ @@ -2046,25 +2353,27 @@ ResetRootPort ( Reset Root Hub port. Arguments: - UsbHCInterface - The EFI_USB_HC_PROTOCOL instance. - PortNum - The given port to be reset. - RetryTimes - RetryTimes when failed + UsbBusDev - Bus controller of the device. + PortNum - The given port to be reset. + RetryTimes - RetryTimes when failed + Returns: - N/A + EFI_SUCCESS + EFI_DEVICE_ERROR --*/ { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_USB_PORT_STATUS PortStatus; // // reset root port // - Status = UsbHCInterface->SetRootHubPortFeature ( - UsbHCInterface, - PortNum, - EfiUsbPortReset - ); - + Status = UsbVirtualHcSetRootHubPortFeature ( + UsbBusDev, + PortNum, + EfiUsbPortReset + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -2074,46 +2383,56 @@ ResetRootPort ( // // clear reset root port // - Status = UsbHCInterface->ClearRootHubPortFeature ( - UsbHCInterface, - PortNum, - EfiUsbPortReset - ); - + Status = UsbVirtualHcClearRootHubPortFeature ( + UsbBusDev, + PortNum, + EfiUsbPortReset + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } gBS->Stall (1000); - Status = ClearRootPortConnectionChangeStatus (PortNum, UsbHCInterface); - - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - // - // Set port enable - // - Status = UsbHCInterface->SetRootHubPortFeature ( - UsbHCInterface, - PortNum, - EfiUsbPortEnable - ); + Status = UsbVirtualHcClearRootHubPortFeature ( + UsbBusDev, + PortNum, + EfiUsbPortConnectChange + ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } - Status = UsbHCInterface->ClearRootHubPortFeature ( - UsbHCInterface, - PortNum, - EfiUsbPortEnableChange - ); + UsbVirtualHcGetRootHubPortStatus ( + UsbBusDev, + PortNum, + &PortStatus + ); + if (PortStatus.PortStatus & USB_PORT_STAT_OWNER) { + // + // Set port enable + // + Status = UsbVirtualHcSetRootHubPortFeature ( + UsbBusDev, + PortNum, + EfiUsbPortEnable + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = UsbVirtualHcClearRootHubPortFeature ( + UsbBusDev, + PortNum, + EfiUsbPortEnableChange + ); + } + gBS->Stall ((1 + RetryTimes) * 50 * 1000); return EFI_SUCCESS; } - EFI_STATUS ResetHubPort ( IN USB_IO_CONTROLLER_DEVICE *UsbIoController, @@ -2202,10 +2521,6 @@ ResetHubPort ( return EFI_SUCCESS; } - - - - STATIC EFI_STATUS ReportUsbStatusCode ( @@ -2236,7 +2551,6 @@ Routine Description: ); } - EFI_STATUS IsDeviceDisconnected ( IN USB_IO_CONTROLLER_DEVICE *UsbIoController, @@ -2264,7 +2578,6 @@ IsDeviceDisconnected ( EFI_STATUS Status; EFI_USB_IO_PROTOCOL *UsbIo; EFI_USB_PORT_STATUS PortStatus; - EFI_USB_HC_PROTOCOL *UsbHCInterface; ParentController = UsbIoController->Parent; ParentIoDev = ParentController->UsbDevice; @@ -2275,12 +2588,11 @@ IsDeviceDisconnected ( // // Connected to the root hub // - UsbHCInterface = ParentIoDev->BusController->UsbHCInterface; - Status = UsbHCInterface->GetRootHubPortStatus ( - UsbHCInterface, - HubPort, - &PortStatus - ); + UsbVirtualHcGetRootHubPortStatus ( + ParentIoDev->BusController, + HubPort, + &PortStatus + ); } else { UsbIo = &UsbIoController->UsbIo; @@ -2303,3 +2615,1135 @@ IsDeviceDisconnected ( return EFI_SUCCESS; } + +STATIC +EFI_STATUS +UsbSetTransactionTranslator ( + IN USB_IO_CONTROLLER_DEVICE *ParentHubController, + IN UINT8 ParentPort, + IN OUT USB_IO_DEVICE *Device + ) +/*++ + + Routine Description: + + Set Transaction Translator parameter + + Arguments: + + ParentHubController - Controller structure of the parent Hub device + ParentPort - Number of parent port + Device - Structure of the device + + Returns: + + EFI_SUCCESS Success + EFI_OUT_OF_RESOURCES Cannot allocate resources + +--*/ +{ + USB_IO_CONTROLLER_DEVICE *AncestorHubController; + + AncestorHubController = ParentHubController; + Device->Translator = NULL; + + if (EFI_USB_SPEED_HIGH == Device->DeviceSpeed) { + return EFI_SUCCESS; + } + + do { + if (EFI_USB_SPEED_HIGH == AncestorHubController->UsbDevice->DeviceSpeed) { + break; + } + + if (NULL == AncestorHubController->Parent) { + return EFI_SUCCESS; + } + + AncestorHubController = AncestorHubController->Parent; + } while (1); + + Device->Translator = AllocatePool (sizeof (EFI_USB2_HC_TRANSACTION_TRANSLATOR)); + if (NULL == Device->Translator) { + return EFI_OUT_OF_RESOURCES; + } + + Device->Translator->TranslatorHubAddress = AncestorHubController->UsbDevice->DeviceAddress; + Device->Translator->TranslatorPortNumber = ParentPort; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +UsbUnsetTransactionTranslator ( + USB_IO_DEVICE *Device + ) +/*++ + + Routine Description: + + Unset Transaction Translator parameter + + Arguments: + + Device - Structure of the device + + Returns: + + EFI_SUCCESS Success + +--*/ +{ + if (Device->Translator) { + gBS->FreePool (Device->Translator); + Device->Translator = NULL; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +IdentifyDeviceSpeed ( + USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + USB_IO_DEVICE *NewDevice, + UINT8 Index + ) +/*++ + + Routine Description: + + Identify speed of USB device + + Arguments: + + UsbBusDev - UsbBus controller structure of the device + NewDevice - Devcie controller structure + Index - Number of the port + + Returns: + + EFI_SUCCESS Success + EFI_NOT_FOUND Device release to CHC or can't be found + +--*/ +{ + EFI_STATUS Status; + EFI_USB_PORT_STATUS HubPortStatus; + + UsbVirtualHcGetRootHubPortStatus ( + UsbBusDev, + Index, + (EFI_USB_PORT_STATUS *) &HubPortStatus + ); + + // + // Check device device + // + if (!(HubPortStatus.PortStatus & USB_PORT_STAT_OWNER)) { + // + // EHC Port Owner + // + if (HubPortStatus.PortStatus & USB_PORT_STAT_HIGH_SPEED) { + DEBUG ((gUSBDebugLevel, "High Speed Device attached to EHC\n")); + NewDevice->DeviceSpeed = EFI_USB_SPEED_HIGH; + } else { + Status = ReleasePortToCHC (UsbBusDev, Index); + if (EFI_ERROR (Status)) { + DEBUG ((gUSBErrorLevel, "Fail to release port to CHC\n")); + } else { + DEBUG ((gUSBDebugLevel, "Success to release port to CHC\n")); + } + return EFI_DEVICE_ERROR; + } + } else { + // + // CHC Port Owner + // + if (HubPortStatus.PortStatus & USB_PORT_STAT_LOW_SPEED) { + DEBUG ((gUSBDebugLevel, "Low Speed Device attached to CHC\n")); + NewDevice->DeviceSpeed = EFI_USB_SPEED_LOW; + } else { + DEBUG ((gUSBDebugLevel, "FULL Speed Device attached to CHC\n")); + NewDevice->DeviceSpeed = EFI_USB_SPEED_FULL; + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ReleasePortToCHC ( + USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + UINT8 PortNum + ) +/*++ + + Routine Description: + + Set bit to release the port owner to CHC + + Arguments: + + UsbBusDev - UsbBus controller structure of the device + PortNum - Number of the port + + Returns: + + EFI_SUCCESS Success + EFI_DEVICE_ERROR Fail + +--*/ +{ + EFI_STATUS Status; + + Status = UsbVirtualHcSetRootHubPortFeature ( + UsbBusDev, + PortNum, + EfiUsbPortOwner + ); + + gBS->Stall (100 * 1000); + + return Status; +} + +EFI_STATUS +EFIAPI +UsbVirtualHcGetCapability ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + OUT UINT8 *MaxSpeed, + OUT UINT8 *PortNumber, + OUT UINT8 *Is64BitCapable + ) +/*++ + + Routine Description: + + Virtual interface to Retrieves the capablility of root hub ports + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + MaxSpeed - A pointer to the number of the host controller. + PortNumber - A pointer to the number of the root hub ports. + Is64BitCapable - A pointer to the flag for whether controller supports + 64-bit memory addressing. + + Returns: + + EFI_SUCCESS + The host controller capability were retrieved successfully. + EFI_INVALID_PARAMETER + MaxSpeed or PortNumber or Is64BitCapable is NULL. + EFI_DEVICE_ERROR + An error was encountered while attempting to retrieve the capabilities. + +--*/ +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + if (UsbBusDev->Hc2ProtocolSupported) { + Status = UsbBusDev->Usb2HCInterface->GetCapability ( + UsbBusDev->Usb2HCInterface, + MaxSpeed, + PortNumber, + Is64BitCapable + ); + } else { + Status = UsbBusDev->UsbHCInterface->GetRootHubPortNumber ( + UsbBusDev->UsbHCInterface, + PortNumber + ); + *MaxSpeed = EFI_USB_SPEED_FULL; + *Is64BitCapable = (UINT8) FALSE; + } + + return Status; +} + +EFI_STATUS +EFIAPI +UsbVirtualHcReset ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT16 Attributes + ) +/*++ + + Routine Description: + + Virtual interface to provides software reset for the USB host controller + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + Attributes - A bit mask of the reset operation to perform. + See below for a list of the supported bit mask values. + + #define EFI_USB_HC_RESET_GLOBAL 0x0001 // Hc2 and Hc + #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002 // Hc2 and Hc + #define EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG 0x0004 // Hc2 + #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008 // Hc2 + + EFI_USB_HC_RESET_GLOBAL + If this bit is set, a global reset signal will be sent to the USB bus. + This resets all of the USB bus logic, including the USB host + controller hardware and all the devices attached on the USB bus. + EFI_USB_HC_RESET_HOST_CONTROLLER + If this bit is set, the USB host controller hardware will be reset. + No reset signal will be sent to the USB bus. + EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG + If this bit is set, a global reset signal will be sent to the USB bus. + This resets all of the USB bus logic, including the USB host + controller hardware and all the devices attached on the USB bus. + If this is an EHCI controller and the debug port has configured, then + this is will still reset the host controller. + EFI_USB_HC_RESET_HOST_WITH_DEBUG + If this bit is set, the USB host controller hardware will be reset. + If this is an EHCI controller and the debug port has been configured, + then this will still reset the host controller. + + Returns: + + EFI_SUCCESS + The reset operation succeeded. + EFI_INVALID_PARAMETER + Attributes is not valid. + EFI_UNSUPPOURTED + The type of reset specified by Attributes is not currently supported by + the host controller hardware. + EFI_ACCESS_DENIED + Reset operation is rejected due to the debug port being configured and + active; only EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG or + EFI_USB_HC_RESET_HOST_WITH_DEBUG reset Atrributes can be used to + perform reset operation for this host controller. + EFI_DEVICE_ERROR + An error was encountered while attempting to perform + the reset operation. + +--*/ +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + if (UsbBusDev->Hc2ProtocolSupported) { + Status = UsbBusDev->Usb2HCInterface->Reset ( + UsbBusDev->Usb2HCInterface, + EFI_USB_HC_RESET_GLOBAL + ); + } else { + Status = UsbBusDev->UsbHCInterface->Reset ( + UsbBusDev->UsbHCInterface, + EFI_USB_HC_RESET_GLOBAL + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +UsbVirtualHcGetState ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + OUT EFI_USB_HC_STATE *State + ) +/*++ + + Routine Description: + + Virtual interface to retrieves current state of the USB host controller + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + State - A pointer to the EFI_USB_HC_STATE data structure that + indicates current state of the USB host controller. + Type EFI_USB_HC_STATE is defined below. + + typedef enum { + EfiUsbHcStateHalt, + EfiUsbHcStateOperational, + EfiUsbHcStateSuspend, + EfiUsbHcStateMaximum + } EFI_USB_HC_STATE; + + Returns: + + EFI_SUCCESS + The state information of the host controller was returned in State. + EFI_INVALID_PARAMETER + State is NULL. + EFI_DEVICE_ERROR + An error was encountered while attempting to retrieve the + host controller's current state. + +--*/ +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + if (UsbBusDev->Hc2ProtocolSupported) { + Status = UsbBusDev->Usb2HCInterface->GetState ( + UsbBusDev->Usb2HCInterface, + State + ); + } else { + Status = UsbBusDev->UsbHCInterface->GetState ( + UsbBusDev->UsbHCInterface, + State + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +UsbVirtualHcSetState ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN EFI_USB_HC_STATE State + ) +/*++ + + Routine Description: + + Virtual interface to sets the USB host controller to a specific state + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + State - Indicates the state of the host controller that will be set. + + Returns: + + EFI_SUCCESS + The USB host controller was successfully placed in the state + specified by State. + EFI_INVALID_PARAMETER + State is invalid. + EFI_DEVICE_ERROR + Failed to set the state specified by State due to device error. + +--*/ +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + if (UsbBusDev->Hc2ProtocolSupported) { + Status = UsbBusDev->Usb2HCInterface->SetState ( + UsbBusDev->Usb2HCInterface, + State + ); + } else { + Status = UsbBusDev->UsbHCInterface->SetState ( + UsbBusDev->UsbHCInterface, + State + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +UsbVirtualHcGetRootHubPortStatus ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus + ) +/*++ + + Routine Description: + + Virtual interface to retrieves the current status of a USB root hub port + both for Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + PortNumber - Specifies the root hub port from which the status + is to be retrieved. This value is zero-based. For example, + if a root hub has two ports, then the first port is numbered 0, + and the second port is numbered 1. + PortStatus - A pointer to the current port status bits and + port status change bits. + + Returns: + + EFI_SUCCESS The status of the USB root hub port specified by PortNumber + was returned in PortStatus. + EFI_INVALID_PARAMETER PortNumber is invalid. + EFI_DEVICE_ERROR Can't read register + +--*/ +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + if (UsbBusDev->Hc2ProtocolSupported) { + Status = UsbBusDev->Usb2HCInterface->GetRootHubPortStatus ( + UsbBusDev->Usb2HCInterface, + PortNumber, + PortStatus + ); + } else { + Status = UsbBusDev->UsbHCInterface->GetRootHubPortStatus ( + UsbBusDev->UsbHCInterface, + PortNumber, + PortStatus + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +UsbVirtualHcSetRootHubPortFeature ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +/*++ + + Routine Description: + Virual interface to sets a feature for the specified root hub port + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + PortNumber - Specifies the root hub port whose feature + is requested to be set. + PortFeature - Indicates the feature selector associated + with the feature set request. + + Returns: + + EFI_SUCCESS + The feature specified by PortFeature was set for the + USB root hub port specified by PortNumber. + EFI_INVALID_PARAMETER + PortNumber is invalid or PortFeature is invalid. + EFI_DEVICE_ERROR + Can't read register + +--*/ +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + if (UsbBusDev->Hc2ProtocolSupported) { + Status = UsbBusDev->Usb2HCInterface->SetRootHubPortFeature ( + UsbBusDev->Usb2HCInterface, + PortNumber, + PortFeature + ); + } else { + Status = UsbBusDev->UsbHCInterface->SetRootHubPortFeature ( + UsbBusDev->UsbHCInterface, + PortNumber, + PortFeature + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +UsbVirtualHcClearRootHubPortFeature ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +/*++ + + Routine Description: + + Virtual interface to clears a feature for the specified root hub port + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + PortNumber - Specifies the root hub port whose feature + is requested to be cleared. + PortFeature - Indicates the feature selector associated with the + feature clear request. + + Returns: + + EFI_SUCCESS + The feature specified by PortFeature was cleared for the + USB root hub port specified by PortNumber. + EFI_INVALID_PARAMETER + PortNumber is invalid or PortFeature is invalid. + EFI_DEVICE_ERROR + Can't read register + +--*/ +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + if (UsbBusDev->Hc2ProtocolSupported) { + Status = UsbBusDev->Usb2HCInterface->ClearRootHubPortFeature ( + UsbBusDev->Usb2HCInterface, + PortNumber, + PortFeature + ); + } else { + Status = UsbBusDev->UsbHCInterface->ClearRootHubPortFeature ( + UsbBusDev->UsbHCInterface, + PortNumber, + PortFeature + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +UsbVirtualHcControlTransfer ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 DeviceAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + + Virtual interface to submits control transfer to a target USB device + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + DeviceSpeed - Indicates target device speed. + MaximumPacketLength - Indicates the maximum packet size that the + default control transfer endpoint is capable of + sending or receiving. + Request - A pointer to the USB device request that will be sent + to the USB device. + TransferDirection - Specifies the data direction for the transfer. + There are three values available, DataIn, DataOut + and NoData. + Data - A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + DataLength - Indicates the size, in bytes, of the data buffer + specified by Data. + TimeOut - Indicates the maximum time, in microseconds, + which the transfer is allowed to complete. + Translator - A pointr to the transaction translator data. + TransferResult - A pointer to the detailed result information generated + by this control transfer. + + Returns: + + EFI_SUCCESS + The control transfer was completed successfully. + EFI_OUT_OF_RESOURCES + The control transfer could not be completed due to a lack of resources. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_TIMEOUT + The control transfer failed due to timeout. + EFI_DEVICE_ERROR + The control transfer failed due to host controller or device error. + Caller should check TranferResult for detailed error information. + +--*/ +{ + EFI_STATUS Status; + BOOLEAN IsSlowDevice; + + Status = EFI_SUCCESS; + + if (UsbBusDev->Hc2ProtocolSupported) { + Status = UsbBusDev->Usb2HCInterface->ControlTransfer ( + UsbBusDev->Usb2HCInterface, + DeviceAddress, + DeviceSpeed, + MaximumPacketLength, + Request, + TransferDirection, + Data, + DataLength, + TimeOut, + Translator, + TransferResult + ); + } else { + IsSlowDevice = (EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE; + Status = UsbBusDev->UsbHCInterface->ControlTransfer ( + UsbBusDev->UsbHCInterface, + DeviceAddress, + IsSlowDevice, + (UINT8) MaximumPacketLength, + Request, + TransferDirection, + Data, + DataLength, + TimeOut, + TransferResult + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +UsbVirtualHcBulkTransfer ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + + Virtual interface to submits bulk transfer to a bulk endpoint of a USB device + both for Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - The combination of an endpoint number and an + endpoint direction of the target USB device. + Each endpoint address supports data transfer in + one direction except the control endpoint + (whose default endpoint address is 0). + It is the caller's responsibility to make sure that + the EndPointAddress represents a bulk endpoint. + DeviceSpeed - Indicates device speed. The supported values are EFI_USB_SPEED_FULL + and EFI_USB_SPEED_HIGH. + MaximumPacketLength - Indicates the maximum packet size the target endpoint + is capable of sending or receiving. + DataBuffersNumber - Number of data buffers prepared for the transfer. + Data - Array of pointers to the buffers of data that will be transmitted + to USB device or received from USB device. + DataLength - When input, indicates the size, in bytes, of the data buffer + specified by Data. When output, indicates the actually + transferred data size. + DataToggle - A pointer to the data toggle value. On input, it indicates + the initial data toggle value the bulk transfer should adopt; + on output, it is updated to indicate the data toggle value + of the subsequent bulk transfer. + Translator - A pointr to the transaction translator data. + TimeOut - Indicates the maximum time, in microseconds, which the + transfer is allowed to complete. + TransferResult - A pointer to the detailed result information of the + bulk transfer. + + Returns: + + EFI_SUCCESS + The bulk transfer was completed successfully. + EFI_OUT_OF_RESOURCES + The bulk transfer could not be submitted due to lack of resource. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_TIMEOUT + The bulk transfer failed due to timeout. + EFI_DEVICE_ERROR + The bulk transfer failed due to host controller or device error. + Caller should check TranferResult for detailed error information. + +--*/ +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + if (UsbBusDev->Hc2ProtocolSupported) { + Status = UsbBusDev->Usb2HCInterface->BulkTransfer ( + UsbBusDev->Usb2HCInterface, + DeviceAddress, + EndPointAddress, + DeviceSpeed, + MaximumPacketLength, + DataBuffersNumber, + Data, + DataLength, + DataToggle, + TimeOut, + Translator, + TransferResult + ); + } else { + Status = UsbBusDev->UsbHCInterface->BulkTransfer ( + UsbBusDev->UsbHCInterface, + DeviceAddress, + EndPointAddress, + (UINT8) MaximumPacketLength, + *Data, + DataLength, + DataToggle, + TimeOut, + TransferResult + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +UsbVirtualHcAsyncInterruptTransfer ( + IN USB_BUS_CONTROLLER_DEVICE * UsbBusDev, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle, + IN UINTN PollingInterval, + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, + IN VOID *Context OPTIONAL + ) +/*++ + + Routine Description: + + Virtual interface to submits an asynchronous interrupt transfer to an + interrupt endpoint of a USB device for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - The combination of an endpoint number and an endpoint + direction of the target USB device. Each endpoint address + supports data transfer in one direction except the + control endpoint (whose default endpoint address is 0). + It is the caller's responsibility to make sure that + the EndPointAddress represents an interrupt endpoint. + DeviceSpeed - Indicates device speed. + MaximumPacketLength - Indicates the maximum packet size the target endpoint + is capable of sending or receiving. + IsNewTransfer - If TRUE, an asynchronous interrupt pipe is built between + the host and the target interrupt endpoint. + If FALSE, the specified asynchronous interrupt pipe + is canceled. + DataToggle - A pointer to the data toggle value. On input, it is valid + when IsNewTransfer is TRUE, and it indicates the initial + data toggle value the asynchronous interrupt transfer + should adopt. + On output, it is valid when IsNewTransfer is FALSE, + and it is updated to indicate the data toggle value of + the subsequent asynchronous interrupt transfer. + PollingInterval - Indicates the interval, in milliseconds, that the + asynchronous interrupt transfer is polled. + This parameter is required when IsNewTransfer is TRUE. + DataLength - Indicates the length of data to be received at the + rate specified by PollingInterval from the target + asynchronous interrupt endpoint. This parameter + is only required when IsNewTransfer is TRUE. + Translator - A pointr to the transaction translator data. + CallBackFunction - The Callback function.This function is called at the + rate specified by PollingInterval.This parameter is + only required when IsNewTransfer is TRUE. + Context - The context that is passed to the CallBackFunction. + - This is an optional parameter and may be NULL. + + Returns: + + EFI_SUCCESS + The asynchronous interrupt transfer request has been successfully + submitted or canceled. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_OUT_OF_RESOURCES + The request could not be completed due to a lack of resources. + EFI_DEVICE_ERROR + Can't read register + +--*/ +{ + EFI_STATUS Status; + BOOLEAN IsSlowDevice; + + Status = EFI_SUCCESS; + + if (UsbBusDev->Hc2ProtocolSupported) { + Status = UsbBusDev->Usb2HCInterface->AsyncInterruptTransfer ( + UsbBusDev->Usb2HCInterface, + DeviceAddress, + EndPointAddress, + DeviceSpeed, + MaximumPacketLength, + IsNewTransfer, + DataToggle, + PollingInterval, + DataLength, + Translator, + CallBackFunction, + Context + ); + } else { + IsSlowDevice = (EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE; + Status = UsbBusDev->UsbHCInterface->AsyncInterruptTransfer ( + UsbBusDev->UsbHCInterface, + DeviceAddress, + EndPointAddress, + IsSlowDevice, + (UINT8) MaximumPacketLength, + IsNewTransfer, + DataToggle, + PollingInterval, + DataLength, + CallBackFunction, + Context + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +UsbVirtualHcSyncInterruptTransfer ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + + Vitual interface to submits synchronous interrupt transfer to an interrupt endpoint + of a USB device for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - The combination of an endpoint number and an endpoint + direction of the target USB device. Each endpoint + address supports data transfer in one direction + except the control endpoint (whose default + endpoint address is 0). It is the caller's responsibility + to make sure that the EndPointAddress represents + an interrupt endpoint. + DeviceSpeed - Indicates device speed. + MaximumPacketLength - Indicates the maximum packet size the target endpoint + is capable of sending or receiving. + Data - A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + DataLength - On input, the size, in bytes, of the data buffer specified + by Data. On output, the number of bytes transferred. + DataToggle - A pointer to the data toggle value. On input, it indicates + the initial data toggle value the synchronous interrupt + transfer should adopt; + on output, it is updated to indicate the data toggle value + of the subsequent synchronous interrupt transfer. + TimeOut - Indicates the maximum time, in microseconds, which the + transfer is allowed to complete. + Translator - A pointr to the transaction translator data. + TransferResult - A pointer to the detailed result information from + the synchronous interrupt transfer. + + Returns: + + EFI_SUCCESS + The synchronous interrupt transfer was completed successfully. + EFI_OUT_OF_RESOURCES + The synchronous interrupt transfer could not be submitted due + to lack of resource. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_TIMEOUT + The synchronous interrupt transfer failed due to timeout. + EFI_DEVICE_ERROR + The synchronous interrupt transfer failed due to host controller + or device error. Caller should check TranferResult for detailed + error information. + +--*/ +{ + EFI_STATUS Status; + BOOLEAN IsSlowDevice; + + Status = EFI_SUCCESS; + + if (UsbBusDev->Hc2ProtocolSupported) { + Status = UsbBusDev->Usb2HCInterface->SyncInterruptTransfer ( + UsbBusDev->Usb2HCInterface, + DeviceAddress, + EndPointAddress, + DeviceSpeed, + MaximumPacketLength, + Data, + DataLength, + DataToggle, + TimeOut, + Translator, + TransferResult + ); + } else { + IsSlowDevice = (EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE; + Status = UsbBusDev->UsbHCInterface->SyncInterruptTransfer ( + UsbBusDev->UsbHCInterface, + DeviceAddress, + EndPointAddress, + IsSlowDevice, + (UINT8) MaximumPacketLength, + Data, + DataLength, + DataToggle, + TimeOut, + TransferResult + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +UsbVirtualHcIsochronousTransfer ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + + Virtual interface to submits isochronous transfer to a target USB device + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - End point address + DeviceSpeed - Indicates device speed. + MaximumPacketLength - Indicates the maximum packet size that the + default control transfer endpoint is capable of + sending or receiving. + DataBuffersNumber - Number of data buffers prepared for the transfer. + Data - Array of pointers to the buffers of data that will be + transmitted to USB device or received from USB device. + DataLength - Indicates the size, in bytes, of the data buffer + specified by Data. + Translator - A pointr to the transaction translator data. + TransferResult - A pointer to the detailed result information generated + by this control transfer. + + Returns: + + EFI_UNSUPPORTED + +--*/ +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +UsbVirtualHcAsyncIsochronousTransfer ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context + ) +/*++ + + Routine Description: + + Vitual interface to submits Async isochronous transfer to a target USB device + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - End point address + DeviceSpeed - Indicates device speed. + MaximumPacketLength - Indicates the maximum packet size that the + default control transfer endpoint is capable of + sending or receiving. + DataBuffersNumber - Number of data buffers prepared for the transfer. + Data - Array of pointers to the buffers of data that will be transmitted + to USB device or received from USB device. + DataLength - Indicates the size, in bytes, of the data buffer + specified by Data. + Translator - A pointr to the transaction translator data. + IsochronousCallBack - When the transfer complete, the call back function will be called + Context - Pass to the call back function as parameter + + Returns: + + EFI_UNSUPPORTED + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h index 036f4dfe50..47f0fd804f 100644 --- a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h @@ -30,13 +30,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "hub.h" #include "usbutil.h" -//#ifdef EFI_DEBUG extern UINTN gUSBDebugLevel; extern UINTN gUSBErrorLevel; -//#endif -#define MICROSECOND 10000 -#define ONESECOND (1000 * MICROSECOND) +#define MICROSECOND 10000 +#define ONESECOND (1000 * MICROSECOND) #define BUSPOLLING_PERIOD ONESECOND // // We define some maximun value here @@ -120,21 +118,23 @@ typedef struct usb_io_controller_device { struct _usb_bus_controller_device; typedef struct usb_io_device { - UINT8 DeviceAddress; - BOOLEAN IsConfigured; - BOOLEAN IsSlowDevice; - EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor; - LIST_ENTRY ConfigDescListHead; - CONFIG_DESC_LIST_ENTRY *ActiveConfig; - UINT16 LangID[USB_MAXLANID]; + UINT8 DeviceAddress; + BOOLEAN IsConfigured; + BOOLEAN IsSlowDevice; + UINT8 DeviceSpeed; + EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator; + EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor; + LIST_ENTRY ConfigDescListHead; + CONFIG_DESC_LIST_ENTRY *ActiveConfig; + UINT16 LangID[USB_MAXLANID]; - struct _usb_bus_controller_device *BusController; + struct _usb_bus_controller_device *BusController; // // Track the controller handle // - UINT8 NumOfControllers; - USB_IO_CONTROLLER_DEVICE *UsbController[USB_MAXCONTROLLERS]; + UINT8 NumOfControllers; + USB_IO_CONTROLLER_DEVICE *UsbController[USB_MAXCONTROLLERS]; } USB_IO_DEVICE; @@ -154,10 +154,12 @@ typedef struct _usb_bus_controller_device { UINTN Signature; EFI_USB_BUS_PROTOCOL BusIdentify; + EFI_USB2_HC_PROTOCOL *Usb2HCInterface; EFI_USB_HC_PROTOCOL *UsbHCInterface; EFI_DEVICE_PATH_PROTOCOL *DevicePath; UINT8 AddressPool[16]; USB_IO_DEVICE *Root; + BOOLEAN Hc2ProtocolSupported; } USB_BUS_CONTROLLER_DEVICE; #define USB_BUS_CONTROLLER_DEVICE_FROM_THIS(a) \ @@ -177,28 +179,99 @@ extern EFI_GUID gUSBBusDriverGuid; BOOLEAN IsHub ( IN USB_IO_CONTROLLER_DEVICE *Dev - ); + ) +/*++ + + Routine Description: + Tell if a usb controller is a hub controller. + + Arguments: + Dev - UsbIoController device structure. + + Returns: + TRUE/FALSE +--*/ +; EFI_STATUS UsbGetStringtable ( IN USB_IO_DEVICE *UsbIoDevice - ); + ) +/*++ + + Routine Description: + Get the string table stored in a usb device. + + Arguments: + Dev - UsbIoController device structure. + + Returns: + EFI_SUCCESS + EFI_UNSUPPORTED + EFI_OUT_OF_RESOURCES + +--*/ +; EFI_STATUS UsbGetAllConfigurations ( IN USB_IO_DEVICE *UsbIoDevice - ); + ) +/*++ + + Routine Description: + This function is to parse all the configuration descriptor. + + Arguments: + UsbIoDevice - USB_IO_DEVICE device structure. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + EFI_OUT_OF_RESOURCES + +--*/ +; EFI_STATUS UsbSetConfiguration ( IN USB_IO_DEVICE *Dev, IN UINTN ConfigurationValue - ); + ) +/*++ + + Routine Description: + Set the device to a configuration value. + + Arguments: + UsbIoDev - USB_IO_DEVICE to be set configuration + ConfigrationValue - The configuration value to be set to that device + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +; EFI_STATUS UsbSetDefaultConfiguration ( IN USB_IO_DEVICE *Dev - ); + ) +/*++ + + Routine Description: + Set the device to a default configuration value. + + Arguments: + UsbIoDev - USB_IO_DEVICE to be set configuration + + Returns + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +; // // Device Deconfiguration functions @@ -206,56 +279,834 @@ UsbSetDefaultConfiguration ( VOID UsbDestroyAllConfiguration ( IN USB_IO_DEVICE *UsbIoDevice - ); + ) +/*++ + + Routine Description: + Delete all configuration data when device is not used. + + Arguments: + UsbIoDevice - USB_IO_DEVICE to be set configuration + + Returns: + VOID + +--*/ +; EFI_STATUS DoHubConfig ( IN USB_IO_CONTROLLER_DEVICE *HubIoDevice - ); + ) +/*++ + + Routine Description: + Configure the hub + + Arguments: + HubController - Indicating the hub controller device that + will be configured + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ + +; VOID GetDeviceEndPointMaxPacketLength ( IN EFI_USB_IO_PROTOCOL *UsbIo, IN UINT8 EndpointAddr, - OUT UINT8 *MaxPacketLength - ); + OUT UINTN *MaxPacketLength + ) +/*++ + + Routine Description: + Get the Max Packet Length of the speified Endpoint. + + Arguments: + UsbIo - Given Usb Controller device. + EndpointAddr - Given Endpoint address. + MaxPacketLength - The max packet length of that endpoint + + Returns: + N/A + +--*/ +; VOID GetDataToggleBit ( IN EFI_USB_IO_PROTOCOL *UsbIo, IN UINT8 EndpointAddr, OUT UINT8 *DataToggle - ); + ) +/*++ + + Routine Description: + Get the datatoggle of a specified endpoint. + + Arguments: + UsbIo - Given Usb Controller device. + EndpointAddr - Given Endpoint address. + DataToggle - The current data toggle of that endpoint + + Returns: + VOID + +--*/ +; VOID SetDataToggleBit ( IN EFI_USB_IO_PROTOCOL *UsbIo, IN UINT8 EndpointAddr, IN UINT8 DataToggle - ); + ) +/*++ -INTERFACE_DESC_LIST_ENTRY * + Routine Description: + Set the datatoggle of a specified endpoint + + Arguments: + UsbIo - Given Usb Controller device. + EndpointAddr - Given Endpoint address. + DataToggle - The current data toggle of that endpoint to be set + + Returns: + VOID + +--*/ +; + +INTERFACE_DESC_LIST_ENTRY * FindInterfaceListEntry ( IN EFI_USB_IO_PROTOCOL *This - ); + ) +/*++ -ENDPOINT_DESC_LIST_ENTRY * + Routine Description: + Find Interface ListEntry. + + Arguments: + This - EFI_USB_IO_PROTOCOL + + Returns: + INTERFACE_DESC_LIST_ENTRY pointer + +--*/ +; + +ENDPOINT_DESC_LIST_ENTRY * FindEndPointListEntry ( IN EFI_USB_IO_PROTOCOL *This, IN UINT8 EndPointAddress - ); + ) +/*++ + Routine Description: + Find EndPoint ListEntry. + + Arguments: + This - EFI_USB_IO_PROTOCOL + EndpointAddr - Endpoint address. + + Returns: + ENDPOINT_DESC_LIST_ENTRY pointer + +--*/ +; EFI_STATUS IsDeviceDisconnected ( IN USB_IO_CONTROLLER_DEVICE *UsbIoController, IN OUT BOOLEAN *Disconnected - ); + ) +/*++ + + Routine Description: + Reset if the device is disconencted or not + + Arguments: + UsbIoController - Indicating the Usb Controller Device. + Disconnected - Indicate whether the device is disconencted or not + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +; EFI_STATUS UsbDeviceDeConfiguration ( IN USB_IO_DEVICE *UsbIoDevice - ); + ) +/*++ + Routine Description: + Remove Device, Device Handles, Uninstall Protocols. + + Arguments: + UsbIoDevice - The device to be deconfigured. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +; + +EFI_STATUS +EFIAPI +UsbVirtualHcGetCapability ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + OUT UINT8 *MaxSpeed, + OUT UINT8 *PortNumber, + OUT UINT8 *Is64BitCapable + ) +/*++ + + Routine Description: + + Virtual interface to Retrieves the capablility of root hub ports + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + MaxSpeed - A pointer to the number of the host controller. + PortNumber - A pointer to the number of the root hub ports. + Is64BitCapable - A pointer to the flag for whether controller supports + 64-bit memory addressing. + + Returns: + + EFI_SUCCESS + The host controller capability were retrieved successfully. + EFI_INVALID_PARAMETER + MaxSpeed or PortNumber or Is64BitCapable is NULL. + EFI_DEVICE_ERROR + An error was encountered while attempting to retrieve the capabilities. + +--*/ +; + +EFI_STATUS +EFIAPI +UsbVirtualHcReset ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT16 Attributes + ) +/*++ + + Routine Description: + + Virtual interface to provides software reset for the USB host controller + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + Attributes - A bit mask of the reset operation to perform. + See below for a list of the supported bit mask values. + + #define EFI_USB_HC_RESET_GLOBAL 0x0001 // Hc2 and Hc + #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002 // Hc2 and Hc + #define EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG 0x0004 // Hc2 + #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008 // Hc2 + + EFI_USB_HC_RESET_GLOBAL + If this bit is set, a global reset signal will be sent to the USB bus. + This resets all of the USB bus logic, including the USB host + controller hardware and all the devices attached on the USB bus. + EFI_USB_HC_RESET_HOST_CONTROLLER + If this bit is set, the USB host controller hardware will be reset. + No reset signal will be sent to the USB bus. + EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG + If this bit is set, a global reset signal will be sent to the USB bus. + This resets all of the USB bus logic, including the USB host + controller hardware and all the devices attached on the USB bus. + If this is an EHCI controller and the debug port has configured, then + this is will still reset the host controller. + EFI_USB_HC_RESET_HOST_WITH_DEBUG + If this bit is set, the USB host controller hardware will be reset. + If this is an EHCI controller and the debug port has been configured, + then this will still reset the host controller. + + Returns: + + EFI_SUCCESS + The reset operation succeeded. + EFI_INVALID_PARAMETER + Attributes is not valid. + EFI_UNSUPPOURTED + The type of reset specified by Attributes is not currently supported by + the host controller hardware. + EFI_ACCESS_DENIED + Reset operation is rejected due to the debug port being configured and + active; only EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG or + EFI_USB_HC_RESET_HOST_WITH_DEBUG reset Atrributes can be used to + perform reset operation for this host controller. + EFI_DEVICE_ERROR + An error was encountered while attempting to perform + the reset operation. + +--*/ +; + +EFI_STATUS +EFIAPI +UsbVirtualHcGetState ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + OUT EFI_USB_HC_STATE *State + ) +/*++ + + Routine Description: + + Virtual interface to retrieves current state of the USB host controller + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + State - A pointer to the EFI_USB_HC_STATE data structure that + indicates current state of the USB host controller. + Type EFI_USB_HC_STATE is defined below. + + typedef enum { + EfiUsbHcStateHalt, + EfiUsbHcStateOperational, + EfiUsbHcStateSuspend, + EfiUsbHcStateMaximum + } EFI_USB_HC_STATE; + + Returns: + + EFI_SUCCESS + The state information of the host controller was returned in State. + EFI_INVALID_PARAMETER + State is NULL. + EFI_DEVICE_ERROR + An error was encountered while attempting to retrieve the + host controller's current state. + +--*/ +; + +EFI_STATUS +EFIAPI +UsbVirtualHcSetState ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN EFI_USB_HC_STATE State + ) +/*++ + + Routine Description: + + Virtual interface to sets the USB host controller to a specific state + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + State - Indicates the state of the host controller that will be set. + + Returns: + + EFI_SUCCESS + The USB host controller was successfully placed in the state + specified by State. + EFI_INVALID_PARAMETER + State is invalid. + EFI_DEVICE_ERROR + Failed to set the state specified by State due to device error. + +--*/ +; + +EFI_STATUS +EFIAPI +UsbVirtualHcGetRootHubPortStatus ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus + ) +/*++ + + Routine Description: + + Virtual interface to retrieves the current status of a USB root hub port + both for Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + PortNumber - Specifies the root hub port from which the status + is to be retrieved. This value is zero-based. For example, + if a root hub has two ports, then the first port is numbered 0, + and the second port is numbered 1. + PortStatus - A pointer to the current port status bits and + port status change bits. + + Returns: + + EFI_SUCCESS The status of the USB root hub port specified by PortNumber + was returned in PortStatus. + EFI_INVALID_PARAMETER PortNumber is invalid. + EFI_DEVICE_ERROR Can't read register + +--*/ +; + +EFI_STATUS +EFIAPI +UsbVirtualHcSetRootHubPortFeature ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +/*++ + + Routine Description: + Virual interface to sets a feature for the specified root hub port + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + PortNumber - Specifies the root hub port whose feature + is requested to be set. + PortFeature - Indicates the feature selector associated + with the feature set request. + + Returns: + + EFI_SUCCESS + The feature specified by PortFeature was set for the + USB root hub port specified by PortNumber. + EFI_INVALID_PARAMETER + PortNumber is invalid or PortFeature is invalid. + EFI_DEVICE_ERROR + Can't read register + +--*/ +; + +EFI_STATUS +EFIAPI +UsbVirtualHcClearRootHubPortFeature ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +/*++ + + Routine Description: + + Virtual interface to clears a feature for the specified root hub port + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + PortNumber - Specifies the root hub port whose feature + is requested to be cleared. + PortFeature - Indicates the feature selector associated with the + feature clear request. + + Returns: + + EFI_SUCCESS + The feature specified by PortFeature was cleared for the + USB root hub port specified by PortNumber. + EFI_INVALID_PARAMETER + PortNumber is invalid or PortFeature is invalid. + EFI_DEVICE_ERROR + Can't read register + +--*/ +; + +EFI_STATUS +EFIAPI +UsbVirtualHcControlTransfer ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 DeviceAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + + Virtual interface to submits control transfer to a target USB device + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + DeviceSpeed - Indicates target device speed. + MaximumPacketLength - Indicates the maximum packet size that the + default control transfer endpoint is capable of + sending or receiving. + Request - A pointer to the USB device request that will be sent + to the USB device. + TransferDirection - Specifies the data direction for the transfer. + There are three values available, DataIn, DataOut + and NoData. + Data - A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + DataLength - Indicates the size, in bytes, of the data buffer + specified by Data. + TimeOut - Indicates the maximum time, in microseconds, + which the transfer is allowed to complete. + Translator - A pointr to the transaction translator data. + TransferResult - A pointer to the detailed result information generated + by this control transfer. + + Returns: + + EFI_SUCCESS + The control transfer was completed successfully. + EFI_OUT_OF_RESOURCES + The control transfer could not be completed due to a lack of resources. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_TIMEOUT + The control transfer failed due to timeout. + EFI_DEVICE_ERROR + The control transfer failed due to host controller or device error. + Caller should check TranferResult for detailed error information. + +--*/ +; + +EFI_STATUS +EFIAPI +UsbVirtualHcBulkTransfer ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + + Virtual interface to submits bulk transfer to a bulk endpoint of a USB device + both for Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - The combination of an endpoint number and an + endpoint direction of the target USB device. + Each endpoint address supports data transfer in + one direction except the control endpoint + (whose default endpoint address is 0). + It is the caller's responsibility to make sure that + the EndPointAddress represents a bulk endpoint. + DeviceSpeed - Indicates device speed. The supported values are EFI_USB_SPEED_FULL + and EFI_USB_SPEED_HIGH. + MaximumPacketLength - Indicates the maximum packet size the target endpoint + is capable of sending or receiving. + DataBuffersNumber - Number of data buffers prepared for the transfer. + Data - Array of pointers to the buffers of data that will be transmitted + to USB device or received from USB device. + DataLength - When input, indicates the size, in bytes, of the data buffer + specified by Data. When output, indicates the actually + transferred data size. + DataToggle - A pointer to the data toggle value. On input, it indicates + the initial data toggle value the bulk transfer should adopt; + on output, it is updated to indicate the data toggle value + of the subsequent bulk transfer. + Translator - A pointr to the transaction translator data. + TimeOut - Indicates the maximum time, in microseconds, which the + transfer is allowed to complete. + TransferResult - A pointer to the detailed result information of the + bulk transfer. + + Returns: + + EFI_SUCCESS + The bulk transfer was completed successfully. + EFI_OUT_OF_RESOURCES + The bulk transfer could not be submitted due to lack of resource. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_TIMEOUT + The bulk transfer failed due to timeout. + EFI_DEVICE_ERROR + The bulk transfer failed due to host controller or device error. + Caller should check TranferResult for detailed error information. + +--*/ +; + +EFI_STATUS +EFIAPI +UsbVirtualHcAsyncInterruptTransfer ( + IN USB_BUS_CONTROLLER_DEVICE * UsbBusDev, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle, + IN UINTN PollingInterval, + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, + IN VOID *Context OPTIONAL + ) +/*++ + + Routine Description: + + Virtual interface to submits an asynchronous interrupt transfer to an + interrupt endpoint of a USB device for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - The combination of an endpoint number and an endpoint + direction of the target USB device. Each endpoint address + supports data transfer in one direction except the + control endpoint (whose default endpoint address is 0). + It is the caller's responsibility to make sure that + the EndPointAddress represents an interrupt endpoint. + DeviceSpeed - Indicates device speed. + MaximumPacketLength - Indicates the maximum packet size the target endpoint + is capable of sending or receiving. + IsNewTransfer - If TRUE, an asynchronous interrupt pipe is built between + the host and the target interrupt endpoint. + If FALSE, the specified asynchronous interrupt pipe + is canceled. + DataToggle - A pointer to the data toggle value. On input, it is valid + when IsNewTransfer is TRUE, and it indicates the initial + data toggle value the asynchronous interrupt transfer + should adopt. + On output, it is valid when IsNewTransfer is FALSE, + and it is updated to indicate the data toggle value of + the subsequent asynchronous interrupt transfer. + PollingInterval - Indicates the interval, in milliseconds, that the + asynchronous interrupt transfer is polled. + This parameter is required when IsNewTransfer is TRUE. + DataLength - Indicates the length of data to be received at the + rate specified by PollingInterval from the target + asynchronous interrupt endpoint. This parameter + is only required when IsNewTransfer is TRUE. + Translator - A pointr to the transaction translator data. + CallBackFunction - The Callback function.This function is called at the + rate specified by PollingInterval.This parameter is + only required when IsNewTransfer is TRUE. + Context - The context that is passed to the CallBackFunction. + - This is an optional parameter and may be NULL. + + Returns: + + EFI_SUCCESS + The asynchronous interrupt transfer request has been successfully + submitted or canceled. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_OUT_OF_RESOURCES + The request could not be completed due to a lack of resources. + EFI_DEVICE_ERROR + Can't read register + +--*/ +; + +EFI_STATUS +EFIAPI +UsbVirtualHcSyncInterruptTransfer ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + + Vitual interface to submits synchronous interrupt transfer to an interrupt endpoint + of a USB device for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - The combination of an endpoint number and an endpoint + direction of the target USB device. Each endpoint + address supports data transfer in one direction + except the control endpoint (whose default + endpoint address is 0). It is the caller's responsibility + to make sure that the EndPointAddress represents + an interrupt endpoint. + DeviceSpeed - Indicates device speed. + MaximumPacketLength - Indicates the maximum packet size the target endpoint + is capable of sending or receiving. + Data - A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + DataLength - On input, the size, in bytes, of the data buffer specified + by Data. On output, the number of bytes transferred. + DataToggle - A pointer to the data toggle value. On input, it indicates + the initial data toggle value the synchronous interrupt + transfer should adopt; + on output, it is updated to indicate the data toggle value + of the subsequent synchronous interrupt transfer. + TimeOut - Indicates the maximum time, in microseconds, which the + transfer is allowed to complete. + Translator - A pointr to the transaction translator data. + TransferResult - A pointer to the detailed result information from + the synchronous interrupt transfer. + + Returns: + + EFI_SUCCESS + The synchronous interrupt transfer was completed successfully. + EFI_OUT_OF_RESOURCES + The synchronous interrupt transfer could not be submitted due + to lack of resource. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_TIMEOUT + The synchronous interrupt transfer failed due to timeout. + EFI_DEVICE_ERROR + The synchronous interrupt transfer failed due to host controller + or device error. Caller should check TranferResult for detailed + error information. + +--*/ +; + +EFI_STATUS +EFIAPI +UsbVirtualHcIsochronousTransfer ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + + Virtual interface to submits isochronous transfer to a target USB device + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - End point address + DeviceSpeed - Indicates device speed. + MaximumPacketLength - Indicates the maximum packet size that the + default control transfer endpoint is capable of + sending or receiving. + DataBuffersNumber - Number of data buffers prepared for the transfer. + Data - Array of pointers to the buffers of data that will be + transmitted to USB device or received from USB device. + DataLength - Indicates the size, in bytes, of the data buffer + specified by Data. + Translator - A pointr to the transaction translator data. + TransferResult - A pointer to the detailed result information generated + by this control transfer. + + Returns: + + EFI_UNSUPPORTED + +--*/ +; + +EFI_STATUS +EFIAPI +UsbVirtualHcAsyncIsochronousTransfer ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context + ) +/*++ + + Routine Description: + + Vitual interface to submits Async isochronous transfer to a target USB device + for both Hc2 and Hc protocol. + + Arguments: + + UsbBusDev - A pointer to bus controller of the device. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - End point address + DeviceSpeed - Indicates device speed. + MaximumPacketLength - Indicates the maximum packet size that the + default control transfer endpoint is capable of + sending or receiving. + DataBuffersNumber - Number of data buffers prepared for the transfer. + Data - Array of pointers to the buffers of data that will be transmitted + to USB device or received from USB device. + DataLength - Indicates the size, in bytes, of the data buffer + specified by Data. + Translator - A pointr to the transaction translator data. + IsochronousCallBack - When the transfer complete, the call back function will be called + Context - Pass to the call back function as parameter + + Returns: + + EFI_UNSUPPORTED + +--*/ +; #endif diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c index bd87c5ca2e..eb563b8e8b 100644 --- a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c @@ -233,9 +233,9 @@ UsbControlTransfer ( --*/ { USB_IO_CONTROLLER_DEVICE *UsbIoController; - EFI_USB_HC_PROTOCOL *UsbHCInterface; + EFI_STATUS RetStatus; - USB_IO_DEVICE *UsbIoDevice; + USB_IO_DEVICE *UsbIoDev; UINT8 MaxPacketLength; UINT32 TransferResult; BOOLEAN Disconnected; @@ -251,9 +251,9 @@ UsbControlTransfer ( // to perform other parameters checking // UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); - UsbIoDevice = UsbIoController->UsbDevice; - UsbHCInterface = UsbIoDevice->BusController->UsbHCInterface; - MaxPacketLength = UsbIoDevice->DeviceDescriptor.MaxPacketSize0; + UsbIoDev = UsbIoController->UsbDevice; + + MaxPacketLength = UsbIoDev->DeviceDescriptor.MaxPacketSize0; if (Request->Request == USB_DEV_CLEAR_FEATURE && @@ -268,24 +268,23 @@ UsbControlTransfer ( return EFI_DEVICE_ERROR; } } - - - // // using HostController's ControlTransfer to complete the request // - RetStatus = UsbHCInterface->ControlTransfer ( - UsbHCInterface, - UsbIoDevice->DeviceAddress, - UsbIoDevice->IsSlowDevice, - MaxPacketLength, - Request, - Direction, - Data, - &DataLength, - (UINTN) Timeout, - &TransferResult - ); + RetStatus = UsbVirtualHcControlTransfer ( + UsbIoDev->BusController, + UsbIoDev->DeviceAddress, + UsbIoDev->DeviceSpeed, + MaxPacketLength, + Request, + Direction, + Data, + &DataLength, + (UINTN) Timeout, + UsbIoDev->Translator, + &TransferResult + ); + *Status = TransferResult; if (Request->Request == USB_DEV_CLEAR_FEATURE && @@ -346,18 +345,19 @@ UsbBulkTransfer ( --*/ { USB_IO_DEVICE *UsbIoDev; - UINT8 MaxPacketLength; + UINTN MaxPacketLength; UINT8 DataToggle; UINT8 OldToggle; EFI_STATUS RetStatus; - EFI_USB_HC_PROTOCOL *UsbHCInterface; + USB_IO_CONTROLLER_DEVICE *UsbIoController; ENDPOINT_DESC_LIST_ENTRY *EndPointListEntry; UINT32 TransferResult; - - UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); - UsbIoDev = UsbIoController->UsbDevice; - UsbHCInterface = UsbIoDev->BusController->UsbHCInterface; + UINT8 DataBuffersNumber; + + DataBuffersNumber = 1; + UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); + UsbIoDev = UsbIoController->UsbDevice; // // Parameters Checking @@ -408,17 +408,20 @@ UsbBulkTransfer ( // // using HostController's BulkTransfer to complete the request // - RetStatus = UsbHCInterface->BulkTransfer ( - UsbHCInterface, - UsbIoDev->DeviceAddress, - DeviceEndpoint, - MaxPacketLength, - Data, - DataLength, - &DataToggle, - Timeout, - &TransferResult - ); + RetStatus = UsbVirtualHcBulkTransfer ( + UsbIoDev->BusController, + UsbIoDev->DeviceAddress, + DeviceEndpoint, + UsbIoDev->DeviceSpeed, + MaxPacketLength, + DataBuffersNumber, + &Data, + DataLength, + &DataToggle, + Timeout, + UsbIoDev->Translator, + &TransferResult + ); if (OldToggle != DataToggle) { // @@ -474,14 +477,13 @@ UsbSyncInterruptTransfer ( --*/ { - USB_IO_DEVICE *UsbIoDev; - UINT8 MaxPacketLength; - UINT8 DataToggle; - UINT8 OldToggle; - EFI_STATUS RetStatus; - EFI_USB_HC_PROTOCOL *UsbHCInterface; - USB_IO_CONTROLLER_DEVICE *UsbIoController; - ENDPOINT_DESC_LIST_ENTRY *EndPointListEntry; + USB_IO_DEVICE *UsbIoDev; + UINTN MaxPacketLength; + UINT8 DataToggle; + UINT8 OldToggle; + EFI_STATUS RetStatus; + USB_IO_CONTROLLER_DEVICE *UsbIoController; + ENDPOINT_DESC_LIST_ENTRY *EndPointListEntry; // // Parameters Checking @@ -517,8 +519,6 @@ UsbSyncInterruptTransfer ( // UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); UsbIoDev = UsbIoController->UsbDevice; - UsbHCInterface = UsbIoDev->BusController->UsbHCInterface; - GetDeviceEndPointMaxPacketLength ( This, DeviceEndpoint, @@ -535,18 +535,19 @@ UsbSyncInterruptTransfer ( // // using HostController's SyncInterruptTransfer to complete the request // - RetStatus = UsbHCInterface->SyncInterruptTransfer ( - UsbHCInterface, - UsbIoDev->DeviceAddress, - DeviceEndpoint, - UsbIoDev->IsSlowDevice, - MaxPacketLength, - Data, - DataLength, - &DataToggle, - Timeout, - Status - ); + RetStatus = UsbVirtualHcSyncInterruptTransfer ( + UsbIoDev->BusController, + UsbIoDev->DeviceAddress, + DeviceEndpoint, + UsbIoDev->DeviceSpeed, + MaxPacketLength, + Data, + DataLength, + &DataToggle, + Timeout, + UsbIoDev->Translator, + Status + ); if (OldToggle != DataToggle) { // @@ -590,7 +591,7 @@ UsbAsyncInterruptTransfer ( the transfer is to be executed. DataLength - Specifies the length, in bytes, of the data to be received from the USB device. - InterruptCallback - The Callback function. This function is called if + InterruptCallBack - The Callback function. This function is called if the asynchronous interrupt transfer is completed. Context - Passed to InterruptCallback Returns: @@ -600,13 +601,12 @@ UsbAsyncInterruptTransfer ( --*/ { - USB_IO_DEVICE *UsbIoDev; - UINT8 MaxPacketLength; - UINT8 DataToggle; - EFI_USB_HC_PROTOCOL *UsbHCInterface; - EFI_STATUS RetStatus; - USB_IO_CONTROLLER_DEVICE *UsbIoController; - ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry; + USB_IO_DEVICE *UsbIoDev; + UINTN MaxPacketLength; + UINT8 DataToggle; + EFI_STATUS RetStatus; + USB_IO_CONTROLLER_DEVICE *UsbIoController; + ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry; // // Check endpoint @@ -634,25 +634,25 @@ UsbAsyncInterruptTransfer ( UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); UsbIoDev = UsbIoController->UsbDevice; - UsbHCInterface = UsbIoDev->BusController->UsbHCInterface; if (!IsNewTransfer) { // // Delete this transfer // - UsbHCInterface->AsyncInterruptTransfer ( - UsbHCInterface, - UsbIoDev->DeviceAddress, - DeviceEndpoint, - UsbIoDev->IsSlowDevice, - 0, - FALSE, - &DataToggle, - PollingInterval, - DataLength, - NULL, - NULL - ); + UsbVirtualHcAsyncInterruptTransfer ( + UsbIoDev->BusController, + UsbIoDev->DeviceAddress, + DeviceEndpoint, + UsbIoDev->DeviceSpeed, + 0, + FALSE, + &DataToggle, + PollingInterval, + DataLength, + UsbIoDev->Translator, + NULL, + NULL + ); // // We need to store the toggle value @@ -678,19 +678,20 @@ UsbAsyncInterruptTransfer ( &DataToggle ); - RetStatus = UsbHCInterface->AsyncInterruptTransfer ( - UsbHCInterface, - UsbIoDev->DeviceAddress, - DeviceEndpoint, - UsbIoDev->IsSlowDevice, - MaxPacketLength, - TRUE, - &DataToggle, - PollingInterval, - DataLength, - InterruptCallBack, - Context - ); + RetStatus = UsbVirtualHcAsyncInterruptTransfer ( + UsbIoDev->BusController, + UsbIoDev->DeviceAddress, + DeviceEndpoint, + UsbIoDev->DeviceSpeed, + MaxPacketLength, + TRUE, + &DataToggle, + PollingInterval, + DataLength, + UsbIoDev->Translator, + InterruptCallBack, + Context + ); return RetStatus; } @@ -1070,6 +1071,7 @@ UsbGetStringDescriptor ( EFI_SUCCESS EFI_NOT_FOUND EFI_OUT_OF_RESOURCES + EFI_UNSUPPORTED --*/ { diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c index 07eb5805e9..e3380856bf 100644 --- a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c @@ -35,10 +35,10 @@ IsPortConnect ( Tell if there is a device connected to that port according to the Port Status. - Parameters: + Arguments: PortStatus - The status value of that port. - Return Value: + Returns: TRUE FALSE @@ -280,7 +280,6 @@ IsPortResetChange ( } } - BOOLEAN IsPortSuspendChange ( IN UINT16 PortChangeStatus @@ -309,8 +308,7 @@ IsPortSuspendChange ( } } - -INTERFACE_DESC_LIST_ENTRY* +INTERFACE_DESC_LIST_ENTRY * FindInterfaceListEntry ( IN EFI_USB_IO_PROTOCOL *This ) @@ -329,7 +327,7 @@ FindInterfaceListEntry ( { USB_IO_CONTROLLER_DEVICE *UsbIoController; USB_IO_DEVICE *UsbIoDev; - LIST_ENTRY *InterfaceListHead; + LIST_ENTRY *InterfaceListHead; INTERFACE_DESC_LIST_ENTRY *InterfaceListEntry; UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); @@ -367,8 +365,8 @@ FindEndPointListEntry ( Find EndPoint ListEntry. Arguments: - This - EFI_USB_IO_PROTOCOL - EndpointAddr - Endpoint address. + This - EFI_USB_IO_PROTOCOL + EndPointAddress - Endpoint address. Returns: ENDPOINT_DESC_LIST_ENTRY pointer @@ -471,7 +469,7 @@ VOID GetDeviceEndPointMaxPacketLength ( IN EFI_USB_IO_PROTOCOL *UsbIo, IN UINT8 EndpointAddr, - OUT UINT8 *MaxPacketLength + OUT UINTN *MaxPacketLength ) /*++ @@ -498,7 +496,7 @@ GetDeviceEndPointMaxPacketLength ( return ; } - *MaxPacketLength = (UINT8) (EndpointListEntry->EndpointDescriptor.MaxPacketSize); + *MaxPacketLength = (UINTN) (EndpointListEntry->EndpointDescriptor.MaxPacketSize); return ; } diff --git a/EdkModulePkg/EdkModulePkg.spd b/EdkModulePkg/EdkModulePkg.spd index b6efc6934f..6c7da5bd22 100644 --- a/EdkModulePkg/EdkModulePkg.spd +++ b/EdkModulePkg/EdkModulePkg.spd @@ -394,6 +394,7 @@ Bus/Pci/IdeBus/Dxe/idebus.msa Bus/Pci/PciBus/Dxe/PciBus.msa Bus/Pci/Uhci/Dxe/Uhci.msa + Bus/Pci/Ehci/Dxe/Ehci.msa Bus/Pci/Undi/RuntimeDxe/Undi.msa Bus/Scsi/ScsiBus/Dxe/ScsiBus.msa Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.msa @@ -440,6 +441,7 @@ Universal/Console/Terminal/Dxe/Terminal.msa Universal/DataHub/DataHub/Dxe/DataHub.msa Universal/DataHub/DataHubStdErr/Dxe/DataHubStdErr.msa + Universal/DevicePath/Dxe/DevicePath.msa Universal/Debugger/Debugport/Dxe/DebugPort.msa Universal/DebugSupport/Dxe/DebugSupport.msa Universal/Disk/DiskIo/Dxe/DiskIo.msa diff --git a/EdkModulePkg/Universal/DevicePath/Dxe/DevicePath.c b/EdkModulePkg/Universal/DevicePath/Dxe/DevicePath.c new file mode 100644 index 0000000000..79741a4615 --- /dev/null +++ b/EdkModulePkg/Universal/DevicePath/Dxe/DevicePath.c @@ -0,0 +1,107 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DevicePathDriver.c + +Abstract: + + Device Path Driver to produce DevPathUtilities Protocol, DevPathFromText Protocol + and DevPathToText Protocol. + +--*/ + +#include +#include +#include "DevicePath.h" + +DEVICE_PATH_DRIVER_PRIVATE_DATA mPrivateData; + +EFI_GUID mEfiDevicePathMessagingUartFlowControlGuid = DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL; +EFI_GUID mEfiDevicePathMessagingSASGuid = DEVICE_PATH_MESSAGING_SAS; + +STATIC EFI_DEVICE_PATH_UTILITIES_PROTOCOL mDevicePathUtilitiesProtocol = { + GetDevicePathSize, + DuplicateDevicePath, + AppendDevicePath, + AppendDeviceNode, + AppendDevicePathInstance, + GetNextDevicePathInstance, + IsDevicePathMultiInstance, + CreateDeviceNode +}; + +STATIC EFI_DEVICE_PATH_TO_TEXT_PROTOCOL mDevicePathToTextProtocol = { + ConvertDeviceNodeToText, + ConvertDevicePathToText +}; + +STATIC EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL mDevicePathFromTextProtocol = { + ConvertTextToDeviceNode, + ConvertTextToDevicePath +}; + +EFI_STATUS +EFIAPI +DevicePathEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + + Routine Description: + Entry point for EFI drivers. + + Arguments: + ImageHandle - EFI_HANDLE + SystemTable - EFI_SYSTEM_TABLE + + Returns: + EFI_SUCCESS + others + +--*/ +{ + EFI_STATUS Status; + + mPrivateData.Signature = DEVICE_PATH_DRIVER_SIGNATURE; + + mPrivateData.DevicePathUtilities.GetDevicePathSize = GetDevicePathSize; + mPrivateData.DevicePathUtilities.DuplicateDevicePath = DuplicateDevicePath; + mPrivateData.DevicePathUtilities.AppendDevicePath = AppendDevicePath; + mPrivateData.DevicePathUtilities.AppendDeviceNode = AppendDeviceNode; + mPrivateData.DevicePathUtilities.AppendDevicePathInstance = AppendDevicePathInstance; + mPrivateData.DevicePathUtilities.GetNextDevicePathInstance = GetNextDevicePathInstance; + mPrivateData.DevicePathUtilities.IsDevicePathMultiInstance = IsDevicePathMultiInstance; + mPrivateData.DevicePathUtilities.CreateDeviceNode = CreateDeviceNode; + + mPrivateData.DevicePathToText.ConvertDeviceNodeToText = ConvertDeviceNodeToText; + mPrivateData.DevicePathToText.ConvertDevicePathToText = ConvertDevicePathToText; + + mPrivateData.DevicePathFromText.ConvertTextToDeviceNode = ConvertTextToDeviceNode; + mPrivateData.DevicePathFromText.ConvertTextToDevicePath = ConvertTextToDevicePath; + + mPrivateData.Handle = NULL; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &mPrivateData.Handle, + &gEfiDevicePathUtilitiesProtocolGuid, + &mPrivateData.DevicePathUtilities, + &gEfiDevicePathToTextProtocolGuid, + &mPrivateData.DevicePathToText, + &gEfiDevicePathFromTextProtocolGuid, + &mPrivateData.DevicePathFromText, + NULL + ); + + return Status; +} diff --git a/EdkModulePkg/Universal/DevicePath/Dxe/DevicePath.h b/EdkModulePkg/Universal/DevicePath/Dxe/DevicePath.h new file mode 100644 index 0000000000..aa333453ea --- /dev/null +++ b/EdkModulePkg/Universal/DevicePath/Dxe/DevicePath.h @@ -0,0 +1,422 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DevicePathDriver.h + +Abstract: + Definition for Device Path Utilities driver + +--*/ + +#ifndef _DEVICE_PATH_DRIVER_H +#define _DEVICE_PATH_DRIVER_H + +extern EFI_GUID mEfiDevicePathMessagingUartFlowControlGuid; +extern EFI_GUID mEfiDevicePathMessagingSASGuid; + +#define DEVICE_PATH_DRIVER_SIGNATURE EFI_SIGNATURE_32 ('D', 'P', 'D', 'V') + +typedef struct { + + UINT32 Signature; + EFI_HANDLE Handle; + // + // Produced protocols + // + EFI_DEVICE_PATH_UTILITIES_PROTOCOL DevicePathUtilities; + EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL DevicePathFromText; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL DevicePathToText; + +} DEVICE_PATH_DRIVER_PRIVATE_DATA; + +#define MAX_CHAR 480 + +#define MIN_ALIGNMENT_SIZE sizeof(UINTN) +#define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0) + +#define IS_COMMA(a) ((a) == L',') +#define IS_HYPHEN(a) ((a) == L'-') +#define IS_DOT(a) ((a) == L'.') +#define IS_LEFT_PARENTH(a) ((a) == L'(') +#define IS_RIGHT_PARENTH(a) ((a) == L')') +#define IS_SLASH(a) ((a) == L'/') +#define IS_NULL(a) ((a) == L'\0') + +#define DEVICE_NODE_END 1 +#define DEVICE_PATH_INSTANCE_END 2 +#define DEVICE_PATH_END 3 + +#define SetDevicePathInstanceEndNode(a) { \ + (a)->Type = END_DEVICE_PATH_TYPE; \ + (a)->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; \ + (a)->Length[0] = sizeof (EFI_DEVICE_PATH_PROTOCOL); \ + (a)->Length[1] = 0; \ + } + +// +// Private Data structure +// +typedef struct { + CHAR16 *Str; + UINTN Len; + UINTN MaxLen; +} POOL_PRINT; + +typedef struct { + UINT8 Type; + UINT8 SubType; + VOID (*Function) (POOL_PRINT *, VOID *, BOOLEAN, BOOLEAN); +} DEVICE_PATH_TO_TEXT_TABLE; + +typedef struct { + CHAR16 *DevicePathNodeText; + EFI_DEVICE_PATH_PROTOCOL * (*Function) (CHAR16 *); +} DEVICE_PATH_FROM_TEXT_TABLE; + +typedef struct { + BOOLEAN ClassExist; + UINT8 Class; + BOOLEAN SubClassExist; + UINT8 SubClass; +} USB_CLASS_TEXT; + +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_CDCCONTROL 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_IMAGE 6 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_CDCDATA 10 +#define USB_CLASS_SMART_CARD 11 +#define USB_CLASS_VIDEO 14 +#define USB_CLASS_DIAGNOSTIC 220 +#define USB_CLASS_WIRELESS 224 + +#define USB_CLASS_RESERVE 254 +#define USB_SUBCLASS_FW_UPDATE 1 +#define USB_SUBCLASS_IRDA_BRIDGE 2 +#define USB_SUBCLASS_TEST 3 + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEFINED_HARDWARE_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEFINED_MESSAGING_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEFINED_MEDIA_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 HID; + UINT32 UID; + UINT32 CID; + CHAR8 HidUidCidStr[3]; +} ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 NetworkProtocol; + UINT16 LoginOption; + UINT16 Reserved; + UINT16 TargetPortalGroupTag; + UINT64 Lun; + CHAR16 iSCSITargetName[1]; +} ISCSI_DEVICE_PATH_WITH_NAME; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEVICE_PATH_WITH_DATA; + +CHAR16 * +ConvertDeviceNodeToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +/*++ + + Routine Description: + Convert a device node to its text representation. + + Arguments: + DeviceNode - Points to the device node to be converted. + DisplayOnly - If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + AllowShortcuts - If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + Returns: + A pointer - a pointer to the allocated text representation of the device node. + NULL - if DeviceNode is NULL or there was insufficient memory. + +--*/ +; + +CHAR16 * +ConvertDevicePathToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +/*++ + + Routine Description: + Convert a device path to its text representation. + + Arguments: + DeviceNode - Points to the device path to be converted. + DisplayOnly - If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + AllowShortcuts - If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + Returns: + A pointer - a pointer to the allocated text representation of the device path. + NULL - if DeviceNode is NULL or there was insufficient memory. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +ConvertTextToDeviceNode ( + IN CONST CHAR16 *TextDeviceNode + ) +/*++ + + Routine Description: + Convert text to the binary representation of a device node. + + Arguments: + TextDeviceNode - TextDeviceNode points to the text representation of a device + node. Conversion starts with the first character and continues + until the first non-device node character. + + Returns: + A pointer - Pointer to the EFI device node. + NULL - if TextDeviceNode is NULL or there was insufficient memory. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +ConvertTextToDevicePath ( + IN CONST CHAR16 *TextDevicePath + ) +/*++ + + Routine Description: + Convert text to the binary representation of a device path. + + Arguments: + TextDevicePath - TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device node character. + + Returns: + A pointer - Pointer to the allocated device path. + NULL - if TextDeviceNode is NULL or there was insufficient memory. + +--*/ +; + +UINTN +GetDevicePathSize ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + + Routine Description: + Returns the size of the device path, in bytes. + + Arguments: + DevicePath - Points to the start of the EFI device path. + + Returns: + Size - Size of the specified device path, in bytes, including the end-of-path tag. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +DuplicateDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + + Routine Description: + Create a duplicate of the specified path. + + Arguments: + DevicePath - Points to the source EFI device path. + + Returns: + Pointer - A pointer to the duplicate device path. + NULL - Insufficient memory. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *Src1, + IN CONST EFI_DEVICE_PATH_PROTOCOL *Src2 + ) +/*++ + + Routine Description: + Create a new path by appending the second device path to the first. + + Arguments: + Src1 - Points to the first device path. If NULL, then it is ignored. + Src2 - Points to the second device path. If NULL, then it is ignored. + + Returns: + Pointer - A pointer to the newly created device path. + NULL - Memory could not be allocated + or either DevicePath or DeviceNode is NULL. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +AppendDeviceNode ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode + ) +/*++ + + Routine Description: + Creates a new path by appending the device node to the device path. + + Arguments: + DevicePath - Points to the device path. + DeviceNode - Points to the device node. + + Returns: + Pointer - A pointer to the allocated device node. + NULL - Memory could not be allocated + or either DevicePath or DeviceNode is NULL. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePathInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance + ) +/*++ + + Routine Description: + Creates a new path by appending the specified device path instance to the specified device path. + + Arguments: + DevicePath - Points to the device path. If NULL, then ignored. + DevicePathInstance - Points to the device path instance. + + Returns: + Pointer - A pointer to the newly created device path + NULL - Memory could not be allocated or DevicePathInstance is NULL. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +GetNextDevicePathInstance ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathInstance, + OUT UINTN *DevicePathInstanceSize + ) +/*++ + + Routine Description: + Creates a copy of the current device path instance and returns a pointer to the next device path instance. + + Arguments: + DevicePathInstance - On input, this holds the pointer to the current device path + instance. On output, this holds the pointer to the next + device path instance or NULL if there are no more device + path instances in the device path. + DevicePathInstanceSize - On output, this holds the size of the device path instance, + in bytes or zero, if DevicePathInstance is zero. + + Returns: + Pointer - A pointer to the copy of the current device path instance. + NULL - DevicePathInstace was NULL on entry or there was insufficient memory. + +--*/ +; + +BOOLEAN +IsDevicePathMultiInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + + Routine Description: + Returns whether a device path is multi-instance. + + Arguments: + DevicePath - Points to the device path. If NULL, then ignored. + + Returns: + TRUE - The device path has more than one instance + FALSE - The device path is empty or contains only a single instance. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +CreateDeviceNode ( + IN UINT8 NodeType, + IN UINT8 NodeSubType, + IN UINT16 NodeLength + ) +/*++ + + Routine Description: + Creates a device node + + Arguments: + NodeType - NodeType is the device node type (EFI_DEVICE_PATH.Type) for + the new device node. + NodeSubType - NodeSubType is the device node sub-type + EFI_DEVICE_PATH.SubType) for the new device node. + NodeLength - NodeLength is the length of the device node + (EFI_DEVICE_PATH.Length) for the new device node. + + Returns: + Pointer - A pointer to the newly created device node. + NULL - NodeLength is less than + the size of the header or there was insufficient memory. + +--*/ +; + +#endif diff --git a/EdkModulePkg/Universal/DevicePath/Dxe/DevicePath.msa b/EdkModulePkg/Universal/DevicePath/Dxe/DevicePath.msa new file mode 100644 index 0000000000..20dd59848f --- /dev/null +++ b/EdkModulePkg/Universal/DevicePath/Dxe/DevicePath.msa @@ -0,0 +1,109 @@ + + + + + + + DevicePath + DXE_DRIVER + 9B680FCE-AD6B-4F3A-B60B-F59899003443 + 1.0 + Component description file for Device Path Driver. + This driver is for DevicePathUtilities, DevicePahtToText and DevicePathFromText + Copyright (c) 2006, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + DevicePath + + + + DebugLib + + + PrintLib + + + UefiDriverEntryPoint + + + UefiLib + + + BaseLib + + + BaseMemoryLib + + + MemoryAllocationLib + + + UefiBootServicesTableLib + + + + DevicePath.c + DevicePath.h + DevicePathFromText.c + DevicePathToText.c + DevicePathUtilities.c + + + + + + + + gEfiDebugPortProtocolGuid + + + gEfiDevicePathProtocolGuid + + + gEfiDevicePathUtilitiesProtocolGuid + + + gEfiDevicePathFromTextProtocolGuid + + + gEfiDevicePathToTextProtocolGuid + + + + + gEfiPcAnsiGuid + + + gEfiVT100PlusGuid + + + gEfiVT100Guid + + + gEfiVTUTF8Guid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00090000 + + DevicePathEntryPoint + + + diff --git a/EdkModulePkg/Universal/DevicePath/Dxe/DevicePathFromText.c b/EdkModulePkg/Universal/DevicePath/Dxe/DevicePathFromText.c new file mode 100644 index 0000000000..e0864da6f0 --- /dev/null +++ b/EdkModulePkg/Universal/DevicePath/Dxe/DevicePathFromText.c @@ -0,0 +1,2434 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DevicePathFromText.c + +Abstract: + + DevicePathFromText protocol as defined in the UEFI 2.0 specification. + +--*/ + +#include +#include "DevicePath.h" + +CHAR16 * +StrDuplicate ( + IN CONST CHAR16 *Src + ) +/*++ + + Routine Description: + Duplicate a string + + Arguments: + Src - Source string + + Returns: + Duplicated string + +--*/ +{ + UINTN Length; + CHAR16 *ReturnStr; + + Length = StrLen ((CHAR16 *) Src); + + ReturnStr = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), (VOID *) Src); + + return ReturnStr; +} + +CHAR16 * +GetParamByNodeName ( + IN CHAR16 *Str, + IN CHAR16 *NodeName + ) +/*++ + + Routine Description: + Get parameter in a pair of parentheses follow the given node name. + For example, given the "Pci(0,1)" and NodeName "Pci", it returns "0,1". + + Arguments: + Str - Device Path Text + NodeName - Name of the node + + Returns: + Parameter text for the node + +--*/ +{ + CHAR16 *ParamStr; + CHAR16 *StrPointer; + UINTN NodeNameLength; + UINTN ParameterLength; + + // + // Check whether the node name matchs + // + NodeNameLength = StrLen (NodeName); + if (CompareMem (Str, NodeName, NodeNameLength * sizeof (CHAR16)) != 0) { + return NULL; + } + + ParamStr = Str + NodeNameLength; + if (!IS_LEFT_PARENTH (*ParamStr)) { + return NULL; + } + + // + // Skip the found '(' and find first occurrence of ')' + // + ParamStr++; + ParameterLength = 0; + StrPointer = ParamStr; + while (!IS_NULL (*StrPointer)) { + if (IS_RIGHT_PARENTH (*StrPointer)) { + break; + } + StrPointer++; + ParameterLength++; + } + if (IS_NULL (*StrPointer)) { + // + // ')' not found + // + return NULL; + } + + ParamStr = AllocateCopyPool ((ParameterLength + 1) * sizeof (CHAR16), ParamStr); + if (ParamStr == NULL) { + return NULL; + } + // + // Terminate the parameter string + // + ParamStr[ParameterLength] = L'\0'; + + return ParamStr; +} + +CHAR16 * +SplitStr ( + IN OUT CHAR16 **List, + IN CHAR16 Separator + ) +/*++ + + Routine Description: + Get current sub-string from a string list, before return + the list header is moved to next sub-string. The sub-string is separated + by the specified character. For example, the separator is ',', the string + list is "2,0,3", it returns "2", the remain list move to "2,3" + + Arguments: + List - A string list separated by the specified separator + Separator - The separator character + + Returns: + pointer - The current sub-string + +--*/ +{ + CHAR16 *Str; + CHAR16 *ReturnStr; + + Str = *List; + ReturnStr = Str; + + if (IS_NULL (*Str)) { + return ReturnStr; + } + + // + // Find first occurrence of the separator + // + while (!IS_NULL (*Str)) { + if (*Str == Separator) { + break; + } + Str++; + } + + if (*Str == Separator) { + // + // Find a sub-string, terminate it + // + *Str = L'\0'; + Str++; + } + + // + // Move to next sub-string + // + *List = Str; + + return ReturnStr; +} + +CHAR16 * +GetNextParamStr ( + IN OUT CHAR16 **List + ) +{ + // + // The separator is comma + // + return SplitStr (List, L','); +} + +CHAR16 * +GetNextDeviceNodeStr ( + IN OUT CHAR16 **DevicePath, + OUT BOOLEAN *IsInstanceEnd + ) +/*++ + + Routine Description: + Get one device node from entire device path text. + + Arguments: + Str - The entire device path text string + IsInstanceEnd - This node is the end of a device path instance + + Returns: + a pointer - A device node text + NULL - No more device node available + +--*/ +{ + CHAR16 *Str; + CHAR16 *ReturnStr; + UINTN ParenthesesStack; + + Str = *DevicePath; + if (IS_NULL (*Str)) { + return NULL; + } + + // + // Skip the leading '/', '(', ')' and ',' + // + while (!IS_NULL (*Str)) { + if (!IS_SLASH (*Str) && + !IS_COMMA (*Str) && + !IS_LEFT_PARENTH (*Str) && + !IS_RIGHT_PARENTH (*Str)) { + break; + } + Str++; + } + + ReturnStr = Str; + + // + // Scan for the separator of this device node, '/' or ',' + // + ParenthesesStack = 0; + while (!IS_NULL (*Str)) { + if ((IS_COMMA (*Str) || IS_SLASH (*Str)) && (ParenthesesStack == 0)) { + break; + } + + if (IS_LEFT_PARENTH (*Str)) { + ParenthesesStack++; + } else if (IS_RIGHT_PARENTH (*Str)) { + ParenthesesStack--; + } + + Str++; + } + + if (ParenthesesStack != 0) { + // + // The '(' doesn't pair with ')', invalid device path text + // + return NULL; + } + + if (IS_COMMA (*Str)) { + *IsInstanceEnd = TRUE; + *Str = L'\0'; + Str++; + } else { + *IsInstanceEnd = FALSE; + if (!IS_NULL (*Str)) { + *Str = L'\0'; + Str++; + } + } + + *DevicePath = Str; + + return ReturnStr; +} + +BOOLEAN +IsHexDigit ( + OUT UINT8 *Digit, + IN CHAR16 Char + ) +/*++ + + Routine Description: + Determines if a Unicode character is a hexadecimal digit. + The test is case insensitive. + + Arguments: + Digit - Pointer to byte that receives the value of the hex character. + Char - Unicode character to test. + + Returns: + TRUE - If the character is a hexadecimal digit. + FALSE - Otherwise. + +--*/ +{ + if ((Char >= L'0') && (Char <= L'9')) { + *Digit = (UINT8) (Char - L'0'); + return TRUE; + } + + if ((Char >= L'A') && (Char <= L'F')) { + *Digit = (UINT8) (Char - L'A' + 0x0A); + return TRUE; + } + + if ((Char >= L'a') && (Char <= L'f')) { + *Digit = (UINT8) (Char - L'a' + 0x0A); + return TRUE; + } + + return FALSE; +} + +CHAR16 +NibbleToHexChar ( + IN UINT8 Nibble + ) +/*++ + + Routine Description: + Converts the low nibble of a byte to hex unicode character. + + Arguments: + Nibble - lower nibble of a byte. + + Returns: + Hex unicode character. + +--*/ +{ + Nibble &= 0x0F; + if (Nibble <= 0x9) { + return (CHAR16)(Nibble + L'0'); + } + + return (CHAR16)(Nibble - 0xA + L'A'); +} + +EFI_STATUS +HexStringToBuf ( + IN OUT UINT8 *Buf, + IN OUT UINTN *Len, + IN CHAR16 *Str, + OUT UINTN *ConvertedStrLen OPTIONAL + ) +/*++ + + Routine Description: + Converts Unicode string to binary buffer. + The conversion may be partial. + The first character in the string that is not hex digit stops the conversion. + At a minimum, any blob of data could be represented as a hex string. + + Arguments: + Buf - Pointer to buffer that receives the data. + Len - Length in bytes of the buffer to hold converted data. + If routine return with EFI_SUCCESS, containing length of converted data. + If routine return with EFI_BUFFER_TOO_SMALL, containg length of buffer desired. + Str - String to be converted from. + ConvertedStrLen - Length of the Hex String consumed. + + Returns: + EFI_SUCCESS: Routine Success. + EFI_BUFFER_TOO_SMALL: The buffer is too small to hold converted data. + EFI_ + +--*/ +{ + UINTN HexCnt; + UINTN Idx; + UINTN BufferLength; + UINT8 Digit; + UINT8 Byte; + + // + // Find out how many hex characters the string has. + // + for (Idx = 0, HexCnt = 0; IsHexDigit (&Digit, Str[Idx]); Idx++, HexCnt++); + + if (HexCnt == 0) { + *Len = 0; + return EFI_SUCCESS; + } + // + // Two Unicode characters make up 1 buffer byte. Round up. + // + BufferLength = (HexCnt + 1) / 2; + + // + // Test if buffer is passed enough. + // + if (BufferLength > (*Len)) { + *Len = BufferLength; + return EFI_BUFFER_TOO_SMALL; + } + + *Len = BufferLength; + + for (Idx = 0; Idx < HexCnt; Idx++) { + + IsHexDigit (&Digit, Str[HexCnt - 1 - Idx]); + + // + // For odd charaters, write the lower nibble for each buffer byte, + // and for even characters, the upper nibble. + // + if ((Idx & 1) == 0) { + Byte = Digit; + } else { + Byte = Buf[Idx / 2]; + Byte &= 0x0F; + Byte |= Digit << 4; + } + + Buf[Idx / 2] = Byte; + } + + if (ConvertedStrLen != NULL) { + *ConvertedStrLen = HexCnt; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +BufToHexString ( + IN OUT CHAR16 *Str, + IN OUT UINTN *HexStringBufferLength, + IN UINT8 *Buf, + IN UINTN Len + ) +/*++ + + Routine Description: + Converts binary buffer to Unicode string. + At a minimum, any blob of data could be represented as a hex string. + + Arguments: + Str - Pointer to the string. + HexStringBufferLength - Length in bytes of buffer to hold the hex string. Includes tailing '\0' character. + If routine return with EFI_SUCCESS, containing length of hex string buffer. + If routine return with EFI_BUFFER_TOO_SMALL, containg length of hex string buffer desired. + Buf - Buffer to be converted from. + Len - Length in bytes of the buffer to be converted. + + Returns: + EFI_SUCCESS: Routine success. + EFI_BUFFER_TOO_SMALL: The hex string buffer is too small. + +--*/ +{ + UINTN Idx; + UINT8 Byte; + UINTN StrLen; + + // + // Make sure string is either passed or allocate enough. + // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer. + // Plus the Unicode termination character. + // + StrLen = Len * 2; + if (StrLen > ((*HexStringBufferLength) - 1)) { + *HexStringBufferLength = StrLen + 1; + return EFI_BUFFER_TOO_SMALL; + } + + *HexStringBufferLength = StrLen + 1; + // + // Ends the string. + // + Str[StrLen] = L'\0'; + + for (Idx = 0; Idx < Len; Idx++) { + + Byte = Buf[Idx]; + Str[StrLen - 1 - Idx * 2] = NibbleToHexChar (Byte); + Str[StrLen - 2 - Idx * 2] = NibbleToHexChar ((UINT8)(Byte >> 4)); + } + + return EFI_SUCCESS; +} + +CHAR16 * +TrimHexStr ( + IN CHAR16 *Str + ) +/*++ + + Routine Description: + Skip the leading white space and '0x' or '0X' of a hex string + + Arguments: + Str - The hex string + + Returns: + +--*/ +{ + // + // skip preceeding white space + // + while (*Str && *Str == ' ') { + Str += 1; + } + // + // skip preceeding zeros + // + while (*Str && *Str == '0') { + Str += 1; + } + // + // skip preceeding white space + // + if (*Str && (*Str == 'x' || *Str == 'X')) { + Str += 1; + } + + return Str; +} + +UINTN +Xtoi ( + IN CHAR16 *Str + ) +/*++ + +Routine Description: + + Convert hex string to uint + +Arguments: + + Str - The string + +Returns: + +--*/ +{ + UINTN Rvalue; + UINTN Length; + + ASSERT (Str != NULL); + + // + // convert hex digits + // + Rvalue = 0; + Length = sizeof (UINTN); + HexStringToBuf ((UINT8 *) &Rvalue, &Length, TrimHexStr (Str), NULL); + + return Rvalue; +} + +VOID +Xtoi64 ( + IN CHAR16 *Str, + IN UINT64 *Data + ) +/*++ + +Routine Description: + + Convert hex string to 64 bit data. + +Arguments: + + Str - The string + +Returns: + +--*/ +{ + UINTN Length; + + Length = sizeof (UINT64); + HexStringToBuf ((UINT8 *) Data, &Length, TrimHexStr (Str), NULL); +} + +UINTN +Atoi ( + IN CHAR16 *str + ) +/*++ + +Routine Description: + + Convert decimal string to uint + +Arguments: + + Str - The string + +Returns: + +--*/ +{ + UINTN Rvalue; + CHAR16 Char; + UINTN High; + UINTN Low; + + ASSERT (str != NULL); + + High = (UINTN) -1 / 10; + Low = (UINTN) -1 % 10; + // + // skip preceeding white space + // + while (*str && *str == ' ') { + str += 1; + } + // + // convert digits + // + Rvalue = 0; + Char = *(str++); + while (Char) { + if (Char >= '0' && Char <= '9') { + if (Rvalue > High || Rvalue == High && Char - '0' > (INTN) Low) { + return (UINTN) -1; + } + + Rvalue = (Rvalue * 10) + Char - '0'; + } else { + break; + } + + Char = *(str++); + } + + return Rvalue; +} + +EFI_STATUS +StrToBuf ( + OUT UINT8 *Buf, + IN UINTN BufferLength, + IN CHAR16 *Str + ) +{ + UINTN Index; + UINTN StrLength; + UINT8 Digit; + UINT8 Byte; + + // + // Two hex char make up one byte + // + StrLength = BufferLength * sizeof (CHAR16); + + for(Index = 0; Index < StrLength; Index++, Str++) { + + IsHexDigit (&Digit, *Str); + + // + // For odd charaters, write the upper nibble for each buffer byte, + // and for even characters, the lower nibble. + // + if ((Index & 1) == 0) { + Byte = Digit << 4; + } else { + Byte = Buf[Index / 2]; + Byte &= 0xF0; + Byte |= Digit; + } + + Buf[Index / 2] = Byte; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +StrToGuid ( + IN CHAR16 *Str, + OUT EFI_GUID *Guid + ) +{ + UINTN BufferLength; + UINTN ConvertedStrLen; + EFI_STATUS Status; + + BufferLength = sizeof (Guid->Data1); + Status = HexStringToBuf ((UINT8 *) &Guid->Data1, &BufferLength, Str, &ConvertedStrLen); + if (EFI_ERROR (Status)) { + return Status; + } + Str += ConvertedStrLen; + if (IS_HYPHEN (*Str)) { + Str++; + } else { + return EFI_UNSUPPORTED; + } + + BufferLength = sizeof (Guid->Data2); + Status = HexStringToBuf ((UINT8 *) &Guid->Data2, &BufferLength, Str, &ConvertedStrLen); + if (EFI_ERROR (Status)) { + return Status; + } + Str += ConvertedStrLen; + if (IS_HYPHEN (*Str)) { + Str++; + } else { + return EFI_UNSUPPORTED; + } + + BufferLength = sizeof (Guid->Data3); + Status = HexStringToBuf ((UINT8 *) &Guid->Data3, &BufferLength, Str, &ConvertedStrLen); + if (EFI_ERROR (Status)) { + return Status; + } + Str += ConvertedStrLen; + if (IS_HYPHEN (*Str)) { + Str++; + } else { + return EFI_UNSUPPORTED; + } + + StrToBuf (&Guid->Data4[0], 2, Str); + // + // Skip 2 byte hex chars + // + Str += 2 * 2; + + if (IS_HYPHEN (*Str)) { + Str++; + } else { + return EFI_UNSUPPORTED; + } + StrToBuf (&Guid->Data4[2], 6, Str); + + return EFI_SUCCESS; +} + +VOID +StrToIPv4Addr ( + IN OUT CHAR16 **Str, + OUT EFI_IPv4_ADDRESS *IPv4Addr + ) +{ + UINTN Index; + + for (Index = 0; Index < 4; Index++) { + IPv4Addr->Addr[Index] = (UINT8) Atoi (SplitStr (Str, L'.')); + } +} + +VOID +StrToIPv6Addr ( + IN OUT CHAR16 **Str, + OUT EFI_IPv6_ADDRESS *IPv6Addr + ) +{ + UINTN Index; + UINT16 Data; + + for (Index = 0; Index < 8; Index++) { + Data = (UINT16) Xtoi (SplitStr (Str, L':')); + IPv6Addr->Addr[Index * 2] = (UINT8) (Data >> 8); + IPv6Addr->Addr[Index * 2 + 1] = (UINT8) (Data & 0xff); + } +} + +VOID +StrToAscii ( + IN CHAR16 *Str, + IN OUT CHAR8 **AsciiStr + ) +{ + CHAR8 *Dest; + + Dest = *AsciiStr; + while (!IS_NULL (*Str)) { + *(Dest++) = (CHAR8) *(Str++); + } + *Dest = 0; + + // + // Return the string next to it + // + *AsciiStr = Dest + 1; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPci ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *FunctionStr; + CHAR16 *DeviceStr; + PCI_DEVICE_PATH *Pci; + + FunctionStr = GetNextParamStr (&TextDeviceNode); + DeviceStr = GetNextParamStr (&TextDeviceNode); + Pci = (PCI_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_PCI_DP, + sizeof (PCI_DEVICE_PATH) + ); + + Pci->Function = (UINT8) Xtoi (FunctionStr); + Pci->Device = (UINT8) Xtoi (DeviceStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Pci; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPcCard ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *FunctionNumberStr; + PCCARD_DEVICE_PATH *Pccard; + + FunctionNumberStr = GetNextParamStr (&TextDeviceNode); + Pccard = (PCCARD_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_PCCARD_DP, + sizeof (PCCARD_DEVICE_PATH) + ); + + Pccard->FunctionNumber = (UINT8) Xtoi (FunctionNumberStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Pccard; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMemoryMapped ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *StartingAddressStr; + CHAR16 *EndingAddressStr; + MEMMAP_DEVICE_PATH *MemMap; + + StartingAddressStr = GetNextParamStr (&TextDeviceNode); + EndingAddressStr = GetNextParamStr (&TextDeviceNode); + MemMap = (MEMMAP_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + sizeof (MEMMAP_DEVICE_PATH) + ); + + MemMap->MemoryType = 0; + + Xtoi64 (StartingAddressStr, &MemMap->StartingAddress); + Xtoi64 (EndingAddressStr, &MemMap->EndingAddress); + + return (EFI_DEVICE_PATH_PROTOCOL *) MemMap; +} + +EFI_DEVICE_PATH_PROTOCOL * +ConvertFromTextVendor ( + IN CHAR16 *TextDeviceNode, + IN UINT8 Type, + IN UINT8 SubType + ) +{ + CHAR16 *GuidStr; + CHAR16 *DataStr; + UINTN Length; + VENDOR_DEVICE_PATH *Vendor; + + GuidStr = GetNextParamStr (&TextDeviceNode); + + DataStr = GetNextParamStr (&TextDeviceNode); + Length = StrLen (DataStr); + // + // Two hex characters make up 1 buffer byte + // + Length = (Length + 1) / 2; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + Type, + SubType, + sizeof (VENDOR_DEVICE_PATH) + (UINT16) Length + ); + + StrToGuid (GuidStr, &Vendor->Guid); + StrToBuf (((UINT8 *) Vendor) + sizeof (VENDOR_DEVICE_PATH), Length, DataStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenHw ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextVendor ( + TextDeviceNode, + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP + ); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextCtrl ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *ControllerStr; + CONTROLLER_DEVICE_PATH *Controller; + + ControllerStr = GetNextParamStr (&TextDeviceNode); + Controller = (CONTROLLER_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_CONTROLLER_DP, + sizeof (CONTROLLER_DEVICE_PATH) + ); + Controller->ControllerNumber = (UINT32) Xtoi (ControllerStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Controller; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpi ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *HIDStr; + CHAR16 *UIDStr; + ACPI_HID_DEVICE_PATH *Acpi; + + HIDStr = GetNextParamStr (&TextDeviceNode); + UIDStr = GetNextParamStr (&TextDeviceNode); + Acpi = (ACPI_HID_DEVICE_PATH *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_DP, + sizeof (ACPI_HID_DEVICE_PATH) + ); + + if ((HIDStr[0] == L'P') && (HIDStr[1] == L'N') && (HIDStr[2] == L'P')) { + HIDStr += 3; + } + + Acpi->HID = EISA_PNP_ID (Xtoi (HIDStr)); + Acpi->UID = (UINT32) Xtoi (UIDStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Acpi; +} + +EFI_DEVICE_PATH_PROTOCOL * +ConvertFromTextAcpi ( + IN CHAR16 *TextDeviceNode, + IN UINT32 Hid + ) +{ + CHAR16 *UIDStr; + ACPI_HID_DEVICE_PATH *Acpi; + + UIDStr = GetNextParamStr (&TextDeviceNode); + Acpi = (ACPI_HID_DEVICE_PATH *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_DP, + sizeof (ACPI_HID_DEVICE_PATH) + ); + + Acpi->HID = Hid; + Acpi->UID = (UINT32) Xtoi (UIDStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Acpi; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPciRoot ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x0a0341d0); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFloppy ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x060441d0); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextKeyboard ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x030141d0); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextSerial ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x050141d0); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextParallelPort ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x040141d0); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpiEx ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *HIDStr; + CHAR16 *CIDStr; + CHAR16 *UIDStr; + CHAR16 *HIDSTRStr; + CHAR16 *CIDSTRStr; + CHAR16 *UIDSTRStr; + CHAR8 *AsciiStr; + UINT16 Length; + ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR *AcpiExt; + + HIDStr = GetNextParamStr (&TextDeviceNode); + CIDStr = GetNextParamStr (&TextDeviceNode); + UIDStr = GetNextParamStr (&TextDeviceNode); + HIDSTRStr = GetNextParamStr (&TextDeviceNode); + CIDSTRStr = GetNextParamStr (&TextDeviceNode); + UIDSTRStr = GetNextParamStr (&TextDeviceNode); + Length = sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + + (UINT16) StrLen (HIDSTRStr) + 1 + + (UINT16) StrLen (UIDSTRStr) + 1 + + (UINT16) StrLen (CIDSTRStr) + 1; + AcpiExt = (ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_EXTENDED_DP, + Length + ); + + if ((HIDStr[0] == L'P') && (HIDStr[1] == L'N') && (HIDStr[2] == L'P')) { + HIDStr += 3; + AcpiExt->HID = EISA_PNP_ID (Xtoi (HIDStr)); + } else { + AcpiExt->HID = (UINT32) Xtoi (HIDStr); + } + + AcpiExt->UID = (UINT32) Xtoi (UIDStr); + AcpiExt->CID = (UINT32) Xtoi (CIDStr); + + AsciiStr = AcpiExt->HidUidCidStr; + StrToAscii (HIDSTRStr, &AsciiStr); + StrToAscii (UIDSTRStr, &AsciiStr); + StrToAscii (CIDSTRStr, &AsciiStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) AcpiExt; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpiExp ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *HIDStr; + CHAR16 *CIDStr; + CHAR16 *UIDSTRStr; + CHAR8 *AsciiStr; + UINT16 Length; + ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR *AcpiExt; + + HIDStr = GetNextParamStr (&TextDeviceNode); + CIDStr = GetNextParamStr (&TextDeviceNode); + UIDSTRStr = GetNextParamStr (&TextDeviceNode); + Length = sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + (UINT16) StrLen (UIDSTRStr) + 3; + AcpiExt = (ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_EXTENDED_DP, + Length + ); + + if ((HIDStr[0] == L'P') && (HIDStr[1] == L'N') && (HIDStr[2] == L'P')) { + HIDStr += 3; + AcpiExt->HID = EISA_PNP_ID (Xtoi (HIDStr)); + } else { + AcpiExt->HID = (UINT32) Xtoi (HIDStr); + } + + AcpiExt->UID = 0; + AcpiExt->CID = (UINT32) Xtoi (CIDStr); + + AsciiStr = AcpiExt->HidUidCidStr; + // + // HID string is NULL + // + *AsciiStr = 0; + // + // Convert UID string + // + AsciiStr++; + StrToAscii (UIDSTRStr, &AsciiStr); + // + // CID string is NULL + // + *AsciiStr = 0; + + return (EFI_DEVICE_PATH_PROTOCOL *) AcpiExt; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAta ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PrimarySecondaryStr; + CHAR16 *SlaveMasterStr; + CHAR16 *LunStr; + ATAPI_DEVICE_PATH *Atapi; + + Atapi = (ATAPI_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_ATAPI_DP, + sizeof (ATAPI_DEVICE_PATH) + ); + + PrimarySecondaryStr = GetNextParamStr (&TextDeviceNode); + SlaveMasterStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + + Atapi->PrimarySecondary = (StrCmp (PrimarySecondaryStr, L"Primary") == 0) ? (UINT8) 0 : (UINT8) 1; + Atapi->SlaveMaster = (StrCmp (SlaveMasterStr, L"Master") == 0) ? (UINT8) 0 : (UINT8) 1; + Atapi->Lun = (UINT16) Xtoi (LunStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Atapi; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextScsi ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PunStr; + CHAR16 *LunStr; + SCSI_DEVICE_PATH *Scsi; + + PunStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + Scsi = (SCSI_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_SCSI_DP, + sizeof (SCSI_DEVICE_PATH) + ); + + Scsi->Pun = (UINT16) Xtoi (PunStr); + Scsi->Lun = (UINT16) Xtoi (LunStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Scsi; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFibre ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *WWNStr; + CHAR16 *LunStr; + FIBRECHANNEL_DEVICE_PATH *Fibre; + + WWNStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + Fibre = (FIBRECHANNEL_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_FIBRECHANNEL_DP, + sizeof (FIBRECHANNEL_DEVICE_PATH) + ); + + Fibre->Reserved = 0; + Xtoi64 (WWNStr, &Fibre->WWN); + Xtoi64 (LunStr, &Fibre->Lun); + + return (EFI_DEVICE_PATH_PROTOCOL *) Fibre; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromText1394 ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *GuidStr; + F1394_DEVICE_PATH *F1394; + + GuidStr = GetNextParamStr (&TextDeviceNode); + F1394 = (F1394_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_1394_DP, + sizeof (F1394_DEVICE_PATH) + ); + + F1394->Reserved = 0; + Xtoi64 (GuidStr, &F1394->Guid); + + return (EFI_DEVICE_PATH_PROTOCOL *) F1394; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsb ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PortStr; + CHAR16 *InterfaceStr; + USB_DEVICE_PATH *Usb; + + PortStr = GetNextParamStr (&TextDeviceNode); + InterfaceStr = GetNextParamStr (&TextDeviceNode); + Usb = (USB_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_USB_DP, + sizeof (USB_DEVICE_PATH) + ); + + Usb->ParentPortNumber = (UINT8) Xtoi (PortStr); + Usb->InterfaceNumber = (UINT8) Xtoi (InterfaceStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Usb; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextI2O ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *TIDStr; + I2O_DEVICE_PATH *I2O; + + TIDStr = GetNextParamStr (&TextDeviceNode); + I2O = (I2O_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_I2O_DP, + sizeof (I2O_DEVICE_PATH) + ); + + I2O->Tid = (UINT32) Xtoi (TIDStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) I2O; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextInfiniband ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *FlagsStr; + CHAR16 *GuidStr; + CHAR16 *SidStr; + CHAR16 *TidStr; + CHAR16 *DidStr; + EFI_GUID PortGid; + INFINIBAND_DEVICE_PATH *InfiniBand; + + FlagsStr = GetNextParamStr (&TextDeviceNode); + GuidStr = GetNextParamStr (&TextDeviceNode); + SidStr = GetNextParamStr (&TextDeviceNode); + TidStr = GetNextParamStr (&TextDeviceNode); + DidStr = GetNextParamStr (&TextDeviceNode); + InfiniBand = (INFINIBAND_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_INFINIBAND_DP, + sizeof (INFINIBAND_DEVICE_PATH) + ); + + InfiniBand->ResourceFlags = (UINT32) Xtoi (FlagsStr); + StrToGuid (GuidStr, &PortGid); + CopyMem (InfiniBand->PortGid, &PortGid, sizeof (EFI_GUID)); + Xtoi64 (SidStr, &InfiniBand->ServiceId); + Xtoi64 (TidStr, &InfiniBand->TargetPortId); + Xtoi64 (DidStr, &InfiniBand->DeviceId); + + return (EFI_DEVICE_PATH_PROTOCOL *) InfiniBand; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenMsg ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextVendor ( + TextDeviceNode, + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP + ); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenPcAnsi ( + IN CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + sizeof (VENDOR_DEVICE_PATH)); + Vendor->Guid = gEfiPcAnsiGuid; + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenVt100 ( + IN CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + sizeof (VENDOR_DEVICE_PATH)); + Vendor->Guid = gEfiVT100Guid; + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenVt100Plus ( + IN CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + sizeof (VENDOR_DEVICE_PATH)); + Vendor->Guid = gEfiVT100PlusGuid; + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenUtf8 ( + IN CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + sizeof (VENDOR_DEVICE_PATH)); + Vendor->Guid = gEfiVTUTF8Guid; + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUartFlowCtrl ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *ValueStr; + UART_FLOW_CONTROL_DEVICE_PATH *UartFlowControl; + + ValueStr = GetNextParamStr (&TextDeviceNode); + UartFlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + sizeof (UART_FLOW_CONTROL_DEVICE_PATH) + ); + + UartFlowControl->Guid = mEfiDevicePathMessagingUartFlowControlGuid; + if (StrCmp (ValueStr, L"XonXoff") == 0) { + UartFlowControl->FlowControlMap = 2; + } else if (StrCmp (ValueStr, L"Hardware") == 0) { + UartFlowControl->FlowControlMap = 1; + } else { + UartFlowControl->FlowControlMap = 0; + } + + return (EFI_DEVICE_PATH_PROTOCOL *) UartFlowControl; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextSAS ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *AddressStr; + CHAR16 *LunStr; + CHAR16 *RTPStr; + CHAR16 *SASSATAStr; + CHAR16 *LocationStr; + CHAR16 *ConnectStr; + CHAR16 *DriveBayStr; + CHAR16 *ReservedStr; + UINT16 Info; + SAS_DEVICE_PATH *Sas; + + AddressStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + RTPStr = GetNextParamStr (&TextDeviceNode); + SASSATAStr = GetNextParamStr (&TextDeviceNode); + LocationStr = GetNextParamStr (&TextDeviceNode); + ConnectStr = GetNextParamStr (&TextDeviceNode); + DriveBayStr = GetNextParamStr (&TextDeviceNode); + ReservedStr = GetNextParamStr (&TextDeviceNode); + Info = 0x0000; + Sas = (SAS_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + sizeof (SAS_DEVICE_PATH) + ); + + Sas->Guid = mEfiDevicePathMessagingSASGuid; + Xtoi64 (AddressStr, &Sas->SasAddress); + Xtoi64 (LunStr, &Sas->Lun); + Sas->RelativeTargetPort = (UINT16) Xtoi (RTPStr); + if (StrCmp (SASSATAStr, L"NoTopology") == 0) + ; + else { + if (StrCmp (DriveBayStr, L"0") == 0) { + Info |= 0x0001; + } else { + Info |= 0x0002; + Info |= (Xtoi (DriveBayStr) << 8); + } + + if (StrCmp (SASSATAStr, L"SATA") == 0) { + Info |= 0x0010; + } + + if (StrCmp (LocationStr, L"External") == 0) { + Info |= 0x0020; + } + + if (StrCmp (ConnectStr, L"Expanded") == 0) { + Info |= 0x0040; + } + } + + Sas->DeviceTopology = Info; + Sas->Reserved = (UINT32) Xtoi (ReservedStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Sas; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextDebugPort ( + IN CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEFINED_MESSAGING_DEVICE_PATH *Vend; + + Vend = (VENDOR_DEFINED_MESSAGING_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + sizeof (VENDOR_DEFINED_MESSAGING_DEVICE_PATH) + ); + + Vend->Guid = gEfiDebugPortProtocolGuid; + + return (EFI_DEVICE_PATH_PROTOCOL *) Vend; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMAC ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *AddressStr; + CHAR16 *IfTypeStr; + UINTN Length; + MAC_ADDR_DEVICE_PATH *MAC; + + AddressStr = GetNextParamStr (&TextDeviceNode); + IfTypeStr = GetNextParamStr (&TextDeviceNode); + MAC = (MAC_ADDR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_MAC_ADDR_DP, + sizeof (MAC_ADDR_DEVICE_PATH) + ); + + MAC->IfType = (UINT8) Xtoi (IfTypeStr); + + Length = sizeof (EFI_MAC_ADDRESS); + StrToBuf (&MAC->MacAddress.Addr[0], Length, AddressStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) MAC; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextIPv4 ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *RemoteIPStr; + CHAR16 *ProtocolStr; + CHAR16 *TypeStr; + CHAR16 *LocalIPStr; + IPv4_DEVICE_PATH *IPv4; + + RemoteIPStr = GetNextParamStr (&TextDeviceNode); + ProtocolStr = GetNextParamStr (&TextDeviceNode); + TypeStr = GetNextParamStr (&TextDeviceNode); + LocalIPStr = GetNextParamStr (&TextDeviceNode); + IPv4 = (IPv4_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_IPv4_DP, + sizeof (IPv4_DEVICE_PATH) + ); + + StrToIPv4Addr (&RemoteIPStr, &IPv4->RemoteIpAddress); + IPv4->Protocol = (StrCmp (ProtocolStr, L"UDP") == 0) ? (UINT16) 0 : (UINT16) 1; + if (StrCmp (TypeStr, L"Static") == 0) { + IPv4->StaticIpAddress = TRUE; + } else { + IPv4->StaticIpAddress = FALSE; + } + + StrToIPv4Addr (&LocalIPStr, &IPv4->LocalIpAddress); + + IPv4->LocalPort = 0; + IPv4->RemotePort = 0; + + return (EFI_DEVICE_PATH_PROTOCOL *) IPv4; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextIPv6 ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *RemoteIPStr; + CHAR16 *ProtocolStr; + CHAR16 *TypeStr; + CHAR16 *LocalIPStr; + IPv6_DEVICE_PATH *IPv6; + + RemoteIPStr = GetNextParamStr (&TextDeviceNode); + ProtocolStr = GetNextParamStr (&TextDeviceNode); + TypeStr = GetNextParamStr (&TextDeviceNode); + LocalIPStr = GetNextParamStr (&TextDeviceNode); + IPv6 = (IPv6_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_IPv6_DP, + sizeof (IPv6_DEVICE_PATH) + ); + + StrToIPv6Addr (&RemoteIPStr, &IPv6->RemoteIpAddress); + IPv6->Protocol = (StrCmp (ProtocolStr, L"UDP") == 0) ? (UINT16) 0 : (UINT16) 1; + if (StrCmp (TypeStr, L"Static") == 0) { + IPv6->StaticIpAddress = TRUE; + } else { + IPv6->StaticIpAddress = FALSE; + } + + StrToIPv6Addr (&LocalIPStr, &IPv6->LocalIpAddress); + + IPv6->LocalPort = 0; + IPv6->RemotePort = 0; + + return (EFI_DEVICE_PATH_PROTOCOL *) IPv6; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUart ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *BaudStr; + CHAR16 *DataBitsStr; + CHAR16 *ParityStr; + CHAR16 *StopBitsStr; + UART_DEVICE_PATH *Uart; + + BaudStr = GetNextParamStr (&TextDeviceNode); + DataBitsStr = GetNextParamStr (&TextDeviceNode); + ParityStr = GetNextParamStr (&TextDeviceNode); + StopBitsStr = GetNextParamStr (&TextDeviceNode); + Uart = (UART_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_UART_DP, + sizeof (UART_DEVICE_PATH) + ); + + Uart->BaudRate = (StrCmp (BaudStr, L"DEFAULT") == 0) ? 115200 : Atoi (BaudStr); + Uart->DataBits = (StrCmp (DataBitsStr, L"DEFAULT") == 0) ? (UINT8) 8 : (UINT8) Atoi (DataBitsStr); + switch (*ParityStr) { + case L'D': + Uart->Parity = 0; + break; + + case L'N': + Uart->Parity = 1; + break; + + case L'E': + Uart->Parity = 2; + break; + + case L'O': + Uart->Parity = 3; + break; + + case L'M': + Uart->Parity = 4; + break; + + case L'S': + Uart->Parity = 5; + + default: + Uart->Parity = 0xff; + } + + if (StrCmp (StopBitsStr, L"D") == 0) { + Uart->StopBits = (UINT8) 0; + } else if (StrCmp (StopBitsStr, L"1") == 0) { + Uart->StopBits = (UINT8) 1; + } else if (StrCmp (StopBitsStr, L"1.5") == 0) { + Uart->StopBits = (UINT8) 2; + } else if (StrCmp (StopBitsStr, L"2") == 0) { + Uart->StopBits = (UINT8) 3; + } else { + Uart->StopBits = 0xff; + } + + return (EFI_DEVICE_PATH_PROTOCOL *) Uart; +} + +EFI_DEVICE_PATH_PROTOCOL * +ConvertFromTextUsbClass ( + IN CHAR16 *TextDeviceNode, + IN USB_CLASS_TEXT *UsbClassText + ) +{ + CHAR16 *VIDStr; + CHAR16 *PIDStr; + CHAR16 *ClassStr; + CHAR16 *SubClassStr; + CHAR16 *ProtocolStr; + USB_CLASS_DEVICE_PATH *UsbClass; + + UsbClass = (USB_CLASS_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_USB_CLASS_DP, + sizeof (USB_CLASS_DEVICE_PATH) + ); + + VIDStr = GetNextParamStr (&TextDeviceNode); + PIDStr = GetNextParamStr (&TextDeviceNode); + if (UsbClassText->ClassExist) { + ClassStr = GetNextParamStr (&TextDeviceNode); + UsbClass->DeviceClass = (UINT8) Xtoi (ClassStr); + } else { + UsbClass->DeviceClass = UsbClassText->Class; + } + if (UsbClassText->SubClassExist) { + SubClassStr = GetNextParamStr (&TextDeviceNode); + UsbClass->DeviceSubClass = (UINT8) Xtoi (SubClassStr); + } else { + UsbClass->DeviceSubClass = UsbClassText->SubClass; + } + + ProtocolStr = GetNextParamStr (&TextDeviceNode); + + UsbClass->VendorId = (UINT16) Xtoi (VIDStr); + UsbClass->ProductId = (UINT16) Xtoi (PIDStr); + UsbClass->DeviceProtocol = (UINT8) Xtoi (ProtocolStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) UsbClass; +} + + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbClass ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = TRUE; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbAudio ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_AUDIO; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbCDCControl ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_CDCCONTROL; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbHID ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_HID; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbImage ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_IMAGE; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbPrinter ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_PRINTER; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbMassStorage ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_MASS_STORAGE; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbHub ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_HUB; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbCDCData ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_CDCDATA; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbSmartCard ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_SMART_CARD; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbVideo ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_VIDEO; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbDiagnostic ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_DIAGNOSTIC; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbWireless ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_WIRELESS; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbDeviceFirmwareUpdate ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_RESERVE; + UsbClassText.SubClassExist = FALSE; + UsbClassText.SubClass = USB_SUBCLASS_FW_UPDATE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbIrdaBridge ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_RESERVE; + UsbClassText.SubClassExist = FALSE; + UsbClassText.SubClass = USB_SUBCLASS_IRDA_BRIDGE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbTestAndMeasurement ( + IN CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_RESERVE; + UsbClassText.SubClassExist = FALSE; + UsbClassText.SubClass = USB_SUBCLASS_TEST; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbWwid ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *VIDStr; + CHAR16 *PIDStr; + CHAR16 *InterfaceNumStr; + USB_WWID_DEVICE_PATH *UsbWwid; + + VIDStr = GetNextParamStr (&TextDeviceNode); + PIDStr = GetNextParamStr (&TextDeviceNode); + InterfaceNumStr = GetNextParamStr (&TextDeviceNode); + UsbWwid = (USB_WWID_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_USB_WWID_DP, + sizeof (USB_WWID_DEVICE_PATH) + ); + + UsbWwid->VendorId = (UINT16) Xtoi (VIDStr); + UsbWwid->ProductId = (UINT16) Xtoi (PIDStr); + UsbWwid->InterfaceNumber = (UINT16) Xtoi (InterfaceNumStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) UsbWwid; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUnit ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *LunStr; + DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit; + + LunStr = GetNextParamStr (&TextDeviceNode); + LogicalUnit = (DEVICE_LOGICAL_UNIT_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_DEVICE_LOGICAL_UNIT_DP, + sizeof (DEVICE_LOGICAL_UNIT_DEVICE_PATH) + ); + + LogicalUnit->Lun = (UINT8) Xtoi (LunStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) LogicalUnit; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextiSCSI ( + IN CHAR16 *TextDeviceNode + ) +{ + UINT16 Options; + CHAR16 *NameStr; + CHAR16 *PortalGroupStr; + CHAR16 *LunStr; + CHAR16 *HeaderDigestStr; + CHAR16 *DataDigestStr; + CHAR16 *AuthenticationStr; + CHAR16 *ProtocolStr; + ISCSI_DEVICE_PATH_WITH_NAME *iSCSI; + + NameStr = GetNextParamStr (&TextDeviceNode); + PortalGroupStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + HeaderDigestStr = GetNextParamStr (&TextDeviceNode); + DataDigestStr = GetNextParamStr (&TextDeviceNode); + AuthenticationStr = GetNextParamStr (&TextDeviceNode); + ProtocolStr = GetNextParamStr (&TextDeviceNode); + iSCSI = (ISCSI_DEVICE_PATH_WITH_NAME *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_ISCSI_DP, + sizeof (ISCSI_DEVICE_PATH_WITH_NAME) + (UINT16) (StrLen (NameStr) * 2) + ); + + StrCpy (iSCSI->iSCSITargetName, NameStr); + iSCSI->TargetPortalGroupTag = (UINT16) Xtoi (PortalGroupStr); + Xtoi64 (LunStr, &iSCSI->Lun); + + Options = 0x0000; + if (StrCmp (HeaderDigestStr, L"CRC32C") == 0) { + Options |= 0x0002; + } + + if (StrCmp (DataDigestStr, L"CRC32C") == 0) { + Options |= 0x0008; + } + + if (StrCmp (AuthenticationStr, L"None") == 0) { + Options |= 0x0800; + } + + if (StrCmp (AuthenticationStr, L"CHAP_UNI") == 0) { + Options |= 0x1000; + } + + iSCSI->LoginOption = (UINT16) Options; + + iSCSI->NetworkProtocol = (UINT16) StrCmp (ProtocolStr, L"TCP"); + iSCSI->Reserved = (UINT16) 0; + + return (EFI_DEVICE_PATH_PROTOCOL *) iSCSI; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextHD ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PartitionStr; + CHAR16 *TypeStr; + CHAR16 *SignatureStr; + CHAR16 *StartStr; + CHAR16 *SizeStr; + UINT32 Signature32; + EFI_GUID SignatureGuid; + HARDDRIVE_DEVICE_PATH *Hd; + + PartitionStr = GetNextParamStr (&TextDeviceNode); + TypeStr = GetNextParamStr (&TextDeviceNode); + SignatureStr = GetNextParamStr (&TextDeviceNode); + StartStr = GetNextParamStr (&TextDeviceNode); + SizeStr = GetNextParamStr (&TextDeviceNode); + Hd = (HARDDRIVE_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_HARDDRIVE_DP, + sizeof (HARDDRIVE_DEVICE_PATH) + ); + + Hd->PartitionNumber = (UINT32) Atoi (PartitionStr); + + ZeroMem (Hd->Signature, 16); + Hd->MBRType = (UINT8) 0; + + if (StrCmp (TypeStr, L"None") == 0) { + Hd->SignatureType = (UINT8) 0; + } else if (StrCmp (TypeStr, L"MBR") == 0) { + Hd->SignatureType = SIGNATURE_TYPE_MBR; + Hd->MBRType = 0x01; + + Signature32 = (UINT32) Xtoi (SignatureStr); + CopyMem (Hd->Signature, &Signature32, sizeof (UINT32)); + } else if (StrCmp (TypeStr, L"GUID") == 0) { + Hd->SignatureType = SIGNATURE_TYPE_GUID; + Hd->MBRType = 0x02; + + StrToGuid (SignatureStr, &SignatureGuid); + CopyMem (Hd->Signature, &SignatureGuid, sizeof (EFI_GUID)); + } else { + Hd->SignatureType = 0xff; + + } + + Xtoi64 (StartStr, &Hd->PartitionStart); + Xtoi64 (SizeStr, &Hd->PartitionSize); + + return (EFI_DEVICE_PATH_PROTOCOL *) Hd; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextCDROM ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *EntryStr; + CHAR16 *StartStr; + CHAR16 *SizeStr; + CDROM_DEVICE_PATH *CDROM; + + EntryStr = GetNextParamStr (&TextDeviceNode); + StartStr = GetNextParamStr (&TextDeviceNode); + SizeStr = GetNextParamStr (&TextDeviceNode); + CDROM = (CDROM_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_CDROM_DP, + sizeof (CDROM_DEVICE_PATH) + ); + + CDROM->BootEntry = (UINT32) Xtoi (EntryStr); + Xtoi64 (StartStr, &CDROM->PartitionStart); + Xtoi64 (SizeStr, &CDROM->PartitionSize); + + return (EFI_DEVICE_PATH_PROTOCOL *) CDROM; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenMEDIA ( + IN CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextVendor ( + TextDeviceNode, + MEDIA_DEVICE_PATH, + MEDIA_VENDOR_DP + ); +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFilePath ( + IN CHAR16 *TextDeviceNode + ) +{ + FILEPATH_DEVICE_PATH *File; + + File = (FILEPATH_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_FILEPATH_DP, + sizeof (FILEPATH_DEVICE_PATH) + (UINT16) (StrLen (TextDeviceNode) * 2) + ); + + StrCpy (File->PathName, TextDeviceNode); + + return (EFI_DEVICE_PATH_PROTOCOL *) File; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMedia ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *GuidStr; + MEDIA_PROTOCOL_DEVICE_PATH *Media; + + GuidStr = GetNextParamStr (&TextDeviceNode); + Media = (MEDIA_PROTOCOL_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_PROTOCOL_DP, + sizeof (MEDIA_PROTOCOL_DEVICE_PATH) + ); + + StrToGuid (GuidStr, &Media->Protocol); + + return (EFI_DEVICE_PATH_PROTOCOL *) Media; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextBBS ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *TypeStr; + CHAR16 *IdStr; + CHAR16 *FlagsStr; + UINT8 *AsciiStr; + BBS_BBS_DEVICE_PATH *Bbs; + + TypeStr = GetNextParamStr (&TextDeviceNode); + IdStr = GetNextParamStr (&TextDeviceNode); + FlagsStr = GetNextParamStr (&TextDeviceNode); + Bbs = (BBS_BBS_DEVICE_PATH *) CreateDeviceNode ( + BBS_DEVICE_PATH, + BBS_BBS_DP, + sizeof (BBS_BBS_DEVICE_PATH) + (UINT16) (StrLen (IdStr)) + ); + + if (StrCmp (TypeStr, L"Floppy") == 0) { + Bbs->DeviceType = BBS_TYPE_FLOPPY; + } else if (StrCmp (TypeStr, L"HD") == 0) { + Bbs->DeviceType = BBS_TYPE_HARDDRIVE; + } else if (StrCmp (TypeStr, L"CDROM") == 0) { + Bbs->DeviceType = BBS_TYPE_CDROM; + } else if (StrCmp (TypeStr, L"PCMCIA") == 0) { + Bbs->DeviceType = BBS_TYPE_PCMCIA; + } else if (StrCmp (TypeStr, L"USB") == 0) { + Bbs->DeviceType = BBS_TYPE_USB; + } else if (StrCmp (TypeStr, L"Network") == 0) { + Bbs->DeviceType = BBS_TYPE_EMBEDDED_NETWORK; + } else { + Bbs->DeviceType = BBS_TYPE_UNKNOWN; + } + + AsciiStr = Bbs->String; + StrToAscii (IdStr, &AsciiStr); + + Bbs->StatusFlag = (UINT16) Xtoi (FlagsStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Bbs; +} + +DEVICE_PATH_FROM_TEXT_TABLE DevPathFromTextTable[] = { + L"Pci", + DevPathFromTextPci, + L"PcCard", + DevPathFromTextPcCard, + L"MemoryMapped", + DevPathFromTextMemoryMapped, + L"VenHw", + DevPathFromTextVenHw, + L"Ctrl", + DevPathFromTextCtrl, + L"Acpi", + DevPathFromTextAcpi, + L"PciRoot", + DevPathFromTextPciRoot, + L"Floppy", + DevPathFromTextFloppy, + L"Keyboard", + DevPathFromTextKeyboard, + L"Serial", + DevPathFromTextSerial, + L"ParallelPort", + DevPathFromTextParallelPort, + L"AcpiEx", + DevPathFromTextAcpiEx, + L"AcpiExp", + DevPathFromTextAcpiExp, + L"Ata", + DevPathFromTextAta, + L"Scsi", + DevPathFromTextScsi, + L"Fibre", + DevPathFromTextFibre, + L"I1394", + DevPathFromText1394, + L"USB", + DevPathFromTextUsb, + L"I2O", + DevPathFromTextI2O, + L"Infiniband", + DevPathFromTextInfiniband, + L"VenMsg", + DevPathFromTextVenMsg, + L"VenPcAnsi", + DevPathFromTextVenPcAnsi, + L"VenVt100", + DevPathFromTextVenVt100, + L"VenVt100Plus", + DevPathFromTextVenVt100Plus, + L"VenUtf8", + DevPathFromTextVenUtf8, + L"UartFlowCtrl", + DevPathFromTextUartFlowCtrl, + L"SAS", + DevPathFromTextSAS, + L"DebugPort", + DevPathFromTextDebugPort, + L"MAC", + DevPathFromTextMAC, + L"IPv4", + DevPathFromTextIPv4, + L"IPv6", + DevPathFromTextIPv6, + L"Uart", + DevPathFromTextUart, + L"UsbClass", + DevPathFromTextUsbClass, + L"UsbAudio", + DevPathFromTextUsbAudio, + L"UsbCDCControl", + DevPathFromTextUsbCDCControl, + L"UsbHID", + DevPathFromTextUsbHID, + L"UsbImage", + DevPathFromTextUsbImage, + L"UsbPrinter", + DevPathFromTextUsbPrinter, + L"UsbMassStorage", + DevPathFromTextUsbMassStorage, + L"UsbHub", + DevPathFromTextUsbHub, + L"UsbCDCData", + DevPathFromTextUsbCDCData, + L"UsbSmartCard", + DevPathFromTextUsbSmartCard, + L"UsbVideo", + DevPathFromTextUsbVideo, + L"UsbDiagnostic", + DevPathFromTextUsbDiagnostic, + L"UsbWireless", + DevPathFromTextUsbWireless, + L"UsbDeviceFirmwareUpdate", + DevPathFromTextUsbDeviceFirmwareUpdate, + L"UsbIrdaBridge", + DevPathFromTextUsbIrdaBridge, + L"UsbTestAndMeasurement", + DevPathFromTextUsbTestAndMeasurement, + L"UsbWwid", + DevPathFromTextUsbWwid, + L"Unit", + DevPathFromTextUnit, + L"iSCSI", + DevPathFromTextiSCSI, + L"HD", + DevPathFromTextHD, + L"CDROM", + DevPathFromTextCDROM, + L"VenMEDIA", + DevPathFromTextVenMEDIA, + L"Media", + DevPathFromTextMedia, + L"BBS", + DevPathFromTextBBS, + NULL, + NULL +}; + +EFI_DEVICE_PATH_PROTOCOL * +ConvertTextToDeviceNode ( + IN CONST CHAR16 *TextDeviceNode + ) +/*++ + + Routine Description: + Convert text to the binary representation of a device node. + + Arguments: + TextDeviceNode - TextDeviceNode points to the text representation of a device + node. Conversion starts with the first character and continues + until the first non-device node character. + + Returns: + A pointer - Pointer to the EFI device node. + NULL - If TextDeviceNode is NULL or there was insufficient memory or text unsupported. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL * (*DumpNode) (CHAR16 *); + CHAR16 *ParamStr; + EFI_DEVICE_PATH_PROTOCOL *DeviceNode; + CHAR16 *DeviceNodeStr; + UINTN Index; + + if ((TextDeviceNode == NULL) || (IS_NULL (*TextDeviceNode))) { + return NULL; + } + + ParamStr = NULL; + DumpNode = NULL; + DeviceNodeStr = StrDuplicate (TextDeviceNode); + + for (Index = 0; DevPathFromTextTable[Index].Function; Index++) { + ParamStr = GetParamByNodeName (DeviceNodeStr, DevPathFromTextTable[Index].DevicePathNodeText); + if (ParamStr != NULL) { + DumpNode = DevPathFromTextTable[Index].Function; + break; + } + } + + if (DumpNode == NULL) { + // + // A file path + // + DumpNode = DevPathFromTextFilePath; + DeviceNode = DumpNode (DeviceNodeStr); + } else { + DeviceNode = DumpNode (ParamStr); + gBS->FreePool (ParamStr); + } + + gBS->FreePool (DeviceNodeStr); + + return DeviceNode; +} + +EFI_DEVICE_PATH_PROTOCOL * +ConvertTextToDevicePath ( + IN CONST CHAR16 *TextDevicePath + ) +/*++ + + Routine Description: + Convert text to the binary representation of a device path. + + Arguments: + TextDevicePath - TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device node character. + + Returns: + A pointer - Pointer to the allocated device path. + NULL - If TextDeviceNode is NULL or there was insufficient memory. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL * (*DumpNode) (CHAR16 *); + CHAR16 *ParamStr; + EFI_DEVICE_PATH_PROTOCOL *DeviceNode; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + CHAR16 *DevicePathStr; + CHAR16 *Str; + CHAR16 *DeviceNodeStr; + UINT8 IsInstanceEnd; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + if ((TextDevicePath == NULL) || (IS_NULL (*TextDevicePath))) { + return NULL; + } + + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH); + SetDevicePathEndNode (DevicePath); + + ParamStr = NULL; + DeviceNodeStr = NULL; + DevicePathStr = StrDuplicate (TextDevicePath); + + Str = DevicePathStr; + while ((DeviceNodeStr = GetNextDeviceNodeStr (&Str, &IsInstanceEnd)) != NULL) { + DumpNode = NULL; + for (Index = 0; DevPathFromTextTable[Index].Function; Index++) { + ParamStr = GetParamByNodeName (DeviceNodeStr, DevPathFromTextTable[Index].DevicePathNodeText); + if (ParamStr != NULL) { + DumpNode = DevPathFromTextTable[Index].Function; + break; + } + } + + if (DumpNode == NULL) { + // + // A file path + // + DumpNode = DevPathFromTextFilePath; + DeviceNode = DumpNode (DeviceNodeStr); + } else { + DeviceNode = DumpNode (ParamStr); + gBS->FreePool (ParamStr); + } + + NewDevicePath = AppendDeviceNode (DevicePath, DeviceNode); + gBS->FreePool (DevicePath); + gBS->FreePool (DeviceNode); + DevicePath = NewDevicePath; + + if (IsInstanceEnd) { + DeviceNode = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH); + SetDevicePathInstanceEndNode (DeviceNode); + + NewDevicePath = AppendDeviceNode (DevicePath, DeviceNode); + gBS->FreePool (DevicePath); + gBS->FreePool (DeviceNode); + DevicePath = NewDevicePath; + } + } + + gBS->FreePool (DevicePathStr); + return DevicePath; +} diff --git a/EdkModulePkg/Universal/DevicePath/Dxe/DevicePathToText.c b/EdkModulePkg/Universal/DevicePath/Dxe/DevicePathToText.c new file mode 100644 index 0000000000..64fd5658fd --- /dev/null +++ b/EdkModulePkg/Universal/DevicePath/Dxe/DevicePathToText.c @@ -0,0 +1,1526 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DevicePathToText.c + +Abstract: + + DevicePathToText protocol as defined in the UEFI 2.0 specification. + +--*/ + +#include +#include "DevicePath.h" + +EFI_DEVICE_PATH_PROTOCOL * +UnpackDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +/*++ + + Routine Description: + Function unpacks a device path data structure so that all the nodes of a device path + are naturally aligned. + + Arguments: + DevPath - A pointer to a device path data structure + + Returns: + If the memory for the device path is successfully allocated, then a pointer to the + new device path is returned. Otherwise, NULL is returned. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *Src; + EFI_DEVICE_PATH_PROTOCOL *Dest; + EFI_DEVICE_PATH_PROTOCOL *NewPath; + UINTN Size; + + if (DevPath == NULL) { + return NULL; + } + // + // Walk device path and round sizes to valid boundries + // + Src = DevPath; + Size = 0; + for (;;) { + Size += DevicePathNodeLength (Src); + Size += ALIGN_SIZE (Size); + + if (IsDevicePathEnd (Src)) { + break; + } + + Src = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (Src); + } + // + // Allocate space for the unpacked path + // + NewPath = AllocateZeroPool (Size); + if (NewPath != NULL) { + + ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0); + + // + // Copy each node + // + Src = DevPath; + Dest = NewPath; + for (;;) { + Size = DevicePathNodeLength (Src); + CopyMem (Dest, Src, Size); + Size += ALIGN_SIZE (Size); + SetDevicePathNodeLength (Dest, Size); + Dest->Type |= EFI_DP_TYPE_UNPACKED; + Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size); + + if (IsDevicePathEnd (Src)) { + break; + } + + Src = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (Src); + } + } + + return NewPath; +} + +VOID * +ReallocatePool ( + IN VOID *OldPool, + IN UINTN OldSize, + IN UINTN NewSize + ) +/*++ + + Routine Description: + Adjusts the size of a previously allocated buffer. + + Arguments: + OldPool - A pointer to the buffer whose size is being adjusted. + OldSize - The size of the current buffer. + NewSize - The size of the new buffer. + + Returns: + EFI_SUCEESS - The requested number of bytes were allocated. + EFI_OUT_OF_RESOURCES - The pool requested could not be allocated. + EFI_INVALID_PARAMETER - The buffer was invalid. + +--*/ +{ + VOID *NewPool; + + NewPool = NULL; + if (NewSize) { + NewPool = AllocateZeroPool (NewSize); + } + + if (OldPool) { + if (NewPool) { + CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize); + } + + gBS->FreePool (OldPool); + } + + return NewPool; +} + +CHAR16 * +CatPrint ( + IN OUT POOL_PRINT *Str, + IN CHAR16 *Fmt, + ... + ) +/*++ + + Routine Description: + Concatenates a formatted unicode string to allocated pool. + The caller must free the resulting buffer. + + Arguments: + Str - Tracks the allocated pool, size in use, and + amount of pool allocated. + Fmt - The format string + + Returns: + Allocated buffer with the formatted string printed in it. + The caller must free the allocated buffer. The buffer + allocation is not packed. + +--*/ +{ + UINT16 *AppendStr; + VA_LIST Args; + UINTN Size; + + AppendStr = AllocateZeroPool (0x1000); + if (AppendStr == NULL) { + return Str->Str; + } + + VA_START (Args, Fmt); + UnicodeVSPrint (AppendStr, 0x1000, Fmt, Args); + VA_END (Args); + if (NULL == Str->Str) { + Size = StrSize (AppendStr); + Str->Str = AllocateZeroPool (Size); + ASSERT (Str->Str != NULL); + } else { + Size = StrSize (AppendStr) + StrSize (Str->Str) - sizeof (UINT16); + Str->Str = ReallocatePool ( + Str->Str, + StrSize (Str->Str), + Size + ); + ASSERT (Str->Str != NULL); + } + + Str->MaxLen = MAX_CHAR * sizeof (UINT16); + if (Size < Str->MaxLen) { + StrCat (Str->Str, AppendStr); + Str->Len = Size - sizeof (UINT16); + } + + gBS->FreePool (AppendStr); + return Str->Str; +} + +VOID +DevPathToTextPci ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + PCI_DEVICE_PATH *Pci; + + Pci = DevPath; + CatPrint (Str, L"Pci(%x,%x)", Pci->Function, Pci->Device); +} + +VOID +DevPathToTextPccard ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + PCCARD_DEVICE_PATH *Pccard; + + Pccard = DevPath; + CatPrint (Str, L"PcCard(%x)", Pccard->FunctionNumber); +} + +VOID +DevPathToTextMemMap ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + MEMMAP_DEVICE_PATH *MemMap; + + MemMap = DevPath; + CatPrint ( + Str, + L"MemoryMapped(%lx,%lx)", + MemMap->StartingAddress, + MemMap->EndingAddress + ); +} + +VOID +DevPathToTextVendor ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + VENDOR_DEVICE_PATH *Vendor; + CHAR16 *Type; + UINTN Index; + UINT32 FlowControlMap; + UINT16 Info; + + Vendor = (VENDOR_DEVICE_PATH *) DevPath; + switch (DevicePathType (&Vendor->Header)) { + case HARDWARE_DEVICE_PATH: + Type = L"Hw"; + break; + + case MESSAGING_DEVICE_PATH: + Type = L"Msg"; + if (AllowShortcuts) { + if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) { + CatPrint (Str, L"VenPcAnsi()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) { + CatPrint (Str, L"VenVt100()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) { + CatPrint (Str, L"VenVt100Plus()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) { + CatPrint (Str, L"VenUft8()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &mEfiDevicePathMessagingUartFlowControlGuid)) { + FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap); + switch (FlowControlMap & 0x00000003) { + case 0: + CatPrint (Str, L"UartFlowCtrl(%s)", L"None"); + break; + + case 1: + CatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware"); + break; + + case 2: + CatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff"); + break; + + default: + break; + } + + return ; + } else if (CompareGuid (&Vendor->Guid, &mEfiDevicePathMessagingSASGuid)) { + CatPrint ( + Str, + L"SAS(%lx,%lx,%x,", + ((SAS_DEVICE_PATH *) Vendor)->SasAddress, + ((SAS_DEVICE_PATH *) Vendor)->Lun, + ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort + ); + Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology); + if ((Info & 0x0f) == 0) { + CatPrint (Str, L"NoTopology,0,0,0,"); + } else if (((Info & 0x0f) == 1) || ((Info & 0x0f) == 2)) { + CatPrint ( + Str, + L"%s,%s,%s,", + (Info & (0x1 << 4)) ? L"SATA" : L"SAS", + (Info & (0x1 << 5)) ? L"External" : L"Internal", + (Info & (0x1 << 6)) ? L"Expanded" : L"Direct" + ); + if ((Info & 0x0f) == 1) { + CatPrint (Str, L"0,"); + } else { + CatPrint (Str, L"%x,", (Info >> 8) & 0xff); + } + } else { + CatPrint (Str, L"0,0,0,0,"); + } + + CatPrint (Str, L"%x)", ((SAS_DEVICE_PATH *) Vendor)->Reserved); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) { + CatPrint (Str, L"DebugPort()"); + return ; + } else { + return ; + // + // reserved + // + } + } + break; + + case MEDIA_DEVICE_PATH: + Type = L"Media"; + break; + + default: + Type = L"?"; + break; + } + + CatPrint (Str, L"Ven%s(%g,", Type, &Vendor->Guid); + for (Index = 0; Index < DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH); Index++) { + CatPrint (Str, L"%02x", ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]); + } + + CatPrint (Str, L")"); +} + +VOID +DevPathToTextController ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + CONTROLLER_DEVICE_PATH *Controller; + + Controller = DevPath; + CatPrint ( + Str, + L"Ctrl(%x)", + (UINT16 *)Controller->ControllerNumber + ); +} + +VOID +DevPathToTextAcpi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + ACPI_HID_DEVICE_PATH *Acpi; + + Acpi = DevPath; + if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + if (AllowShortcuts) { + switch (EISA_ID_TO_NUM (Acpi->HID)) { + case 0x0a03: + CatPrint (Str, L"PciRoot(%x)", Acpi->UID); + break; + + case 0x0604: + CatPrint (Str, L"Floppy(%x)", Acpi->UID); + break; + + case 0x0301: + CatPrint (Str, L"Keyboard(%x)", Acpi->UID); + break; + + case 0x0501: + CatPrint (Str, L"Serial(%x)", Acpi->UID); + break; + + case 0x0401: + CatPrint (Str, L"ParallelPort(%x)", Acpi->UID); + break; + + default: + break; + } + + return ; + } + + CatPrint (Str, L"Acpi(PNP%04x,%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID); + } else { + CatPrint (Str, L"Acpi(%08x,%x)", Acpi->HID, Acpi->UID); + } +} + +#define NextStrA(a) ((UINT8 *) (((UINT8 *) (a)) + AsciiStrLen (a) + 1)) + +VOID +DevPathToTextExtAcpi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR *AcpiExt; + + AcpiExt = DevPath; + + if (AllowShortcuts) { + if ((*(AcpiExt->HidUidCidStr) == '\0') && + (*(NextStrA (NextStrA (AcpiExt->HidUidCidStr))) == '\0') && + (AcpiExt->UID == 0) + ) { + if ((AcpiExt->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + CatPrint ( + Str, + L"AcpiExp(PNP%04x,%x,%a)", + EISA_ID_TO_NUM (AcpiExt->HID), + AcpiExt->CID, + NextStrA (AcpiExt->HidUidCidStr) + ); + } else { + CatPrint ( + Str, + L"AcpiExp(%08x,%x,%a)", + AcpiExt->HID, + AcpiExt->CID, + NextStrA (AcpiExt->HidUidCidStr) + ); + } + } + return ; + } + + if ((AcpiExt->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + CatPrint ( + Str, + L"AcpiEx(PNP%04x,%x,%x,%a,%a,%a)", + EISA_ID_TO_NUM (AcpiExt->HID), + AcpiExt->CID, + AcpiExt->UID, + AcpiExt->HidUidCidStr, + NextStrA (NextStrA (AcpiExt->HidUidCidStr)), + NextStrA (AcpiExt->HidUidCidStr) + ); + } else { + CatPrint ( + Str, + L"AcpiEx(%08x,%x,%x,%a,%a,%a)", + AcpiExt->HID, + AcpiExt->CID, + AcpiExt->UID, + AcpiExt->HidUidCidStr, + NextStrA (NextStrA (AcpiExt->HidUidCidStr)), + NextStrA (AcpiExt->HidUidCidStr) + ); + } +} + +VOID +DevPathToTextAtapi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + ATAPI_DEVICE_PATH *Atapi; + + Atapi = DevPath; + + if (DisplayOnly) { + CatPrint (Str, L"Ata(%x)", Atapi->Lun); + } else { + CatPrint ( + Str, + L"Ata(%s,%s,%x)", + Atapi->PrimarySecondary ? L"Secondary" : L"Primary", + Atapi->SlaveMaster ? L"Slave" : L"Master", + Atapi->Lun + ); + } +} + +VOID +DevPathToTextScsi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + SCSI_DEVICE_PATH *Scsi; + + Scsi = DevPath; + CatPrint (Str, L"Scsi(%x,%x)", Scsi->Pun, Scsi->Lun); +} + +VOID +DevPathToTextFibre ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + FIBRECHANNEL_DEVICE_PATH *Fibre; + + Fibre = DevPath; + CatPrint (Str, L"Fibre(%lx,%lx)", Fibre->WWN, Fibre->Lun); +} + +VOID +DevPathToText1394 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + F1394_DEVICE_PATH *F1394; + + F1394 = DevPath; + CatPrint (Str, L"I1394(%lx)", F1394->Guid); +} + +VOID +DevPathToTextUsb ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + USB_DEVICE_PATH *Usb; + + Usb = DevPath; + CatPrint (Str, L"USB(%x,%x)", Usb->ParentPortNumber, Usb->InterfaceNumber); +} + +VOID +DevPathToTextUsbWWID ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + USB_WWID_DEVICE_PATH *UsbWWId; + + UsbWWId = DevPath; + CatPrint ( + Str, + L"UsbWwid(%x,%x,%x,\"WWID\")", + UsbWWId->VendorId, + UsbWWId->ProductId, + UsbWWId->InterfaceNumber + ); +} + +VOID +DevPathToTextLogicalUnit ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit; + + LogicalUnit = DevPath; + CatPrint (Str, L"Unit(%x)", LogicalUnit->Lun); +} + +VOID +DevPathToTextUsbClass ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + USB_CLASS_DEVICE_PATH *UsbClass; + + UsbClass = DevPath; + + if (AllowShortcuts == TRUE) { + switch (UsbClass->DeviceClass) { + case 1: + CatPrint ( + Str, + L"UsbAudio(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 2: + CatPrint ( + Str, + L"UsbCDCControl(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 3: + CatPrint ( + Str, + L"UsbHID(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 6: + CatPrint ( + Str, + L"UsbImage(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 7: + CatPrint ( + Str, + L"UsbPrinter(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 8: + CatPrint ( + Str, + L"UsbMassStorage(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 9: + CatPrint ( + Str, + L"UsbHub(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 10: + CatPrint ( + Str, + L"UsbCDCData(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 11: + CatPrint ( + Str, + L"UsbSmartCard(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 14: + CatPrint ( + Str, + L"UsbVideo(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 220: + CatPrint ( + Str, + L"UsbDiagnostic(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 224: + CatPrint ( + Str, + L"UsbWireless(%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); + break; + + case 254: + if (UsbClass->DeviceSubClass == 1) { + CatPrint ( + Str, + L"UsbDeviceFirmwareUpdate(%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceProtocol + ); + } else if (UsbClass->DeviceSubClass == 2) { + CatPrint ( + Str, + L"UsbIrdaBridge(%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceProtocol + ); + } else if (UsbClass->DeviceSubClass == 3) { + CatPrint ( + Str, + L"UsbTestAndMeasurement(%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceProtocol + ); + } + break; + + default: + break; + } + + return ; + } + + CatPrint ( + Str, + L"UsbClass(%x,%x,%x,%x,%x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceClass, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); +} + +VOID +DevPathToTextI2O ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + I2O_DEVICE_PATH *I2O; + + I2O = DevPath; + CatPrint (Str, L"I2O(%x)", I2O->Tid); +} + +VOID +DevPathToTextMacAddr ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + MAC_ADDR_DEVICE_PATH *MAC; + UINTN HwAddressSize; + UINTN Index; + + MAC = DevPath; + + HwAddressSize = sizeof (EFI_MAC_ADDRESS); + if (MAC->IfType == 0x01 || MAC->IfType == 0x00) { + HwAddressSize = 6; + } + + CatPrint (Str, L"MAC("); + + for (Index = 0; Index < HwAddressSize; Index++) { + CatPrint (Str, L"%02x", MAC->MacAddress.Addr[Index]); + } + + CatPrint (Str, L",%x)", MAC->IfType); +} + +VOID +DevPathToTextIPv4 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + IPv4_DEVICE_PATH *IP; + + IP = DevPath; + if (DisplayOnly == TRUE) { + CatPrint ( + Str, + L"IPv4(%d.%d.%d.%d)", + IP->RemoteIpAddress.Addr[0], + IP->RemoteIpAddress.Addr[1], + IP->RemoteIpAddress.Addr[2], + IP->RemoteIpAddress.Addr[3] + ); + return ; + } + + CatPrint ( + Str, + L"IPv4(%d.%d.%d.%d,%s,%s,%d.%d.%d.%d)", + IP->RemoteIpAddress.Addr[0], + IP->RemoteIpAddress.Addr[1], + IP->RemoteIpAddress.Addr[2], + IP->RemoteIpAddress.Addr[3], + IP->Protocol ? L"TCP" : L"UDP", + (IP->StaticIpAddress == TRUE) ? L"Static" : L"DHCP", + IP->LocalIpAddress.Addr[0], + IP->LocalIpAddress.Addr[1], + IP->LocalIpAddress.Addr[2], + IP->LocalIpAddress.Addr[3] + ); +} + +VOID +DevPathToTextIPv6 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + IPv6_DEVICE_PATH *IP; + + IP = DevPath; + if (DisplayOnly == TRUE) { + CatPrint ( + Str, + L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)", + IP->RemoteIpAddress.Addr[0], + IP->RemoteIpAddress.Addr[1], + IP->RemoteIpAddress.Addr[2], + IP->RemoteIpAddress.Addr[3], + IP->RemoteIpAddress.Addr[4], + IP->RemoteIpAddress.Addr[5], + IP->RemoteIpAddress.Addr[6], + IP->RemoteIpAddress.Addr[7], + IP->RemoteIpAddress.Addr[8], + IP->RemoteIpAddress.Addr[9], + IP->RemoteIpAddress.Addr[10], + IP->RemoteIpAddress.Addr[11], + IP->RemoteIpAddress.Addr[12], + IP->RemoteIpAddress.Addr[13], + IP->RemoteIpAddress.Addr[14], + IP->RemoteIpAddress.Addr[15] + ); + return ; + } + + CatPrint ( + Str, + L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x,%s,%s,%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)", + IP->RemoteIpAddress.Addr[0], + IP->RemoteIpAddress.Addr[1], + IP->RemoteIpAddress.Addr[2], + IP->RemoteIpAddress.Addr[3], + IP->RemoteIpAddress.Addr[4], + IP->RemoteIpAddress.Addr[5], + IP->RemoteIpAddress.Addr[6], + IP->RemoteIpAddress.Addr[7], + IP->RemoteIpAddress.Addr[8], + IP->RemoteIpAddress.Addr[9], + IP->RemoteIpAddress.Addr[10], + IP->RemoteIpAddress.Addr[11], + IP->RemoteIpAddress.Addr[12], + IP->RemoteIpAddress.Addr[13], + IP->RemoteIpAddress.Addr[14], + IP->RemoteIpAddress.Addr[15], + IP->Protocol ? L"TCP" : L"UDP", + (IP->StaticIpAddress == TRUE) ? L"Static" : L"DHCP", + IP->LocalIpAddress.Addr[0], + IP->LocalIpAddress.Addr[1], + IP->LocalIpAddress.Addr[2], + IP->LocalIpAddress.Addr[3], + IP->LocalIpAddress.Addr[4], + IP->LocalIpAddress.Addr[5], + IP->LocalIpAddress.Addr[6], + IP->LocalIpAddress.Addr[7], + IP->LocalIpAddress.Addr[8], + IP->LocalIpAddress.Addr[9], + IP->LocalIpAddress.Addr[10], + IP->LocalIpAddress.Addr[11], + IP->LocalIpAddress.Addr[12], + IP->LocalIpAddress.Addr[13], + IP->LocalIpAddress.Addr[14], + IP->LocalIpAddress.Addr[15] + ); +} + +VOID +DevPathToTextInfiniBand ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + INFINIBAND_DEVICE_PATH *InfiniBand; + + InfiniBand = DevPath; + CatPrint ( + Str, + L"Infiniband(%x,%g,%lx,%lx,%lx)", + InfiniBand->ResourceFlags, + InfiniBand->PortGid, + InfiniBand->ServiceId, + InfiniBand->TargetPortId, + InfiniBand->DeviceId + ); +} + +VOID +DevPathToTextUart ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + UART_DEVICE_PATH *Uart; + CHAR8 Parity; + + Uart = DevPath; + switch (Uart->Parity) { + case 0: + Parity = 'D'; + break; + + case 1: + Parity = 'N'; + break; + + case 2: + Parity = 'E'; + break; + + case 3: + Parity = 'O'; + break; + + case 4: + Parity = 'M'; + break; + + case 5: + Parity = 'S'; + break; + + default: + Parity = 'x'; + break; + } + + if (Uart->BaudRate == 0) { + CatPrint (Str, L"Uart(DEFAULT,"); + } else { + CatPrint (Str, L"Uart(%ld,", Uart->BaudRate); + } + + if (Uart->DataBits == 0) { + CatPrint (Str, L"DEFAULT,"); + } else { + CatPrint (Str, L"%d,", Uart->DataBits); + } + + CatPrint (Str, L"%c,", Parity); + + switch (Uart->StopBits) { + case 0: + CatPrint (Str, L"D)"); + break; + + case 1: + CatPrint (Str, L"1)"); + break; + + case 2: + CatPrint (Str, L"1.5)"); + break; + + case 3: + CatPrint (Str, L"2)"); + break; + + default: + CatPrint (Str, L"x)"); + break; + } +} + +VOID +DevPathToTextiSCSI ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + ISCSI_DEVICE_PATH_WITH_NAME *iSCSI; + UINT16 Options; + + iSCSI = DevPath; + CatPrint ( + Str, + L"iSCSI(%s,%x,%lx,", + iSCSI->iSCSITargetName, + iSCSI->TargetPortalGroupTag, + iSCSI->Lun + ); + + Options = iSCSI->LoginOption; + CatPrint (Str, L"%s,", ((Options >> 1) & 0x0001) ? L"CRC32C" : L"None"); + CatPrint (Str, L"%s,", ((Options >> 3) & 0x0001) ? L"CRC32C" : L"None"); + if ((Options >> 11) & 0x0001) { + CatPrint (Str, L"%s,", L"None"); + } else if ((Options >> 12) & 0x0001) { + CatPrint (Str, L"%s,", L"CHAP_UNI"); + } else { + CatPrint (Str, L"%s,", L"CHAP_BI"); + + } + + CatPrint (Str, L"%s)", (iSCSI->NetworkProtocol == 0) ? L"TCP" : L"reserved"); +} + +VOID +DevPathToTextHardDrive ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + HARDDRIVE_DEVICE_PATH *Hd; + + Hd = DevPath; + switch (Hd->SignatureType) { + case 0: + CatPrint ( + Str, + L"HD(%d,%s,0,", + Hd->PartitionNumber, + L"None" + ); + break; + + case SIGNATURE_TYPE_MBR: + CatPrint ( + Str, + L"HD(%d,%s,%08x,", + Hd->PartitionNumber, + L"MBR", + *((UINT32 *) (&(Hd->Signature[0]))) + ); + break; + + case SIGNATURE_TYPE_GUID: + CatPrint ( + Str, + L"HD(%d,%s,%g,", + Hd->PartitionNumber, + L"GUID", + (EFI_GUID *) &(Hd->Signature[0]) + ); + break; + + default: + break; + } + + CatPrint (Str, L"%lx,%lx)", Hd->PartitionStart, Hd->PartitionSize); +} + +VOID +DevPathToTextCDROM ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + CDROM_DEVICE_PATH *Cd; + + Cd = DevPath; + if (DisplayOnly == TRUE) { + CatPrint (Str, L"CDROM(%x)", Cd->BootEntry); + return ; + } + + CatPrint (Str, L"CDROM(%x,%lx,%lx)", Cd->BootEntry, Cd->PartitionStart, Cd->PartitionSize); +} + +VOID +DevPathToTextFilePath ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + FILEPATH_DEVICE_PATH *Fp; + + Fp = DevPath; + CatPrint (Str, L"%s", Fp->PathName); +} + +VOID +DevPathToTextMediaProtocol ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + MEDIA_PROTOCOL_DEVICE_PATH *MediaProt; + + MediaProt = DevPath; + CatPrint (Str, L"Media(%g)", &MediaProt->Protocol); +} + +VOID +DevPathToTextBBS ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + BBS_BBS_DEVICE_PATH *Bbs; + CHAR16 *Type; + + Bbs = DevPath; + switch (Bbs->DeviceType) { + case BBS_TYPE_FLOPPY: + Type = L"Floppy"; + break; + + case BBS_TYPE_HARDDRIVE: + Type = L"HD"; + break; + + case BBS_TYPE_CDROM: + Type = L"CDROM"; + break; + + case BBS_TYPE_PCMCIA: + Type = L"PCMCIA"; + break; + + case BBS_TYPE_USB: + Type = L"USB"; + break; + + case BBS_TYPE_EMBEDDED_NETWORK: + Type = L"Network"; + break; + + default: + Type = L"?"; + break; + } + + CatPrint (Str, L"BBS(%s,%a", Type, Bbs->String); + + if (DisplayOnly == TRUE) { + CatPrint (Str, L")"); + return ; + } + + CatPrint (Str, L",%x)", Bbs->StatusFlag); +} + +VOID +DevPathToTextEndInstance ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + CatPrint (Str, L","); +} + +VOID +DevPathToTextNodeUnknown ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + CatPrint (Str, L"?"); +} + +DEVICE_PATH_TO_TEXT_TABLE DevPathToTextTable[] = { + HARDWARE_DEVICE_PATH, + HW_PCI_DP, + DevPathToTextPci, + HARDWARE_DEVICE_PATH, + HW_PCCARD_DP, + DevPathToTextPccard, + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + DevPathToTextMemMap, + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + DevPathToTextVendor, + HARDWARE_DEVICE_PATH, + HW_CONTROLLER_DP, + DevPathToTextController, + ACPI_DEVICE_PATH, + ACPI_DP, + DevPathToTextAcpi, + ACPI_DEVICE_PATH, + ACPI_EXTENDED_DP, + DevPathToTextExtAcpi, + MESSAGING_DEVICE_PATH, + MSG_ATAPI_DP, + DevPathToTextAtapi, + MESSAGING_DEVICE_PATH, + MSG_SCSI_DP, + DevPathToTextScsi, + MESSAGING_DEVICE_PATH, + MSG_FIBRECHANNEL_DP, + DevPathToTextFibre, + MESSAGING_DEVICE_PATH, + MSG_1394_DP, + DevPathToText1394, + MESSAGING_DEVICE_PATH, + MSG_USB_DP, + DevPathToTextUsb, + MESSAGING_DEVICE_PATH, + MSG_USB_WWID_DP, + DevPathToTextUsbWWID, + MESSAGING_DEVICE_PATH, + MSG_DEVICE_LOGICAL_UNIT_DP, + DevPathToTextLogicalUnit, + MESSAGING_DEVICE_PATH, + MSG_USB_CLASS_DP, + DevPathToTextUsbClass, + MESSAGING_DEVICE_PATH, + MSG_I2O_DP, + DevPathToTextI2O, + MESSAGING_DEVICE_PATH, + MSG_MAC_ADDR_DP, + DevPathToTextMacAddr, + MESSAGING_DEVICE_PATH, + MSG_IPv4_DP, + DevPathToTextIPv4, + MESSAGING_DEVICE_PATH, + MSG_IPv6_DP, + DevPathToTextIPv6, + MESSAGING_DEVICE_PATH, + MSG_INFINIBAND_DP, + DevPathToTextInfiniBand, + MESSAGING_DEVICE_PATH, + MSG_UART_DP, + DevPathToTextUart, + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + DevPathToTextVendor, + MESSAGING_DEVICE_PATH, + MSG_ISCSI_DP, + DevPathToTextiSCSI, + MEDIA_DEVICE_PATH, + MEDIA_HARDDRIVE_DP, + DevPathToTextHardDrive, + MEDIA_DEVICE_PATH, + MEDIA_CDROM_DP, + DevPathToTextCDROM, + MEDIA_DEVICE_PATH, + MEDIA_VENDOR_DP, + DevPathToTextVendor, + MEDIA_DEVICE_PATH, + MEDIA_FILEPATH_DP, + DevPathToTextFilePath, + MEDIA_DEVICE_PATH, + MEDIA_PROTOCOL_DP, + DevPathToTextMediaProtocol, + MEDIA_DEVICE_PATH, + MEDIA_FILEPATH_DP, + DevPathToTextFilePath, + BBS_DEVICE_PATH, + BBS_BBS_DP, + DevPathToTextBBS, + END_DEVICE_PATH_TYPE, + END_INSTANCE_DEVICE_PATH_SUBTYPE, + DevPathToTextEndInstance, + 0, + 0, + NULL +}; + +CHAR16 * +ConvertDeviceNodeToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +/*++ + + Routine Description: + Convert a device node to its text representation. + + Arguments: + DeviceNode - Points to the device node to be converted. + DisplayOnly - If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + AllowShortcuts - If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + Returns: + A pointer - a pointer to the allocated text representation of the device node. + NULL - if DeviceNode is NULL or there was insufficient memory. + +--*/ +{ + POOL_PRINT Str; + UINTN Index; + UINTN NewSize; + VOID (*DumpNode)(POOL_PRINT *, VOID *, BOOLEAN, BOOLEAN); + + if (DeviceNode == NULL) { + return NULL; + } + + ZeroMem (&Str, sizeof (Str)); + + // + // Process the device path node + // + DumpNode = NULL; + for (Index = 0; DevPathToTextTable[Index].Function != NULL; Index++) { + if (DevicePathType (DeviceNode) == DevPathToTextTable[Index].Type && + DevicePathSubType (DeviceNode) == DevPathToTextTable[Index].SubType + ) { + DumpNode = DevPathToTextTable[Index].Function; + break; + } + } + // + // If not found, use a generic function + // + if (DumpNode == NULL) { + DumpNode = DevPathToTextNodeUnknown; + } + + // + // Print this node + // + DumpNode (&Str, (VOID *) DeviceNode, DisplayOnly, AllowShortcuts); + + // + // Shrink pool used for string allocation + // + NewSize = (Str.Len + 1) * sizeof (CHAR16); + Str.Str = ReallocatePool (Str.Str, NewSize, NewSize); + ASSERT (Str.Str != NULL); + Str.Str[Str.Len] = 0; + return Str.Str; +} + +CHAR16 * +ConvertDevicePathToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +/*++ + + Routine Description: + Convert a device path to its text representation. + + Arguments: + DeviceNode - Points to the device path to be converted. + DisplayOnly - If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + AllowShortcuts - If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + Returns: + A pointer - a pointer to the allocated text representation of the device path. + NULL - if DeviceNode is NULL or there was insufficient memory. + +--*/ +{ + POOL_PRINT Str; + EFI_DEVICE_PATH_PROTOCOL *DevPathNode; + EFI_DEVICE_PATH_PROTOCOL *UnpackDevPath; + UINTN Index; + UINTN NewSize; + VOID (*DumpNode) (POOL_PRINT *, VOID *, BOOLEAN, BOOLEAN); + + if (DevicePath == NULL) { + return NULL; + } + + ZeroMem (&Str, sizeof (Str)); + + // + // Unpacked the device path + // + UnpackDevPath = UnpackDevicePath ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath); + ASSERT (UnpackDevPath != NULL); + + // + // Process each device path node + // + DevPathNode = UnpackDevPath; + while (!IsDevicePathEnd (DevPathNode)) { + // + // Find the handler to dump this device path node + // + DumpNode = NULL; + for (Index = 0; DevPathToTextTable[Index].Function; Index += 1) { + + if (DevicePathType (DevPathNode) == DevPathToTextTable[Index].Type && + DevicePathSubType (DevPathNode) == DevPathToTextTable[Index].SubType + ) { + DumpNode = DevPathToTextTable[Index].Function; + break; + } + } + // + // If not found, use a generic function + // + if (!DumpNode) { + DumpNode = DevPathToTextNodeUnknown; + } + // + // Put a path seperator in if needed + // + if (Str.Len && DumpNode != DevPathToTextEndInstance) { + if (*(Str.Str + Str.Len / sizeof (CHAR16) - 1) != L',') { + CatPrint (&Str, L"/"); + } + } + // + // Print this node of the device path + // + DumpNode (&Str, DevPathNode, DisplayOnly, AllowShortcuts); + + // + // Next device path node + // + DevPathNode = NextDevicePathNode (DevPathNode); + } + // + // Shrink pool used for string allocation + // + gBS->FreePool (UnpackDevPath); + + NewSize = (Str.Len + 1) * sizeof (CHAR16); + Str.Str = ReallocatePool (Str.Str, NewSize, NewSize); + ASSERT (Str.Str != NULL); + Str.Str[Str.Len] = 0; + return Str.Str; +} diff --git a/EdkModulePkg/Universal/DevicePath/Dxe/DevicePathUtilities.c b/EdkModulePkg/Universal/DevicePath/Dxe/DevicePathUtilities.c new file mode 100644 index 0000000000..2b54c76832 --- /dev/null +++ b/EdkModulePkg/Universal/DevicePath/Dxe/DevicePathUtilities.c @@ -0,0 +1,421 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DevicePathUtilities.c + +Abstract: + + Implementation file for Device Path Utilities Protocol + +--*/ + +#include +#include +#include "DevicePath.h" + +UINTN +GetDevicePathSize ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + + Routine Description: + Returns the size of the device path, in bytes. + + Arguments: + DevicePath - Points to the start of the EFI device path. + + Returns: + Size - Size of the specified device path, in bytes, including the end-of-path tag. + +--*/ +{ + CONST EFI_DEVICE_PATH_PROTOCOL *Start; + + if (DevicePath == NULL) { + return 0; + } + + // + // Search for the end of the device path structure + // + Start = (EFI_DEVICE_PATH_PROTOCOL *) DevicePath; + while (!IsDevicePathEnd (DevicePath)) { + DevicePath = NextDevicePathNode (DevicePath); + } + + // + // Compute the size and add back in the size of the end device path structure + // + return ((UINTN) DevicePath - (UINTN) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL); +} + +EFI_DEVICE_PATH_PROTOCOL * +DuplicateDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + + Routine Description: + Create a duplicate of the specified path. + + Arguments: + DevicePath - Points to the source EFI device path. + + Returns: + Pointer - A pointer to the duplicate device path. + NULL - Insufficient memory. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + UINTN Size; + + if (DevicePath == NULL) { + return NULL; + } + + // + // Compute the size + // + Size = GetDevicePathSize (DevicePath); + if (Size == 0) { + return NULL; + } + + // + // Allocate space for duplicate device path + // + NewDevicePath = AllocateCopyPool (Size, (VOID *) DevicePath); + + return NewDevicePath; +} + +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *Src1, + IN CONST EFI_DEVICE_PATH_PROTOCOL *Src2 + ) +/*++ + + Routine Description: + Create a new path by appending the second device path to the first. + + Arguments: + Src1 - Points to the first device path. If NULL, then it is ignored. + Src2 - Points to the second device path. If NULL, then it is ignored. + + Returns: + Pointer - A pointer to the newly created device path. + NULL - Memory could not be allocated + or either DevicePath or DeviceNode is NULL. + +--*/ +{ + UINTN Size; + UINTN Size1; + UINTN Size2; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath; + + // + // If there's only 1 path, just duplicate it + // + if (Src1 == NULL) { + ASSERT (!IsDevicePathUnpacked (Src2)); + return DuplicateDevicePath (Src2); + } + + if (Src2 == NULL) { + ASSERT (!IsDevicePathUnpacked (Src1)); + return DuplicateDevicePath (Src1); + } + + // + // Allocate space for the combined device path. It only has one end node of + // length EFI_DEVICE_PATH_PROTOCOL + // + Size1 = GetDevicePathSize (Src1); + Size2 = GetDevicePathSize (Src2); + Size = Size1 + Size2 - sizeof (EFI_DEVICE_PATH_PROTOCOL); + + NewDevicePath = AllocateCopyPool (Size, (VOID *) Src1); + + if (NewDevicePath != NULL) { + // + // Over write Src1 EndNode and do the copy + // + SecondDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath + (Size1 - sizeof (EFI_DEVICE_PATH_PROTOCOL))); + CopyMem (SecondDevicePath, (VOID *) Src2, Size2); + } + + return NewDevicePath; +} + +EFI_DEVICE_PATH_PROTOCOL * +AppendDeviceNode ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode + ) +/*++ + + Routine Description: + Creates a new path by appending the device node to the device path. + + Arguments: + DevicePath - Points to the device path. + DeviceNode - Points to the device node. + + Returns: + Pointer - A pointer to the allocated device node. + NULL - Memory could not be allocated + or either DevicePath or DeviceNode is NULL. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *Temp; + EFI_DEVICE_PATH_PROTOCOL *NextNode; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + UINTN NodeLength; + + if ((DevicePath == NULL) || (DeviceNode == NULL)) { + return NULL; + } + + // + // Build a Node that has a terminator on it + // + NodeLength = DevicePathNodeLength (DeviceNode); + + Temp = AllocateCopyPool (NodeLength + sizeof (EFI_DEVICE_PATH_PROTOCOL), (VOID *) DeviceNode); + if (Temp == NULL) { + return NULL; + } + + // + // Add and end device path node to convert Node to device path + // + NextNode = NextDevicePathNode (Temp); + SetDevicePathEndNode (NextNode); + + // + // Append device paths + // + NewDevicePath = AppendDevicePath (DevicePath, Temp); + gBS->FreePool (Temp); + return NewDevicePath; +} + +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePathInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance + ) +/*++ + + Routine Description: + Creates a new path by appending the specified device path instance to the specified device path. + + Arguments: + DevicePath - Points to the device path. If NULL, then ignored. + DevicePathInstance - Points to the device path instance. + + Returns: + Pointer - A pointer to the newly created device path + NULL - Memory could not be allocated or DevicePathInstance is NULL. + +--*/ +{ + UINT8 *Ptr; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + UINTN SrcSize; + UINTN InstanceSize; + + if (DevicePathInstance == NULL) { + return NULL; + } + + if (DevicePath == NULL) { + return DuplicateDevicePath (DevicePathInstance); + } + + SrcSize = GetDevicePathSize (DevicePath); + InstanceSize = GetDevicePathSize (DevicePathInstance); + + Ptr = AllocateCopyPool (SrcSize + InstanceSize, (VOID *) DevicePath); + if (Ptr != NULL) { + + DevPath = (EFI_DEVICE_PATH_PROTOCOL *) (Ptr + (SrcSize - sizeof (EFI_DEVICE_PATH_PROTOCOL))); + // + // Convert the End to an End Instance, since we are + // appending another instacne after this one its a good + // idea. + // + DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; + + DevPath = NextDevicePathNode (DevPath); + CopyMem (DevPath, (VOID *) DevicePathInstance, InstanceSize); + } + + return (EFI_DEVICE_PATH_PROTOCOL *) Ptr; +} + +EFI_DEVICE_PATH_PROTOCOL * +GetNextDevicePathInstance ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathInstance, + OUT UINTN *DevicePathInstanceSize + ) +/*++ + + Routine Description: + Creates a copy of the current device path instance and returns a pointer to the next device path instance. + + Arguments: + DevicePathInstance - On input, this holds the pointer to the current device path + instance. On output, this holds the pointer to the next + device path instance or NULL if there are no more device + path instances in the device path. + DevicePathInstanceSize - On output, this holds the size of the device path instance, + in bytes or zero, if DevicePathInstance is zero. + + Returns: + Pointer - A pointer to the copy of the current device path instance. + NULL - DevicePathInstace was NULL on entry or there was insufficient memory. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_DEVICE_PATH_PROTOCOL *ReturnValue; + UINT8 Temp; + + if (*DevicePathInstance == NULL) { + if (DevicePathInstanceSize != NULL) { + *DevicePathInstanceSize = 0; + } + + return NULL; + } + + // + // Find the end of the device path instance + // + DevPath = *DevicePathInstance; + while (!IsDevicePathEndType (DevPath)) { + DevPath = NextDevicePathNode (DevPath); + } + + // + // Compute the size of the device path instance + // + if (DevicePathInstanceSize != NULL) { + *DevicePathInstanceSize = ((UINTN) DevPath - (UINTN) (*DevicePathInstance)) + sizeof (EFI_DEVICE_PATH_PROTOCOL); + } + + // + // Make a copy and return the device path instance + // + Temp = DevPath->SubType; + DevPath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; + ReturnValue = DuplicateDevicePath (*DevicePathInstance); + DevPath->SubType = Temp; + + // + // If DevPath is the end of an entire device path, then another instance + // does not follow, so *DevicePath is set to NULL. + // + if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) { + *DevicePathInstance = NULL; + } else { + *DevicePathInstance = NextDevicePathNode (DevPath); + } + + return ReturnValue; +} + +BOOLEAN +IsDevicePathMultiInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + + Routine Description: + Returns whether a device path is multi-instance. + + Arguments: + DevicePath - Points to the device path. If NULL, then ignored. + + Returns: + TRUE - The device path has more than one instance + FALSE - The device path is empty or contains only a single instance. + +--*/ +{ + CONST EFI_DEVICE_PATH_PROTOCOL *Node; + + if (DevicePath == NULL) { + return FALSE; + } + + Node = DevicePath; + while (!IsDevicePathEnd (Node)) { + if (EfiIsDevicePathEndInstance (Node)) { + return TRUE; + } + + Node = NextDevicePathNode (Node); + } + + return FALSE; +} + +EFI_DEVICE_PATH_PROTOCOL * +CreateDeviceNode ( + IN UINT8 NodeType, + IN UINT8 NodeSubType, + IN UINT16 NodeLength + ) +/*++ + + Routine Description: + Creates a device node + + Arguments: + NodeType - NodeType is the device node type (EFI_DEVICE_PATH.Type) for + the new device node. + NodeSubType - NodeSubType is the device node sub-type + EFI_DEVICE_PATH.SubType) for the new device node. + NodeLength - NodeLength is the length of the device node + (EFI_DEVICE_PATH.Length) for the new device node. + + Returns: + Pointer - A pointer to the newly created device node. + NULL - NodeLength is less than + the size of the header or there was insufficient memory. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + + if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { + return NULL; + } + + Node = (EFI_DEVICE_PATH_PROTOCOL *) AllocateZeroPool ((UINTN) NodeLength); + if (Node != NULL) { + Node->Type = NodeType; + Node->SubType = NodeSubType; + SetDevicePathNodeLength (Node, NodeLength); + } + + return Node; +} diff --git a/EdkNt32Pkg/Nt32.fpd b/EdkNt32Pkg/Nt32.fpd index 50b6c855b6..62a0f6116b 100644 --- a/EdkNt32Pkg/Nt32.fpd +++ b/EdkNt32Pkg/Nt32.fpd @@ -3473,6 +3473,73 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. BS_DRIVER + + + + + + + + + + + + + + + PcdMaximumUnicodeStringLength + 0x00000001 + gEfiMdePkgTokenSpaceGuid + UINT32 + 4 + 1000000 + + + PcdMaximumAsciiStringLength + 0x00000002 + gEfiMdePkgTokenSpaceGuid + UINT32 + 4 + 1000000 + + + PcdDebugPropertyMask + 0x00000005 + gEfiMdePkgTokenSpaceGuid + UINT8 + 1 + 0x0f + + + PcdDebugPrintErrorLevel + 0x00000006 + gEfiMdePkgTokenSpaceGuid + UINT32 + 4 + 0x80000000 + + + PcdReportStatusCodePropertyMask + 0x00000007 + gEfiMdePkgTokenSpaceGuid + UINT8 + 1 + 0x07 + + + PcdDebugClearMemoryValue + 0x00000008 + gEfiMdePkgTokenSpaceGuid + UINT8 + 1 + 0xAF + + + + FV_RECOVERY + BS_DRIVER + + @@ -4579,6 +4646,98 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. BS_DRIVER + + + + + + + + + + + + + + + + PcdMaximumUnicodeStringLength + 0x00000001 + gEfiMdePkgTokenSpaceGuid + UINT32 + 4 + 1000000 + + + PcdMaximumAsciiStringLength + 0x00000002 + gEfiMdePkgTokenSpaceGuid + UINT32 + 4 + 1000000 + + + PcdSpinLockTimeout + 0x00000004 + gEfiMdePkgTokenSpaceGuid + UINT32 + 4 + 10000000 + + + PcdMaximumLinkedListLength + 0x00000003 + gEfiMdePkgTokenSpaceGuid + UINT32 + 4 + 1000000 + + + PcdReportStatusCodePropertyMask + 0x00000007 + gEfiMdePkgTokenSpaceGuid + UINT8 + 1 + 0x07 + + + PcdDebugPropertyMask + 0x00000005 + gEfiMdePkgTokenSpaceGuid + UINT8 + 1 + 0x0f + + + PcdDebugPrintErrorLevel + 0x00000006 + gEfiMdePkgTokenSpaceGuid + UINT32 + 4 + 0x80000000 + + + PcdDebugClearMemoryValue + 0x00000008 + gEfiMdePkgTokenSpaceGuid + UINT8 + 1 + 0xAF + + + PcdPerformanceLibraryPropertyMask + 0x00000009 + gEfiMdePkgTokenSpaceGuid + UINT8 + 1 + 0 + + + + FV_MAIN + BS_DRIVER + + diff --git a/MdePkg/Include/Guid/PcAnsi.h b/MdePkg/Include/Guid/PcAnsi.h index c9b74ab03e..afbfc73bab 100644 --- a/MdePkg/Include/Guid/PcAnsi.h +++ b/MdePkg/Include/Guid/PcAnsi.h @@ -40,6 +40,16 @@ 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88 } \ } +#define EFI_UART_DEVICE_PATH_GUID \ + { \ + 0x37499a9d, 0x542f, 0x4c89, {0xa0, 0x26, 0x35, 0xda, 0x14, 0x20, 0x94, 0xe4 } \ + } + +#define EFI_SAS_DEVICE_PATH_GUID \ + { \ + 0xb4dd87d4, 0x8b00, 0xd911, {0xaf, 0xdc, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d } \ + } + extern EFI_GUID gEfiPcAnsiGuid; extern EFI_GUID gEfiVT100Guid; extern EFI_GUID gEfiVT100PlusGuid; diff --git a/MdePkg/Include/IndustryStandard/Usb.h b/MdePkg/Include/IndustryStandard/Usb.h index dca7351ff1..d3328a5461 100644 --- a/MdePkg/Include/IndustryStandard/Usb.h +++ b/MdePkg/Include/IndustryStandard/Usb.h @@ -255,6 +255,8 @@ typedef struct { #define USB_PORT_STAT_RESET 0x0010 #define USB_PORT_STAT_POWER 0x0100 #define USB_PORT_STAT_LOW_SPEED 0x0200 +#define USB_PORT_STAT_HIGH_SPEED 0x0400 +#define USB_PORT_STAT_OWNER 0x0800 #define USB_PORT_STAT_C_CONNECTION 0x0001 #define USB_PORT_STAT_C_ENABLE 0x0002 @@ -270,6 +272,7 @@ typedef enum { EfiUsbPortSuspend = 2, EfiUsbPortReset = 4, EfiUsbPortPower = 8, + EfiUsbPortOwner = 13, EfiUsbPortConnectChange = 16, EfiUsbPortEnableChange = 17, EfiUsbPortSuspendChange = 18, diff --git a/MdePkg/Include/Protocol/DevicePathFromText.h b/MdePkg/Include/Protocol/DevicePathFromText.h index a3a6c431ca..0d1ce3208a 100644 --- a/MdePkg/Include/Protocol/DevicePathFromText.h +++ b/MdePkg/Include/Protocol/DevicePathFromText.h @@ -64,8 +64,8 @@ EFI_DEVICE_PATH_PROTOCOL* ; typedef struct { - EFI_DEVICE_PATH_FROM_TEXT_NODE ConvertDeviceNodeFromText; - EFI_DEVICE_PATH_FROM_TEXT_PATH ConvertDevicePathFromText; + EFI_DEVICE_PATH_FROM_TEXT_NODE ConvertTextToDeviceNode; + EFI_DEVICE_PATH_FROM_TEXT_PATH ConvertTextToDevicePath; } EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL; extern EFI_GUID gEfiDevicePathFromTextProtocolGuid; diff --git a/MdePkg/Include/Protocol/Usb2HostController.h b/MdePkg/Include/Protocol/Usb2HostController.h index 5326d5b623..2a9d02da07 100644 --- a/MdePkg/Include/Protocol/Usb2HostController.h +++ b/MdePkg/Include/Protocol/Usb2HostController.h @@ -269,6 +269,7 @@ EFI_STATUS IN OUT UINT8 *DataToggle, IN UINTN PollingInterval OPTIONAL, IN UINTN DataLength OPTIONAL, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator OPTIONAL, IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL, IN VOID *Context OPTIONAL ) @@ -305,16 +306,17 @@ EFI_STATUS typedef EFI_STATUS (EFIAPI *EFI_USB2_HC_PROTOCOL_SYNC_INTERRUPT_TRANSFER) ( - IN EFI_USB2_HC_PROTOCOL *This, - IN UINT8 DeviceAddress, - IN UINT8 EndPointAddress, - IN UINT8 DeviceSpeed, - IN UINTN MaximumPacketLength, - IN OUT VOID *Data, - IN OUT UINTN *DataLength, - IN OUT UINT8 *DataToggle, - IN UINTN TimeOut, - OUT UINT32 *TransferResult + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult ) ; diff --git a/MdePkg/Include/Uefi/UefiSpec.h b/MdePkg/Include/Uefi/UefiSpec.h index 9993cd44e7..3410ad2821 100644 --- a/MdePkg/Include/Uefi/UefiSpec.h +++ b/MdePkg/Include/Uefi/UefiSpec.h @@ -1839,11 +1839,7 @@ typedef struct { #define HW_CONTROLLER_DP 0x05 typedef struct { EFI_DEVICE_PATH_PROTOCOL Header; -#if EDK_RELEASE_VERSION >= 0x00020000 UINT32 ControllerNumber; -#else - UINT32 Controller; -#endif } CONTROLLER_DEVICE_PATH; // @@ -1945,6 +1941,7 @@ typedef struct { UINT8 DeviceProtocol; } USB_CLASS_DEVICE_PATH; +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) #define MSG_USB_WWID_DP 0x10 typedef struct { EFI_DEVICE_PATH_PROTOCOL Header; @@ -1957,8 +1954,9 @@ typedef struct { #define MSG_DEVICE_LOGICAL_UNIT_DP 0x11 typedef struct { EFI_DEVICE_PATH_PROTOCOL Header; - UINT8 LUN; + UINT8 Lun; } DEVICE_LOGICAL_UNIT_DEVICE_PATH; +#endif #define MSG_I2O_DP 0x06 typedef struct { @@ -2030,8 +2028,27 @@ typedef struct { #define DEVICE_PATH_MESSAGING_VT_100 EFI_VT_100_GUID #define DEVICE_PATH_MESSAGING_VT_100_PLUS EFI_VT_100_PLUS_GUID #define DEVICE_PATH_MESSAGING_VT_UTF8 EFI_VT_UTF8_GUID -#define DEVICE_PATH_MESSAGING_SAS EFI_SAS_DEVICE_PATH_GUID +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + +#define DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL EFI_UART_DEVICE_PATH_GUID +#define DEVICE_PATH_MESSAGING_SAS EFI_SAS_DEVICE_PATH_GUID + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT32 FlowControlMap; +} UART_FLOW_CONTROL_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT32 Reserved; + UINT64 SasAddress; + UINT64 Lun; + UINT16 DeviceTopology; + UINT16 RelativeTargetPort; +} SAS_DEVICE_PATH; #define MSG_ISCSI_DP 0x13 typedef struct { @@ -2053,6 +2070,7 @@ typedef struct { #define ISCSI_LOGIN_OPTION_CHAP_BI 0x0000 #define ISCSI_LOGIN_OPTION_CHAP_UNI 0x2000 +#endif // // Media Device Path