+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2006, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
- Uhci.c\r
-\r
-Abstract:\r
-\r
-\r
-Revision History\r
---*/\r
-\r
-#include "uhci.h"\r
-\r
-//\r
-// UHCI Driver Global Variables\r
-//\r
-EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding = {\r
- UHCIDriverBindingSupported,\r
- UHCIDriverBindingStart,\r
- UHCIDriverBindingStop,\r
- 0xa,\r
- NULL,\r
- NULL\r
-};\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCIDriverBindingSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
- that has UsbHcProtocol installed will be supported.\r
-\r
- Arguments:\r
- This - Protocol instance pointer.\r
- Controller - Handle of device to test\r
- RemainingDevicePath - Not used\r
-\r
- Returns:\r
- EFI_SUCCESS - This driver supports this device.\r
- EFI_UNSUPPORTED - This driver does not support this device.\r
-\r
---*/\r
-{\r
- EFI_STATUS OpenStatus;\r
- EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- USB_CLASSC UsbClassCReg;\r
-\r
- //\r
- // Test whether there is PCI IO Protocol attached on the controller handle.\r
- //\r
- OpenStatus = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &PciIo,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (OpenStatus)) {\r
- return OpenStatus;\r
- }\r
-\r
- Status = PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- CLASSC,\r
- sizeof (USB_CLASSC) / sizeof (UINT8),\r
- &UsbClassCReg\r
- );\r
- if (EFI_ERROR (Status)) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return EFI_UNSUPPORTED;\r
- }\r
- //\r
- // Test whether the controller belongs to UHCI type\r
- //\r
- if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
- (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
- (UsbClassCReg.PI != PCI_CLASSC_PI_UHCI)) {\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return EFI_UNSUPPORTED;\r
- }\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return EFI_SUCCESS;\r
-\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCIDriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Starting the Usb UHCI Driver\r
-\r
- Arguments:\r
- This - Protocol instance pointer.\r
- Controller - Handle of device to test\r
- RemainingDevicePath - Not used\r
-\r
- Returns:\r
- EFI_SUCCESS - This driver supports this device.\r
- EFI_UNSUPPORTED - This driver does not support this device.\r
- EFI_DEVICE_ERROR - This driver cannot be started due to device\r
- Error\r
- EFI_OUT_OF_RESOURCES\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- UINTN FlBaseAddrReg;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- USB_HC_DEV *HcDev;\r
- UINT64 Supports;\r
-\r
- HcDev = NULL;\r
-\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &PciIo,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Turn off USB emulation\r
- //\r
- TurnOffUSBEmulation (PciIo);\r
-\r
- //\r
- // Enable the USB Host Controller\r
- //\r
- Status = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationSupported,\r
- 0,\r
- &Supports\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Supports &= EFI_PCI_DEVICE_ENABLE;\r
- Status = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationEnable,\r
- Supports,\r
- NULL\r
- );\r
- }\r
- if (EFI_ERROR (Status)) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // allocate memory for UHC private data structure\r
- //\r
- HcDev = AllocateZeroPool (sizeof (USB_HC_DEV));\r
- if (HcDev == NULL) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // init EFI_USB_HC_PROTOCOL protocol interface and install the protocol\r
- //\r
- HcDev->UsbHc.Reset = UHCIReset;\r
- HcDev->UsbHc.GetState = UHCIGetState;\r
- HcDev->UsbHc.SetState = UHCISetState;\r
- HcDev->UsbHc.ControlTransfer = UHCIControlTransfer;\r
- HcDev->UsbHc.BulkTransfer = UHCIBulkTransfer;\r
- HcDev->UsbHc.AsyncInterruptTransfer = UHCIAsyncInterruptTransfer;\r
- HcDev->UsbHc.SyncInterruptTransfer = UHCISyncInterruptTransfer;\r
- HcDev->UsbHc.IsochronousTransfer = UHCIIsochronousTransfer;\r
- HcDev->UsbHc.AsyncIsochronousTransfer = UHCIAsyncIsochronousTransfer;\r
- HcDev->UsbHc.GetRootHubPortNumber = UHCIGetRootHubPortNumber;\r
- HcDev->UsbHc.GetRootHubPortStatus = UHCIGetRootHubPortStatus;\r
- HcDev->UsbHc.SetRootHubPortFeature = UHCISetRootHubPortFeature;\r
- HcDev->UsbHc.ClearRootHubPortFeature = UHCIClearRootHubPortFeature;\r
-\r
- HcDev->UsbHc.MajorRevision = 0x1;\r
- HcDev->UsbHc.MinorRevision = 0x1;\r
-\r
- //\r
- //\r
- // init EFI_USB2_HC_PROTOCOL protocol interface and install the protocol\r
- //\r
- HcDev->Usb2Hc.GetCapability = UHCI2GetCapability;\r
- HcDev->Usb2Hc.Reset = UHCI2Reset;\r
- HcDev->Usb2Hc.GetState = UHCI2GetState;\r
- HcDev->Usb2Hc.SetState = UHCI2SetState;\r
- HcDev->Usb2Hc.ControlTransfer = UHCI2ControlTransfer;\r
- HcDev->Usb2Hc.BulkTransfer = UHCI2BulkTransfer;\r
- HcDev->Usb2Hc.AsyncInterruptTransfer = UHCI2AsyncInterruptTransfer;\r
- HcDev->Usb2Hc.SyncInterruptTransfer = UHCI2SyncInterruptTransfer;\r
- HcDev->Usb2Hc.IsochronousTransfer = UHCI2IsochronousTransfer;\r
- HcDev->Usb2Hc.AsyncIsochronousTransfer = UHCI2AsyncIsochronousTransfer;\r
- HcDev->Usb2Hc.GetRootHubPortStatus = UHCI2GetRootHubPortStatus;\r
- HcDev->Usb2Hc.SetRootHubPortFeature = UHCI2SetRootHubPortFeature;\r
- HcDev->Usb2Hc.ClearRootHubPortFeature = UHCI2ClearRootHubPortFeature;\r
-\r
- HcDev->Usb2Hc.MajorRevision = 0x1;\r
- HcDev->Usb2Hc.MinorRevision = 0x1;\r
-\r
- //\r
- // Init UHCI private data structures\r
- //\r
- HcDev->Signature = USB_HC_DEV_SIGNATURE;\r
- HcDev->PciIo = PciIo;\r
-\r
- FlBaseAddrReg = USBFLBASEADD;\r
-\r
- //\r
- // Allocate and Init Host Controller's Frame List Entry\r
- //\r
- Status = CreateFrameList (HcDev, (UINT32) FlBaseAddrReg);\r
- if (EFI_ERROR (Status)) {\r
-\r
- if (HcDev != NULL) {\r
- gBS->FreePool (HcDev);\r
- }\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // Init interrupt list head in the HcDev structure.\r
- //\r
- InitializeListHead (&(HcDev->InterruptListHead));\r
-\r
- //\r
- // Create timer for interrupt transfer result polling\r
- //\r
- Status = gBS->CreateEvent (\r
- EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- MonitorInterruptTrans,\r
- HcDev,\r
- &HcDev->InterruptTransTimer\r
- );\r
- if (EFI_ERROR (Status)) {\r
-\r
- FreeFrameListEntry (HcDev);\r
-\r
- if (HcDev != NULL) {\r
- gBS->FreePool (HcDev);\r
- }\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // Here set interrupt transfer polling timer in 50ms unit.\r
- //\r
- Status = gBS->SetTimer (\r
- HcDev->InterruptTransTimer,\r
- TimerPeriodic,\r
- INTERRUPT_POLLING_TIME\r
- );\r
- if (EFI_ERROR (Status)) {\r
- gBS->CloseEvent (HcDev->InterruptTransTimer);\r
-\r
- FreeFrameListEntry (HcDev);\r
-\r
- if (HcDev != NULL) {\r
- gBS->FreePool (HcDev);\r
- }\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // QH,TD structures must in common buffer that will be\r
- // accessed by both cpu and usb bus master at the same time.\r
- // so, there must has memory management for QH,TD structures.\r
- //\r
- Status = InitializeMemoryManagement (HcDev);\r
- if (EFI_ERROR (Status)) {\r
-\r
- gBS->CloseEvent (HcDev->InterruptTransTimer);\r
-\r
- FreeFrameListEntry (HcDev);\r
-\r
- if (HcDev != NULL) {\r
- gBS->FreePool (HcDev);\r
- }\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return Status;\r
- }\r
-\r
- //\r
- // Install Host Controller Protocol\r
- //\r
- Status = gBS->InstallProtocolInterface (\r
- &Controller,\r
- &gEfiUsbHcProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &HcDev->UsbHc\r
- );\r
- if (EFI_ERROR (Status)) {\r
- gBS->CloseEvent (HcDev->InterruptTransTimer);\r
- FreeFrameListEntry (HcDev);\r
- DelMemoryManagement (HcDev);\r
-\r
- if (HcDev != NULL) {\r
- gBS->FreePool (HcDev);\r
- }\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return Status;\r
- }\r
-\r
- //\r
- // Install USB2.0 Host Controller Protocol\r
- //\r
- Status = gBS->InstallProtocolInterface (\r
- &Controller,\r
- &gEfiUsb2HcProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &HcDev->Usb2Hc\r
- );\r
- if (EFI_ERROR (Status)) {\r
- gBS->CloseEvent (HcDev->InterruptTransTimer);\r
- FreeFrameListEntry (HcDev);\r
- DelMemoryManagement (HcDev);\r
-\r
- if (HcDev != NULL) {\r
- gBS->FreePool (HcDev);\r
- }\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return Status;\r
- }\r
-\r
- //\r
- // component name protocol.\r
- //\r
-\r
- HcDev->ControllerNameTable = NULL;\r
- AddUnicodeString (\r
- "eng",\r
- gUhciComponentName.SupportedLanguages,\r
- &HcDev->ControllerNameTable,\r
- (CHAR16 *) L"Usb Universal Host Controller"\r
- );\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-UnInstallUHCInterface (\r
- IN EFI_HANDLE Controller,\r
- IN EFI_USB_HC_PROTOCOL *This\r
- )\r
-/*++\r
- Routine Description:\r
- UnInstall UHCInterface\r
- Arguments:\r
- Controller - Controller handle\r
- This - Protocol instance pointer.\r
- Returns:\r
- EFI_SUCCESS\r
- others\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
- EFI_STATUS Status;\r
- UINT64 Supports;\r
-\r
- HcDev = USB_HC_DEV_FROM_THIS (This);\r
-\r
- gBS->UninstallProtocolInterface (\r
- Controller,\r
- &gEfiUsbHcProtocolGuid,\r
- &HcDev->UsbHc\r
- );\r
-\r
- gBS->UninstallProtocolInterface (\r
- Controller,\r
- &gEfiUsb2HcProtocolGuid,\r
- &HcDev->Usb2Hc\r
- );\r
- //\r
- // first stop USB Host Controller\r
- //\r
- This->SetState (This, EfiUsbHcStateHalt);\r
-\r
- //\r
- // Delete interrupt transfer polling timer\r
- //\r
- gBS->CloseEvent (HcDev->InterruptTransTimer);\r
-\r
- //\r
- // Delete all the asynchronous interrupt transfers in the interrupt list\r
- // and free associated memory\r
- //\r
- ReleaseInterruptList (HcDev, &(HcDev->InterruptListHead));\r
-\r
- //\r
- // free Frame List Entry.\r
- //\r
- FreeFrameListEntry (HcDev);\r
-\r
- //\r
- // Free common buffer allocated for QH,TD structures\r
- //\r
- DelMemoryManagement (HcDev);\r
-\r
- if (HcDev->ControllerNameTable) {\r
- FreeUnicodeStringTable (HcDev->ControllerNameTable);\r
- }\r
- //\r
- // Disable the USB Host Controller\r
- //\r
- Status = HcDev->PciIo->Attributes (\r
- HcDev->PciIo,\r
- EfiPciIoAttributeOperationSupported,\r
- 0,\r
- &Supports\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Supports &= EFI_PCI_DEVICE_ENABLE;\r
- Status = HcDev->PciIo->Attributes (\r
- HcDev->PciIo,\r
- EfiPciIoAttributeOperationDisable,\r
- Supports,\r
- NULL\r
- );\r
- }\r
-\r
- gBS->FreePool (HcDev);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCIDriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Stop this driver on ControllerHandle. Support stoping any child handles\r
- created by this driver.\r
-\r
- Arguments:\r
- This - Protocol instance pointer.\r
- Controller - Handle of device to stop driver on\r
- NumberOfChildren - Number of Children in the ChildHandleBuffer\r
- ChildHandleBuffer - List of handles for the children we need to stop.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- others\r
-\r
---*/\r
-{\r
- EFI_USB_HC_PROTOCOL *UsbHc;\r
- EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
- EFI_STATUS OpenStatus;\r
-\r
- OpenStatus = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiUsbHcProtocolGuid,\r
- (VOID **)&UsbHc,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
-\r
- //\r
- // Test whether the Controller handler passed in is a valid\r
- // Usb controller handle that should be supported, if not,\r
- // return the error status directly\r
- //\r
- if (EFI_ERROR (OpenStatus)) {\r
- return OpenStatus;\r
- }\r
-\r
- OpenStatus = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiUsb2HcProtocolGuid,\r
- (VOID **) &Usb2Hc,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
-\r
- //\r
- // Test whether the Controller handler passed in is a valid\r
- // Usb controller handle that should be supported, if not,\r
- // return the error status directly\r
- //\r
- if (EFI_ERROR (OpenStatus)) {\r
- return OpenStatus;\r
- }\r
- //\r
- // free all the controller related memory and uninstall UHCI Protocol.\r
- //\r
- UnInstallUHCInterface (Controller, UsbHc);\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return EFI_SUCCESS;\r
-\r
-}\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCIReset (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT16 Attributes\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Provides software reset for the USB host controller.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
-\r
- Attributes A bit mask of the reset operation to perform.\r
- See below for a list of the supported bit mask values.\r
-\r
- #define EFI_USB_HC_RESET_GLOBAL 0x0001\r
- #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002\r
-\r
- EFI_USB_HC_RESET_GLOBAL\r
- If this bit is set, a global reset signal will be sent to the USB bus.\r
- This resets all of the USB bus logic, including the USB host\r
- controller hardware and all the devices attached on the USB bus.\r
- EFI_USB_HC_RESET_HOST_CONTROLLER\r
- If this bit is set, the USB host controller hardware will be reset.\r
- No reset signal will be sent to the USB bus.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The reset operation succeeded.\r
- EFI_INVALID_PARAMETER\r
- Attributes is not valid.\r
- EFI_DEVICE_ERROR\r
- An error was encountered while attempting to perform\r
- the reset operation.\r
---*/\r
-{\r
- BOOLEAN Match;\r
- USB_HC_DEV *HcDev;\r
- UINT32 CommandRegAddr;\r
- UINT32 FlBaseAddrReg;\r
- UINT16 Command;\r
- EFI_STATUS Status;\r
-\r
- Match = FALSE;\r
- HcDev = USB_HC_DEV_FROM_THIS (This);\r
-\r
- CommandRegAddr = (UINT32) (USBCMD);\r
- FlBaseAddrReg = (UINT32) (USBFLBASEADD);\r
-\r
- if ((Attributes & EFI_USB_HC_RESET_GLOBAL) != 0) {\r
- Match = TRUE;\r
- //\r
- // set the Global Reset bit in the command register\r
- //\r
- Status = ReadUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- &Command\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- Command |= USBCMD_GRESET;\r
- Status = WriteUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- Command\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- //\r
- // Wait 50ms for root port to let reset complete\r
- // See UHCI spec page122 Reset signaling\r
- //\r
- gBS->Stall (ROOT_PORT_REST_TIME);\r
-\r
- //\r
- // Clear the Global Reset bit to zero.\r
- //\r
- Command &= ~USBCMD_GRESET;\r
- Status = WriteUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- Command\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // UHCI spec page120 reset recovery time\r
- //\r
- gBS->Stall (PORT_RESET_RECOVERY_TIME);\r
- }\r
-\r
- if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) {\r
- Match = TRUE;\r
- //\r
- // set Host Controller Reset bit to 1\r
- //\r
- Status = ReadUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- &Command\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- Command |= USBCMD_HCRESET;\r
- Status = WriteUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- Command\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // this bit will be reset by Host Controller when reset is completed.\r
- // wait 10ms to let reset complete\r
- //\r
- gBS->Stall (PORT_RESET_RECOVERY_TIME);\r
- }\r
-\r
- if (!Match) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Delete all old transactions on the USB bus\r
- //\r
- CleanUsbTransactions (HcDev);\r
-\r
- //\r
- // Initialize Universal Host Controller's Frame List Data Structure\r
- //\r
- InitFrameList (HcDev);\r
-\r
- //\r
- // Reset may cause Frame List Base Address Register reset to zero,\r
- // so set the original value back again.\r
- //\r
- SetFrameListBaseAddress (\r
- HcDev->PciIo,\r
- FlBaseAddrReg,\r
- (UINT32) ((UINTN) HcDev->FrameListEntry)\r
- );\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCIGetState (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- OUT EFI_USB_HC_STATE *State\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Retrieves current state of the USB host controller.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
-\r
- State A pointer to the EFI_USB_HC_STATE data structure that\r
- indicates current state of the USB host controller.\r
- Type EFI_USB_HC_STATE is defined below.\r
-\r
- typedef enum {\r
- EfiUsbHcStateHalt,\r
- EfiUsbHcStateOperational,\r
- EfiUsbHcStateSuspend,\r
- EfiUsbHcStateMaximum\r
- } EFI_USB_HC_STATE;\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The state information of the host controller was returned in State.\r
- EFI_INVALID_PARAMETER\r
- State is NULL.\r
- EFI_DEVICE_ERROR\r
- An error was encountered while attempting to retrieve the\r
- host controller's current state.\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
- UINT32 CommandRegAddr;\r
- UINT32 StatusRegAddr;\r
- UINT16 UhcCommand;\r
- UINT16 UhcStatus;\r
- EFI_STATUS Status;\r
-\r
- if (State == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- HcDev = USB_HC_DEV_FROM_THIS (This);\r
-\r
- CommandRegAddr = (UINT32) (USBCMD);\r
- StatusRegAddr = (UINT32) (USBSTS);\r
-\r
- Status = ReadUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- &UhcCommand\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- Status = ReadUHCCommandReg (\r
- HcDev->PciIo,\r
- StatusRegAddr,\r
- &UhcStatus\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if (UhcCommand & USBCMD_EGSM) {\r
- *State = EfiUsbHcStateSuspend;\r
- return EFI_SUCCESS;\r
- }\r
-\r
- if ((UhcStatus & USBSTS_HCH) == 0) {\r
- *State = EfiUsbHcStateOperational;\r
- } else {\r
- *State = EfiUsbHcStateHalt;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCISetState (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN EFI_USB_HC_STATE State\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Sets the USB host controller to a specific state.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
-\r
- State Indicates the state of the host controller that will be set.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The USB host controller was successfully placed in the state\r
- specified by State.\r
- EFI_INVALID_PARAMETER\r
- State is invalid.\r
- EFI_DEVICE_ERROR\r
- Failed to set the state specified by State due to device error.\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
- UINT32 CommandRegAddr;\r
- UINT32 StatusRegAddr;\r
- UINT16 Command;\r
- EFI_USB_HC_STATE CurrentState;\r
- EFI_STATUS Status;\r
-\r
- HcDev = USB_HC_DEV_FROM_THIS (This);\r
-\r
- CommandRegAddr = (UINT32) (USBCMD);\r
- StatusRegAddr = (UINT32) (USBSTS);\r
-\r
- Status = UHCIGetState (This, &CurrentState);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- switch (State) {\r
-\r
- case EfiUsbHcStateHalt:\r
- if (CurrentState == EfiUsbHcStateHalt) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- Status = ReadUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- &Command\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- Command &= ~USBCMD_RS;\r
-\r
- Status = WriteUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- Command\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- StatusRegAddr = (UINT32) (USBSTS);\r
- //\r
- // ensure the HC is in halt status after send the stop command\r
- //\r
- if (WaitForUHCHalt (HcDev->PciIo, StatusRegAddr, STALL_1_SECOND) == EFI_TIMEOUT) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- break;\r
-\r
- case EfiUsbHcStateOperational:\r
- if (IsHostSysOrProcessErr (HcDev->PciIo, StatusRegAddr)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- switch (CurrentState) {\r
-\r
- case EfiUsbHcStateOperational:\r
- return EFI_SUCCESS;\r
-\r
- case EfiUsbHcStateHalt:\r
- //\r
- // Set Run/Stop bit to 1.\r
- //\r
- Status = ReadUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- &Command\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- Command |= USBCMD_RS | USBCMD_MAXP;\r
- Status = WriteUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- Command\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- break;\r
-\r
- case EfiUsbHcStateSuspend:\r
- Status = ReadUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- &Command\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- //\r
- // FGR(Force Global Resume) bit is 0\r
- //\r
- if ((Command | (~USBCMD_FGR)) != 0xFF) {\r
- //\r
- // Write FGR bit to 1\r
- //\r
- Command |= USBCMD_FGR;\r
- WriteUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- Command\r
- );\r
- }\r
-\r
- //\r
- // wait 20ms to let resume complete\r
- // (20ms is specified by UHCI spec)\r
- //\r
- gBS->Stall (FORCE_GLOBAL_RESUME_TIME);\r
-\r
- //\r
- // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0\r
- //\r
- Command &= ~USBCMD_FGR;\r
- Command &= ~USBCMD_EGSM;\r
- Command |= USBCMD_RS;\r
- WriteUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- Command\r
- );\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- break;\r
-\r
- case EfiUsbHcStateSuspend:\r
- if (CurrentState == EfiUsbHcStateSuspend) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- Status = UHCISetState (This, EfiUsbHcStateHalt);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Set Enter Global Suspend Mode bit to 1.\r
- //\r
- Status = ReadUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- &Command\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- Command |= USBCMD_EGSM;\r
- Status = WriteUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- Command\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- break;\r
-\r
- default:\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCIGetRootHubPortNumber (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- OUT UINT8 *PortNumber\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Retrieves the number of root hub ports.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
-\r
- PortNumber A pointer to the number of the root hub ports.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The port number was retrieved successfully.\r
- EFI_INVALID_PARAMETER\r
- PortNumber is NULL.\r
- EFI_DEVICE_ERROR\r
- An error was encountered while attempting to\r
- retrieve the port number.\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
- UINT32 PSAddr;\r
- UINT16 RHPortControl;\r
- UINT32 Index;\r
- EFI_STATUS Status;\r
-\r
- HcDev = USB_HC_DEV_FROM_THIS (This);\r
-\r
- if (PortNumber == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- *PortNumber = 0;\r
-\r
- for (Index = 0; Index < 2; Index++) {\r
- PSAddr = (UINT32) (USBPORTSC1 + Index * 2);\r
- Status = ReadRootPortReg (\r
- HcDev->PciIo,\r
- PSAddr,\r
- &RHPortControl\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Port Register content is valid\r
- //\r
- if (RHPortControl != 0xff) {\r
- (*PortNumber)++;\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCIGetRootHubPortStatus (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 PortNumber,\r
- OUT EFI_USB_PORT_STATUS *PortStatus\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Retrieves the current status of a USB root hub port.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB_HC_PROTOCOL.\r
-\r
- PortNumber Specifies the root hub port from which the status\r
- is to be retrieved. This value is zero-based. For example,\r
- if a root hub has two ports, then the first port is numbered 0,\r
- and the second port is numbered 1.\r
-\r
- PortStatus A pointer to the current port status bits and\r
- port status change bits.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The status of the USB root hub port specified by PortNumber\r
- was returned in PortStatus.\r
- EFI_INVALID_PARAMETER\r
- PortNumber is invalid.\r
- EFI_DEVICE_ERROR - Can't read register\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
- UINT32 PSAddr;\r
- UINT16 RHPortStatus;\r
- UINT8 TotalPortNumber;\r
- EFI_STATUS Status;\r
-\r
- if (PortStatus == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- UHCIGetRootHubPortNumber (This, &TotalPortNumber);\r
- if (PortNumber >= TotalPortNumber) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- HcDev = USB_HC_DEV_FROM_THIS (This);\r
- PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);\r
-\r
- //\r
- // Clear port status\r
- //\r
- PortStatus->PortStatus = 0;\r
- PortStatus->PortChangeStatus = 0;\r
-\r
- Status = ReadRootPortReg (\r
- HcDev->PciIo,\r
- PSAddr,\r
- &RHPortStatus\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Fill Port Status bits\r
- //\r
-\r
- //\r
- // Current Connect Status\r
- //\r
- if (RHPortStatus & USBPORTSC_CCS) {\r
- PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;\r
- }\r
- //\r
- // Port Enabled/Disabled\r
- //\r
- if (RHPortStatus & USBPORTSC_PED) {\r
- PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;\r
- }\r
-\r
- //\r
- // Port Suspend\r
- //\r
- if (RHPortStatus & USBPORTSC_SUSP) {\r
- PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;\r
- }\r
-\r
- //\r
- // Port Reset\r
- //\r
- if (RHPortStatus & USBPORTSC_PR) {\r
- PortStatus->PortStatus |= USB_PORT_STAT_RESET;\r
- }\r
-\r
- //\r
- // Low Speed Device Attached\r
- //\r
- if (RHPortStatus & USBPORTSC_LSDA) {\r
- PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
- }\r
- //\r
- // CHC will always return one in this bit\r
- //\r
- PortStatus->PortStatus |= USB_PORT_STAT_OWNER;\r
- //\r
- // Fill Port Status Change bits\r
- //\r
-\r
- //\r
- // Connect Status Change\r
- //\r
- if (RHPortStatus & USBPORTSC_CSC) {\r
- PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;\r
- }\r
-\r
- //\r
- // Port Enabled/Disabled Change\r
- //\r
- if (RHPortStatus & USBPORTSC_PEDC) {\r
- PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCISetRootHubPortFeature (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 PortNumber,\r
- IN EFI_USB_PORT_FEATURE PortFeature\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Sets a feature for the specified root hub port.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB_HC_PROTOCOL.\r
-\r
- PortNumber Specifies the root hub port whose feature\r
- is requested to be set.\r
-\r
- PortFeature Indicates the feature selector associated\r
- with the feature set request.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The feature specified by PortFeature was set for the\r
- USB root hub port specified by PortNumber.\r
- EFI_INVALID_PARAMETER\r
- PortNumber is invalid or PortFeature is invalid.\r
- EFI_DEVICE_ERROR\r
- Can't read register\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
- UINT32 PSAddr;\r
- UINT32 CommandRegAddr;\r
- //\r
- // root hub port status\r
- //\r
- UINT16 RHPortControl;\r
- UINT16 Command;\r
- UINT8 TotalPortNumber;\r
- EFI_STATUS Status;\r
-\r
- UHCIGetRootHubPortNumber (This, &TotalPortNumber);\r
- if (PortNumber >= TotalPortNumber) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- HcDev = USB_HC_DEV_FROM_THIS (This);\r
-\r
- PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);\r
- CommandRegAddr = (UINT32) (USBCMD);\r
-\r
- Status = ReadRootPortReg (\r
- HcDev->PciIo,\r
- PSAddr,\r
- &RHPortControl\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- switch (PortFeature) {\r
-\r
- case EfiUsbPortSuspend:\r
- Status = ReadUHCCommandReg (\r
- HcDev->PciIo,\r
- CommandRegAddr,\r
- &Command\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if (!(Command & USBCMD_EGSM)) {\r
- //\r
- // if global suspend is not active, can set port suspend\r
- //\r
- RHPortControl &= 0xfff5;\r
- RHPortControl |= USBPORTSC_SUSP;\r
- }\r
- break;\r
-\r
- case EfiUsbPortReset:\r
- RHPortControl &= 0xfff5;\r
- //\r
- // Set the reset bit\r
- //\r
- RHPortControl |= USBPORTSC_PR;\r
- break;\r
-\r
- case EfiUsbPortPower:\r
- break;\r
-\r
- case EfiUsbPortEnable:\r
- RHPortControl &= 0xfff5;\r
- RHPortControl |= USBPORTSC_PED;\r
- break;\r
-\r
- default:\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- WriteRootPortReg (\r
- HcDev->PciIo,\r
- PSAddr,\r
- RHPortControl\r
- );\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCIClearRootHubPortFeature (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 PortNumber,\r
- IN EFI_USB_PORT_FEATURE PortFeature\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Clears a feature for the specified root hub port.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
-\r
- PortNumber Specifies the root hub port whose feature\r
- is requested to be cleared.\r
-\r
- PortFeature Indicates the feature selector associated with the\r
- feature clear request.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The feature specified by PortFeature was cleared for the\r
- USB root hub port specified by PortNumber.\r
- EFI_INVALID_PARAMETER\r
- PortNumber is invalid or PortFeature is invalid.\r
- EFI_DEVICE_ERROR\r
- Can't read register\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
- UINT32 PSAddr;\r
- UINT16 RHPortControl;\r
- UINT8 TotalPortNumber;\r
- EFI_STATUS Status;\r
-\r
- UHCIGetRootHubPortNumber (This, &TotalPortNumber);\r
-\r
- if (PortNumber >= TotalPortNumber) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- HcDev = USB_HC_DEV_FROM_THIS (This);\r
- PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);\r
-\r
- Status = ReadRootPortReg (\r
- HcDev->PciIo,\r
- PSAddr,\r
- &RHPortControl\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- switch (PortFeature) {\r
- //\r
- // clear PORT_ENABLE feature means disable port.\r
- //\r
- case EfiUsbPortEnable:\r
- RHPortControl &= 0xfff5;\r
- RHPortControl &= ~USBPORTSC_PED;\r
- break;\r
-\r
- //\r
- // clear PORT_SUSPEND feature means resume the port.\r
- // (cause a resume on the specified port if in suspend mode)\r
- //\r
- case EfiUsbPortSuspend:\r
- RHPortControl &= 0xfff5;\r
- RHPortControl &= ~USBPORTSC_SUSP;\r
- break;\r
-\r
- //\r
- // no operation\r
- //\r
- case EfiUsbPortPower:\r
- break;\r
-\r
- //\r
- // clear PORT_RESET means clear the reset signal.\r
- //\r
- case EfiUsbPortReset:\r
- RHPortControl &= 0xfff5;\r
- RHPortControl &= ~USBPORTSC_PR;\r
- break;\r
-\r
- //\r
- // clear connect status change\r
- //\r
- case EfiUsbPortConnectChange:\r
- RHPortControl &= 0xfff5;\r
- RHPortControl |= USBPORTSC_CSC;\r
- break;\r
-\r
- //\r
- // clear enable/disable status change\r
- //\r
- case EfiUsbPortEnableChange:\r
- RHPortControl &= 0xfff5;\r
- RHPortControl |= USBPORTSC_PEDC;\r
- break;\r
-\r
- //\r
- // root hub does not support this request\r
- //\r
- case EfiUsbPortSuspendChange:\r
- break;\r
-\r
- //\r
- // root hub does not support this request\r
- //\r
- case EfiUsbPortOverCurrentChange:\r
- break;\r
-\r
- //\r
- // root hub does not support this request\r
- //\r
- case EfiUsbPortResetChange:\r
- break;\r
-\r
- default:\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- WriteRootPortReg (\r
- HcDev->PciIo,\r
- PSAddr,\r
- RHPortControl\r
- );\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCIControlTransfer (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 DeviceAddress,\r
- IN BOOLEAN IsSlowDevice,\r
- IN UINT8 MaximumPacketLength,\r
- IN EFI_USB_DEVICE_REQUEST *Request,\r
- IN EFI_USB_DATA_DIRECTION TransferDirection,\r
- IN OUT VOID *Data, OPTIONAL\r
- IN OUT UINTN *DataLength, OPTIONAL\r
- IN UINTN TimeOut,\r
- OUT UINT32 *TransferResult\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Submits control transfer to a target USB device.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
-\r
- DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
-\r
- IsSlowDevice Indicates whether the target device is slow device\r
- or full-speed device.\r
-\r
- MaximumPacketLength Indicates the maximum packet size that the\r
- default control transfer endpoint is capable of\r
- sending or receiving.\r
-\r
- Request A pointer to the USB device request that will be sent\r
- to the USB device.\r
-\r
- TransferDirection Specifies the data direction for the transfer.\r
- There are three values available, DataIn, DataOut\r
- and NoData.\r
-\r
- Data A pointer to the buffer of data that will be transmitted\r
- to USB device or received from USB device.\r
-\r
- DataLength Indicates the size, in bytes, of the data buffer\r
- specified by Data.\r
-\r
- TimeOut Indicates the maximum time, in microseconds,\r
- which the transfer is allowed to complete.\r
-\r
- TransferResult A pointer to the detailed result information generated\r
- by this control transfer.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The control transfer was completed successfully.\r
- EFI_OUT_OF_RESOURCES\r
- The control transfer could not be completed due to a lack of resources.\r
- EFI_INVALID_PARAMETER\r
- Some parameters are invalid.\r
- EFI_TIMEOUT\r
- The control transfer failed due to timeout.\r
- EFI_DEVICE_ERROR\r
- The control transfer failed due to host controller or device error.\r
- Caller should check TranferResult for detailed error information.\r
-\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
- UINT32 StatusReg;\r
- UINT32 FrameNumReg;\r
- UINT8 PktID;\r
- QH_STRUCT *PtrQH;\r
- TD_STRUCT *PtrTD;\r
- TD_STRUCT *PtrPreTD;\r
- TD_STRUCT *PtrSetupTD;\r
- TD_STRUCT *PtrStatusTD;\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- UINTN DataLen;\r
- UINT8 *PtrDataSource;\r
- UINT8 *Ptr;\r
- UINT8 DataToggle;\r
- UINT16 LoadFrameListIndex;\r
- UINT8 PktSize;\r
-\r
- UINT8 *RequestMappedAddress;\r
- VOID *RequestMapping;\r
- UINTN RequestLen;\r
-\r
- EFI_PHYSICAL_ADDRESS TempPtr;\r
- VOID *Mapping;\r
-\r
- TD_STRUCT *PtrFirstDataTD;\r
- TD_STRUCT *ptrLastDataTD;\r
- BOOLEAN FirstTD;\r
-\r
- FirstTD = FALSE;\r
- RequestMappedAddress = NULL;\r
- RequestMapping = NULL;\r
- Mapping = NULL;\r
- PtrFirstDataTD = NULL;\r
- ptrLastDataTD = NULL;\r
- PktID = INPUT_PACKET_ID;\r
- Mapping = NULL;\r
- HcDev = USB_HC_DEV_FROM_THIS (This);\r
- StatusReg = (UINT32) (USBSTS);\r
- FrameNumReg = (UINT32) (USBFRNUM);\r
- PtrPreTD = NULL;\r
- PtrTD = NULL;\r
-\r
- //\r
- // Parameters Checking\r
- //\r
- if (Request == NULL || TransferResult == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // if errors exist that cause host controller halt,\r
- // then return EFI_DEVICE_ERROR.\r
- //\r
- if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
-\r
- ClearStatusReg (HcDev->PciIo, StatusReg);\r
- *TransferResult = EFI_USB_ERR_SYSTEM;\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- //\r
- // low speed usb devices are limited to only an eight-byte\r
- // maximum data payload size\r
- //\r
- if (IsSlowDevice && (MaximumPacketLength != 8)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (MaximumPacketLength != 8 &&\r
- MaximumPacketLength != 16 &&\r
- MaximumPacketLength != 32 &&\r
- MaximumPacketLength != 64) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((TransferDirection != EfiUsbNoData) && (DataLength == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- switch (TransferDirection) {\r
-\r
- case EfiUsbDataIn:\r
- PktID = INPUT_PACKET_ID;\r
- PtrDataSource = Data;\r
- DataLen = *DataLength;\r
-\r
- //\r
- // map the source data buffer for bus master access.\r
- // BusMasterWrite means cpu read\r
- //\r
- Status = HcDev->PciIo->Map (\r
- HcDev->PciIo,\r
- EfiPciIoOperationBusMasterWrite,\r
- PtrDataSource,\r
- &DataLen,\r
- &TempPtr,\r
- &Mapping\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Ptr = (UINT8 *) ((UINTN) TempPtr);\r
- break;\r
-\r
- case EfiUsbDataOut:\r
- PktID = OUTPUT_PACKET_ID;\r
- PtrDataSource = Data;\r
- DataLen = *DataLength;\r
-\r
- //\r
- // map the source data buffer for bus master access.\r
- // BusMasterRead means cpu write\r
- //\r
- Status = HcDev->PciIo->Map (\r
- HcDev->PciIo,\r
- EfiPciIoOperationBusMasterRead,\r
- PtrDataSource,\r
- &DataLen,\r
- &TempPtr,\r
- &Mapping\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Ptr = (UINT8 *) ((UINTN) TempPtr);\r
- break;\r
-\r
- //\r
- // no data stage\r
- //\r
- case EfiUsbNoData:\r
- if ((DataLength != NULL) && (*DataLength != 0)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- PktID = OUTPUT_PACKET_ID;\r
- PtrDataSource = NULL;\r
- DataLen = 0;\r
- Ptr = NULL;\r
- break;\r
-\r
- default:\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Status = ClearStatusReg (HcDev->PciIo, StatusReg);\r
- if (EFI_ERROR (Status)) {\r
- HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // create QH structure and init\r
- //\r
- Status = CreateQH (HcDev, &PtrQH);\r
- if (EFI_ERROR (Status)) {\r
- HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
- return Status;\r
- }\r
-\r
- //\r
- // map the Request for bus master access.\r
- // BusMasterRead means cpu write\r
- //\r
- RequestLen = sizeof (EFI_USB_DEVICE_REQUEST);\r
- Status = HcDev->PciIo->Map (\r
- HcDev->PciIo,\r
- EfiPciIoOperationBusMasterRead,\r
- (UINT8 *) Request,\r
- &RequestLen,\r
- &TempPtr,\r
- &RequestMapping\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
- UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
- return Status;\r
- }\r
-\r
- RequestMappedAddress = (UINT8 *) ((UINTN) TempPtr);\r
-\r
- //\r
- // generate Setup Stage TD\r
- //\r
- Status = GenSetupStageTD (\r
- HcDev,\r
- DeviceAddress,\r
- 0,\r
- IsSlowDevice,\r
- (UINT8 *) RequestMappedAddress,\r
- sizeof (EFI_USB_DEVICE_REQUEST),\r
- &PtrSetupTD\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
- UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
- HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);\r
- return Status;\r
- }\r
-\r
- //\r
- // Data Stage of Control Transfer\r
- //\r
- DataToggle = 1;\r
- FirstTD = TRUE;\r
- while (DataLen > 0) {\r
- //\r
- // create TD structures and link together\r
- //\r
-\r
- //\r
- // PktSize is the data load size that each TD carries.\r
- //\r
- PktSize = (UINT8) DataLen;\r
- if (DataLen > MaximumPacketLength) {\r
- PktSize = MaximumPacketLength;\r
- }\r
-\r
- Status = GenDataTD (\r
- HcDev,\r
- DeviceAddress,\r
- 0,\r
- Ptr,\r
- PktSize,\r
- PktID,\r
- DataToggle,\r
- IsSlowDevice,\r
- &PtrTD\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // free all resources occupied\r
- //\r
- HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
- UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
- HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);\r
- DeleteQueuedTDs (HcDev, PtrSetupTD);\r
- DeleteQueuedTDs (HcDev, PtrFirstDataTD);\r
- return Status;\r
- }\r
-\r
- //\r
- // Link two TDs in vertical depth\r
- //\r
- if (FirstTD) {\r
- PtrFirstDataTD = PtrTD;\r
- PtrFirstDataTD->ptrNextTD = NULL;\r
- FirstTD = FALSE;\r
- } else {\r
- LinkTDToTD (PtrPreTD, PtrTD);\r
- }\r
-\r
- PtrPreTD = PtrTD;\r
-\r
- DataToggle ^= 1;\r
- Ptr += PktSize;\r
- DataLen -= PktSize;\r
- }\r
-\r
- ptrLastDataTD = PtrTD;\r
-\r
- //\r
- // Status Stage of Control Transfer\r
- //\r
- if (PktID == OUTPUT_PACKET_ID) {\r
- PktID = INPUT_PACKET_ID;\r
- } else {\r
- PktID = OUTPUT_PACKET_ID;\r
- }\r
-\r
- //\r
- // create Status Stage TD structure\r
- //\r
- Status = CreateStatusTD (\r
- HcDev,\r
- DeviceAddress,\r
- 0,\r
- PktID,\r
- IsSlowDevice,\r
- &PtrStatusTD\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
- UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
- HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);\r
- DeleteQueuedTDs (HcDev, PtrSetupTD);\r
- DeleteQueuedTDs (HcDev, PtrFirstDataTD);\r
- return Status;\r
- }\r
-\r
- if (IsSlowDevice) {\r
- //\r
- // link setup TD structures to QH structure\r
- //\r
- LinkTDToQH (PtrQH, PtrSetupTD);\r
-\r
- LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
-\r
- //\r
- // link QH-TDs to total 100 frame list entry to speed up the execution.\r
- //\r
- for (Index = 0; Index < 100; Index++) {\r
- LinkQHToFrameList (\r
- HcDev->FrameListEntry,\r
- (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
- PtrQH\r
- );\r
- }\r
- //\r
- // Poll QH-TDs execution and get result.\r
- // detail status is returned\r
- //\r
- Status = ExecuteControlTransfer (\r
- HcDev,\r
- PtrSetupTD,\r
- LoadFrameListIndex,\r
- DataLength,\r
- TimeOut,\r
- TransferResult\r
- );\r
- //\r
- // Remove Control Transfer QH-TDs structure from the frame list\r
- // and update the pointers in the Frame List\r
- // and other pointers in other related QH structures.\r
- //\r
- for (Index = 0; Index < 100; Index++) {\r
- DelLinkSingleQH (\r
- HcDev,\r
- PtrQH,\r
- (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
- FALSE,\r
- FALSE\r
- );\r
- }\r
- //\r
- // delete setup stage TD; the QH is reserved for the next stages.\r
- //\r
- DeleteQueuedTDs (HcDev, PtrSetupTD);\r
-\r
- //\r
- // if setup stage error, return error\r
- //\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- //\r
- // some control transfers do not have Data Stage\r
- //\r
- if (PtrFirstDataTD != NULL) {\r
-\r
- LinkTDToQH (PtrQH, PtrFirstDataTD);\r
- LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
-\r
- for (Index = 0; Index < 500; Index++) {\r
- LinkQHToFrameList (\r
- HcDev->FrameListEntry,\r
- (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
- PtrQH\r
- );\r
- }\r
-\r
- Status = ExecuteControlTransfer (\r
- HcDev,\r
- PtrFirstDataTD,\r
- LoadFrameListIndex,\r
- DataLength,\r
- TimeOut,\r
- TransferResult\r
- );\r
-\r
- for (Index = 0; Index < 500; Index++) {\r
- DelLinkSingleQH (\r
- HcDev,\r
- PtrQH,\r
- (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
- FALSE,\r
- FALSE\r
- );\r
- }\r
- //\r
- // delete data stage TD; the QH is reserved for the next stage.\r
- //\r
- DeleteQueuedTDs (HcDev, PtrFirstDataTD);\r
- }\r
- //\r
- // if data stage error, goto done and return error\r
- //\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- LinkTDToQH (PtrQH, PtrStatusTD);\r
- //\r
- // get the frame list index that the QH-TDs will be linked to.\r
- //\r
- LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
-\r
- for (Index = 0; Index < 100; Index++) {\r
- //\r
- // put the QH-TDs directly or indirectly into the proper place\r
- // in the Frame List\r
- //\r
- LinkQHToFrameList (\r
- HcDev->FrameListEntry,\r
- (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
- PtrQH\r
- );\r
- }\r
- //\r
- // Poll QH-TDs execution and get result.\r
- // detail status is returned\r
- //\r
- Status = ExecuteControlTransfer (\r
- HcDev,\r
- PtrStatusTD,\r
- LoadFrameListIndex,\r
- DataLength,\r
- TimeOut,\r
- TransferResult\r
- );\r
-\r
- //\r
- // Delete Control Transfer QH-TDs structure\r
- // and update the pointers in the Frame List\r
- // and other pointers in other related QH structures.\r
- //\r
- // TRUE means must search other framelistindex\r
- //\r
- for (Index = 0; Index < 100; Index++) {\r
- DelLinkSingleQH (\r
- HcDev,\r
- PtrQH,\r
- (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
- FALSE,\r
- FALSE\r
- );\r
- }\r
-\r
- DeleteQueuedTDs (HcDev, PtrStatusTD);\r
-\r
- } else {\r
- //\r
- // link setup stage TD with data stage TD\r
- //\r
- PtrPreTD = PtrSetupTD;\r
- if (PtrFirstDataTD != NULL) {\r
- LinkTDToTD (PtrSetupTD, PtrFirstDataTD);\r
- PtrPreTD = ptrLastDataTD;\r
- }\r
- //\r
- // link status TD with previous TD\r
- //\r
- LinkTDToTD (PtrPreTD, PtrStatusTD);\r
-\r
- //\r
- // link QH with TD\r
- //\r
- LinkTDToQH (PtrQH, PtrSetupTD);\r
-\r
- LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
- for (Index = 0; Index < 500; Index++) {\r
- //\r
- // put the QH-TDs directly or indirectly into the proper place\r
- // in the Frame List\r
- //\r
- LinkQHToFrameList (\r
- HcDev->FrameListEntry,\r
- (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
- PtrQH\r
- );\r
- }\r
- //\r
- // Poll QH-TDs execution and get result.\r
- // detail status is returned\r
- //\r
- Status = ExecuteControlTransfer (\r
- HcDev,\r
- PtrSetupTD,\r
- LoadFrameListIndex,\r
- DataLength,\r
- TimeOut,\r
- TransferResult\r
- );\r
- //\r
- // Remove Control Transfer QH-TDs structure from the frame list\r
- // and update the pointers in the Frame List\r
- // and other pointers in other related QH structures.\r
- //\r
- for (Index = 0; Index < 500; Index++) {\r
- DelLinkSingleQH (\r
- HcDev,\r
- PtrQH,\r
- (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),\r
- FALSE,\r
- FALSE\r
- );\r
- }\r
-\r
- DeleteQueuedTDs (HcDev, PtrSetupTD);\r
- }\r
-\r
-Done:\r
-\r
- UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
-\r
- if (Mapping != NULL) {\r
- HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
- }\r
-\r
- if (RequestMapping != NULL) {\r
- HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);\r
- }\r
- //\r
- // if has errors that cause host controller halt,\r
- // then return EFI_DEVICE_ERROR directly.\r
- //\r
- if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
-\r
- ClearStatusReg (HcDev->PciIo, StatusReg);\r
- *TransferResult |= EFI_USB_ERR_SYSTEM;\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- ClearStatusReg (HcDev->PciIo, StatusReg);\r
- HcDev->PciIo->Flush (HcDev->PciIo);\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCIBulkTransfer (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN UINT8 MaximumPacketLength,\r
- IN OUT VOID *Data,\r
- IN OUT UINTN *DataLength,\r
- IN OUT UINT8 *DataToggle,\r
- IN UINTN TimeOut,\r
- OUT UINT32 *TransferResult\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Submits bulk transfer to a bulk endpoint of a USB device.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
-\r
- DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
- EndPointAddress The combination of an endpoint number and an\r
- endpoint direction of the target USB device.\r
- Each endpoint address supports data transfer in\r
- one direction except the control endpoint\r
- (whose default endpoint address is 0).\r
- It is the caller's responsibility to make sure that\r
- the EndPointAddress represents a bulk endpoint.\r
-\r
- MaximumPacketLength Indicates the maximum packet size the target endpoint\r
- is capable of sending or receiving.\r
-\r
- Data A pointer to the buffer of data that will be transmitted\r
- to USB device or received from USB device.\r
- DataLength When input, indicates the size, in bytes, of the data buffer\r
- specified by Data. When output, indicates the actually\r
- transferred data size.\r
-\r
- DataToggle A pointer to the data toggle value. On input, it indicates\r
- the initial data toggle value the bulk transfer should adopt;\r
- on output, it is updated to indicate the data toggle value\r
- of the subsequent bulk transfer.\r
-\r
- TimeOut Indicates the maximum time, in microseconds, which the\r
- transfer is allowed to complete.\r
-\r
- TransferResult A pointer to the detailed result information of the\r
- bulk transfer.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The bulk transfer was completed successfully.\r
- EFI_OUT_OF_RESOURCES\r
- The bulk transfer could not be submitted due to lack of resource.\r
- EFI_INVALID_PARAMETER\r
- Some parameters are invalid.\r
- EFI_TIMEOUT\r
- The bulk transfer failed due to timeout.\r
- EFI_DEVICE_ERROR\r
- The bulk transfer failed due to host controller or device error.\r
- Caller should check TranferResult for detailed error information.\r
-\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
- UINT32 StatusReg;\r
- UINT32 FrameNumReg;\r
- UINTN DataLen;\r
- QH_STRUCT *PtrQH;\r
- TD_STRUCT *PtrFirstTD;\r
- TD_STRUCT *PtrTD;\r
- TD_STRUCT *PtrPreTD;\r
- UINT16 LoadFrameListIndex;\r
- UINT16 SavedFrameListIndex;\r
- UINT8 PktID;\r
- UINT8 *PtrDataSource;\r
- UINT8 *Ptr;\r
- BOOLEAN IsFirstTD;\r
- EFI_STATUS Status;\r
- UINT32 Index;\r
- UINT8 PktSize;\r
-\r
- EFI_USB_DATA_DIRECTION TransferDirection;\r
- //\r
- // Used to calculate how many entries are linked to the\r
- // specified bulk transfer QH-TDs\r
- //\r
- UINT32 LinkTimes;\r
-\r
- BOOLEAN ShortPacketEnable;\r
- EFI_PHYSICAL_ADDRESS TempPtr;\r
- VOID *Mapping;\r
-\r
- HcDev = USB_HC_DEV_FROM_THIS (This);\r
- StatusReg = (UINT32) (USBSTS);\r
- FrameNumReg = (UINT32) (USBFRNUM);\r
- PktID = INPUT_PACKET_ID;\r
- PtrTD = NULL;\r
- PtrFirstTD = NULL;\r
- PtrPreTD = NULL;\r
- LinkTimes = 1;\r
- DataLen = 0;\r
- Ptr = NULL;\r
- ShortPacketEnable = FALSE;\r
- Mapping = NULL;\r
-\r
- //\r
- // Parameters Checking\r
- //\r
-\r
- if ((DataLength == NULL) ||\r
- (Data == NULL) ||\r
- (TransferResult == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // if has errors that cause host controller halt,\r
- // then return EFI_DEVICE_ERROR directly.\r
- //\r
- if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
-\r
- ClearStatusReg (HcDev->PciIo, StatusReg);\r
- *TransferResult = EFI_USB_ERR_SYSTEM;\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if (*DataLength == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (MaximumPacketLength != 8 &&\r
- MaximumPacketLength != 16 &&\r
- MaximumPacketLength != 32 &&\r
- MaximumPacketLength != 64) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Enable the maximum packet size (64bytes)\r
- // that can be used for full speed bandwidth reclamation\r
- // at the end of a frame.\r
- //\r
- EnableMaxPacketSize (HcDev);\r
-\r
- Status = ClearStatusReg (HcDev->PciIo, StatusReg);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- //\r
- // construct QH and TD data structures,\r
- // and link them together\r
- //\r
- if (EndPointAddress & 0x80) {\r
- TransferDirection = EfiUsbDataIn;\r
- } else {\r
- TransferDirection = EfiUsbDataOut;\r
- }\r
-\r
- switch (TransferDirection) {\r
-\r
- case EfiUsbDataIn:\r
- ShortPacketEnable = TRUE;\r
- PktID = INPUT_PACKET_ID;\r
- PtrDataSource = Data;\r
- DataLen = *DataLength;\r
-\r
- //\r
- // BusMasterWrite means cpu read\r
- //\r
- Status = HcDev->PciIo->Map (\r
- HcDev->PciIo,\r
- EfiPciIoOperationBusMasterWrite,\r
- PtrDataSource,\r
- &DataLen,\r
- &TempPtr,\r
- &Mapping\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Ptr = (UINT8 *) ((UINTN) TempPtr);\r
- break;\r
-\r
- case EfiUsbDataOut:\r
- PktID = OUTPUT_PACKET_ID;\r
- PtrDataSource = Data;\r
- DataLen = *DataLength;\r
-\r
- //\r
- // BusMasterRead means cpu write\r
- //\r
- Status = HcDev->PciIo->Map (\r
- HcDev->PciIo,\r
- EfiPciIoOperationBusMasterRead,\r
- PtrDataSource,\r
- &DataLen,\r
- &TempPtr,\r
- &Mapping\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Ptr = (UINT8 *) ((UINTN) TempPtr);\r
- break;\r
-\r
- default:\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // create QH structure and init\r
- //\r
- Status = CreateQH (HcDev, &PtrQH);\r
- if (EFI_ERROR (Status)) {\r
- HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
- return Status;\r
- }\r
-\r
- //\r
- // i is used to calculate the total number of TDs.\r
- //\r
- Index = 0;\r
-\r
- IsFirstTD = TRUE;\r
- while (DataLen > 0) {\r
-\r
- //\r
- // create TD structures and link together\r
- //\r
-\r
- PktSize = (UINT8) DataLen;\r
- if (DataLen > MaximumPacketLength) {\r
- PktSize = MaximumPacketLength;\r
- }\r
-\r
- Status = GenDataTD (\r
- HcDev,\r
- DeviceAddress,\r
- EndPointAddress,\r
- Ptr,\r
- PktSize,\r
- PktID,\r
- *DataToggle,\r
- FALSE,\r
- &PtrTD\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
- UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
- DeleteQueuedTDs (HcDev, PtrFirstTD);\r
- return Status;\r
- }\r
-\r
- //\r
- // Enable short packet detection.\r
- // (default action is disabling short packet detection)\r
- //\r
- if (ShortPacketEnable) {\r
- EnableorDisableTDShortPacket (PtrTD, TRUE);\r
- }\r
-\r
- if (IsFirstTD) {\r
- PtrFirstTD = PtrTD;\r
- PtrFirstTD->ptrNextTD = NULL;\r
- IsFirstTD = FALSE;\r
- } else {\r
- //\r
- // Link two TDs in vertical depth\r
- //\r
- LinkTDToTD (PtrPreTD, PtrTD);\r
- }\r
-\r
- Index++;\r
-\r
- PtrPreTD = PtrTD;\r
-\r
- *DataToggle ^= 1;\r
- Ptr += PktSize;\r
- DataLen -= PktSize;\r
- }\r
-\r
- //\r
- // link TD structures to QH structure\r
- //\r
- LinkTDToQH (PtrQH, PtrFirstTD);\r
-\r
- //\r
- // calculate how many entries are linked to the specified bulk transfer QH-TDs\r
- // the below values are referred to the USB spec revision1.1.\r
- //\r
- switch (MaximumPacketLength) {\r
- case 8:\r
- LinkTimes = Index / 71 + 1;\r
- break;\r
-\r
- case 16:\r
- LinkTimes = Index / 51 + 1;\r
- break;\r
-\r
- case 32:\r
- LinkTimes = Index / 33 + 1;\r
- break;\r
-\r
- case 64:\r
- LinkTimes = Index / 19 + 1;\r
- break;\r
- }\r
-\r
- LinkTimes += 500;\r
-\r
- //\r
- // put QH-TDs into Frame list\r
- //\r
- LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
- SavedFrameListIndex = LoadFrameListIndex;\r
-\r
- for (Index = 0; Index <= LinkTimes; Index++) {\r
-\r
- //\r
- // put the QH-TD directly or indirectly into the proper place\r
- // in the Frame List\r
- //\r
- LinkQHToFrameList (HcDev->FrameListEntry, LoadFrameListIndex, PtrQH);\r
-\r
- LoadFrameListIndex += 1;\r
- LoadFrameListIndex &= 0x3FF;\r
- }\r
-\r
- LoadFrameListIndex = SavedFrameListIndex;\r
-\r
- //\r
- // Execute QH-TD and get result\r
- //\r
- //\r
- // detail status is put into the Result field in the pIRP\r
- // the Data Toggle value is also re-updated to the value\r
- // of the last successful TD\r
- //\r
- Status = ExecBulkorSyncInterruptTransfer (\r
- HcDev,\r
- PtrFirstTD,\r
- LoadFrameListIndex,\r
- DataLength,\r
- DataToggle,\r
- TimeOut,\r
- TransferResult\r
- );\r
-\r
- //\r
- // Delete Bulk transfer QH-TD structure\r
- // and maitain the pointers in the Frame List\r
- // and other pointers in related QH structure\r
- //\r
- // TRUE means must search other framelistindex\r
- //\r
- for (Index = 0; Index <= LinkTimes; Index++) {\r
- DelLinkSingleQH (\r
- HcDev,\r
- PtrQH,\r
- LoadFrameListIndex,\r
- FALSE,\r
- FALSE\r
- );\r
- LoadFrameListIndex += 1;\r
- LoadFrameListIndex &= 0x3FF;\r
- }\r
-\r
- UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
-\r
- DeleteQueuedTDs (HcDev, PtrFirstTD);\r
-\r
- if (Mapping != NULL) {\r
- HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
- }\r
-\r
- //\r
- // if has errors that cause host controller halt,\r
- // then return EFI_DEVICE_ERROR directly.\r
- //\r
- if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
-\r
- ClearStatusReg (HcDev->PciIo, StatusReg);\r
- *TransferResult |= EFI_USB_ERR_SYSTEM;\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- ClearStatusReg (HcDev->PciIo, StatusReg);\r
-\r
- HcDev->PciIo->Flush (HcDev->PciIo);\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCIAsyncInterruptTransfer (\r
- IN EFI_USB_HC_PROTOCOL * This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN BOOLEAN IsSlowDevice,\r
- IN UINT8 MaximumPacketLength,\r
- IN BOOLEAN IsNewTransfer,\r
- IN OUT UINT8 *DataToggle,\r
- IN UINTN PollingInterval, OPTIONAL\r
- IN UINTN DataLength, OPTIONAL\r
- IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, OPTIONAL\r
- IN VOID *Context OPTIONAL\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Submits an asynchronous interrupt transfer to an\r
- interrupt endpoint of a USB device.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
-\r
- DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
-\r
- EndPointAddress The combination of an endpoint number and an endpoint\r
- direction of the target USB device. Each endpoint address\r
- supports data transfer in one direction except the\r
- control endpoint (whose default endpoint address is 0).\r
- It is the caller's responsibility to make sure that\r
- the EndPointAddress represents an interrupt endpoint.\r
-\r
- IsSlowDevice Indicates whether the target device is slow device\r
- or full-speed device.\r
-\r
- MaximumPacketLength Indicates the maximum packet size the target endpoint\r
- is capable of sending or receiving.\r
-\r
- IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between\r
- the host and the target interrupt endpoint.\r
- If FALSE, the specified asynchronous interrupt pipe\r
- is canceled.\r
-\r
- DataToggle A pointer to the data toggle value. On input, it is valid\r
- when IsNewTransfer is TRUE, and it indicates the initial\r
- data toggle value the asynchronous interrupt transfer\r
- should adopt.\r
- On output, it is valid when IsNewTransfer is FALSE,\r
- and it is updated to indicate the data toggle value of\r
- the subsequent asynchronous interrupt transfer.\r
-\r
- PollingInterval Indicates the interval, in milliseconds, that the\r
- asynchronous interrupt transfer is polled.\r
- This parameter is required when IsNewTransfer is TRUE.\r
-\r
- DataLength Indicates the length of data to be received at the\r
- rate specified by PollingInterval from the target\r
- asynchronous interrupt endpoint. This parameter\r
- is only required when IsNewTransfer is TRUE.\r
-\r
- CallBackFunction The Callback function.This function is called at the\r
- rate specified by PollingInterval.This parameter is\r
- only required when IsNewTransfer is TRUE.\r
-\r
- Context The context that is passed to the CallBackFunction.\r
- This is an optional parameter and may be NULL.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The asynchronous interrupt transfer request has been successfully\r
- submitted or canceled.\r
- EFI_INVALID_PARAMETER\r
- Some parameters are invalid.\r
- EFI_OUT_OF_RESOURCES\r
- The request could not be completed due to a lack of resources.\r
- EFI_DEVICE_ERROR\r
- Can't read register\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
- UINT32 StatusReg;\r
- UINT32 FrameNumReg;\r
- UINTN DataLen;\r
- QH_STRUCT *ptrFirstQH;\r
- QH_STRUCT *PtrQH;\r
- QH_STRUCT *ptrPreQH;\r
- TD_STRUCT *PtrFirstTD;\r
- TD_STRUCT *PtrTD;\r
- TD_STRUCT *PtrPreTD;\r
- UINT16 LoadFrameListIndex;\r
- UINT16 Index;\r
- UINT8 PktID;\r
- UINT8 *Ptr;\r
- UINT8 *MappedPtr;\r
- BOOLEAN IsFirstTD;\r
- BOOLEAN IsFirstQH;\r
- EFI_STATUS Status;\r
- BOOLEAN ShortPacketEnable;\r
- UINT8 CurrentDataToggle;\r
- EFI_PHYSICAL_ADDRESS TempPtr;\r
- VOID *Mapping;\r
- UINT8 PktSize;\r
- QH_STRUCT *TempQH;\r
- EFI_TPL OldTpl;\r
-\r
- HcDev = USB_HC_DEV_FROM_THIS (This);\r
- StatusReg = (UINT32) (USBSTS);\r
- FrameNumReg = (UINT32) (USBFRNUM);\r
- Mapping = NULL;\r
- ShortPacketEnable = FALSE;\r
-\r
- PktID = INPUT_PACKET_ID;\r
- PtrTD = NULL;\r
- PtrFirstTD = NULL;\r
- PtrPreTD = NULL;\r
- Ptr = NULL;\r
- PtrQH = NULL;\r
- ptrPreQH = NULL;\r
- ptrFirstQH = NULL;\r
-\r
- if ((EndPointAddress & 0x80) == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // delete Async interrupt transfer request\r
- //\r
- if (!IsNewTransfer) {\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
-\r
- Status = DeleteAsyncINTQHTDs (\r
- HcDev,\r
- DeviceAddress,\r
- EndPointAddress,\r
- DataToggle\r
- );\r
-\r
- gBS->RestoreTPL (OldTpl);\r
-\r
- return Status;\r
- }\r
- //\r
- // if has errors that cause host controller halt,\r
- // then return EFI_DEVICE_ERROR directly.\r
- //\r
- if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
-\r
- ClearStatusReg (HcDev->PciIo, StatusReg);\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- ClearStatusReg (HcDev->PciIo, StatusReg);\r
-\r
- //\r
- // submit Async interrupt transfer request\r
- //\r
- if (PollingInterval < 1 || PollingInterval > 255) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (DataLength == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- ShortPacketEnable = TRUE;\r
- PktID = INPUT_PACKET_ID;\r
- DataLen = DataLength;\r
- Ptr = AllocatePool (DataLen);\r
- if (Ptr == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // BusMasterWrite means cpu read\r
- //\r
- Status = HcDev->PciIo->Map (\r
- HcDev->PciIo,\r
- EfiPciIoOperationBusMasterWrite,\r
- Ptr,\r
- &DataLen,\r
- &TempPtr,\r
- &Mapping\r
- );\r
- if (EFI_ERROR (Status)) {\r
- gBS->FreePool (Ptr);\r
- return Status;\r
- }\r
-\r
- MappedPtr = (UINT8 *) ((UINTN) TempPtr);\r
-\r
- CurrentDataToggle = *DataToggle;\r
-\r
- IsFirstTD = TRUE;\r
-\r
- while (DataLen > 0) {\r
- //\r
- // create TD structures and link together\r
- //\r
-\r
- PktSize = (UINT8) DataLen;\r
- if (DataLen > MaximumPacketLength) {\r
- PktSize = MaximumPacketLength;\r
- }\r
-\r
- Status = GenDataTD (\r
- HcDev,\r
- DeviceAddress,\r
- EndPointAddress,\r
- MappedPtr,\r
- PktSize,\r
- PktID,\r
- CurrentDataToggle,\r
- IsSlowDevice,\r
- &PtrTD\r
- );\r
- if (EFI_ERROR (Status)) {\r
- gBS->FreePool (Ptr);\r
- HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
- DeleteQueuedTDs (HcDev, PtrFirstTD);\r
- return Status;\r
- }\r
- //\r
- // Enable short packet detection.\r
- //\r
- if (ShortPacketEnable) {\r
- EnableorDisableTDShortPacket (PtrTD, TRUE);\r
- }\r
-\r
- if (IsFirstTD) {\r
- PtrFirstTD = PtrTD;\r
- PtrFirstTD->ptrNextTD = NULL;\r
- IsFirstTD = FALSE;\r
- } else {\r
- //\r
- // Link two TDs in vertical depth\r
- //\r
- LinkTDToTD (PtrPreTD, PtrTD);\r
- }\r
-\r
- PtrPreTD = PtrTD;\r
-\r
- CurrentDataToggle ^= 1;\r
- MappedPtr += PktSize;\r
- DataLen -= PktSize;\r
- }\r
-\r
- //\r
- // roll one value back\r
- //\r
- CurrentDataToggle ^= 1;\r
-\r
- //\r
- // create a list of QH structures and init,\r
- // link TDs to all the QHs, and link all the QHs together using internal\r
- // defined pointer of the QH_STRUCT.\r
- //\r
- IsFirstQH = TRUE;\r
- ptrPreQH = NULL;\r
- for (Index = 0; Index < 1024;) {\r
-\r
- Status = CreateQH (HcDev, &PtrQH);\r
- if (EFI_ERROR (Status)) {\r
- gBS->FreePool (Ptr);\r
- HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
- DeleteQueuedTDs (HcDev, PtrFirstTD);\r
- PtrQH = ptrFirstQH;\r
- while (PtrQH) {\r
- TempQH = PtrQH;\r
- PtrQH = TempQH->ptrNextIntQH;\r
- UhciFreePool (HcDev, (UINT8 *) TempQH, sizeof (QH_STRUCT));\r
- }\r
-\r
- return Status;\r
- }\r
-\r
- //\r
- // link TD structures to QH structure\r
- //\r
- LinkTDToQH (PtrQH, PtrFirstTD);\r
-\r
- if (IsFirstQH) {\r
- ptrFirstQH = PtrQH;\r
- ptrFirstQH->ptrNextIntQH = NULL;\r
- IsFirstQH = FALSE;\r
- } else {\r
- //\r
- // link neighbor QH structures together\r
- //\r
- ptrPreQH->ptrNextIntQH = PtrQH;\r
- }\r
-\r
- ptrPreQH = PtrQH;\r
-\r
- Index = (UINT16) (PollingInterval + Index);\r
- }\r
- //\r
- // last QH in QH list should set its next QH pointer to NULL.\r
- //\r
- PtrQH->ptrNextIntQH = NULL;\r
-\r
- //\r
- // Save QH-TD structures in Interrupt transfer list,\r
- // for monitor interrupt transfer execution routine use.\r
- //\r
- InsertQHTDToINTList (\r
- HcDev,\r
- ptrFirstQH,\r
- PtrFirstTD,\r
- DeviceAddress,\r
- EndPointAddress,\r
- CurrentDataToggle,\r
- DataLength,\r
- PollingInterval,\r
- Mapping,\r
- Ptr,\r
- CallBackFunction,\r
- Context\r
- );\r
-\r
- //\r
- // put QHs-TDs into Frame list\r
- //\r
- LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
-\r
- PtrQH = ptrFirstQH;\r
-\r
- for (Index = LoadFrameListIndex; Index < (1024 + LoadFrameListIndex);) {\r
-\r
- //\r
- // put the QH-TD directly or indirectly into the proper place\r
- // in the Frame List\r
- //\r
- LinkQHToFrameList (HcDev->FrameListEntry, (UINT16) (Index & 0x3FF), PtrQH);\r
-\r
- Index = (UINT16) (PollingInterval + Index);\r
-\r
- PtrQH = PtrQH->ptrNextIntQH;\r
- }\r
-\r
- HcDev->PciIo->Flush (HcDev->PciIo);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCISyncInterruptTransfer (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN BOOLEAN IsSlowDevice,\r
- IN UINT8 MaximumPacketLength,\r
- IN OUT VOID *Data,\r
- IN OUT UINTN *DataLength,\r
- IN OUT UINT8 *DataToggle,\r
- IN UINTN TimeOut,\r
- OUT UINT32 *TransferResult\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Submits synchronous interrupt transfer to an interrupt endpoint\r
- of a USB device.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
-\r
- DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
-\r
- EndPointAddress The combination of an endpoint number and an endpoint\r
- direction of the target USB device. Each endpoint\r
- address supports data transfer in one direction\r
- except the control endpoint (whose default\r
- endpoint address is 0). It is the caller's responsibility\r
- to make sure that the EndPointAddress represents\r
- an interrupt endpoint.\r
-\r
- IsSlowDevice Indicates whether the target device is slow device\r
- or full-speed device.\r
-\r
- MaximumPacketLength Indicates the maximum packet size the target endpoint\r
- is capable of sending or receiving.\r
-\r
- Data A pointer to the buffer of data that will be transmitted\r
- to USB device or received from USB device.\r
-\r
- DataLength On input, the size, in bytes, of the data buffer specified\r
- by Data. On output, the number of bytes transferred.\r
-\r
- DataToggle A pointer to the data toggle value. On input, it indicates\r
- the initial data toggle value the synchronous interrupt\r
- transfer should adopt;\r
- on output, it is updated to indicate the data toggle value\r
- of the subsequent synchronous interrupt transfer.\r
-\r
- TimeOut Indicates the maximum time, in microseconds, which the\r
- transfer is allowed to complete.\r
-\r
- TransferResult A pointer to the detailed result information from\r
- the synchronous interrupt transfer.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The synchronous interrupt transfer was completed successfully.\r
- EFI_OUT_OF_RESOURCES\r
- The synchronous interrupt transfer could not be submitted due\r
- to lack of resource.\r
- EFI_INVALID_PARAMETER\r
- Some parameters are invalid.\r
- EFI_TIMEOUT\r
- The synchronous interrupt transfer failed due to timeout.\r
- EFI_DEVICE_ERROR\r
- The synchronous interrupt transfer failed due to host controller\r
- or device error. Caller should check TranferResult for detailed\r
- error information.\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
- UINT32 StatusReg;\r
- UINT32 FrameNumReg;\r
- UINTN DataLen;\r
- QH_STRUCT *PtrQH;\r
- TD_STRUCT *PtrFirstTD;\r
- TD_STRUCT *PtrTD;\r
- TD_STRUCT *PtrPreTD;\r
- UINT16 LoadFrameListIndex;\r
- UINT16 SavedFrameListIndex;\r
- UINT32 Index;\r
- UINT32 LinkTimes;\r
- UINT8 PktID;\r
- UINT8 *PtrDataSource;\r
- UINT8 *Ptr;\r
- BOOLEAN IsFirstTD;\r
- EFI_STATUS Status;\r
- BOOLEAN ShortPacketEnable;\r
- EFI_PHYSICAL_ADDRESS TempPtr;\r
- VOID *Mapping;\r
- UINT8 PktSize;\r
-\r
- HcDev = USB_HC_DEV_FROM_THIS (This);\r
- StatusReg = (UINT32) (USBSTS);\r
- FrameNumReg = (UINT32) (USBFRNUM);\r
- ShortPacketEnable = FALSE;\r
- Mapping = NULL;\r
- PktID = INPUT_PACKET_ID;\r
- PtrTD = NULL;\r
- PtrFirstTD = NULL;\r
- PtrPreTD = NULL;\r
- DataLen = 0;\r
- Ptr = NULL;\r
- Index = 0;\r
- LinkTimes = 0;\r
-\r
- //\r
- // Parameters Checking\r
- //\r
-\r
- if ((DataLength == NULL) ||\r
- (Data == NULL) ||\r
- (TransferResult == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // if has errors that cause host controller halt,\r
- // then return EFI_DEVICE_ERROR directly.\r
- //\r
- if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
-\r
- ClearStatusReg (HcDev->PciIo, StatusReg);\r
- *TransferResult = EFI_USB_ERR_SYSTEM;\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if ((EndPointAddress & 0x80) == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (*DataLength == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (MaximumPacketLength > 64) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (IsSlowDevice && (MaximumPacketLength > 8)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (TransferResult == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- ClearStatusReg (HcDev->PciIo, StatusReg);\r
-\r
- //\r
- // submit Sync interrupt transfer request\r
- //\r
- ShortPacketEnable = TRUE;\r
- PktID = INPUT_PACKET_ID;\r
- DataLen = *DataLength;\r
- PtrDataSource = Data;\r
-\r
- //\r
- // create QH structure and init\r
- //\r
- Status = CreateQH (HcDev, &PtrQH);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // BusMasterWrite means cpu read\r
- //\r
- Status = HcDev->PciIo->Map (\r
- HcDev->PciIo,\r
- EfiPciIoOperationBusMasterWrite,\r
- PtrDataSource,\r
- &DataLen,\r
- &TempPtr,\r
- &Mapping\r
- );\r
- if (EFI_ERROR (Status)) {\r
- UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
- return Status;\r
- }\r
-\r
- Ptr = (UINT8 *) ((UINTN) TempPtr);\r
-\r
- IsFirstTD = TRUE;\r
- while (DataLen > 0) {\r
- //\r
- // create TD structures and link together\r
- //\r
- PktSize = (UINT8) DataLen;\r
- if (DataLen > MaximumPacketLength) {\r
- PktSize = MaximumPacketLength;\r
- }\r
-\r
- Status = GenDataTD (\r
- HcDev,\r
- DeviceAddress,\r
- EndPointAddress,\r
- Ptr,\r
- PktSize,\r
- PktID,\r
- *DataToggle,\r
- IsSlowDevice,\r
- &PtrTD\r
- );\r
- if (EFI_ERROR (Status)) {\r
- UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
- HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
- DeleteQueuedTDs (HcDev, PtrFirstTD);\r
- return Status;\r
- }\r
- //\r
- // Enable short packet detection.\r
- //\r
- if (ShortPacketEnable) {\r
- EnableorDisableTDShortPacket (PtrTD, TRUE);\r
- }\r
-\r
- if (IsFirstTD) {\r
- PtrFirstTD = PtrTD;\r
- PtrFirstTD->ptrNextTD = NULL;\r
- IsFirstTD = FALSE;\r
- } else {\r
- //\r
- // Link two TDs in vertical depth\r
- //\r
- LinkTDToTD (PtrPreTD, PtrTD);\r
- }\r
-\r
- Index++;\r
-\r
- PtrPreTD = PtrTD;\r
-\r
- *DataToggle ^= 1;\r
- Ptr += PktSize;\r
- DataLen -= PktSize;\r
- }\r
-\r
- //\r
- // link TD structures to QH structure\r
- //\r
- LinkTDToQH (PtrQH, PtrFirstTD);\r
-\r
- switch (MaximumPacketLength) {\r
- case 8:\r
- LinkTimes = Index / 71 + 1;\r
- break;\r
-\r
- case 16:\r
- LinkTimes = Index / 51 + 1;\r
- break;\r
-\r
- case 32:\r
- LinkTimes = Index / 33 + 1;\r
- break;\r
-\r
- case 64:\r
- LinkTimes = Index / 19 + 1;\r
- break;\r
- }\r
-\r
- LinkTimes += 100;\r
-\r
- LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);\r
- SavedFrameListIndex = LoadFrameListIndex;\r
-\r
- for (Index = 0; Index < LinkTimes; Index++) {\r
-\r
- //\r
- // put the QH-TD directly or indirectly into the proper place\r
- // in the Frame List\r
- //\r
- LinkQHToFrameList (HcDev->FrameListEntry, LoadFrameListIndex, PtrQH);\r
-\r
- LoadFrameListIndex += 1;\r
- LoadFrameListIndex &= 0x3FF;\r
- }\r
-\r
- LoadFrameListIndex = SavedFrameListIndex;\r
- //\r
- // detail status is put into the Result field in the pIRP\r
- // the Data Toggle value is also re-updated to the value\r
- // of the last successful TD\r
- //\r
- Status = ExecBulkorSyncInterruptTransfer (\r
- HcDev,\r
- PtrFirstTD,\r
- LoadFrameListIndex,\r
- DataLength,\r
- DataToggle,\r
- TimeOut,\r
- TransferResult\r
- );\r
- //\r
- // Delete Sync Interrupt transfer QH-TD structure\r
- // and maintain the pointers in the Frame List\r
- // and other pointers in related QH structure\r
- //\r
- // TRUE means must search other framelistindex\r
- //\r
- for (Index = 0; Index <= LinkTimes; Index++) {\r
- DelLinkSingleQH (\r
- HcDev,\r
- PtrQH,\r
- LoadFrameListIndex,\r
- FALSE,\r
- FALSE\r
- );\r
- LoadFrameListIndex += 1;\r
- LoadFrameListIndex &= 0x3FF;\r
- }\r
-\r
- UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
-\r
- DeleteQueuedTDs (HcDev, PtrFirstTD);\r
-\r
- HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
-\r
- //\r
- // if has errors that cause host controller halt,\r
- // then return EFI_DEVICE_ERROR directly.\r
- //\r
- if (!IsStatusOK (HcDev->PciIo, StatusReg)) {\r
-\r
- ClearStatusReg (HcDev->PciIo, StatusReg);\r
- *TransferResult |= EFI_USB_ERR_SYSTEM;\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- ClearStatusReg (HcDev->PciIo, StatusReg);\r
-\r
- HcDev->PciIo->Flush (HcDev->PciIo);\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCIIsochronousTransfer (\r
- IN EFI_USB_HC_PROTOCOL *This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN UINT8 MaximumPacketLength,\r
- IN OUT VOID *Data,\r
- IN UINTN DataLength,\r
- OUT UINT32 *TransferResult\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Submits isochronous transfer to a target USB device.\r
-\r
- Arguments:\r
-\r
- This - A pointer to the EFI_USB_HC_PROTOCOL instance.\r
- DeviceAddress - Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
- EndPointAddress - End point address\r
- MaximumPacketLength - Indicates the maximum packet size that the\r
- default control transfer endpoint is capable of\r
- sending or receiving.\r
- Data - A pointer to the buffer of data that will be transmitted\r
- to USB device or received from USB device.\r
- DataLength - Indicates the size, in bytes, of the data buffer\r
- specified by Data.\r
- TransferResult - A pointer to the detailed result information generated\r
- by this control transfer.\r
- Returns:\r
- EFI_UNSUPPORTED\r
-\r
---*/\r
-{\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCIAsyncIsochronousTransfer (\r
- IN EFI_USB_HC_PROTOCOL * This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN UINT8 MaximumPacketLength,\r
- IN OUT VOID *Data,\r
- IN UINTN DataLength,\r
- IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
- IN VOID *Context OPTIONAL\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Submits Async isochronous transfer to a target USB device.\r
-\r
- Arguments:\r
-\r
- This - A pointer to the EFI_USB_HC_PROTOCOL instance.\r
-\r
- DeviceAddress - Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
-\r
- EndPointAddress - End point address\r
-\r
- MaximumPacketLength - Indicates the maximum packet size that the\r
- default control transfer endpoint is capable of\r
- sending or receiving.\r
-\r
- Data - A pointer to the buffer of data that will be transmitted\r
- to USB device or received from USB device.\r
-\r
- IsochronousCallBack - When the transfer complete, the call back function will be called\r
-\r
- Context - Pass to the call back function as parameter\r
-\r
- Returns:\r
- EFI_UNSUPPORTED\r
-\r
---*/\r
-{\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-//\r
-// UEFI 2.0 Protocol\r
-//\r
-EFI_STATUS\r
-EFIAPI\r
-UHCI2GetCapability(\r
- IN EFI_USB2_HC_PROTOCOL * This,\r
- OUT UINT8 *MaxSpeed,\r
- OUT UINT8 *PortNumber,\r
- OUT UINT8 *Is64BitCapable\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Retrieves capabilities of USB host controller according to UEFI 2.0 spec.\r
-\r
- Arguments:\r
- This - A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-\r
- MaxSpeed - A pointer to the max speed USB host controller supports.\r
-\r
- PortNumber - A pointer to the number of root hub ports.\r
-\r
- Is64BitCapable - A pointer to an integer to show whether USB host controller\r
- supports 64-bit memory addressing.\r
- Returns:\r
- EFI_SUCCESS\r
- The host controller capabilities were retrieved successfully.\r
- EFI_INVALID_PARAMETER\r
- MaxSpeed or PortNumber or Is64BitCapable is NULL.\r
- EFI_DEVICE_ERROR\r
- An error was encountered while attempting to retrieve the capabilities.\r
-\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
-\r
- HcDev = USB2_HC_DEV_FROM_THIS (This);\r
-\r
- if ((NULL == MaxSpeed)\r
- ||(NULL == PortNumber)\r
- || (NULL == Is64BitCapable))\r
- {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- *MaxSpeed = EFI_USB_SPEED_FULL;\r
- *Is64BitCapable = (UINT8)FALSE;\r
- return UHCIGetRootHubPortNumber(&HcDev->UsbHc, PortNumber);\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCI2Reset (\r
- IN EFI_USB2_HC_PROTOCOL * This,\r
- IN UINT16 Attributes\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Provides software reset for the USB host controller according to UEFI 2.0 spec.\r
-\r
- Arguments:\r
- This - A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-\r
- Attributes - A bit mask of the reset operation to perform.\r
- See below for a list of the supported bit mask values.\r
-\r
- #define EFI_USB_HC_RESET_GLOBAL 0x0001\r
- #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002\r
- #define EFI_USB_HC_RESET_GLOBAL _WITH_DEBUG 0x0004\r
- #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008\r
-\r
- EFI_USB_HC_RESET_GLOBAL\r
- If this bit is set, a global reset signal will be sent to the USB bus.\r
- This resets all of the USB bus logic, including the USB host\r
- controller hardware and all the devices attached on the USB bus.\r
- EFI_USB_HC_RESET_HOST_CONTROLLER\r
- If this bit is set, the USB host controller hardware will be reset.\r
- No reset signal will be sent to the USB bus.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The reset operation succeeded.\r
- EFI_INVALID_PARAMETER\r
- Attributes is not valid.\r
- EFI_UNSUPPORTED\r
- The type of reset specified by Attributes is not currently supported by the host controller hardware.\r
- EFI_ACCESS_DENIED\r
- Reset operation is rejected due to the debug port being configured and active.\r
- EFI_DEVICE_ERROR\r
- An error was encountered while attempting to perform\r
- the reset operation.\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
-\r
- HcDev = USB2_HC_DEV_FROM_THIS (This);\r
-\r
- if (Attributes==EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG || Attributes==EFI_USB_HC_RESET_HOST_WITH_DEBUG)\r
- return EFI_UNSUPPORTED;\r
-\r
- return UHCIReset(\r
- &HcDev->UsbHc,\r
- Attributes\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCI2GetState (\r
- IN EFI_USB2_HC_PROTOCOL * This,\r
- OUT EFI_USB_HC_STATE * State\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Retrieves current state of the USB host controller according to UEFI 2.0 spec.\r
-\r
- Arguments:\r
-\r
- This - A pointer to the EFI_USB_HC_PROTOCOL instance.\r
-\r
- State - A pointer to the EFI_USB_HC_STATE data structure that\r
- indicates current state of the USB host controller.\r
- Type EFI_USB_HC_STATE is defined below.\r
-\r
- typedef enum {\r
- EfiUsbHcStateHalt,\r
- EfiUsbHcStateOperational,\r
- EfiUsbHcStateSuspend,\r
- EfiUsbHcStateMaximum\r
- } EFI_USB_HC_STATE;\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The state information of the host controller was returned in State.\r
- EFI_INVALID_PARAMETER\r
- State is NULL.\r
- EFI_DEVICE_ERROR\r
- An error was encountered while attempting to retrieve the\r
- host controller's current state.\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
-\r
- HcDev = USB2_HC_DEV_FROM_THIS (This);\r
- return UHCIGetState(\r
- &HcDev->UsbHc,\r
- State\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCI2SetState (\r
- IN EFI_USB2_HC_PROTOCOL * This,\r
- IN EFI_USB_HC_STATE State\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Sets the USB host controller to a specific state according to UEFI 2.0 spec.\r
-\r
- Arguments:\r
-\r
- This - A pointer to the EFI_USB_HC_PROTOCOL instance.\r
-\r
- State - Indicates the state of the host controller that will be set.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The USB host controller was successfully placed in the state\r
- specified by State.\r
- EFI_INVALID_PARAMETER\r
- State is invalid.\r
- EFI_DEVICE_ERROR\r
- Failed to set the state specified by State due to device error.\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
-\r
- HcDev = USB2_HC_DEV_FROM_THIS (This);\r
- return UHCISetState(\r
- &HcDev->UsbHc,\r
- State\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCI2ControlTransfer (\r
- IN EFI_USB2_HC_PROTOCOL * This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 DeviceSpeed,\r
- IN UINTN MaximumPacketLength,\r
- IN EFI_USB_DEVICE_REQUEST * Request,\r
- IN EFI_USB_DATA_DIRECTION TransferDirection,\r
- IN OUT VOID *Data,\r
- IN OUT UINTN *DataLength,\r
- IN UINTN TimeOut,\r
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
- OUT UINT32 *TransferResult\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Submits control transfer to a target USB device accroding to UEFI 2.0 spec..\r
-\r
- Arguments:\r
-\r
- This - A pointer to the EFI_USB_HC_PROTOCOL instance.\r
-\r
- DeviceAddress -Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
-\r
- DeviceSpeed - Indicates transfer speed of device.\r
-\r
- MaximumPacketLength - Indicates the maximum packet size that the\r
- default control transfer endpoint is capable of\r
- sending or receiving.\r
-\r
- Request - A pointer to the USB device request that will be sent\r
- to the USB device.\r
-\r
- TransferDirection - Specifies the data direction for the transfer.\r
- There are three values available, DataIn, DataOut\r
- and NoData.\r
-\r
- Data -A pointer to the buffer of data that will be transmitted\r
- to USB device or received from USB device.\r
-\r
- DataLength - Indicates the size, in bytes, of the data buffer\r
- specified by Data.\r
-\r
- TimeOut - Indicates the maximum time, in microseconds,\r
- which the transfer is allowed to complete.\r
-\r
- TransferResult - A pointer to the detailed result information generated\r
- by this control transfer.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The control transfer was completed successfully.\r
- EFI_OUT_OF_RESOURCES\r
- The control transfer could not be completed due to a lack of resources.\r
- EFI_INVALID_PARAMETER\r
- Some parameters are invalid.\r
- EFI_TIMEOUT\r
- The control transfer failed due to timeout.\r
- EFI_DEVICE_ERROR\r
- The control transfer failed due to host controller or device error.\r
- Caller should check TranferResult for detailed error information.\r
-\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
- BOOLEAN IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
-\r
- HcDev = USB2_HC_DEV_FROM_THIS (This);\r
-\r
- return UHCIControlTransfer(\r
- &HcDev->UsbHc,\r
- DeviceAddress,\r
- IsSlowDevice,\r
- (UINT8) MaximumPacketLength,\r
- Request,\r
- TransferDirection,\r
- Data,\r
- DataLength,\r
- TimeOut,\r
- TransferResult\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCI2BulkTransfer (\r
- IN EFI_USB2_HC_PROTOCOL * This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN UINT8 DeviceSpeed,\r
- IN UINTN MaximumPacketLength,\r
- IN UINT8 DataBuffersNumber,\r
- IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
- IN OUT UINTN *DataLength,\r
- IN OUT UINT8 *DataToggle,\r
- IN UINTN TimeOut,\r
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
- OUT UINT32 *TransferResult\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Submits bulk transfer to a bulk endpoint of a USB device according to UEFI 2.0 spec.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-\r
- DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
-\r
- EndPointAddress The combination of an endpoint number and an\r
- endpoint direction of the target USB device.\r
- Each endpoint address supports data transfer in\r
- one direction except the control endpoint\r
- (whose default endpoint address is 0).\r
- It is the caller's responsibility to make sure that\r
- the EndPointAddress represents a bulk endpoint.\r
-\r
- DeviceSpeed Indicates device speed. The supported values are EFI_USB_SPEED_FULL\r
- and EFI_USB_SPEED_HIGH.\r
-\r
- MaximumPacketLength Indicates the maximum packet size the target endpoint\r
- is capable of sending or receiving.\r
-\r
- DataBuffersNumber Number of data buffers prepared for the transfer.\r
-\r
- Data Array of pointers to the buffers of data that will be transmitted\r
- to USB device or received from USB device.\r
-\r
- DataLength When input, indicates the size, in bytes, of the data buffer\r
- specified by Data. When output, indicates the actually\r
- transferred data size.\r
-\r
- DataToggle A pointer to the data toggle value. On input, it indicates\r
- the initial data toggle value the bulk transfer should adopt;\r
- on output, it is updated to indicate the data toggle value\r
- of the subsequent bulk transfer.\r
-\r
- Translator A pointr to the transaction translator data.\r
-\r
- TimeOut Indicates the maximum time, in microseconds, which the\r
- transfer is allowed to complete.\r
-\r
- TransferResult A pointer to the detailed result information of the\r
- bulk transfer.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The bulk transfer was completed successfully.\r
-\r
- EFI_OUT_OF_RESOURCES\r
- The bulk transfer could not be submitted due to lack of resource.\r
-\r
- EFI_INVALID_PARAMETER\r
- Some parameters are invalid.\r
-\r
- EFI_TIMEOUT\r
- The bulk transfer failed due to timeout.\r
-\r
- EFI_DEVICE_ERROR\r
- The bulk transfer failed due to host controller or device error.\r
- Caller should check TranferResult for detailed error information.\r
-\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
-\r
- HcDev = USB2_HC_DEV_FROM_THIS (This);\r
-\r
- if( Data == NULL || DeviceSpeed==EFI_USB_SPEED_LOW)\r
- return EFI_INVALID_PARAMETER;\r
- /* For full-speed bulk transfers only the data pointed by Data[0] shall be used */\r
-\r
- return UHCIBulkTransfer (\r
- &HcDev->UsbHc,\r
- DeviceAddress,\r
- EndPointAddress,\r
- (UINT8) MaximumPacketLength,\r
- *Data,\r
- DataLength,\r
- DataToggle,\r
- TimeOut,\r
- TransferResult\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCI2AsyncInterruptTransfer (\r
- IN EFI_USB2_HC_PROTOCOL * This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN UINT8 DeviceSpeed,\r
- IN UINTN MaximumPacketLength,\r
- IN BOOLEAN IsNewTransfer,\r
- IN OUT UINT8 *DataToggle,\r
- IN UINTN PollingInterval,\r
- IN UINTN DataLength,\r
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
- IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,\r
- IN VOID *Context\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Submits an asynchronous interrupt transfer to an\r
- interrupt endpoint of a USB device according to UEFI 2.0 spec.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-\r
- DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
-\r
- EndPointAddress The combination of an endpoint number and an endpoint\r
- direction of the target USB device. Each endpoint address\r
- supports data transfer in one direction except the\r
- control endpoint (whose default endpoint address is 0).\r
- It is the caller's responsibility to make sure that\r
- the EndPointAddress represents an interrupt endpoint.\r
-\r
- DeviceSpeed Indicates device speed.\r
-\r
- MaximumPacketLength Indicates the maximum packet size the target endpoint\r
- is capable of sending or receiving.\r
-\r
- IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between\r
- the host and the target interrupt endpoint.\r
- If FALSE, the specified asynchronous interrupt pipe\r
- is canceled.\r
-\r
- DataToggle A pointer to the data toggle value. On input, it is valid\r
- when IsNewTransfer is TRUE, and it indicates the initial\r
- data toggle value the asynchronous interrupt transfer\r
- should adopt.\r
- On output, it is valid when IsNewTransfer is FALSE,\r
- and it is updated to indicate the data toggle value of\r
- the subsequent asynchronous interrupt transfer.\r
-\r
- PollingInterval Indicates the interval, in milliseconds, that the\r
- asynchronous interrupt transfer is polled.\r
- This parameter is required when IsNewTransfer is TRUE.\r
-\r
- DataLength Indicates the length of data to be received at the\r
- rate specified by PollingInterval from the target\r
- asynchronous interrupt endpoint. This parameter\r
- is only required when IsNewTransfer is TRUE.\r
-\r
- Translator A pointr to the transaction translator data.\r
-\r
- CallBackFunction The Callback function.This function is called at the\r
- rate specified by PollingInterval.This parameter is\r
- only required when IsNewTransfer is TRUE.\r
-\r
- Context The context that is passed to the CallBackFunction.\r
- This is an optional parameter and may be NULL.\r
-\r
- Returns:\r
-\r
- EFI_SUCCESS\r
- The asynchronous interrupt transfer request has been successfully\r
- submitted or canceled.\r
-\r
- EFI_INVALID_PARAMETER\r
- Some parameters are invalid.\r
-\r
- EFI_OUT_OF_RESOURCES\r
- The request could not be completed due to a lack of resources.\r
-\r
- EFI_DEVICE_ERROR\r
- Can't read register\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
- BOOLEAN IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
-\r
- HcDev = USB2_HC_DEV_FROM_THIS (This);\r
- return UHCIAsyncInterruptTransfer(\r
- &HcDev->UsbHc,\r
- DeviceAddress,\r
- EndPointAddress,\r
- IsSlowDevice,\r
- (UINT8) MaximumPacketLength,\r
- IsNewTransfer,\r
- DataToggle,\r
- PollingInterval,\r
- DataLength,\r
- CallBackFunction,\r
- Context\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCI2SyncInterruptTransfer (\r
- IN EFI_USB2_HC_PROTOCOL * This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN UINT8 DeviceSpeed,\r
- IN UINTN MaximumPacketLength,\r
- IN OUT VOID *Data,\r
- IN OUT UINTN *DataLength,\r
- IN OUT UINT8 *DataToggle,\r
- IN UINTN TimeOut,\r
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
- OUT UINT32 *TransferResult\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Submits synchronous interrupt transfer to an interrupt endpoint\r
- of a USB device according to UEFI 2.0 spec.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-\r
- DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
-\r
- EndPointAddress The combination of an endpoint number and an endpoint\r
- direction of the target USB device. Each endpoint\r
- address supports data transfer in one direction\r
- except the control endpoint (whose default\r
- endpoint address is 0). It is the caller's responsibility\r
- to make sure that the EndPointAddress represents\r
- an interrupt endpoint.\r
-\r
- DeviceSpeed Indicates device speed.\r
-\r
- MaximumPacketLength Indicates the maximum packet size the target endpoint\r
- is capable of sending or receiving.\r
-\r
- Data A pointer to the buffer of data that will be transmitted\r
- to USB device or received from USB device.\r
-\r
- DataLength On input, the size, in bytes, of the data buffer specified\r
- by Data. On output, the number of bytes transferred.\r
-\r
- DataToggle A pointer to the data toggle value. On input, it indicates\r
- the initial data toggle value the synchronous interrupt\r
- transfer should adopt;\r
- on output, it is updated to indicate the data toggle value\r
- of the subsequent synchronous interrupt transfer.\r
-\r
- TimeOut Indicates the maximum time, in microseconds, which the\r
- transfer is allowed to complete.\r
- Translator A pointr to the transaction translator data.\r
- TransferResult A pointer to the detailed result information from\r
- the synchronous interrupt transfer.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The synchronous interrupt transfer was completed successfully.\r
- EFI_OUT_OF_RESOURCES\r
- The synchronous interrupt transfer could not be submitted due\r
- to lack of resource.\r
- EFI_INVALID_PARAMETER\r
- Some parameters are invalid.\r
- EFI_TIMEOUT\r
- The synchronous interrupt transfer failed due to timeout.\r
- EFI_DEVICE_ERROR\r
- The synchronous interrupt transfer failed due to host controller\r
- or device error. Caller should check TranferResult for detailed\r
- error information.\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
- BOOLEAN IsSlowDevice;\r
-\r
- if(DeviceSpeed==EFI_USB_SPEED_HIGH)\r
- return EFI_INVALID_PARAMETER;\r
-\r
- IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
- HcDev = USB2_HC_DEV_FROM_THIS (This);\r
-\r
- return UHCISyncInterruptTransfer(\r
- &HcDev->UsbHc,\r
- DeviceAddress,\r
- EndPointAddress,\r
- IsSlowDevice,\r
- (UINT8) MaximumPacketLength,\r
- Data,\r
- DataLength,\r
- DataToggle,\r
- TimeOut,\r
- TransferResult\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCI2IsochronousTransfer (\r
- IN EFI_USB2_HC_PROTOCOL * This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN UINT8 DeviceSpeed,\r
- IN UINTN MaximumPacketLength,\r
- IN UINT8 DataBuffersNumber,\r
- IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
- IN UINTN DataLength,\r
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
- OUT UINT32 *TransferResult\r
- )\r
-/*++\r
-\r
- Routine Description:\r
-\r
- Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-\r
- DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
-\r
- EndPointAddress End point address\r
-\r
- DeviceSpeed Indicates device speed.\r
-\r
- MaximumPacketLength Indicates the maximum packet size that the\r
- default control transfer endpoint is capable of\r
- sending or receiving.\r
-\r
- DataBuffersNumber Number of data buffers prepared for the transfer.\r
-\r
- Data Array of pointers to the buffers of data that will be\r
- transmitted to USB device or received from USB device.\r
-\r
- DataLength Indicates the size, in bytes, of the data buffer\r
- specified by Data.\r
-\r
- Translator A pointr to the transaction translator data.\r
-\r
- TransferResult A pointer to the detailed result information generated\r
- by this control transfer.\r
- Returns:\r
-\r
- EFI_UNSUPPORTED\r
-\r
---*/\r
-{\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCI2AsyncIsochronousTransfer (\r
- IN EFI_USB2_HC_PROTOCOL * This,\r
- IN UINT8 DeviceAddress,\r
- IN UINT8 EndPointAddress,\r
- IN UINT8 DeviceSpeed,\r
- IN UINTN MaximumPacketLength,\r
- IN UINT8 DataBuffersNumber,\r
- IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
- IN UINTN DataLength,\r
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
- IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
- IN VOID *Context\r
- )\r
-/*++\r
-\r
- Routine Description:\r
-\r
- Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-\r
- DeviceAddress Represents the address of the target device on the USB,\r
- which is assigned during USB enumeration.\r
-\r
- EndPointAddress End point address\r
-\r
- DeviceSpeed Indicates device speed.\r
-\r
- MaximumPacketLength Indicates the maximum packet size that the\r
- default control transfer endpoint is capable of\r
- sending or receiving.\r
-\r
- DataBuffersNumber Number of data buffers prepared for the transfer.\r
-\r
- Data Array of pointers to the buffers of data that will be transmitted\r
- to USB device or received from USB device.\r
-\r
- Translator A pointr to the transaction translator data.\r
-\r
- IsochronousCallBack When the transfer complete, the call back function will be called\r
-\r
- Context Pass to the call back function as parameter\r
-\r
- Returns:\r
-\r
- EFI_UNSUPPORTED\r
-\r
---*/\r
-{\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCI2GetRootHubPortStatus (\r
- IN EFI_USB2_HC_PROTOCOL * This,\r
- IN UINT8 PortNumber,\r
- OUT EFI_USB_PORT_STATUS * PortStatus\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB2_HC_PROTOCOL.\r
-\r
- PortNumber Specifies the root hub port from which the status\r
- is to be retrieved. This value is zero-based. For example,\r
- if a root hub has two ports, then the first port is numbered 0,\r
- and the second port is numbered 1.\r
-\r
- PortStatus A pointer to the current port status bits and\r
- port status change bits.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The status of the USB root hub port specified by PortNumber\r
- was returned in PortStatus.\r
- EFI_INVALID_PARAMETER\r
- PortNumber is invalid.\r
- EFI_DEVICE_ERROR - Can't read register\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
-\r
- HcDev = USB2_HC_DEV_FROM_THIS (This);\r
-\r
- return UHCIGetRootHubPortStatus(\r
- &HcDev->UsbHc,\r
- PortNumber,\r
- PortStatus\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCI2SetRootHubPortFeature (\r
- IN EFI_USB2_HC_PROTOCOL * This,\r
- IN UINT8 PortNumber,\r
- IN EFI_USB_PORT_FEATURE PortFeature\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Sets a feature for the specified root hub port according to UEFI 2.0 spec.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB2_HC_PROTOCOL.\r
-\r
- PortNumber Specifies the root hub port whose feature\r
- is requested to be set.\r
-\r
- PortFeature Indicates the feature selector associated\r
- with the feature set request.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The feature specified by PortFeature was set for the\r
- USB root hub port specified by PortNumber.\r
- EFI_INVALID_PARAMETER\r
- PortNumber is invalid or PortFeature is invalid.\r
- EFI_DEVICE_ERROR\r
- Can't read register\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
-\r
- HcDev = USB2_HC_DEV_FROM_THIS (This);\r
- return UHCISetRootHubPortFeature(\r
- &HcDev->UsbHc,\r
- PortNumber,\r
- PortFeature\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UHCI2ClearRootHubPortFeature (\r
- IN EFI_USB2_HC_PROTOCOL * This,\r
- IN UINT8 PortNumber,\r
- IN EFI_USB_PORT_FEATURE PortFeature\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Clears a feature for the specified root hub port according to Uefi 2.0 spec.\r
-\r
- Arguments:\r
-\r
- This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
-\r
- PortNumber Specifies the root hub port whose feature\r
- is requested to be cleared.\r
-\r
- PortFeature Indicates the feature selector associated with the\r
- feature clear request.\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- The feature specified by PortFeature was cleared for the\r
- USB root hub port specified by PortNumber.\r
- EFI_INVALID_PARAMETER\r
- PortNumber is invalid or PortFeature is invalid.\r
- EFI_DEVICE_ERROR\r
- Can't read register\r
---*/\r
-{\r
- USB_HC_DEV *HcDev;\r
-\r
- HcDev = USB2_HC_DEV_FROM_THIS (This);\r
- return UHCIClearRootHubPortFeature(\r
- &HcDev->UsbHc,\r
- PortNumber,\r
- PortFeature\r
- );\r
-}\r
-\r
-VOID\r
-EFIAPI\r
-MonitorInterruptTrans (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-/*++\r
- Routine Description:\r
- Interrupt transfer periodic check handler\r
- Arguments:\r
- Event - Interrupt event\r
- Contex - Pointer to USB_HC_DEV\r
- Returns:\r
- None\r
---*/\r
-{\r
-\r
- USB_HC_DEV *HcDev;\r
- INTERRUPT_LIST *PtrList;\r
- LIST_ENTRY *Link;\r
- UINT32 Result;\r
- VOID *DataBuffer;\r
- UINTN DataLen;\r
- UINTN ActualLen;\r
- UINTN ErrTDPos;\r
- LIST_ENTRY *NextLink;\r
-\r
- HcDev = (USB_HC_DEV *) Context;\r
-\r
- //\r
- // interrupt transfer list is empty, means that no interrupt transfer\r
- // is submitted by far.\r
- //\r
- if (IsListEmpty (&(HcDev->InterruptListHead))) {\r
- return ;\r
- }\r
-\r
- NextLink = HcDev->InterruptListHead.ForwardLink;\r
- do {\r
-\r
- Link = NextLink;\r
- NextLink = Link->ForwardLink;\r
-\r
- PtrList = INTERRUPT_LIST_FROM_LINK (Link);\r
-\r
- //\r
- // get TD execution results.\r
- // ErrTDPos is zero-based value indicating the first error TD's position\r
- // in the TDs' list.\r
- // This value is only valid when Result not equal NOERROR.\r
- //\r
- ExecuteAsyncINTTDs (\r
- HcDev,\r
- PtrList,\r
- &Result,\r
- &ErrTDPos,\r
- &ActualLen\r
- );\r
-\r
- //\r
- // interrupt transfer has not been executed yet.\r
- //\r
- if (((Result & EFI_USB_ERR_NAK) == EFI_USB_ERR_NAK) ||\r
- ((Result & EFI_USB_ERR_NOTEXECUTE) == EFI_USB_ERR_NOTEXECUTE)) {\r
- continue;\r
- }\r
- //\r
- // get actual data length transferred data and its data length.\r
- //\r
- DataLen = ActualLen;\r
- DataBuffer = AllocatePool (DataLen);\r
- if (DataBuffer == NULL) {\r
- return ;\r
- }\r
-\r
- CopyMem (\r
- DataBuffer,\r
- PtrList->PtrFirstTD->pTDBuffer,\r
- DataLen\r
- );\r
-\r
- //\r
- // only if interrupt endpoint responds\r
- // and the interrupt transfer stops because of completion\r
- // or error, then we will call callback function.\r
- //\r
- if (Result == EFI_USB_NOERROR) {\r
- //\r
- // add for real platform debug\r
- //\r
- if (PtrList->InterruptCallBack != NULL) {\r
- (PtrList->InterruptCallBack) (\r
- DataBuffer,\r
- DataLen,\r
- PtrList->InterruptContext,\r
- Result\r
- );\r
- }\r
-\r
- if (DataBuffer) {\r
- gBS->FreePool (DataBuffer);\r
- }\r
-\r
- //\r
- // update should done after data buffer got.\r
- //\r
- UpdateAsyncINTQHTDs (PtrList, Result, (UINT32) ErrTDPos);\r
-\r
- } else {\r
-\r
- DEBUG ((EFI_D_ERROR, "interrupt transfer error code is %x\n", Result));\r
-\r
- if (DataBuffer) {\r
- gBS->FreePool (DataBuffer);\r
- }\r
- //\r
- // leave error recovery to its related device driver.\r
- // A common case of the error recovery is to re-submit the interrupt\r
- // transfer.\r
- // When an interrupt transfer is re-submitted, its position in the linked\r
- // list is changed. It is inserted to the head of the linked list, while\r
- // this function scans the whole list from head to tail. Thus, the\r
- // re-submitted interrupt transfer's callback function will not be called\r
- // again in this round.\r
- //\r
- if (PtrList->InterruptCallBack != NULL) {\r
- (PtrList->InterruptCallBack) (\r
- NULL,\r
- 0,\r
- PtrList->InterruptContext,\r
- Result\r
- );\r
- }\r
- }\r
- } while (NextLink != &(HcDev->InterruptListHead));\r
-\r
-}\r