Changed old event definitions reference to these new event definitions. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2729 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			3720 lines
		
	
	
		
			106 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3720 lines
		
	
	
		
			106 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| Copyright (c) 2006, Intel Corporation
 | |
| All rights reserved. This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
|   Module Name:
 | |
| 
 | |
|     UsbBus.c
 | |
| 
 | |
|   Abstract:
 | |
| 
 | |
|     USB Bus Driver
 | |
| 
 | |
|   Revision History
 | |
| 
 | |
| --*/
 | |
| 
 | |
| #include "usbbus.h"
 | |
| 
 | |
| 
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED    UINTN    gUSBDebugLevel  = EFI_D_INFO;
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED    UINTN    gUSBErrorLevel  = EFI_D_ERROR;
 | |
| 
 | |
| //
 | |
| // The UsbBusProtocol is just used to locate USB_BUS_CONTROLLER
 | |
| // structure in the UsbBusDriverControllerDriverStop(). Then we can
 | |
| // Close all opened protocols and release this structure.
 | |
| //
 | |
| STATIC EFI_GUID             mUsbBusProtocolGuid = EFI_USB_BUS_PROTOCOL_GUID;
 | |
| 
 | |
| EFI_DRIVER_BINDING_PROTOCOL gUsbBusDriverBinding = {
 | |
|   UsbBusControllerDriverSupported,
 | |
|   UsbBusControllerDriverStart,
 | |
|   UsbBusControllerDriverStop,
 | |
|   0xa,
 | |
|   NULL,
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| //
 | |
| // Internal use only
 | |
| //
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ReportUsbStatusCode (
 | |
|   IN USB_BUS_CONTROLLER_DEVICE     *UsbBusController,
 | |
|   IN EFI_STATUS_CODE_TYPE          Type,
 | |
|   IN EFI_STATUS_CODE_VALUE         Code
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| USB_IO_CONTROLLER_DEVICE    *
 | |
| CreateUsbIoControllerDevice (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| InitUsbIoController (
 | |
|   IN USB_IO_CONTROLLER_DEVICE     *UsbIoController
 | |
|   );
 | |
| 
 | |
| //
 | |
| // USB Device Configuration / Deconfiguration
 | |
| //
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| UsbDeviceConfiguration (
 | |
|   IN USB_IO_CONTROLLER_DEVICE     *ParentHubController,
 | |
|   IN EFI_HANDLE                   HostController,
 | |
|   IN UINT8                        ParentPort,
 | |
|   IN USB_IO_DEVICE                *UsbIoDevice
 | |
|   );
 | |
| 
 | |
| //
 | |
| // Usb Bus enumeration function
 | |
| //
 | |
| STATIC
 | |
| VOID
 | |
| RootHubEnumeration (
 | |
|   IN EFI_EVENT     Event,
 | |
|   IN VOID          *Context
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| VOID
 | |
| HubEnumeration (
 | |
|   IN EFI_EVENT     Event,
 | |
|   IN VOID          *Context
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| UsbSetTransactionTranslator (
 | |
|   IN USB_IO_CONTROLLER_DEVICE     *ParentHubController,
 | |
|   IN UINT8                        ParentPort,
 | |
|   IN OUT USB_IO_DEVICE            *Device
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| UsbUnsetTransactionTranslator (
 | |
|   USB_IO_DEVICE *Device
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| IdentifyDeviceSpeed (
 | |
|   USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
 | |
|   USB_IO_DEVICE             *NewDevice,
 | |
|   UINT8                     Index
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ReleasePortToCHC (
 | |
|   USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
 | |
|   UINT8                     PortNum
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ResetRootPort (
 | |
|   IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
 | |
|   IN UINT8                     PortNum,
 | |
|   IN UINT8                     RetryTimes
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ResetHubPort (
 | |
|   IN USB_IO_CONTROLLER_DEVICE    *UsbIoController,
 | |
|   IN UINT8                       PortIndex
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ParentPortReset (
 | |
|   IN USB_IO_CONTROLLER_DEVICE    *UsbIoController,
 | |
|   IN BOOLEAN                     ReConfigure,
 | |
|   IN UINT8                       RetryTimes
 | |
|   );
 | |
| 
 | |
| //
 | |
| // Following are address allocate and free functions
 | |
| //
 | |
| STATIC
 | |
| UINT8
 | |
| UsbAllocateAddress (
 | |
|   IN UINT8    *AddressPool
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Allocate address for usb device
 | |
| 
 | |
|   Arguments:
 | |
|    AddressPool - Pool of usb device address
 | |
| 
 | |
|   Returns:
 | |
|    Usb device address
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINT8 ByteIndex;
 | |
|   UINT8 BitIndex;
 | |
| 
 | |
|   for (ByteIndex = 0; ByteIndex < 16; ByteIndex++) {
 | |
|     for (BitIndex = 0; BitIndex < 8; BitIndex++) {
 | |
|       if ((AddressPool[ByteIndex] & (1 << BitIndex)) == 0) {
 | |
|         //
 | |
|         // Found one, covert to address, and mark it use
 | |
|         //
 | |
|         AddressPool[ByteIndex] = (UINT8) (AddressPool[ByteIndex] | (1 << BitIndex));
 | |
|         return (UINT8) (ByteIndex * 8 + BitIndex);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| 
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| VOID
 | |
| UsbFreeAddress (
 | |
|   IN UINT8     DevAddress,
 | |
|   IN UINT8     *AddressPool
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Free address for usb device
 | |
| 
 | |
|   Arguments:
 | |
|    DevAddress  - Usb device address
 | |
|    AddressPool - Pool of usb device address
 | |
| 
 | |
|   Returns:
 | |
|    VOID
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINT8 WhichByte;
 | |
|   UINT8 WhichBit;
 | |
|   //
 | |
|   // Locate the position
 | |
|   //
 | |
|   WhichByte = (UINT8) (DevAddress / 8);
 | |
|   WhichBit  = (UINT8) (DevAddress & 0x7);
 | |
| 
 | |
|   AddressPool[WhichByte] = (UINT8) (AddressPool[WhichByte] & (~(1 << WhichBit)));
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbBusControllerDriverSupported (
 | |
|   IN EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN EFI_HANDLE                      Controller,
 | |
|   IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Test to see if this driver supports ControllerHandle. Any ControllerHandle
 | |
|     that has UsbHcProtocol installed will be supported.
 | |
| 
 | |
|   Arguments:
 | |
|     This                - Protocol instance pointer.
 | |
|     Controller          - Handle of device to test
 | |
|     RemainingDevicePath - Device Path Protocol instance pointer
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS         - This driver supports this device.
 | |
|     EFI_UNSUPPORTED     - This driver does not support this device.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                 Status;
 | |
|   EFI_DEVICE_PATH_PROTOCOL   *ParentDevicePath;
 | |
|   EFI_USB2_HC_PROTOCOL       *Usb2Hc;
 | |
|   EFI_USB_HC_PROTOCOL        *UsbHc;
 | |
|   EFI_DEV_PATH_PTR           Node;
 | |
| 
 | |
|   //
 | |
|   // Check Device Path
 | |
|   //
 | |
|   if (RemainingDevicePath != NULL) {
 | |
|     Node.DevPath = RemainingDevicePath;
 | |
|     if (Node.DevPath->Type != MESSAGING_DEVICE_PATH ||
 | |
|         Node.DevPath->SubType != MSG_USB_DP         ||
 | |
|         DevicePathNodeLength(Node.DevPath) != sizeof(USB_DEVICE_PATH)) {
 | |
|       return EFI_UNSUPPORTED;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Open the IO Abstraction(s) needed to perform the supported test
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Controller,
 | |
|                   &gEfiDevicePathProtocolGuid,
 | |
|                   (VOID **) &ParentDevicePath,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Controller,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
|   if (Status == EFI_ALREADY_STARTED) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   gBS->CloseProtocol (
 | |
|          Controller,
 | |
|          &gEfiDevicePathProtocolGuid,
 | |
|          This->DriverBindingHandle,
 | |
|          Controller
 | |
|          );
 | |
| 
 | |
|   //
 | |
|   // Check whether USB Host Controller Protocol is already
 | |
|   // installed on this handle. If it is installed, we can start
 | |
|   // USB Bus Driver now.
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Controller,
 | |
|                   &gEfiUsb2HcProtocolGuid,
 | |
|                   (VOID **) &Usb2Hc,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Controller,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
|   if (Status == EFI_ALREADY_STARTED) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = gBS->OpenProtocol (
 | |
|                     Controller,
 | |
|                     &gEfiUsbHcProtocolGuid,
 | |
|                     (VOID **) &UsbHc,
 | |
|                     This->DriverBindingHandle,
 | |
|                     Controller,
 | |
|                     EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                     );
 | |
|     if (Status == EFI_ALREADY_STARTED) {
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     gBS->CloseProtocol (
 | |
|       Controller,
 | |
|       &gEfiUsbHcProtocolGuid,
 | |
|       This->DriverBindingHandle,
 | |
|       Controller
 | |
|       );
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   gBS->CloseProtocol (
 | |
|     Controller,
 | |
|     &gEfiUsb2HcProtocolGuid,
 | |
|     This->DriverBindingHandle,
 | |
|     Controller
 | |
|     );
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbBusControllerDriverStart (
 | |
|   IN EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN EFI_HANDLE                      Controller,
 | |
|   IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Starting the Usb Bus Driver
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     This                - Protocol instance pointer.
 | |
|     Controller          - Handle of device to test
 | |
|     RemainingDevicePath - Not used
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS         - This driver supports this device.
 | |
|     EFI_DEVICE_ERROR    - This driver cannot be started due to device
 | |
|     EFI_OUT_OF_RESOURCES- Can't allocate memory resources
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   EFI_STATUS                OpenStatus;
 | |
|   USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
 | |
|   USB_IO_DEVICE             *RootHub;
 | |
|   USB_IO_CONTROLLER_DEVICE  *RootHubController;
 | |
|   UINT8                     MaxSpeed;
 | |
|   UINT8                     PortNumber;
 | |
|   UINT8                     Is64BitCapable;
 | |
| 
 | |
|   //
 | |
|   // Allocate USB_BUS_CONTROLLER_DEVICE structure
 | |
|   //
 | |
|   UsbBusDev = NULL;
 | |
|   UsbBusDev = AllocateZeroPool (sizeof (USB_BUS_CONTROLLER_DEVICE));
 | |
|   if (UsbBusDev == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   UsbBusDev->Signature      = USB_BUS_DEVICE_SIGNATURE;
 | |
|   UsbBusDev->AddressPool[0] = 1;
 | |
| 
 | |
|   //
 | |
|   // Get the Device Path Protocol on Controller's handle
 | |
|   //
 | |
|   OpenStatus = gBS->OpenProtocol (
 | |
|                       Controller,
 | |
|                       &gEfiDevicePathProtocolGuid,
 | |
|                       (VOID **) &UsbBusDev->DevicePath,
 | |
|                       This->DriverBindingHandle,
 | |
|                       Controller,
 | |
|                       EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                       );
 | |
| 
 | |
|   if (EFI_ERROR (OpenStatus)) {
 | |
|     gBS->FreePool (UsbBusDev);
 | |
|     return OpenStatus;
 | |
|   }
 | |
|   //
 | |
|   // Locate the Host Controller Interface
 | |
|   //
 | |
|   OpenStatus = gBS->OpenProtocol (
 | |
|                       Controller,
 | |
|                       &gEfiUsb2HcProtocolGuid,
 | |
|                       (VOID **) &(UsbBusDev->Usb2HCInterface),
 | |
|                       This->DriverBindingHandle,
 | |
|                       Controller,
 | |
|                       EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                       );
 | |
|   if (EFI_ERROR (OpenStatus)) {
 | |
| 
 | |
|     UsbBusDev->Hc2ProtocolSupported = FALSE;
 | |
|     OpenStatus = gBS->OpenProtocol (
 | |
|                         Controller,
 | |
|                         &gEfiUsbHcProtocolGuid,
 | |
|                         (VOID **) &(UsbBusDev->UsbHCInterface),
 | |
|                         This->DriverBindingHandle,
 | |
|                         Controller,
 | |
|                         EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                         );
 | |
|     if (EFI_ERROR (OpenStatus)) {
 | |
|       //
 | |
|       // Report Status Code here since we will reset the host controller
 | |
|       //
 | |
|       REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | |
|         EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | |
|         EFI_IO_BUS_USB | EFI_IOB_EC_CONTROLLER_ERROR,
 | |
|         UsbBusDev->DevicePath
 | |
|         );
 | |
| 
 | |
|       gBS->CloseProtocol (
 | |
|              Controller,
 | |
|              &gEfiDevicePathProtocolGuid,
 | |
|              This->DriverBindingHandle,
 | |
|              Controller
 | |
|              );
 | |
|       gBS->FreePool (UsbBusDev);
 | |
|       return OpenStatus;
 | |
|     }
 | |
| 
 | |
|     DEBUG ((gUSBDebugLevel, "UsbHcProtocol Opened.\n"));
 | |
|   } else {
 | |
|     DEBUG ((gUSBDebugLevel, "Usb2HcProtocol Opened.\n"));
 | |
|     UsbBusDev->Hc2ProtocolSupported = TRUE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Attach EFI_USB_BUS_PROTOCOL to controller handle,
 | |
|   // for locate UsbBusDev later
 | |
|   //
 | |
|   Status = gBS->InstallProtocolInterface (
 | |
|                   &Controller,
 | |
|                   &mUsbBusProtocolGuid,
 | |
|                   EFI_NATIVE_INTERFACE,
 | |
|                   &UsbBusDev->BusIdentify
 | |
|                   );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
| 
 | |
|     gBS->CloseProtocol (
 | |
|            Controller,
 | |
|            &gEfiDevicePathProtocolGuid,
 | |
|            This->DriverBindingHandle,
 | |
|            Controller
 | |
|            );
 | |
|     if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|       gBS->CloseProtocol (
 | |
|              Controller,
 | |
|              &gEfiUsb2HcProtocolGuid,
 | |
|              This->DriverBindingHandle,
 | |
|              Controller
 | |
|              );
 | |
|     } else {
 | |
|       gBS->CloseProtocol (
 | |
|              Controller,
 | |
|              &gEfiUsbHcProtocolGuid,
 | |
|              This->DriverBindingHandle,
 | |
|              Controller
 | |
|              );
 | |
|     }
 | |
| 
 | |
|     gBS->FreePool (UsbBusDev);
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Add root hub to the tree
 | |
|   //
 | |
|   RootHub = NULL;
 | |
|   RootHub = AllocateZeroPool (sizeof (USB_IO_DEVICE));
 | |
|   if (RootHub == NULL) {
 | |
|     gBS->UninstallProtocolInterface (
 | |
|            Controller,
 | |
|            &mUsbBusProtocolGuid,
 | |
|            &UsbBusDev->BusIdentify
 | |
|            );
 | |
|     gBS->CloseProtocol (
 | |
|            Controller,
 | |
|            &gEfiDevicePathProtocolGuid,
 | |
|            This->DriverBindingHandle,
 | |
|            Controller
 | |
|            );
 | |
|     if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|       gBS->CloseProtocol (
 | |
|              Controller,
 | |
|              &gEfiUsb2HcProtocolGuid,
 | |
|              This->DriverBindingHandle,
 | |
|              Controller
 | |
|              );
 | |
|     } else {
 | |
|       gBS->CloseProtocol (
 | |
|              Controller,
 | |
|              &gEfiUsbHcProtocolGuid,
 | |
|              This->DriverBindingHandle,
 | |
|              Controller
 | |
|              );
 | |
|     }
 | |
| 
 | |
|     gBS->FreePool (UsbBusDev);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   RootHub->BusController  = UsbBusDev;
 | |
|   RootHub->DeviceAddress  = UsbAllocateAddress (UsbBusDev->AddressPool);
 | |
| 
 | |
|   UsbBusDev->Root         = RootHub;
 | |
| 
 | |
|   //
 | |
|   // Allocate Root Hub Controller
 | |
|   //
 | |
|   RootHubController = CreateUsbIoControllerDevice ();
 | |
|   if (RootHubController == NULL) {
 | |
|     gBS->UninstallProtocolInterface (
 | |
|            Controller,
 | |
|            &mUsbBusProtocolGuid,
 | |
|            &UsbBusDev->BusIdentify
 | |
|            );
 | |
|     gBS->CloseProtocol (
 | |
|            Controller,
 | |
|            &gEfiDevicePathProtocolGuid,
 | |
|            This->DriverBindingHandle,
 | |
|            Controller
 | |
|            );
 | |
|     if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|       gBS->CloseProtocol (
 | |
|              Controller,
 | |
|              &gEfiUsb2HcProtocolGuid,
 | |
|              This->DriverBindingHandle,
 | |
|              Controller
 | |
|              );
 | |
|     } else {
 | |
|       gBS->CloseProtocol (
 | |
|              Controller,
 | |
|              &gEfiUsbHcProtocolGuid,
 | |
|              This->DriverBindingHandle,
 | |
|              Controller
 | |
|              );
 | |
|     }
 | |
|     gBS->FreePool (UsbBusDev);
 | |
|     gBS->FreePool (RootHub);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   UsbVirtualHcGetCapability (
 | |
|     UsbBusDev,
 | |
|     &MaxSpeed,
 | |
|     &PortNumber,
 | |
|     &Is64BitCapable
 | |
|     );
 | |
|   RootHubController->DownstreamPorts  = PortNumber;
 | |
|   RootHubController->UsbDevice        = RootHub;
 | |
|   RootHubController->IsUsbHub         = TRUE;
 | |
|   RootHubController->DevicePath       = UsbBusDev->DevicePath;
 | |
|   RootHubController->HostController   = Controller;
 | |
| 
 | |
|   RootHub->NumOfControllers           = 1;
 | |
|   RootHub->UsbController[0]           = RootHubController;
 | |
|   RootHub->DeviceSpeed                = MaxSpeed;
 | |
| 
 | |
|   //
 | |
|   // Report Status Code here since we will reset the host controller
 | |
|   //
 | |
|   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | |
|     EFI_PROGRESS_CODE,
 | |
|     EFI_IO_BUS_USB | EFI_IOB_PC_RESET,
 | |
|     UsbBusDev->DevicePath
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Reset USB Host Controller
 | |
|   //
 | |
|   UsbVirtualHcReset (
 | |
|     UsbBusDev,
 | |
|     EFI_USB_HC_RESET_GLOBAL
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Report Status Code while we are going to bring up the Host Controller
 | |
|   // and start bus enumeration
 | |
|   //
 | |
|   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | |
|     EFI_PROGRESS_CODE,
 | |
|     EFI_IO_BUS_USB | EFI_IOB_PC_ENABLE,
 | |
|     UsbBusDev->DevicePath
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Start USB Host Controller
 | |
|   //
 | |
|   UsbVirtualHcSetState (
 | |
|     UsbBusDev,
 | |
|     EfiUsbHcStateOperational
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Create a timer to query root ports periodically
 | |
|   //
 | |
|   Status = gBS->CreateEvent (
 | |
|                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
 | |
|                   TPL_CALLBACK,
 | |
|                   RootHubEnumeration,
 | |
|                   RootHubController,
 | |
|                   &RootHubController->HubNotify
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     gBS->UninstallProtocolInterface (
 | |
|            Controller,
 | |
|            &mUsbBusProtocolGuid,
 | |
|            &UsbBusDev->BusIdentify
 | |
|            );
 | |
| 
 | |
|     gBS->CloseProtocol (
 | |
|            Controller,
 | |
|            &gEfiDevicePathProtocolGuid,
 | |
|            This->DriverBindingHandle,
 | |
|            Controller
 | |
|            );
 | |
| 
 | |
|     if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|       gBS->CloseProtocol (
 | |
|              Controller,
 | |
|              &gEfiUsb2HcProtocolGuid,
 | |
|              This->DriverBindingHandle,
 | |
|              Controller
 | |
|              );
 | |
|     } else {
 | |
|       gBS->CloseProtocol (
 | |
|              Controller,
 | |
|              &gEfiUsbHcProtocolGuid,
 | |
|              This->DriverBindingHandle,
 | |
|              Controller
 | |
|              );
 | |
|     }
 | |
| 
 | |
|     gBS->FreePool (RootHubController);
 | |
|     gBS->FreePool (RootHub);
 | |
|     gBS->FreePool (UsbBusDev);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Before depending on the timer to check root ports periodically,
 | |
|   // here we should check them immediately for the first time, or
 | |
|   // there will be an interval between bus start and devices start.
 | |
|   //
 | |
|   gBS->SignalEvent (RootHubController->HubNotify);
 | |
| 
 | |
|   Status = gBS->SetTimer (
 | |
|                   RootHubController->HubNotify,
 | |
|                   TimerPeriodic,
 | |
|                   BUSPOLLING_PERIOD
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     gBS->UninstallProtocolInterface (
 | |
|            Controller,
 | |
|            &mUsbBusProtocolGuid,
 | |
|            &UsbBusDev->BusIdentify
 | |
|            );
 | |
| 
 | |
|     gBS->CloseProtocol (
 | |
|            Controller,
 | |
|            &gEfiDevicePathProtocolGuid,
 | |
|            This->DriverBindingHandle,
 | |
|            Controller
 | |
|            );
 | |
| 
 | |
|     if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|       gBS->CloseProtocol (
 | |
|              Controller,
 | |
|              &gEfiUsb2HcProtocolGuid,
 | |
|              This->DriverBindingHandle,
 | |
|              Controller
 | |
|              );
 | |
|     } else {
 | |
|       gBS->CloseProtocol (
 | |
|              Controller,
 | |
|              &gEfiUsbHcProtocolGuid,
 | |
|              This->DriverBindingHandle,
 | |
|              Controller
 | |
|              );
 | |
|     }
 | |
| 
 | |
|     gBS->CloseEvent (RootHubController->HubNotify);
 | |
|     gBS->FreePool (RootHubController);
 | |
|     gBS->FreePool (RootHub);
 | |
|     gBS->FreePool (UsbBusDev);
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| //
 | |
| // Stop the bus controller
 | |
| //
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbBusControllerDriverStop (
 | |
|   IN EFI_DRIVER_BINDING_PROTOCOL     *This,
 | |
|   IN EFI_HANDLE                      Controller,
 | |
|   IN UINTN                           NumberOfChildren,
 | |
|   IN EFI_HANDLE                      *ChildHandleBuffer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Stop this driver on ControllerHandle. Support stoping any child handles
 | |
|     created by this driver.
 | |
| 
 | |
|   Arguments:
 | |
|     This              - Protocol instance pointer.
 | |
|     Controller        - Handle of device to stop driver on
 | |
|     NumberOfChildren  - Number of Children in the ChildHandleBuffer
 | |
|     ChildHandleBuffer - List of handles for the children we need to stop.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_DEVICE_ERROR
 | |
|     others
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   USB_IO_DEVICE             *Root;
 | |
|   USB_IO_CONTROLLER_DEVICE  *RootHubController;
 | |
|   USB_BUS_CONTROLLER_DEVICE *UsbBusController;
 | |
|   EFI_USB_BUS_PROTOCOL      *UsbIdentifier;
 | |
|   UINT8                     Index2;
 | |
|   USB_IO_CONTROLLER_DEVICE  *UsbController;
 | |
|   USB_IO_DEVICE             *UsbIoDevice;
 | |
|   USB_IO_CONTROLLER_DEVICE  *HubController;
 | |
|   UINTN                     Index;
 | |
|   EFI_USB_IO_PROTOCOL       *UsbIo;
 | |
| 
 | |
|   if (NumberOfChildren > 0) {
 | |
| 
 | |
|     for (Index = 0; Index < NumberOfChildren; Index++) {
 | |
|       Status = gBS->OpenProtocol (
 | |
|                       ChildHandleBuffer[Index],
 | |
|                       &gEfiUsbIoProtocolGuid,
 | |
|                       (VOID **) &UsbIo,
 | |
|                       This->DriverBindingHandle,
 | |
|                       Controller,
 | |
|                       EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                       );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         //
 | |
|         // We are here since the handle passed in does not support
 | |
|         // UsbIo protocol. There are several reasons that will cause
 | |
|         // this.
 | |
|         // For combo device such as keyboard, it may have 2 devices
 | |
|         // in one, namely, keyboard and mouse. If we deconfigure one
 | |
|         // of them, the other will be freed at the same time. This will
 | |
|         // cause the status error. But this is the correct behavior.
 | |
|         // For hub device, if we deconfigure hub first, the other chile
 | |
|         // device will be disconnected also, this will also provide us
 | |
|         // a status error. Now we will only report EFI_SUCCESS since Uhc
 | |
|         // driver will be disconnected at the second time.(pls see
 | |
|         // CoreDisconnectController for details)
 | |
|         //
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       UsbController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (UsbIo);
 | |
|       UsbIoDevice   = UsbController->UsbDevice;
 | |
|       HubController = UsbController->Parent;
 | |
|       UsbDeviceDeConfiguration (UsbIoDevice);
 | |
|       for (Index2 = 0; Index2 < HubController->DownstreamPorts; Index2++) {
 | |
|         if (HubController->Children[Index2] == UsbIoDevice) {
 | |
|           HubController->Children[Index2] = NULL;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
|   //
 | |
|   // Get the USB_BUS_CONTROLLER_DEVICE
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Controller,
 | |
|                   &mUsbBusProtocolGuid,
 | |
|                   (VOID **) &UsbIdentifier,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Controller,
 | |
|                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                   );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   UsbBusController = USB_BUS_CONTROLLER_DEVICE_FROM_THIS (UsbIdentifier);
 | |
| 
 | |
|   //
 | |
|   // Stop USB Host Controller
 | |
|   //
 | |
| 
 | |
|   //
 | |
|   // Report Status Code here since we will reset the host controller
 | |
|   //
 | |
|   ReportUsbStatusCode (
 | |
|     UsbBusController,
 | |
|     EFI_PROGRESS_CODE,
 | |
|     EFI_IO_BUS_USB | EFI_IOB_PC_RESET
 | |
|     );
 | |
| 
 | |
|   UsbVirtualHcSetState (
 | |
|     UsbBusController,
 | |
|     EfiUsbHcStateHalt
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Deconfiguration all its devices
 | |
|   //
 | |
|   Root              = UsbBusController->Root;
 | |
|   RootHubController = Root->UsbController[0];
 | |
| 
 | |
|   gBS->CloseEvent (RootHubController->HubNotify);
 | |
| 
 | |
|   for (Index2 = 0; Index2 < RootHubController->DownstreamPorts; Index2++) {
 | |
|     if (RootHubController->Children[Index2]) {
 | |
|       UsbDeviceDeConfiguration (RootHubController->Children[Index2]);
 | |
|       RootHubController->Children[Index2] = NULL;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   gBS->FreePool (RootHubController);
 | |
|   gBS->FreePool (Root);
 | |
| 
 | |
|   //
 | |
|   // Uninstall USB Bus Protocol
 | |
|   //
 | |
|   gBS->UninstallProtocolInterface (
 | |
|         Controller,
 | |
|         &mUsbBusProtocolGuid,
 | |
|         &UsbBusController->BusIdentify
 | |
|         );
 | |
| 
 | |
|   //
 | |
|   // Close USB_HC_PROTOCOL & DEVICE_PATH_PROTOCOL
 | |
|   // Opened by this Controller
 | |
|   //
 | |
|   if (UsbBusController->Hc2ProtocolSupported) {
 | |
|     gBS->CloseProtocol (
 | |
|           Controller,
 | |
|           &gEfiUsb2HcProtocolGuid,
 | |
|           This->DriverBindingHandle,
 | |
|           Controller
 | |
|           );
 | |
|   } else {
 | |
|     gBS->CloseProtocol (
 | |
|           Controller,
 | |
|           &gEfiUsbHcProtocolGuid,
 | |
|           This->DriverBindingHandle,
 | |
|           Controller
 | |
|           );
 | |
|   }
 | |
| 
 | |
|   gBS->CloseProtocol (
 | |
|         Controller,
 | |
|         &gEfiDevicePathProtocolGuid,
 | |
|         This->DriverBindingHandle,
 | |
|         Controller
 | |
|         );
 | |
| 
 | |
|   gBS->FreePool (UsbBusController);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| //
 | |
| // USB Device Configuration
 | |
| //
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| UsbDeviceConfiguration (
 | |
|   IN USB_IO_CONTROLLER_DEVICE     *ParentHubController,
 | |
|   IN EFI_HANDLE                   HostController,
 | |
|   IN UINT8                        ParentPort,
 | |
|   IN USB_IO_DEVICE                *UsbIoDevice
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Configurate a new device attached to the usb bus
 | |
| 
 | |
|   Arguments:
 | |
|     ParentHubController   -   Parent Hub which this device is connected.
 | |
|     HostController        -   Host Controller handle
 | |
|     ParentPort            -   Parent Hub port which this device is connected.
 | |
|     UsbIoDevice           -   The device to be configured.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_DEVICE_ERROR
 | |
|     EFI_OUT_OF_RESOURCES
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINT8                     DevAddress;
 | |
|   UINT8                     Index;
 | |
|   EFI_STATUS                Result;
 | |
|   UINT32                    Status;
 | |
|   CHAR16                    *StrManufacturer;
 | |
|   CHAR16                    *StrProduct;
 | |
|   CHAR16                    *StrSerialNumber;
 | |
|   EFI_USB_IO_PROTOCOL       *UsbIo;
 | |
|   UINT8                     NumOfInterface;
 | |
|   USB_IO_CONTROLLER_DEVICE  *FirstController;
 | |
|   USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
 | |
|   USB_IO_CONTROLLER_DEVICE  *UsbIoController;
 | |
| 
 | |
|   UsbBusDev = UsbIoDevice->BusController;
 | |
| 
 | |
|   UsbSetTransactionTranslator (
 | |
|     ParentHubController,
 | |
|     ParentPort,
 | |
|     UsbIoDevice
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Since a USB device must have at least on interface,
 | |
|   // so create this instance first
 | |
|   //
 | |
|   FirstController                   = CreateUsbIoControllerDevice ();
 | |
|   FirstController->UsbDevice        = UsbIoDevice;
 | |
|   UsbIoDevice->UsbController[0]     = FirstController;
 | |
|   FirstController->InterfaceNumber  = 0;
 | |
|   FirstController->ParentPort       = ParentPort;
 | |
|   FirstController->Parent           = ParentHubController;
 | |
|   FirstController->HostController   = HostController;
 | |
| 
 | |
|   InitializeUsbIoInstance (FirstController);
 | |
| 
 | |
|   DEBUG ((gUSBDebugLevel, "Configuration Usb Device at 0x%x...\n", ParentPort));
 | |
| 
 | |
|   //
 | |
|   // Ensure we used the correctly USB I/O instance
 | |
|   //
 | |
|   UsbIo = &FirstController->UsbIo;
 | |
| 
 | |
|   if (UsbIoDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {
 | |
|     ParentPortReset (FirstController, FALSE, 0);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // First retrieve the 1st 8 bytes of
 | |
|   // in order to get the MaxPacketSize for Endpoint 0
 | |
|   //
 | |
|   for (Index = 0; Index < 3; Index++) {
 | |
| 
 | |
|     UsbIoDevice->DeviceDescriptor.MaxPacketSize0 = 8;
 | |
| 
 | |
|     gBS->Stall (100 * 1000);
 | |
| 
 | |
|     Result = UsbGetDescriptor (
 | |
|               UsbIo,
 | |
|               (USB_DT_DEVICE << 8),
 | |
|               0,
 | |
|               8,
 | |
|               &UsbIoDevice->DeviceDescriptor,
 | |
|               &Status
 | |
|               );
 | |
|     if (!EFI_ERROR (Result)) {
 | |
|       DEBUG (
 | |
|         (gUSBDebugLevel,
 | |
|         "Get Device Descriptor Success, MaxPacketSize0 = 0x%x\n",
 | |
|         UsbIoDevice->DeviceDescriptor.MaxPacketSize0)
 | |
|         );
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|   }
 | |
| 
 | |
|   if (Index == 3) {
 | |
|     ReportUsbStatusCode (
 | |
|       UsbBusDev,
 | |
|       EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | |
|       EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR
 | |
|       );
 | |
|     DEBUG ((gUSBErrorLevel, "Get Device Descriptor Fail when configing\n"));
 | |
|     gBS->FreePool (FirstController);
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   DevAddress = UsbAllocateAddress (UsbIoDevice->BusController->AddressPool);
 | |
|   if (DevAddress == 0) {
 | |
|     DEBUG ((gUSBErrorLevel, "Cannot allocate address\n"));
 | |
|     gBS->FreePool (FirstController);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Result = UsbSetDeviceAddress (UsbIo, DevAddress, &Status);
 | |
| 
 | |
|   if (EFI_ERROR (Result)) {
 | |
|     DEBUG ((gUSBErrorLevel, "Set address error\n"));
 | |
|     ReportUsbStatusCode (
 | |
|       UsbBusDev,
 | |
|       EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | |
|       EFI_IO_BUS_USB | EFI_IOB_EC_WRITE_ERROR
 | |
|       );
 | |
| 
 | |
|     UsbFreeAddress (
 | |
|       DevAddress,
 | |
|       UsbIoDevice->BusController->AddressPool
 | |
|       );
 | |
| 
 | |
|     gBS->FreePool (FirstController);
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   UsbIoDevice->DeviceAddress = DevAddress;
 | |
| 
 | |
|   //
 | |
|   // SetAddress Complete Time by Spec, Max 50ms
 | |
|   //
 | |
|   gBS->Stall (10 * 1000);
 | |
| 
 | |
|   //
 | |
|   // Get the whole device descriptor
 | |
|   //
 | |
|   Result = UsbGetDescriptor (
 | |
|             UsbIo,
 | |
|             (USB_DT_DEVICE << 8),
 | |
|             0,
 | |
|             sizeof (EFI_USB_DEVICE_DESCRIPTOR),
 | |
|             &UsbIoDevice->DeviceDescriptor,
 | |
|             &Status
 | |
|             );
 | |
| 
 | |
|   if (EFI_ERROR (Result)) {
 | |
|     DEBUG ((gUSBErrorLevel, "Get whole Device Descriptor error\n"));
 | |
|     ReportUsbStatusCode (
 | |
|       UsbBusDev,
 | |
|       EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | |
|       EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR
 | |
|       );
 | |
|     UsbFreeAddress (
 | |
|       DevAddress,
 | |
|       UsbIoDevice->BusController->AddressPool
 | |
|       );
 | |
| 
 | |
|     gBS->FreePool (FirstController);
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Get & parse all configurations for this device, including
 | |
|   // all configuration descriptors, all interface descriptors, all
 | |
|   // endpoint descriptors
 | |
|   //
 | |
|   Result = UsbGetAllConfigurations (UsbIoDevice);
 | |
| 
 | |
|   if (EFI_ERROR (Result)) {
 | |
|     DEBUG ((gUSBErrorLevel, "Failed to get device configuration\n"));
 | |
|     ReportUsbStatusCode (
 | |
|       UsbBusDev,
 | |
|       EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | |
|       EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR
 | |
|       );
 | |
|     UsbFreeAddress (
 | |
|       DevAddress,
 | |
|       UsbIoDevice->BusController->AddressPool
 | |
|       );
 | |
| 
 | |
|     gBS->FreePool (FirstController);
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Set the 1st configuration value
 | |
|   //
 | |
|   Result = UsbSetDefaultConfiguration (UsbIoDevice);
 | |
|   if (EFI_ERROR (Result)) {
 | |
|     DEBUG ((gUSBErrorLevel, "Failed to set device configuration\n"));
 | |
|     ReportUsbStatusCode (
 | |
|       UsbBusDev,
 | |
|       EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | |
|       EFI_IO_BUS_USB | EFI_IOB_EC_WRITE_ERROR
 | |
|       );
 | |
|     UsbFreeAddress (
 | |
|       DevAddress,
 | |
|       UsbIoDevice->BusController->AddressPool
 | |
|       );
 | |
| 
 | |
|     gBS->FreePool (FirstController);
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   UsbIoDevice->IsConfigured = TRUE;
 | |
| 
 | |
|   //
 | |
|   // Get all string table if applicable
 | |
|   //
 | |
|   Result = UsbGetStringtable (UsbIoDevice);
 | |
|   if (EFI_ERROR (Result)) {
 | |
|     DEBUG ((gUSBDebugLevel, "Device doesn't support string table\n"));
 | |
|   } else {
 | |
| 
 | |
|     StrManufacturer = NULL;
 | |
|     UsbIo->UsbGetStringDescriptor (
 | |
|             UsbIo,
 | |
|             UsbIoDevice->LangID[0],
 | |
|             (UsbIoDevice->DeviceDescriptor).StrManufacturer,
 | |
|             &StrManufacturer
 | |
|             );
 | |
| 
 | |
|     StrProduct = NULL;
 | |
|     UsbIo->UsbGetStringDescriptor (
 | |
|             UsbIo,
 | |
|             UsbIoDevice->LangID[0],
 | |
|             (UsbIoDevice->DeviceDescriptor).StrProduct,
 | |
|             &StrProduct
 | |
|             );
 | |
| 
 | |
|     StrSerialNumber = NULL;
 | |
|     UsbIo->UsbGetStringDescriptor (
 | |
|             UsbIo,
 | |
|             UsbIoDevice->LangID[0],
 | |
|             (UsbIoDevice->DeviceDescriptor).StrSerialNumber,
 | |
|             &StrSerialNumber
 | |
|             );
 | |
| 
 | |
|     if (StrManufacturer) {
 | |
|       gBS->FreePool (StrManufacturer);
 | |
|     }
 | |
| 
 | |
|     if (StrProduct) {
 | |
|       gBS->FreePool (StrProduct);
 | |
|     }
 | |
| 
 | |
|     if (StrSerialNumber) {
 | |
|       gBS->FreePool (StrSerialNumber);
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Create USB_IO_CONTROLLER_DEVICE for
 | |
|   // each detected interface
 | |
|   //
 | |
|   FirstController->CurrentConfigValue =
 | |
|   UsbIoDevice->ActiveConfig->CongfigDescriptor.ConfigurationValue;
 | |
| 
 | |
|   NumOfInterface                      =
 | |
|   UsbIoDevice->ActiveConfig->CongfigDescriptor.NumInterfaces;
 | |
|   UsbIoDevice->NumOfControllers       = NumOfInterface;
 | |
| 
 | |
|   Result = InitUsbIoController (FirstController);
 | |
|   if (EFI_ERROR (Result)) {
 | |
|     ReportUsbStatusCode (
 | |
|       UsbBusDev,
 | |
|       EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | |
|       EFI_IO_BUS_USB | EFI_IOB_EC_INTERFACE_ERROR
 | |
|       );
 | |
|     gBS->FreePool (FirstController);
 | |
|     UsbIoDevice->UsbController[0] = NULL;
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   for (Index = 1; Index < NumOfInterface; Index++) {
 | |
|     UsbIoController                     = CreateUsbIoControllerDevice ();
 | |
|     UsbIoController->UsbDevice          = UsbIoDevice;
 | |
|     UsbIoController->CurrentConfigValue =
 | |
|     UsbIoDevice->ActiveConfig->CongfigDescriptor.ConfigurationValue;
 | |
|     UsbIoController->InterfaceNumber    = Index;
 | |
|     UsbIoDevice->UsbController[Index]   = UsbIoController;
 | |
|     UsbIoController->ParentPort         = ParentPort;
 | |
|     UsbIoController->Parent             = ParentHubController;
 | |
|     UsbIoController->HostController     = HostController;
 | |
| 
 | |
|     //
 | |
|     // First copy the USB_IO Protocol instance
 | |
|     //
 | |
|     CopyMem (
 | |
|       &UsbIoController->UsbIo,
 | |
|       UsbIo,
 | |
|       sizeof (EFI_USB_IO_PROTOCOL)
 | |
|       );
 | |
| 
 | |
|     Result = InitUsbIoController (UsbIoController);
 | |
|     if (EFI_ERROR (Result)) {
 | |
|       ReportUsbStatusCode (
 | |
|         UsbBusDev,
 | |
|         EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | |
|         EFI_IO_BUS_USB | EFI_IOB_EC_INTERFACE_ERROR
 | |
|         );
 | |
|       gBS->FreePool (UsbIoController);
 | |
|       UsbIoDevice->UsbController[Index] = NULL;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| //
 | |
| // USB Device DeConfiguration
 | |
| //
 | |
| EFI_STATUS
 | |
| UsbDeviceDeConfiguration (
 | |
|   IN USB_IO_DEVICE     *UsbIoDevice
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Remove Device, Device Handles, Uninstall Protocols.
 | |
| 
 | |
|   Arguments:
 | |
|     UsbIoDevice     -   The device to be deconfigured.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_DEVICE_ERROR
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_CONTROLLER_DEVICE  *UsbController;
 | |
|   UINT8                     index;
 | |
|   USB_IO_DEVICE             *ChildDevice;
 | |
|   UINT8                     Index;
 | |
|   EFI_USB_IO_PROTOCOL       *UsbIo;
 | |
|   EFI_STATUS                Status;
 | |
| 
 | |
|   //
 | |
|   // Double check UsbIoDevice exists
 | |
|   //
 | |
|   if (UsbIoDevice == NULL) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   UsbUnsetTransactionTranslator (UsbIoDevice);
 | |
| 
 | |
|   for (index = 0; index < UsbIoDevice->NumOfControllers; index++) {
 | |
|     //
 | |
|     // Check if it is a hub, if so, de configuration all its
 | |
|     // downstream ports
 | |
|     //
 | |
|     UsbController = UsbIoDevice->UsbController[index];
 | |
| 
 | |
|     //
 | |
|     // Check the controller pointer
 | |
|     //
 | |
|     if (UsbController == NULL) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     if (UsbController->IsUsbHub) {
 | |
| 
 | |
|       DEBUG ((gUSBDebugLevel, "Hub Deconfig, First Deconfig its downstream ports\n"));
 | |
| 
 | |
|       //
 | |
|       // First Remove interrupt transfer request for the status
 | |
|       // change port
 | |
|       //
 | |
|       UsbIo = &UsbController->UsbIo;
 | |
|       UsbIo->UsbAsyncInterruptTransfer (
 | |
|               UsbIo,
 | |
|               UsbController->HubEndpointAddress,
 | |
|               FALSE,
 | |
|               0,
 | |
|               0,
 | |
|               NULL,
 | |
|               NULL
 | |
|               );
 | |
| 
 | |
|       if (NULL != UsbController->HubNotify) {
 | |
|         gBS->CloseEvent (UsbController->HubNotify);
 | |
|       }
 | |
| 
 | |
|       for (Index = 0; Index < UsbController->DownstreamPorts; Index++) {
 | |
|         if (UsbController->Children[Index]) {
 | |
|           ChildDevice = UsbController->Children[Index];
 | |
|           UsbDeviceDeConfiguration (ChildDevice);
 | |
|           UsbController->Children[Index] = NULL;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     //
 | |
|     // If the controller is managed by a device driver, we need to
 | |
|     // disconnect them
 | |
|     //
 | |
|     if (UsbController->IsManagedByDriver) {
 | |
|       gBS->DisconnectController (
 | |
|             UsbController->Handle,
 | |
|             NULL,
 | |
|             NULL
 | |
|             );
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // remove child handle reference to the USB_HC_PROTOCOL
 | |
|     //
 | |
|     if (UsbIoDevice->BusController->Hc2ProtocolSupported) {
 | |
|       gBS->CloseProtocol (
 | |
|             UsbController->HostController,
 | |
|             &gEfiUsb2HcProtocolGuid,
 | |
|             gUsbBusDriverBinding.DriverBindingHandle,
 | |
|             UsbController->Handle
 | |
|             );
 | |
|     } else {
 | |
|       gBS->CloseProtocol (
 | |
|             UsbController->HostController,
 | |
|             &gEfiUsbHcProtocolGuid,
 | |
|             gUsbBusDriverBinding.DriverBindingHandle,
 | |
|             UsbController->Handle
 | |
|             );
 | |
|     }
 | |
|     //
 | |
|     // Uninstall EFI_USB_IO_PROTOCOL & DEVICE_PATH_PROTOCOL
 | |
|     // installed on this handle
 | |
|     //
 | |
|     Status = gBS->UninstallMultipleProtocolInterfaces (
 | |
|                     UsbController->Handle,
 | |
|                     &gEfiDevicePathProtocolGuid,
 | |
|                     UsbController->DevicePath,
 | |
|                     &gEfiUsbIoProtocolGuid,
 | |
|                     &UsbController->UsbIo,
 | |
|                     NULL
 | |
|                     );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     if (UsbController->DevicePath != NULL) {
 | |
|       gBS->FreePool (UsbController->DevicePath);
 | |
|     }
 | |
| 
 | |
|     gBS->FreePool (UsbController);
 | |
|     UsbIoDevice->UsbController[index] = NULL;
 | |
|   }
 | |
|   //
 | |
|   // Free address for later use
 | |
|   //
 | |
|   UsbFreeAddress (
 | |
|     UsbIoDevice->DeviceAddress,
 | |
|     UsbIoDevice->BusController->AddressPool
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Free all resouces allocated for all its configurations
 | |
|   //
 | |
|   UsbDestroyAllConfiguration (UsbIoDevice);
 | |
| 
 | |
|   if (UsbIoDevice) {
 | |
|     gBS->FreePool (UsbIoDevice);
 | |
|     UsbIoDevice = NULL;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| //
 | |
| // After interrupt complete, this function will be called,
 | |
| // This function need to be well-defined later
 | |
| //
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| OnHubInterruptComplete (
 | |
|   IN  VOID          *Data,
 | |
|   IN  UINTN         DataLength,
 | |
|   IN  VOID          *Context,
 | |
|   IN  UINT32        Result
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Whenever hub interrupt occurs, this routine will be called to check
 | |
|     which event happens.
 | |
| 
 | |
|   Arguments:
 | |
|     Data          -   Hub interrupt transfer data.
 | |
|     DataLength    -   The length of the Data.
 | |
|     Context       -   Hub Controller Device.
 | |
|     Result        -   Hub interrupt transfer status.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_DEVICE_ERROR
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_CONTROLLER_DEVICE  *HubController;
 | |
|   UINT8                     Index;
 | |
|   UINT8                     *ptr;
 | |
|   EFI_USB_IO_PROTOCOL       *UsbIo;
 | |
|   UINT32                    UsbResult;
 | |
|   BOOLEAN                   Disconnected;
 | |
|   EFI_STATUS                Status;
 | |
| 
 | |
|   HubController = (USB_IO_CONTROLLER_DEVICE *) Context;
 | |
|   UsbIo         = &HubController->UsbIo;
 | |
| 
 | |
|   //
 | |
|   // If something error in this interrupt transfer,
 | |
|   //
 | |
|   if (Result != EFI_USB_NOERROR) {
 | |
|     if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
 | |
|       UsbClearEndpointHalt (
 | |
|         UsbIo,
 | |
|         HubController->HubEndpointAddress,
 | |
|         &UsbResult
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Delete & Submit this interrupt again
 | |
|     //
 | |
|     UsbIo->UsbAsyncInterruptTransfer (
 | |
|             UsbIo,
 | |
|             HubController->HubEndpointAddress,
 | |
|             FALSE,
 | |
|             0,
 | |
|             0,
 | |
|             NULL,
 | |
|             NULL
 | |
|             );
 | |
| 
 | |
|     //
 | |
|     // try to detect if the hub itself was disconnected or not
 | |
|     //
 | |
|     Status = IsDeviceDisconnected (
 | |
|               HubController,
 | |
|               &Disconnected
 | |
|               );
 | |
| 
 | |
|     if (!EFI_ERROR (Status) && Disconnected == TRUE) {
 | |
|       DEBUG ((gUSBErrorLevel, "Hub is disconnected\n"));
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|     //
 | |
|     // Hub ports < 7
 | |
|     //
 | |
|     UsbIo->UsbAsyncInterruptTransfer (
 | |
|             UsbIo,
 | |
|             HubController->HubEndpointAddress,
 | |
|             TRUE,
 | |
|             100,
 | |
|             1,
 | |
|             OnHubInterruptComplete,
 | |
|             HubController
 | |
|             );
 | |
| 
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   if (DataLength == 0 || Data == NULL) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Scan which port has status change
 | |
|   // Bit 0 stands for hub itself, other bit stands for
 | |
|   // the corresponding port
 | |
|   //
 | |
|   for (Index = 0; Index < DataLength * 8; Index++) {
 | |
|     ptr = (UINT8 *) Data + Index / 8;
 | |
|     if ((*ptr) & (1 << (Index & 0x7))) {
 | |
|       HubController->StatusChangePort = Index;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Signal hub notify event
 | |
|   //
 | |
|   gBS->SignalEvent (HubController->HubNotify);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| //
 | |
| // USB Root Hub Enumerator
 | |
| //
 | |
| STATIC
 | |
| VOID
 | |
| EFIAPI
 | |
| RootHubEnumeration (
 | |
|   IN EFI_EVENT     Event,
 | |
|   IN VOID          *Context
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     This is USB RootHub enumerator
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     Event   -   Indicating which event is signaled
 | |
|     Context -  actually it is a USB_IO_DEVICE
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     VOID
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_CONTROLLER_DEVICE  *HubController;
 | |
|   EFI_USB_PORT_STATUS       HubPortStatus;
 | |
|   EFI_STATUS                Status;
 | |
|   UINT8                     Index;
 | |
|   USB_IO_DEVICE             *UsbIoDev;
 | |
|   USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
 | |
|   EFI_HANDLE                HostController;
 | |
|   USB_IO_DEVICE             *OldUsbIoDevice;
 | |
|   USB_IO_DEVICE             *NewDevice;
 | |
|   USB_IO_CONTROLLER_DEVICE  *NewController;
 | |
|   UINT8                     Index2;
 | |
|   EFI_USB_IO_PROTOCOL       *UsbIo;
 | |
| 
 | |
|   HubController   = (USB_IO_CONTROLLER_DEVICE *) Context;
 | |
|   HostController  = HubController->HostController;
 | |
|   UsbBusDev       = HubController->UsbDevice->BusController;
 | |
| 
 | |
|   //
 | |
|   // Root hub has the address 1
 | |
|   //
 | |
|   UsbIoDev = HubController->UsbDevice;
 | |
| 
 | |
|   for (Index = 0; Index < HubController->DownstreamPorts; Index++) {
 | |
| 
 | |
|     UsbVirtualHcGetRootHubPortStatus (
 | |
|       UsbBusDev,
 | |
|       Index,
 | |
|       (EFI_USB_PORT_STATUS *) &HubPortStatus
 | |
|       );
 | |
| 
 | |
|     if (!IsPortConnectChange (HubPortStatus.PortChangeStatus)) {
 | |
|       continue;
 | |
|     }
 | |
|     //
 | |
|     // Clear root hub status change status
 | |
|     //
 | |
|     UsbVirtualHcClearRootHubPortFeature (
 | |
|       UsbBusDev,
 | |
|       Index,
 | |
|       EfiUsbPortConnectChange
 | |
|       );
 | |
| 
 | |
|     gBS->Stall (100 * 1000);
 | |
| 
 | |
|     UsbVirtualHcGetRootHubPortStatus (
 | |
|       UsbBusDev,
 | |
|       Index,
 | |
|       (EFI_USB_PORT_STATUS *) &HubPortStatus
 | |
|       );
 | |
| 
 | |
|     if (IsPortConnect (HubPortStatus.PortStatus)) {
 | |
| 
 | |
|       //
 | |
|       // There is something connected to this port
 | |
|       //
 | |
|       DEBUG ((gUSBDebugLevel, "Something connected to Root Hub at Port0x%x\n", Index));
 | |
| 
 | |
|       ReportUsbStatusCode (
 | |
|         UsbBusDev,
 | |
|         EFI_PROGRESS_CODE,
 | |
|         EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG
 | |
|         );
 | |
|       //
 | |
|       // if there is something physically detached, but still logically
 | |
|       // attached...
 | |
|       //
 | |
|       OldUsbIoDevice = HubController->Children[Index];
 | |
| 
 | |
|       if (NULL != OldUsbIoDevice) {
 | |
|         UsbDeviceDeConfiguration (OldUsbIoDevice);
 | |
|         HubController->Children[Index] = NULL;
 | |
|       }
 | |
| 
 | |
|       NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE));
 | |
|       if (NewDevice == NULL) {
 | |
|         return ;
 | |
|       }
 | |
|       //
 | |
|       // Initialize some fields by copying data from
 | |
|       // its parents
 | |
|       //
 | |
|       NewDevice->DeviceDescriptor.MaxPacketSize0  = 8;
 | |
|       NewDevice->BusController                    = UsbIoDev->BusController;
 | |
| 
 | |
|       //
 | |
|       // Process of identify device speed
 | |
|       //
 | |
|       Status = IdentifyDeviceSpeed (
 | |
|                  UsbBusDev,
 | |
|                  NewDevice,
 | |
|                  Index
 | |
|                  );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         gBS->FreePool (NewDevice);
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Configure that device
 | |
|       //
 | |
|       Status = UsbDeviceConfiguration (
 | |
|                 HubController,
 | |
|                 HostController,
 | |
|                 Index,
 | |
|                 NewDevice
 | |
|                 );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         gBS->FreePool (NewDevice);
 | |
|         return ;
 | |
|       }
 | |
|       //
 | |
|       // Add this device to the usb bus tree
 | |
|       //
 | |
|       HubController->Children[Index] = NewDevice;
 | |
| 
 | |
|       for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {
 | |
|         //
 | |
|         // If this device is hub, add to the hub index
 | |
|         //
 | |
|         NewController = NewDevice->UsbController[Index2];
 | |
| 
 | |
|         Status = gBS->ConnectController (
 | |
|                         NewController->Handle,
 | |
|                         NULL,
 | |
|                         NULL,
 | |
|                         TRUE
 | |
|                         );
 | |
|         //
 | |
|         // If connect success, we need to disconnect when
 | |
|         // stop the controller, otherwise we need not call
 | |
|         // gBS->DisconnectController ()
 | |
|         // This is used by those usb devices we don't plan
 | |
|         // to support. We can allocate
 | |
|         // controller handles for them, but we don't have
 | |
|         // device drivers to manage them.
 | |
|         //
 | |
|         NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status));
 | |
| 
 | |
|         if (IsHub (NewController)) {
 | |
| 
 | |
|           NewController->IsUsbHub = TRUE;
 | |
| 
 | |
|           //
 | |
|           // Configure Hub Controller
 | |
|           //
 | |
|           Status = DoHubConfig (NewController);
 | |
|           if (EFI_ERROR (Status)) {
 | |
|             continue;
 | |
|           }
 | |
|           //
 | |
|           // Create an event to do hub enumeration
 | |
|           //
 | |
|           gBS->CreateEvent (
 | |
|                 EVT_NOTIFY_SIGNAL,
 | |
|                 TPL_CALLBACK,
 | |
|                 HubEnumeration,
 | |
|                 NewController,
 | |
|                 &NewController->HubNotify
 | |
|                 );
 | |
| 
 | |
|           //
 | |
|           // Add request to do query hub status
 | |
|           // change endpoint
 | |
|           // Hub ports < 7
 | |
|           //
 | |
|           UsbIo = &NewController->UsbIo;
 | |
|           UsbIo->UsbAsyncInterruptTransfer (
 | |
|                   UsbIo,
 | |
|                   NewController->HubEndpointAddress,
 | |
|                   TRUE,
 | |
|                   100,
 | |
|                   1,
 | |
|                   OnHubInterruptComplete,
 | |
|                   NewController
 | |
|                   );
 | |
| 
 | |
|         }
 | |
|       }
 | |
|     } else {
 | |
|       //
 | |
|       // Something disconnected from USB root hub
 | |
|       //
 | |
|       DEBUG ((gUSBDebugLevel, "Something disconnected from Root Hub at Port0x%x\n", Index));
 | |
| 
 | |
|       OldUsbIoDevice = HubController->Children[Index];
 | |
| 
 | |
|       UsbDeviceDeConfiguration (OldUsbIoDevice);
 | |
| 
 | |
|       HubController->Children[Index] = NULL;
 | |
| 
 | |
|       UsbVirtualHcClearRootHubPortFeature (
 | |
|         UsbBusDev,
 | |
|         Index,
 | |
|         EfiUsbPortEnableChange
 | |
|         );
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ;
 | |
| }
 | |
| //
 | |
| // USB Root Hub Enumerator
 | |
| //
 | |
| STATIC
 | |
| VOID
 | |
| EFIAPI
 | |
| HubEnumeration (
 | |
|   IN EFI_EVENT     Event,
 | |
|   IN VOID          *Context
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     This is Usb Hub enumerator
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     Event    -   Indicating which event is signaled
 | |
|     Context  -  actually it is a USB_IO_DEVICE
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     VOID
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_CONTROLLER_DEVICE  *HubController;
 | |
|   EFI_USB_PORT_STATUS       HubPortStatus;
 | |
|   EFI_STATUS                Status;
 | |
|   USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
 | |
|   EFI_HANDLE                HostController;
 | |
|   USB_IO_DEVICE             *OldUsbIoDevice;
 | |
|   USB_IO_DEVICE             *NewDevice;
 | |
|   USB_IO_CONTROLLER_DEVICE  *NewController;
 | |
|   UINT8                     Index2;
 | |
|   EFI_USB_IO_PROTOCOL       *UsbIo;
 | |
|   UINT8                     StatusChangePort;
 | |
|   UINT8                     Number;
 | |
| 
 | |
|   HubController   = (USB_IO_CONTROLLER_DEVICE *) Context;
 | |
|   HostController  = HubController->HostController;
 | |
|   UsbBusDev       = HubController->UsbDevice->BusController;
 | |
| 
 | |
|   //
 | |
|   // Event from Hub, Get the hub controller handle
 | |
|   //
 | |
|   //
 | |
|   // Get the status change endpoint
 | |
|   //
 | |
|   StatusChangePort = HubController->StatusChangePort;
 | |
| 
 | |
|   //
 | |
|   // Clear HubController Status Change Bit
 | |
|   //
 | |
|   HubController->StatusChangePort = 0;
 | |
| 
 | |
|   if (StatusChangePort == 0) {
 | |
|     //
 | |
|     // Hub changes, we don't handle here
 | |
|     //
 | |
|     return ;
 | |
|   }
 | |
|   //
 | |
|   // Check which event took place at that port
 | |
|   //
 | |
|   UsbIo = &HubController->UsbIo;
 | |
|   Status = HubGetPortStatus (
 | |
|             UsbIo,
 | |
|             StatusChangePort,
 | |
|             (UINT32 *) &HubPortStatus
 | |
|             );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return ;
 | |
|   }
 | |
|   //
 | |
|   // Clear some change status
 | |
|   //
 | |
|   if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) {
 | |
|     //
 | |
|     // Clear Hub port enable change
 | |
|     //
 | |
|     DEBUG ((gUSBDebugLevel, "Port Enable Change\n"));
 | |
|     HubClearPortFeature (
 | |
|       UsbIo,
 | |
|       StatusChangePort,
 | |
|       EfiUsbPortEnableChange
 | |
|       );
 | |
| 
 | |
|     HubGetPortStatus (
 | |
|       UsbIo,
 | |
|       StatusChangePort,
 | |
|       (UINT32 *) &HubPortStatus
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) {
 | |
|     //
 | |
|     // Clear Hub reset change
 | |
|     //
 | |
|     DEBUG ((gUSBDebugLevel, "Port Reset Change\n"));
 | |
|     HubClearPortFeature (
 | |
|       UsbIo,
 | |
|       StatusChangePort,
 | |
|       EfiUsbPortResetChange
 | |
|       );
 | |
| 
 | |
|     HubGetPortStatus (
 | |
|       UsbIo,
 | |
|       StatusChangePort,
 | |
|       (UINT32 *) &HubPortStatus
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_OVERCURRENT) {
 | |
|     //
 | |
|     // Clear Hub overcurrent change
 | |
|     //
 | |
|     DEBUG ((gUSBDebugLevel, "Port Overcurrent Change\n"));
 | |
|     HubClearPortFeature (
 | |
|       UsbIo,
 | |
|       StatusChangePort,
 | |
|       EfiUsbPortOverCurrentChange
 | |
|       );
 | |
| 
 | |
|     HubGetPortStatus (
 | |
|       UsbIo,
 | |
|       StatusChangePort,
 | |
|       (UINT32 *) &HubPortStatus
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   if (IsPortConnectChange (HubPortStatus.PortChangeStatus)) {
 | |
|     //
 | |
|     // First clear port connection change
 | |
|     //
 | |
|     DEBUG ((gUSBDebugLevel, "Port Connection Change\n"));
 | |
|     HubClearPortFeature (
 | |
|       UsbIo,
 | |
|       StatusChangePort,
 | |
|       EfiUsbPortConnectChange
 | |
|       );
 | |
| 
 | |
|     HubGetPortStatus (
 | |
|       UsbIo,
 | |
|       StatusChangePort,
 | |
|       (UINT32 *) &HubPortStatus
 | |
|       );
 | |
| 
 | |
|     if (IsPortConnect (HubPortStatus.PortStatus)) {
 | |
| 
 | |
|       DEBUG ((gUSBDebugLevel, "New Device Connect on Hub port \n"));
 | |
| 
 | |
|       ReportUsbStatusCode (
 | |
|         UsbBusDev,
 | |
|         EFI_PROGRESS_CODE,
 | |
|         EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG
 | |
|         );
 | |
| 
 | |
|       //
 | |
|       // if there is something physically detached, but still logically
 | |
|       // attached...
 | |
|       //
 | |
|       OldUsbIoDevice = HubController->Children[StatusChangePort - 1];
 | |
| 
 | |
|       if (NULL != OldUsbIoDevice) {
 | |
|         UsbDeviceDeConfiguration (OldUsbIoDevice);
 | |
|         HubController->Children[StatusChangePort - 1] = NULL;
 | |
|       }
 | |
| 
 | |
|       NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE));
 | |
|       if (NewDevice == NULL) {
 | |
|         return ;
 | |
|       }
 | |
|       //
 | |
|       // Initialize some fields
 | |
|       //
 | |
|       NewDevice->DeviceDescriptor.MaxPacketSize0  = 8;
 | |
|       NewDevice->BusController                    = HubController->UsbDevice->BusController;
 | |
| 
 | |
|       //
 | |
|       // There is something connected to this port,
 | |
|       // reset that port
 | |
|       //
 | |
|       // Disable the enable bit in port status
 | |
|       //
 | |
|       HubClearPortFeature (
 | |
|         UsbIo,
 | |
|         StatusChangePort,
 | |
|         EfiUsbPortEnable
 | |
|         );
 | |
| 
 | |
|       gBS->Stall (50 * 1000);
 | |
| 
 | |
|       //
 | |
|       // Wait for bit change
 | |
|       //
 | |
|       Number = 10;
 | |
|       do {
 | |
|         HubGetPortStatus (
 | |
|           UsbIo,
 | |
|           StatusChangePort,
 | |
|           (UINT32 *) &HubPortStatus
 | |
|           );
 | |
|         gBS->Stall (10 * 1000);
 | |
|         Number -= 1;
 | |
|       } while ((HubPortStatus.PortStatus & USB_PORT_STAT_ENABLE) == 1 && Number > 0);
 | |
| 
 | |
|       if (Number == 0) {
 | |
|         //
 | |
|         // Cannot disable port, return error
 | |
|         //
 | |
|         DEBUG ((gUSBErrorLevel, "Disable Port Failed\n"));
 | |
|         gBS->FreePool (NewDevice);
 | |
|         return ;
 | |
|       }
 | |
| 
 | |
|       HubSetPortFeature (
 | |
|         UsbIo,
 | |
|         StatusChangePort,
 | |
|         EfiUsbPortReset
 | |
|         );
 | |
| 
 | |
|       gBS->Stall (50 * 1000);
 | |
| 
 | |
|       //
 | |
|       // Wait for port reset complete
 | |
|       //
 | |
|       Number = 10;
 | |
|       do {
 | |
|         HubGetPortStatus (
 | |
|           UsbIo,
 | |
|           StatusChangePort,
 | |
|           (UINT32 *) &HubPortStatus
 | |
|           );
 | |
|         gBS->Stall (10 * 1000);
 | |
|         Number -= 1;
 | |
|       } while ((HubPortStatus.PortStatus & USB_PORT_STAT_RESET) == 1 && Number > 0);
 | |
| 
 | |
|       if (Number == 0) {
 | |
|         //
 | |
|         // Cannot reset port, return error
 | |
|         //
 | |
|         DEBUG ((gUSBErrorLevel, "Reset Port Failed\n"));
 | |
|         gBS->FreePool (NewDevice);
 | |
|         return ;
 | |
|       }
 | |
|       //
 | |
|       // Check high speed or full speed device
 | |
|       //
 | |
|       if (HubPortStatus.PortStatus & USB_PORT_STAT_LOW_SPEED) {
 | |
|         DEBUG ((gUSBDebugLevel, "Low Speed Device Attached to Hub\n"));
 | |
|         NewDevice->DeviceSpeed = EFI_USB_SPEED_LOW;
 | |
|       } else if (HubPortStatus.PortStatus & USB_PORT_STAT_HIGH_SPEED) {
 | |
|         DEBUG ((gUSBDebugLevel, "High Speed Device Attached to Hub\n"));
 | |
|         NewDevice->DeviceSpeed = EFI_USB_SPEED_HIGH;
 | |
|       } else {
 | |
|         DEBUG ((gUSBDebugLevel, "Full Speed Device Attached to Hub\n"));
 | |
|         NewDevice->DeviceSpeed = EFI_USB_SPEED_FULL;
 | |
|       }
 | |
|       //
 | |
|       // Configure that device
 | |
|       //
 | |
|       Status = UsbDeviceConfiguration (
 | |
|                 HubController,
 | |
|                 HostController,
 | |
|                 (UINT8) (StatusChangePort - 1),
 | |
|                 NewDevice
 | |
|                 );
 | |
| 
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         gBS->FreePool (NewDevice);
 | |
|         return ;
 | |
|       }
 | |
|       //
 | |
|       // Add this device to the usb bus tree
 | |
|       // StatusChangePort is begin from 1,
 | |
|       //
 | |
|       HubController->Children[StatusChangePort - 1] = NewDevice;
 | |
| 
 | |
|       for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {
 | |
|         //
 | |
|         // If this device is hub, add to the hub index
 | |
|         //
 | |
|         NewController = NewDevice->UsbController[Index2];
 | |
| 
 | |
|         //
 | |
|         // Connect the controller to the driver image
 | |
|         //
 | |
|         Status = gBS->ConnectController (
 | |
|                         NewController->Handle,
 | |
|                         NULL,
 | |
|                         NULL,
 | |
|                         TRUE
 | |
|                         );
 | |
|         //
 | |
|         // If connect success, we need to disconnect when
 | |
|         // stop the controller, otherwise we need not call
 | |
|         // gBS->DisconnectController ()
 | |
|         // This is used by those usb devices we don't plan
 | |
|         // to support. We can allocate
 | |
|         // controller handles for them, but we don't have
 | |
|         // device drivers to manage them.
 | |
|         //
 | |
|         NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status));
 | |
| 
 | |
|         //
 | |
|         // If this device is hub, add to the hub index
 | |
|         //
 | |
|         if (IsHub (NewController)) {
 | |
| 
 | |
|           NewController->IsUsbHub = TRUE;
 | |
| 
 | |
|           //
 | |
|           // Configure Hub
 | |
|           //
 | |
|           Status = DoHubConfig (NewController);
 | |
| 
 | |
|           if (EFI_ERROR (Status)) {
 | |
|             continue;
 | |
|           }
 | |
|           //
 | |
|           // Create an event to do hub enumeration
 | |
|           //
 | |
|           gBS->CreateEvent (
 | |
|                 EVT_NOTIFY_SIGNAL,
 | |
|                 TPL_CALLBACK,
 | |
|                 HubEnumeration,
 | |
|                 NewController,
 | |
|                 &NewController->HubNotify
 | |
|                 );
 | |
| 
 | |
|           //
 | |
|           // Add request to do query hub status
 | |
|           // change endpoint
 | |
|           //
 | |
|           UsbIo = &NewController->UsbIo;
 | |
|           UsbIo->UsbAsyncInterruptTransfer (
 | |
|                   UsbIo,
 | |
|                   NewController->HubEndpointAddress,  // Hub endpoint address
 | |
|                   TRUE,
 | |
|                   100,
 | |
|                   1,                                  // Hub ports < 7
 | |
|                   OnHubInterruptComplete,
 | |
|                   NewController
 | |
|                   );
 | |
|         }
 | |
|       }
 | |
|     } else {
 | |
|       //
 | |
|       // Something disconnected from USB hub
 | |
|       //
 | |
|       DEBUG ((gUSBDebugLevel, "Something Device Detached on Hub port\n"));
 | |
| 
 | |
|       OldUsbIoDevice = HubController->Children[StatusChangePort - 1];
 | |
| 
 | |
|       UsbDeviceDeConfiguration (OldUsbIoDevice);
 | |
| 
 | |
|       HubController->Children[StatusChangePort - 1] = NULL;
 | |
| 
 | |
|     }
 | |
| 
 | |
|     return ;
 | |
|   }
 | |
| 
 | |
|   return ;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| USB_IO_CONTROLLER_DEVICE *
 | |
| CreateUsbIoControllerDevice (
 | |
|   VOID
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Allocate a structure for USB_IO_CONTROLLER_DEVICE
 | |
| 
 | |
|   Arguments:
 | |
|     N/A
 | |
| 
 | |
|   Returns:
 | |
|     A pointer to a USB_IO_CONTROLLER_DEVICE structure,
 | |
|     Or NULL.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_CONTROLLER_DEVICE  *UsbIoControllerDev;
 | |
| 
 | |
|   //
 | |
|   // Allocate USB_IO_CONTROLLER_DEVICE structure
 | |
|   //
 | |
|   UsbIoControllerDev  = NULL;
 | |
|   UsbIoControllerDev  = AllocateZeroPool (sizeof (USB_IO_CONTROLLER_DEVICE));
 | |
| 
 | |
|   if (UsbIoControllerDev == NULL) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   UsbIoControllerDev->Signature = USB_IO_CONTROLLER_SIGNATURE;
 | |
| 
 | |
|   return UsbIoControllerDev;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| InitUsbIoController (
 | |
|   IN USB_IO_CONTROLLER_DEVICE     *UsbIoController
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Init and install EFI_USB_IO_PROTOCOL onto that controller.
 | |
| 
 | |
|   Arguments:
 | |
|     UsbIoController   -   The Controller to be operated.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     Others
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_DEVICE_PATH           UsbNode;
 | |
|   EFI_STATUS                Status;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
 | |
|   EFI_USB_HC_PROTOCOL       *UsbHcProtocol;
 | |
|   EFI_USB2_HC_PROTOCOL      *Usb2HcProtocol;
 | |
| 
 | |
|   //
 | |
|   // Build the child device path for each new USB_IO device
 | |
|   //
 | |
|   ZeroMem (&UsbNode, sizeof (UsbNode));
 | |
|   UsbNode.Header.Type     = MESSAGING_DEVICE_PATH;
 | |
|   UsbNode.Header.SubType  = MSG_USB_DP;
 | |
|   SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode));
 | |
|   UsbNode.InterfaceNumber     = UsbIoController->InterfaceNumber;
 | |
|   UsbNode.ParentPortNumber    = UsbIoController->ParentPort;
 | |
|   ParentDevicePath            = UsbIoController->Parent->DevicePath;
 | |
| 
 | |
|   UsbIoController->DevicePath =
 | |
|   AppendDevicePathNode (ParentDevicePath, &UsbNode.Header);
 | |
|   if (UsbIoController->DevicePath == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                   &UsbIoController->Handle,
 | |
|                   &gEfiDevicePathProtocolGuid,
 | |
|                   UsbIoController->DevicePath,
 | |
|                   &gEfiUsbIoProtocolGuid,
 | |
|                   &UsbIoController->UsbIo,
 | |
|                   NULL
 | |
|                   );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (UsbIoController->UsbDevice->BusController->Hc2ProtocolSupported) {
 | |
|     Status = gBS->OpenProtocol (
 | |
|                     UsbIoController->HostController,
 | |
|                     &gEfiUsb2HcProtocolGuid,
 | |
|                     (VOID **)&Usb2HcProtocol,
 | |
|                     gUsbBusDriverBinding.DriverBindingHandle,
 | |
|                     UsbIoController->Handle,
 | |
|                     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | |
|                     );
 | |
|   } else {
 | |
|     Status = gBS->OpenProtocol (
 | |
|                     UsbIoController->HostController,
 | |
|                     &gEfiUsbHcProtocolGuid,
 | |
|                     (VOID **)&UsbHcProtocol,
 | |
|                     gUsbBusDriverBinding.DriverBindingHandle,
 | |
|                     UsbIoController->Handle,
 | |
|                     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | |
|                     );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ParentPortReset (
 | |
|   IN USB_IO_CONTROLLER_DEVICE    *UsbIoController,
 | |
|   IN BOOLEAN                     ReConfigure,
 | |
|   IN UINT8                       RetryTimes
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Reset parent hub port to which this device is connected.
 | |
| 
 | |
|   Arguments:
 | |
|     UsbIoController   - Indicating the Usb Controller Device.
 | |
|     ReConfigure       - Do we need to reconfigure it.
 | |
|     RetryTimes        - Retry Times when failed
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_DEVICE_ERROR
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_DEVICE             *ParentIoDev;
 | |
|   USB_IO_DEVICE             *UsbIoDev;
 | |
|   USB_IO_CONTROLLER_DEVICE  *ParentController;
 | |
|   UINT8                     HubPort;
 | |
|   UINT32                    Status;
 | |
|   EFI_STATUS                Result;
 | |
|   EFI_USB_IO_PROTOCOL       *UsbIo;
 | |
|   UINT8                     Address;
 | |
| 
 | |
|   ParentController  = UsbIoController->Parent;
 | |
|   ParentIoDev       = ParentController->UsbDevice;
 | |
|   UsbIoDev          = UsbIoController->UsbDevice;
 | |
|   HubPort           = UsbIoController->ParentPort;
 | |
| 
 | |
|   gBS->Stall (100 * 1000);
 | |
| 
 | |
|   if (ParentIoDev->DeviceAddress == 1) {
 | |
|     DEBUG ((gUSBDebugLevel, "Reset from Root Hub 0x%x\n", HubPort));
 | |
|     ResetRootPort (ParentIoDev->BusController, HubPort, RetryTimes);
 | |
|   } else {
 | |
|     DEBUG ((gUSBDebugLevel, "Reset from Hub, Addr 0x%x\n", ParentIoDev->DeviceAddress));
 | |
|     ResetHubPort (ParentController, (UINT8) (HubPort + 1));
 | |
|   }
 | |
|   //
 | |
|   // If we only need port reset, just return
 | |
|   //
 | |
|   if (!ReConfigure) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
|   //
 | |
|   // Re-config that USB device
 | |
|   //
 | |
|   UsbIo = &UsbIoController->UsbIo;
 | |
| 
 | |
|   //
 | |
|   // Assign a unique address to this device
 | |
|   //
 | |
|   Address                 = UsbIoDev->DeviceAddress;
 | |
|   UsbIoDev->DeviceAddress = 0;
 | |
| 
 | |
|   Result                  = UsbSetDeviceAddress (UsbIo, Address, &Status);
 | |
|   UsbIoDev->DeviceAddress = Address;
 | |
| 
 | |
|   if (EFI_ERROR (Result)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Set the device to the default configuration
 | |
|   //
 | |
|   Result = UsbSetDefaultConfiguration (UsbIoDev);
 | |
|   if (EFI_ERROR (Result)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbPortReset (
 | |
|   IN EFI_USB_IO_PROTOCOL      *This
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Resets and reconfigures the USB controller.  This function will
 | |
|     work for all USB devices except USB Hub Controllers.
 | |
| 
 | |
|   Arguments:
 | |
|     This          -   Indicates the calling context.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_INVALID_PARAMETER
 | |
|     EFI_DEVICE_ERROR
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_CONTROLLER_DEVICE  *UsbIoController;
 | |
| 
 | |
|   UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
 | |
| 
 | |
|   if (IsHub (UsbIoController)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Since at this time, this device has already been configured,
 | |
|   // it needs to be re-configured.
 | |
|   //
 | |
|   return ParentPortReset (UsbIoController, TRUE, 0);
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ResetRootPort (
 | |
|   IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
 | |
|   IN UINT8                     PortNum,
 | |
|   IN UINT8                     RetryTimes
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Reset Root Hub port.
 | |
| 
 | |
|   Arguments:
 | |
|     UsbBusDev       - Bus controller of the device.
 | |
|     PortNum         - The given port to be reset.
 | |
|     RetryTimes      - RetryTimes when failed
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_DEVICE_ERROR
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS          Status;
 | |
|   EFI_USB_PORT_STATUS PortStatus;
 | |
| 
 | |
|   //
 | |
|   // reset root port
 | |
|   //
 | |
|   Status = UsbVirtualHcSetRootHubPortFeature (
 | |
|             UsbBusDev,
 | |
|             PortNum,
 | |
|             EfiUsbPortReset
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   gBS->Stall (50 * 1000);
 | |
| 
 | |
|   //
 | |
|   // clear reset root port
 | |
|   //
 | |
|   Status = UsbVirtualHcClearRootHubPortFeature (
 | |
|             UsbBusDev,
 | |
|             PortNum,
 | |
|             EfiUsbPortReset
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   gBS->Stall (1000);
 | |
| 
 | |
|   Status = UsbVirtualHcClearRootHubPortFeature (
 | |
|             UsbBusDev,
 | |
|             PortNum,
 | |
|             EfiUsbPortConnectChange
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   UsbVirtualHcGetRootHubPortStatus (
 | |
|     UsbBusDev,
 | |
|     PortNum,
 | |
|     &PortStatus
 | |
|     );
 | |
|   if (PortStatus.PortStatus & USB_PORT_STAT_OWNER) {
 | |
|     //
 | |
|     // Set port enable
 | |
|     //
 | |
|     Status = UsbVirtualHcSetRootHubPortFeature (
 | |
|               UsbBusDev,
 | |
|               PortNum,
 | |
|               EfiUsbPortEnable
 | |
|               );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
| 
 | |
|     Status = UsbVirtualHcClearRootHubPortFeature (
 | |
|               UsbBusDev,
 | |
|               PortNum,
 | |
|               EfiUsbPortEnableChange
 | |
|               );
 | |
|   }
 | |
| 
 | |
|   gBS->Stall ((1 + RetryTimes) * 50 * 1000);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ResetHubPort (
 | |
|   IN USB_IO_CONTROLLER_DEVICE    *UsbIoController,
 | |
|   IN UINT8                       PortIndex
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Reset Hub port.
 | |
| 
 | |
|   Arguments:
 | |
|     UsbIoController  -   The USB_IO_CONTROLLER_DEVICE instance.
 | |
|     PortIndex        -   The given port to be reset.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_DEVICE_ERROR
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_USB_IO_PROTOCOL *UsbIo;
 | |
|   EFI_USB_PORT_STATUS HubPortStatus;
 | |
|   UINT8               Number;
 | |
| 
 | |
|   ASSERT (UsbIoController->IsUsbHub == TRUE);
 | |
| 
 | |
|   UsbIo = &UsbIoController->UsbIo;
 | |
| 
 | |
|   HubSetPortFeature (
 | |
|     UsbIo,
 | |
|     PortIndex,
 | |
|     EfiUsbPortReset
 | |
|     );
 | |
| 
 | |
|   gBS->Stall (10 * 1000);
 | |
| 
 | |
|   //
 | |
|   // Wait for port reset complete
 | |
|   //
 | |
|   Number = 10;
 | |
|   do {
 | |
|     HubGetPortStatus (
 | |
|       UsbIo,
 | |
|       PortIndex,
 | |
|       (UINT32 *) &HubPortStatus
 | |
|       );
 | |
|     gBS->Stall (10 * 100);
 | |
|     Number -= 1;
 | |
|   } while ((HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0 && Number > 0);
 | |
| 
 | |
|   if (Number == 0) {
 | |
|     //
 | |
|     // Cannot reset port, return error
 | |
|     //
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   gBS->Stall (1000);
 | |
| 
 | |
|   HubGetPortStatus (
 | |
|     UsbIo,
 | |
|     PortIndex,
 | |
|     (UINT32 *) &HubPortStatus
 | |
|     );
 | |
|   //
 | |
|   // reset port will cause some bits change, clear them
 | |
|   //
 | |
|   if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) {
 | |
|     DEBUG ((gUSBDebugLevel, "Port Enable Change\n"));
 | |
|     HubClearPortFeature (
 | |
|       UsbIo,
 | |
|       PortIndex,
 | |
|       EfiUsbPortEnableChange
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) {
 | |
|     DEBUG ((gUSBDebugLevel, "Port Reset Change\n"));
 | |
|     HubClearPortFeature (
 | |
|       UsbIo,
 | |
|       PortIndex,
 | |
|       EfiUsbPortResetChange
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ReportUsbStatusCode (
 | |
|   IN USB_BUS_CONTROLLER_DEVICE     *UsbBusController,
 | |
|   IN EFI_STATUS_CODE_TYPE          Type,
 | |
|   IN EFI_STATUS_CODE_VALUE         Code
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   report a error Status code of USB bus driver controller
 | |
| 
 | |
|  Arguments:
 | |
|    UsbBusController - USB_BUS_CONTROLLER_DEVICE
 | |
|    Type             - EFI_STATUS_CODE_TYPE
 | |
|    Code             - EFI_STATUS_CODE_VALUE
 | |
|  Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   return REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | |
|           Type,
 | |
|           Code,
 | |
|           UsbBusController->DevicePath
 | |
|           );
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| IsDeviceDisconnected (
 | |
|   IN USB_IO_CONTROLLER_DEVICE    *UsbIoController,
 | |
|   IN OUT BOOLEAN                 *Disconnected
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Reset if the device is disconencted or not
 | |
| 
 | |
|   Arguments:
 | |
|     UsbIoController   -   Indicating the Usb Controller Device.
 | |
|     Disconnected      -   Indicate whether the device is disconencted or not
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS
 | |
|     EFI_DEVICE_ERROR
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_DEVICE             *ParentIoDev;
 | |
|   USB_IO_CONTROLLER_DEVICE  *ParentController;
 | |
|   UINT8                     HubPort;
 | |
|   EFI_STATUS                Status;
 | |
|   EFI_USB_PORT_STATUS       PortStatus;
 | |
| 
 | |
|   ParentController  = UsbIoController->Parent;
 | |
|   ParentIoDev       = ParentController->UsbDevice;
 | |
|   HubPort           = UsbIoController->ParentPort;
 | |
| 
 | |
|   if (ParentIoDev->DeviceAddress == 1) {
 | |
|     //
 | |
|     // Connected to the root hub
 | |
|     //
 | |
|     UsbVirtualHcGetRootHubPortStatus (
 | |
|       ParentIoDev->BusController,
 | |
|       HubPort,
 | |
|       &PortStatus
 | |
|       );
 | |
| 
 | |
|   } else {
 | |
|     Status = HubGetPortStatus (
 | |
|               &ParentController->UsbIo,
 | |
|               (UINT8) (HubPort + 1),
 | |
|               (UINT32 *) &PortStatus
 | |
|               );
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return IsDeviceDisconnected (ParentController, Disconnected);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   *Disconnected = FALSE;
 | |
| 
 | |
|   if (!IsPortConnect (PortStatus.PortStatus)) {
 | |
|     *Disconnected = TRUE;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| UsbSetTransactionTranslator (
 | |
|   IN USB_IO_CONTROLLER_DEVICE     *ParentHubController,
 | |
|   IN UINT8                        ParentPort,
 | |
|   IN OUT USB_IO_DEVICE            *Device
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Set Transaction Translator parameter
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     ParentHubController  - Controller structure of the parent Hub device
 | |
|     ParentPort           - Number of parent port
 | |
|     Device               - Structure of the device
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS            Success
 | |
|     EFI_OUT_OF_RESOURCES   Cannot allocate resources
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   USB_IO_CONTROLLER_DEVICE  *AncestorHubController;
 | |
| 
 | |
|   AncestorHubController = ParentHubController;
 | |
|   Device->Translator    = NULL;
 | |
| 
 | |
|   if (EFI_USB_SPEED_HIGH == Device->DeviceSpeed) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   do {
 | |
|     if (EFI_USB_SPEED_HIGH == AncestorHubController->UsbDevice->DeviceSpeed) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     if (NULL == AncestorHubController->Parent) {
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     AncestorHubController = AncestorHubController->Parent;
 | |
|   } while (1);
 | |
| 
 | |
|   Device->Translator = AllocatePool (sizeof (EFI_USB2_HC_TRANSACTION_TRANSLATOR));
 | |
|   if (NULL == Device->Translator) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Device->Translator->TranslatorHubAddress  = AncestorHubController->UsbDevice->DeviceAddress;
 | |
|   Device->Translator->TranslatorPortNumber  = ParentPort;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| UsbUnsetTransactionTranslator (
 | |
|   USB_IO_DEVICE *Device
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Unset Transaction Translator parameter
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     Device - Structure of the device
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS    Success
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   if (Device->Translator) {
 | |
|     gBS->FreePool (Device->Translator);
 | |
|     Device->Translator = NULL;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| IdentifyDeviceSpeed (
 | |
|   USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
 | |
|   USB_IO_DEVICE             *NewDevice,
 | |
|   UINT8                     Index
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Identify speed of USB device
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     UsbBusDev  - UsbBus controller structure of the device
 | |
|     NewDevice  - Devcie controller structure
 | |
|     Index      - Number of the port
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS        Success
 | |
|     EFI_NOT_FOUND      Device release to CHC or can't be found
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS             Status;
 | |
|   EFI_USB_PORT_STATUS    HubPortStatus;
 | |
| 
 | |
|   UsbVirtualHcGetRootHubPortStatus (
 | |
|     UsbBusDev,
 | |
|     Index,
 | |
|     (EFI_USB_PORT_STATUS *) &HubPortStatus
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Check device device
 | |
|   //
 | |
|   if (!(HubPortStatus.PortStatus & USB_PORT_STAT_OWNER)) {
 | |
|     //
 | |
|     // EHC Port Owner
 | |
|     //
 | |
|     if (HubPortStatus.PortStatus & USB_PORT_STAT_HIGH_SPEED) {
 | |
|       DEBUG ((gUSBDebugLevel, "High Speed Device attached to EHC\n"));
 | |
|       NewDevice->DeviceSpeed = EFI_USB_SPEED_HIGH;
 | |
|     } else {
 | |
|       Status = ReleasePortToCHC (UsbBusDev, Index);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         DEBUG ((gUSBErrorLevel, "Fail to release port to CHC\n"));
 | |
|       } else {
 | |
|         DEBUG ((gUSBDebugLevel, "Success to release port to CHC\n"));
 | |
|       }
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
|   } else {
 | |
|     //
 | |
|     // CHC Port Owner
 | |
|     //
 | |
|     if (HubPortStatus.PortStatus & USB_PORT_STAT_LOW_SPEED) {
 | |
|       DEBUG ((gUSBDebugLevel, "Low Speed Device attached to CHC\n"));
 | |
|       NewDevice->DeviceSpeed = EFI_USB_SPEED_LOW;
 | |
|     } else {
 | |
|       DEBUG ((gUSBDebugLevel, "FULL Speed Device attached to CHC\n"));
 | |
|       NewDevice->DeviceSpeed = EFI_USB_SPEED_FULL;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ReleasePortToCHC (
 | |
|   USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
 | |
|   UINT8                     PortNum
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Set bit to release the port owner to CHC
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     UsbBusDev  - UsbBus controller structure of the device
 | |
|     PortNum    - Number of the port
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS        Success
 | |
|     EFI_DEVICE_ERROR   Fail
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = UsbVirtualHcSetRootHubPortFeature (
 | |
|             UsbBusDev,
 | |
|             PortNum,
 | |
|             EfiUsbPortOwner
 | |
|             );
 | |
| 
 | |
|   gBS->Stall (100 * 1000);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbVirtualHcGetCapability (
 | |
|   IN  USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
 | |
|   OUT UINT8                     *MaxSpeed,
 | |
|   OUT UINT8                     *PortNumber,
 | |
|   OUT UINT8                     *Is64BitCapable
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Virtual interface to Retrieves the capablility of root hub ports
 | |
|     for both Hc2 and Hc protocol.
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     UsbBusDev       - A pointer to bus controller of the device.
 | |
|     MaxSpeed        - A pointer to the number of the host controller.
 | |
|     PortNumber      - A pointer to the number of the root hub ports.
 | |
|     Is64BitCapable  - A pointer to the flag for whether controller supports
 | |
|                       64-bit memory addressing.
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS
 | |
|           The host controller capability were retrieved successfully.
 | |
|     EFI_INVALID_PARAMETER
 | |
|           MaxSpeed or PortNumber or Is64BitCapable is NULL.
 | |
|     EFI_DEVICE_ERROR
 | |
|           An error was encountered while attempting to retrieve the capabilities.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|     Status = UsbBusDev->Usb2HCInterface->GetCapability (
 | |
|                                           UsbBusDev->Usb2HCInterface,
 | |
|                                           MaxSpeed,
 | |
|                                           PortNumber,
 | |
|                                           Is64BitCapable
 | |
|                                           );
 | |
|   } else {
 | |
|     Status = UsbBusDev->UsbHCInterface->GetRootHubPortNumber (
 | |
|                                           UsbBusDev->UsbHCInterface,
 | |
|                                           PortNumber
 | |
|                                           );
 | |
|     *MaxSpeed       = EFI_USB_SPEED_FULL;
 | |
|     *Is64BitCapable = (UINT8) FALSE;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbVirtualHcReset (
 | |
|   IN  USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
 | |
|   IN UINT16                     Attributes
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Virtual interface to provides software reset for the USB host controller
 | |
|     for both Hc2 and Hc protocol.
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     UsbBusDev   - A pointer to bus controller of the device.
 | |
|     Attributes  - A bit mask of the reset operation to perform.
 | |
|                 See below for a list of the supported bit mask values.
 | |
| 
 | |
|   #define EFI_USB_HC_RESET_GLOBAL  0x0001               // Hc2 and Hc
 | |
|   #define EFI_USB_HC_RESET_HOST_CONTROLLER  0x0002      // Hc2 and Hc
 | |
|   #define EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG  0x0004    // Hc2
 | |
|   #define EFI_USB_HC_RESET_HOST_WITH_DEBUG  0x0008      // Hc2
 | |
| 
 | |
|   EFI_USB_HC_RESET_GLOBAL
 | |
|         If this bit is set, a global reset signal will be sent to the USB bus.
 | |
|         This resets all of the USB bus logic, including the USB host
 | |
|         controller hardware and all the devices attached on the USB bus.
 | |
|   EFI_USB_HC_RESET_HOST_CONTROLLER
 | |
|         If this bit is set, the USB host controller hardware will be reset.
 | |
|         No reset signal will be sent to the USB bus.
 | |
|   EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
 | |
|         If this bit is set, a global reset signal will be sent to the USB bus.
 | |
|         This resets all of the USB bus logic, including the USB host
 | |
|         controller hardware and all the devices attached on the USB bus.
 | |
|         If this is an EHCI controller and the debug port has configured, then
 | |
|         this is will still reset the host controller.
 | |
|   EFI_USB_HC_RESET_HOST_WITH_DEBUG
 | |
|         If this bit is set, the USB host controller hardware will be reset.
 | |
|         If this is an EHCI controller and the debug port has been configured,
 | |
|         then this will still reset the host controller.
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS
 | |
|         The reset operation succeeded.
 | |
|     EFI_INVALID_PARAMETER
 | |
|         Attributes is not valid.
 | |
|     EFI_UNSUPPOURTED
 | |
|         The type of reset specified by Attributes is not currently supported by
 | |
|         the host controller hardware.
 | |
|     EFI_ACCESS_DENIED
 | |
|         Reset operation is rejected due to the debug port being configured and
 | |
|         active; only EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG or
 | |
|         EFI_USB_HC_RESET_HOST_WITH_DEBUG reset Atrributes can be used to
 | |
|         perform reset operation for this host controller.
 | |
|     EFI_DEVICE_ERROR
 | |
|         An error was encountered while attempting to perform
 | |
|         the reset operation.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|     Status = UsbBusDev->Usb2HCInterface->Reset (
 | |
|                                           UsbBusDev->Usb2HCInterface,
 | |
|                                           EFI_USB_HC_RESET_GLOBAL
 | |
|                                           );
 | |
|   } else {
 | |
|     Status = UsbBusDev->UsbHCInterface->Reset (
 | |
|                                           UsbBusDev->UsbHCInterface,
 | |
|                                           EFI_USB_HC_RESET_GLOBAL
 | |
|                                           );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbVirtualHcGetState (
 | |
|   IN  USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
 | |
|   OUT EFI_USB_HC_STATE          *State
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Virtual interface to retrieves current state of the USB host controller
 | |
|     for both Hc2 and Hc protocol.
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     UsbBusDev - A pointer to bus controller of the device.
 | |
|     State     - A pointer to the EFI_USB_HC_STATE data structure that
 | |
|               indicates current state of the USB host controller.
 | |
|               Type EFI_USB_HC_STATE is defined below.
 | |
| 
 | |
|     typedef enum {
 | |
|       EfiUsbHcStateHalt,
 | |
|       EfiUsbHcStateOperational,
 | |
|       EfiUsbHcStateSuspend,
 | |
|       EfiUsbHcStateMaximum
 | |
|     } EFI_USB_HC_STATE;
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS
 | |
|             The state information of the host controller was returned in State.
 | |
|     EFI_INVALID_PARAMETER
 | |
|             State is NULL.
 | |
|     EFI_DEVICE_ERROR
 | |
|             An error was encountered while attempting to retrieve the
 | |
|             host controller's current state.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|     Status = UsbBusDev->Usb2HCInterface->GetState (
 | |
|                                           UsbBusDev->Usb2HCInterface,
 | |
|                                           State
 | |
|                                           );
 | |
|   } else {
 | |
|     Status = UsbBusDev->UsbHCInterface->GetState (
 | |
|                                           UsbBusDev->UsbHCInterface,
 | |
|                                           State
 | |
|                                           );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbVirtualHcSetState (
 | |
|   IN  USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
 | |
|   IN EFI_USB_HC_STATE           State
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Virtual interface to sets the USB host controller to a specific state
 | |
|     for both Hc2 and Hc protocol.
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     UsbBusDev   - A pointer to bus controller of the device.
 | |
|     State       - Indicates the state of the host controller that will be set.
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS
 | |
|           The USB host controller was successfully placed in the state
 | |
|           specified by State.
 | |
|     EFI_INVALID_PARAMETER
 | |
|           State is invalid.
 | |
|     EFI_DEVICE_ERROR
 | |
|           Failed to set the state specified by State due to device error.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|     Status = UsbBusDev->Usb2HCInterface->SetState (
 | |
|                                           UsbBusDev->Usb2HCInterface,
 | |
|                                           State
 | |
|                                           );
 | |
|   } else {
 | |
|     Status = UsbBusDev->UsbHCInterface->SetState (
 | |
|                                           UsbBusDev->UsbHCInterface,
 | |
|                                           State
 | |
|                                           );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbVirtualHcGetRootHubPortStatus (
 | |
|   IN  USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
 | |
|   IN  UINT8                     PortNumber,
 | |
|   OUT EFI_USB_PORT_STATUS       *PortStatus
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Virtual interface to retrieves the current status of a USB root hub port
 | |
|     both for Hc2 and Hc protocol.
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     UsbBusDev   - A pointer to bus controller of the device.
 | |
|     PortNumber  - Specifies the root hub port from which the status
 | |
|                 is to be retrieved.  This value is zero-based. For example,
 | |
|                 if a root hub has two ports, then the first port is numbered 0,
 | |
|                 and the second port is numbered 1.
 | |
|     PortStatus  - A pointer to the current port status bits and
 | |
|                 port status change bits.
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS  The status of the USB root hub port specified by PortNumber
 | |
|                  was returned in PortStatus.
 | |
|     EFI_INVALID_PARAMETER PortNumber is invalid.
 | |
|     EFI_DEVICE_ERROR      Can't read register
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|     Status = UsbBusDev->Usb2HCInterface->GetRootHubPortStatus (
 | |
|                                           UsbBusDev->Usb2HCInterface,
 | |
|                                           PortNumber,
 | |
|                                           PortStatus
 | |
|                                           );
 | |
|   } else {
 | |
|     Status = UsbBusDev->UsbHCInterface->GetRootHubPortStatus (
 | |
|                                           UsbBusDev->UsbHCInterface,
 | |
|                                           PortNumber,
 | |
|                                           PortStatus
 | |
|                                           );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbVirtualHcSetRootHubPortFeature (
 | |
|   IN  USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
 | |
|   IN  UINT8                     PortNumber,
 | |
|   IN  EFI_USB_PORT_FEATURE      PortFeature
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Virual interface to sets a feature for the specified root hub port
 | |
|     for both Hc2 and Hc protocol.
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     UsbBusDev   - A pointer to bus controller of the device.
 | |
|     PortNumber  - Specifies the root hub port whose feature
 | |
|                 is requested to be set.
 | |
|     PortFeature - Indicates the feature selector associated
 | |
|                 with the feature set request.
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS
 | |
|         The feature specified by PortFeature was set for the
 | |
|         USB root hub port specified by PortNumber.
 | |
|     EFI_INVALID_PARAMETER
 | |
|         PortNumber is invalid or PortFeature is invalid.
 | |
|     EFI_DEVICE_ERROR
 | |
|         Can't read register
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|     Status = UsbBusDev->Usb2HCInterface->SetRootHubPortFeature (
 | |
|                                           UsbBusDev->Usb2HCInterface,
 | |
|                                           PortNumber,
 | |
|                                           PortFeature
 | |
|                                           );
 | |
|   } else {
 | |
|     Status = UsbBusDev->UsbHCInterface->SetRootHubPortFeature (
 | |
|                                           UsbBusDev->UsbHCInterface,
 | |
|                                           PortNumber,
 | |
|                                           PortFeature
 | |
|                                           );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbVirtualHcClearRootHubPortFeature (
 | |
|   IN  USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
 | |
|   IN  UINT8                     PortNumber,
 | |
|   IN  EFI_USB_PORT_FEATURE      PortFeature
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Virtual interface to clears a feature for the specified root hub port
 | |
|     for both Hc2 and Hc protocol.
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     UsbBusDev   - A pointer to bus controller of the device.
 | |
|     PortNumber  - Specifies the root hub port whose feature
 | |
|                 is requested to be cleared.
 | |
|     PortFeature - Indicates the feature selector associated with the
 | |
|                 feature clear request.
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS
 | |
|         The feature specified by PortFeature was cleared for the
 | |
|         USB root hub port specified by PortNumber.
 | |
|     EFI_INVALID_PARAMETER
 | |
|         PortNumber is invalid or PortFeature is invalid.
 | |
|     EFI_DEVICE_ERROR
 | |
|         Can't read register
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|     Status = UsbBusDev->Usb2HCInterface->ClearRootHubPortFeature (
 | |
|                                           UsbBusDev->Usb2HCInterface,
 | |
|                                           PortNumber,
 | |
|                                           PortFeature
 | |
|                                           );
 | |
|   } else {
 | |
|     Status = UsbBusDev->UsbHCInterface->ClearRootHubPortFeature (
 | |
|                                           UsbBusDev->UsbHCInterface,
 | |
|                                           PortNumber,
 | |
|                                           PortFeature
 | |
|                                           );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbVirtualHcControlTransfer (
 | |
|   IN  USB_BUS_CONTROLLER_DEVICE            *UsbBusDev,
 | |
|   IN  UINT8                                DeviceAddress,
 | |
|   IN  UINT8                                DeviceSpeed,
 | |
|   IN  UINTN                                MaximumPacketLength,
 | |
|   IN  EFI_USB_DEVICE_REQUEST               *Request,
 | |
|   IN  EFI_USB_DATA_DIRECTION               TransferDirection,
 | |
|   IN  OUT VOID                             *Data,
 | |
|   IN  OUT UINTN                            *DataLength,
 | |
|   IN  UINTN                                TimeOut,
 | |
|   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR   *Translator,
 | |
|   OUT UINT32                               *TransferResult
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Virtual interface to submits control transfer to a target USB device
 | |
|     for both Hc2 and Hc protocol.
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     UsbBusDev     - A pointer to bus controller of the device.
 | |
|     DeviceAddress - Represents the address of the target device on the USB,
 | |
|                   which is assigned during USB enumeration.
 | |
|     DeviceSpeed   - Indicates target device speed.
 | |
|     MaximumPacketLength - Indicates the maximum packet size that the
 | |
|                         default control transfer endpoint is capable of
 | |
|                         sending or receiving.
 | |
|     Request       - A pointer to the USB device request that will be sent
 | |
|                   to the USB device.
 | |
|     TransferDirection - Specifies the data direction for the transfer.
 | |
|                       There are three values available, DataIn, DataOut
 | |
|                       and NoData.
 | |
|     Data          - A pointer to the buffer of data that will be transmitted
 | |
|                   to USB device or received from USB device.
 | |
|     DataLength    - Indicates the size, in bytes, of the data buffer
 | |
|                   specified by Data.
 | |
|     TimeOut       - Indicates the maximum time, in microseconds,
 | |
|                   which the transfer is allowed to complete.
 | |
|     Translator      - A pointr to the transaction translator data.
 | |
|     TransferResult  - A pointer to the detailed result information generated
 | |
|                     by this control transfer.
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS
 | |
|         The control transfer was completed successfully.
 | |
|     EFI_OUT_OF_RESOURCES
 | |
|         The control transfer could not be completed due to a lack of resources.
 | |
|     EFI_INVALID_PARAMETER
 | |
|         Some parameters are invalid.
 | |
|     EFI_TIMEOUT
 | |
|         The control transfer failed due to timeout.
 | |
|     EFI_DEVICE_ERROR
 | |
|         The control transfer failed due to host controller or device error.
 | |
|         Caller should check TranferResult for detailed error information.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   BOOLEAN     IsSlowDevice;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|     Status = UsbBusDev->Usb2HCInterface->ControlTransfer (
 | |
|                                           UsbBusDev->Usb2HCInterface,
 | |
|                                           DeviceAddress,
 | |
|                                           DeviceSpeed,
 | |
|                                           MaximumPacketLength,
 | |
|                                           Request,
 | |
|                                           TransferDirection,
 | |
|                                           Data,
 | |
|                                           DataLength,
 | |
|                                           TimeOut,
 | |
|                                           Translator,
 | |
|                                           TransferResult
 | |
|                                           );
 | |
|   } else {
 | |
|     IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);
 | |
|     Status = UsbBusDev->UsbHCInterface->ControlTransfer (
 | |
|                                           UsbBusDev->UsbHCInterface,
 | |
|                                           DeviceAddress,
 | |
|                                           IsSlowDevice,
 | |
|                                           (UINT8) MaximumPacketLength,
 | |
|                                           Request,
 | |
|                                           TransferDirection,
 | |
|                                           Data,
 | |
|                                           DataLength,
 | |
|                                           TimeOut,
 | |
|                                           TransferResult
 | |
|                                           );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbVirtualHcBulkTransfer (
 | |
|   IN  USB_BUS_CONTROLLER_DEVICE           *UsbBusDev,
 | |
|   IN  UINT8                               DeviceAddress,
 | |
|   IN  UINT8                               EndPointAddress,
 | |
|   IN  UINT8                               DeviceSpeed,
 | |
|   IN  UINTN                               MaximumPacketLength,
 | |
|   IN  UINT8                               DataBuffersNumber,
 | |
|   IN  OUT VOID                            *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
 | |
|   IN  OUT UINTN                           *DataLength,
 | |
|   IN  OUT UINT8                           *DataToggle,
 | |
|   IN  UINTN                               TimeOut,
 | |
|   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
 | |
|   OUT UINT32                              *TransferResult
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Virtual interface to submits bulk transfer to a bulk endpoint of a USB device
 | |
|     both for Hc2 and Hc protocol.
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     UsbBusDev         - A pointer to bus controller of the device.
 | |
|     DeviceAddress     - Represents the address of the target device on the USB,
 | |
|                       which is assigned during USB enumeration.
 | |
|     EndPointAddress   - The combination of an endpoint number and an
 | |
|                       endpoint direction of the target USB device.
 | |
|                       Each endpoint address supports data transfer in
 | |
|                       one direction except the control endpoint
 | |
|                       (whose default endpoint address is 0).
 | |
|                       It is the caller's responsibility to make sure that
 | |
|                       the EndPointAddress represents a bulk endpoint.
 | |
|     DeviceSpeed       - Indicates device speed. The supported values are EFI_USB_SPEED_FULL
 | |
|                       and EFI_USB_SPEED_HIGH.
 | |
|     MaximumPacketLength - Indicates the maximum packet size the target endpoint
 | |
|                         is capable of sending or receiving.
 | |
|     DataBuffersNumber - Number of data buffers prepared for the transfer.
 | |
|     Data              - Array of pointers to the buffers of data that will be transmitted
 | |
|                       to USB device or received from USB device.
 | |
|     DataLength        - When input, indicates the size, in bytes, of the data buffer
 | |
|                       specified by Data. When output, indicates the actually
 | |
|                       transferred data size.
 | |
|     DataToggle        - A pointer to the data toggle value. On input, it indicates
 | |
|                       the initial data toggle value the bulk transfer should adopt;
 | |
|                       on output, it is updated to indicate the data toggle value
 | |
|                       of the subsequent bulk transfer.
 | |
|     Translator        - A pointr to the transaction translator data.
 | |
|     TimeOut           - Indicates the maximum time, in microseconds, which the
 | |
|                       transfer is allowed to complete.
 | |
|     TransferResult    - A pointer to the detailed result information of the
 | |
|                       bulk transfer.
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS
 | |
|         The bulk transfer was completed successfully.
 | |
|     EFI_OUT_OF_RESOURCES
 | |
|         The bulk transfer could not be submitted due to lack of resource.
 | |
|     EFI_INVALID_PARAMETER
 | |
|         Some parameters are invalid.
 | |
|     EFI_TIMEOUT
 | |
|         The bulk transfer failed due to timeout.
 | |
|     EFI_DEVICE_ERROR
 | |
|         The bulk transfer failed due to host controller or device error.
 | |
|         Caller should check TranferResult for detailed error information.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|     Status = UsbBusDev->Usb2HCInterface->BulkTransfer (
 | |
|                                           UsbBusDev->Usb2HCInterface,
 | |
|                                           DeviceAddress,
 | |
|                                           EndPointAddress,
 | |
|                                           DeviceSpeed,
 | |
|                                           MaximumPacketLength,
 | |
|                                           DataBuffersNumber,
 | |
|                                           Data,
 | |
|                                           DataLength,
 | |
|                                           DataToggle,
 | |
|                                           TimeOut,
 | |
|                                           Translator,
 | |
|                                           TransferResult
 | |
|                                           );
 | |
|   } else {
 | |
|     Status = UsbBusDev->UsbHCInterface->BulkTransfer (
 | |
|                                           UsbBusDev->UsbHCInterface,
 | |
|                                           DeviceAddress,
 | |
|                                           EndPointAddress,
 | |
|                                           (UINT8) MaximumPacketLength,
 | |
|                                           *Data,
 | |
|                                           DataLength,
 | |
|                                           DataToggle,
 | |
|                                           TimeOut,
 | |
|                                           TransferResult
 | |
|                                           );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbVirtualHcAsyncInterruptTransfer (
 | |
|   IN  USB_BUS_CONTROLLER_DEVICE             * UsbBusDev,
 | |
|   IN  UINT8                                 DeviceAddress,
 | |
|   IN  UINT8                                 EndPointAddress,
 | |
|   IN  UINT8                                 DeviceSpeed,
 | |
|   IN  UINTN                                 MaximumPacketLength,
 | |
|   IN  BOOLEAN                               IsNewTransfer,
 | |
|   IN OUT UINT8                              *DataToggle,
 | |
|   IN  UINTN                                 PollingInterval,
 | |
|   IN  UINTN                                 DataLength,
 | |
|   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,
 | |
|   IN  EFI_ASYNC_USB_TRANSFER_CALLBACK       CallBackFunction,
 | |
|   IN  VOID                                  *Context OPTIONAL
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Virtual interface to submits an asynchronous interrupt transfer to an
 | |
|     interrupt endpoint of a USB device for both Hc2 and Hc protocol.
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     UsbBusDev       - A pointer to bus controller of the device.
 | |
|     DeviceAddress   - Represents the address of the target device on the USB,
 | |
|                     which is assigned during USB enumeration.
 | |
|     EndPointAddress - The combination of an endpoint number and an endpoint
 | |
|                     direction of the target USB device. Each endpoint address
 | |
|                     supports data transfer in one direction except the
 | |
|                     control endpoint (whose default endpoint address is 0).
 | |
|                     It is the caller's responsibility to make sure that
 | |
|                     the EndPointAddress represents an interrupt endpoint.
 | |
|     DeviceSpeed     - Indicates device speed.
 | |
|     MaximumPacketLength  - Indicates the maximum packet size the target endpoint
 | |
|                          is capable of sending or receiving.
 | |
|     IsNewTransfer   - If TRUE, an asynchronous interrupt pipe is built between
 | |
|                     the host and the target interrupt endpoint.
 | |
|                     If FALSE, the specified asynchronous interrupt pipe
 | |
|                     is canceled.
 | |
|     DataToggle      - A pointer to the data toggle value.  On input, it is valid
 | |
|                     when IsNewTransfer is TRUE, and it indicates the initial
 | |
|                     data toggle value the asynchronous interrupt transfer
 | |
|                     should adopt.
 | |
|                     On output, it is valid when IsNewTransfer is FALSE,
 | |
|                     and it is updated to indicate the data toggle value of
 | |
|                     the subsequent asynchronous interrupt transfer.
 | |
|     PollingInterval - Indicates the interval, in milliseconds, that the
 | |
|                     asynchronous interrupt transfer is polled.
 | |
|                     This parameter is required when IsNewTransfer is TRUE.
 | |
|     DataLength      - Indicates the length of data to be received at the
 | |
|                     rate specified by PollingInterval from the target
 | |
|                     asynchronous interrupt endpoint.  This parameter
 | |
|                     is only required when IsNewTransfer is TRUE.
 | |
|     Translator      - A pointr to the transaction translator data.
 | |
|     CallBackFunction  - The Callback function.This function is called at the
 | |
|                       rate specified by PollingInterval.This parameter is
 | |
|                       only required when IsNewTransfer is TRUE.
 | |
|     Context         - The context that is passed to the CallBackFunction.
 | |
|                     - This is an optional parameter and may be NULL.
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS
 | |
|         The asynchronous interrupt transfer request has been successfully
 | |
|         submitted or canceled.
 | |
|     EFI_INVALID_PARAMETER
 | |
|         Some parameters are invalid.
 | |
|     EFI_OUT_OF_RESOURCES
 | |
|         The request could not be completed due to a lack of resources.
 | |
|     EFI_DEVICE_ERROR
 | |
|         Can't read register
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   BOOLEAN     IsSlowDevice;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|     Status = UsbBusDev->Usb2HCInterface->AsyncInterruptTransfer (
 | |
|                                           UsbBusDev->Usb2HCInterface,
 | |
|                                           DeviceAddress,
 | |
|                                           EndPointAddress,
 | |
|                                           DeviceSpeed,
 | |
|                                           MaximumPacketLength,
 | |
|                                           IsNewTransfer,
 | |
|                                           DataToggle,
 | |
|                                           PollingInterval,
 | |
|                                           DataLength,
 | |
|                                           Translator,
 | |
|                                           CallBackFunction,
 | |
|                                           Context
 | |
|                                           );
 | |
|   } else {
 | |
|     IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);
 | |
|     Status = UsbBusDev->UsbHCInterface->AsyncInterruptTransfer (
 | |
|                                           UsbBusDev->UsbHCInterface,
 | |
|                                           DeviceAddress,
 | |
|                                           EndPointAddress,
 | |
|                                           IsSlowDevice,
 | |
|                                           (UINT8) MaximumPacketLength,
 | |
|                                           IsNewTransfer,
 | |
|                                           DataToggle,
 | |
|                                           PollingInterval,
 | |
|                                           DataLength,
 | |
|                                           CallBackFunction,
 | |
|                                           Context
 | |
|                                           );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbVirtualHcSyncInterruptTransfer (
 | |
|   IN  USB_BUS_CONTROLLER_DEVICE             *UsbBusDev,
 | |
|   IN  UINT8                                 DeviceAddress,
 | |
|   IN  UINT8                                 EndPointAddress,
 | |
|   IN  UINT8                                 DeviceSpeed,
 | |
|   IN  UINTN                                 MaximumPacketLength,
 | |
|   IN OUT VOID                               *Data,
 | |
|   IN OUT UINTN                              *DataLength,
 | |
|   IN OUT UINT8                              *DataToggle,
 | |
|   IN  UINTN                                 TimeOut,
 | |
|   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
 | |
|   OUT UINT32                                *TransferResult
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Vitual interface to submits synchronous interrupt transfer to an interrupt endpoint
 | |
|     of a USB device for both Hc2 and Hc protocol.
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     UsbBusDev       - A pointer to bus controller of the device.
 | |
|     DeviceAddress   - Represents the address of the target device on the USB,
 | |
|                     which is assigned during USB enumeration.
 | |
|     EndPointAddress   - The combination of an endpoint number and an endpoint
 | |
|                       direction of the target USB device. Each endpoint
 | |
|                       address supports data transfer in one direction
 | |
|                       except the control endpoint (whose default
 | |
|                       endpoint address is 0). It is the caller's responsibility
 | |
|                       to make sure that the EndPointAddress represents
 | |
|                       an interrupt endpoint.
 | |
|     DeviceSpeed     - Indicates device speed.
 | |
|     MaximumPacketLength - Indicates the maximum packet size the target endpoint
 | |
|                         is capable of sending or receiving.
 | |
|     Data            - A pointer to the buffer of data that will be transmitted
 | |
|                     to USB device or received from USB device.
 | |
|     DataLength      - On input, the size, in bytes, of the data buffer specified
 | |
|                     by Data. On output, the number of bytes transferred.
 | |
|     DataToggle      - A pointer to the data toggle value. On input, it indicates
 | |
|                     the initial data toggle value the synchronous interrupt
 | |
|                     transfer should adopt;
 | |
|                     on output, it is updated to indicate the data toggle value
 | |
|                     of the subsequent synchronous interrupt transfer.
 | |
|     TimeOut         - Indicates the maximum time, in microseconds, which the
 | |
|                     transfer is allowed to complete.
 | |
|     Translator      - A pointr to the transaction translator data.
 | |
|     TransferResult  - A pointer to the detailed result information from
 | |
|                     the synchronous interrupt transfer.
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_SUCCESS
 | |
|         The synchronous interrupt transfer was completed successfully.
 | |
|     EFI_OUT_OF_RESOURCES
 | |
|         The synchronous interrupt transfer could not be submitted due
 | |
|         to lack of resource.
 | |
|     EFI_INVALID_PARAMETER
 | |
|         Some parameters are invalid.
 | |
|     EFI_TIMEOUT
 | |
|         The synchronous interrupt transfer failed due to timeout.
 | |
|     EFI_DEVICE_ERROR
 | |
|         The synchronous interrupt transfer failed due to host controller
 | |
|         or device error. Caller should check TranferResult for detailed
 | |
|         error information.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   BOOLEAN     IsSlowDevice;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   if (UsbBusDev->Hc2ProtocolSupported) {
 | |
|     Status = UsbBusDev->Usb2HCInterface->SyncInterruptTransfer (
 | |
|                                           UsbBusDev->Usb2HCInterface,
 | |
|                                           DeviceAddress,
 | |
|                                           EndPointAddress,
 | |
|                                           DeviceSpeed,
 | |
|                                           MaximumPacketLength,
 | |
|                                           Data,
 | |
|                                           DataLength,
 | |
|                                           DataToggle,
 | |
|                                           TimeOut,
 | |
|                                           Translator,
 | |
|                                           TransferResult
 | |
|                                           );
 | |
|   } else {
 | |
|     IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);
 | |
|     Status = UsbBusDev->UsbHCInterface->SyncInterruptTransfer (
 | |
|                                           UsbBusDev->UsbHCInterface,
 | |
|                                           DeviceAddress,
 | |
|                                           EndPointAddress,
 | |
|                                           IsSlowDevice,
 | |
|                                           (UINT8) MaximumPacketLength,
 | |
|                                           Data,
 | |
|                                           DataLength,
 | |
|                                           DataToggle,
 | |
|                                           TimeOut,
 | |
|                                           TransferResult
 | |
|                                           );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbVirtualHcIsochronousTransfer (
 | |
|   IN  USB_BUS_CONTROLLER_DEVICE             *UsbBusDev,
 | |
|   IN  UINT8                                 DeviceAddress,
 | |
|   IN  UINT8                                 EndPointAddress,
 | |
|   IN  UINT8                                 DeviceSpeed,
 | |
|   IN  UINTN                                 MaximumPacketLength,
 | |
|   IN  UINT8                                 DataBuffersNumber,
 | |
|   IN  OUT VOID                              *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
 | |
|   IN  UINTN                                 DataLength,
 | |
|   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR    *Translator,
 | |
|   OUT UINT32                                *TransferResult
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Virtual interface to submits isochronous transfer to a target USB device
 | |
|     for both Hc2 and Hc protocol.
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     UsbBusDev        - A pointer to bus controller of the device.
 | |
|     DeviceAddress    - Represents the address of the target device on the USB,
 | |
|                      which is assigned during USB enumeration.
 | |
|     EndPointAddress  - End point address
 | |
|     DeviceSpeed      - Indicates device speed.
 | |
|     MaximumPacketLength    - Indicates the maximum packet size that the
 | |
|                            default control transfer endpoint is capable of
 | |
|                            sending or receiving.
 | |
|     DataBuffersNumber - Number of data buffers prepared for the transfer.
 | |
|     Data              - Array of pointers to the buffers of data that will be
 | |
|                       transmitted to USB device or received from USB device.
 | |
|     DataLength        - Indicates the size, in bytes, of the data buffer
 | |
|                       specified by Data.
 | |
|     Translator        - A pointr to the transaction translator data.
 | |
|     TransferResult    - A pointer to the detailed result information generated
 | |
|                       by this control transfer.
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_UNSUPPORTED
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UsbVirtualHcAsyncIsochronousTransfer (
 | |
|   IN  USB_BUS_CONTROLLER_DEVICE           *UsbBusDev,
 | |
|   IN  UINT8                               DeviceAddress,
 | |
|   IN  UINT8                               EndPointAddress,
 | |
|   IN  UINT8                               DeviceSpeed,
 | |
|   IN  UINTN                               MaximumPacketLength,
 | |
|   IN  UINT8                               DataBuffersNumber,
 | |
|   IN OUT VOID                             *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
 | |
|   IN  UINTN                               DataLength,
 | |
|   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
 | |
|   IN  EFI_ASYNC_USB_TRANSFER_CALLBACK     IsochronousCallBack,
 | |
|   IN  VOID                                *Context
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|     Vitual interface to submits Async isochronous transfer to a target USB device
 | |
|     for both Hc2 and Hc protocol.
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     UsbBusDev           - A pointer to bus controller of the device.
 | |
|     DeviceAddress       - Represents the address of the target device on the USB,
 | |
|                         which is assigned during USB enumeration.
 | |
|     EndPointAddress     - End point address
 | |
|     DeviceSpeed         - Indicates device speed.
 | |
|     MaximumPacketLength - Indicates the maximum packet size that the
 | |
|                         default control transfer endpoint is capable of
 | |
|                         sending or receiving.
 | |
|     DataBuffersNumber   - Number of data buffers prepared for the transfer.
 | |
|     Data                - Array of pointers to the buffers of data that will be transmitted
 | |
|                         to USB device or received from USB device.
 | |
|     DataLength          - Indicates the size, in bytes, of the data buffer
 | |
|                         specified by Data.
 | |
|     Translator          - A pointr to the transaction translator data.
 | |
|     IsochronousCallBack - When the transfer complete, the call back function will be called
 | |
|     Context             - Pass to the call back function as parameter
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     EFI_UNSUPPORTED
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 |