2. Use ZeroMem to replace gBS->SetMem; 3. Remove marked code; 4. Add IsHub judgement in UsbPortReset function to following EFI1.1 spec; 5. Add brackets for macro definition git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1740 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			2828 lines
		
	
	
		
			78 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2828 lines
		
	
	
		
			78 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:
 | 
						|
 | 
						|
    Ehci.c
 | 
						|
    
 | 
						|
Abstract: 
 | 
						|
    
 | 
						|
 | 
						|
Revision History
 | 
						|
--*/
 | 
						|
 | 
						|
 | 
						|
#include "Ehci.h"
 | 
						|
 | 
						|
 | 
						|
GLOBAL_REMOVE_IF_UNREFERENCED UINTN    gEHCDebugLevel  = EFI_D_INFO;
 | 
						|
GLOBAL_REMOVE_IF_UNREFERENCED UINTN    gEHCErrorLevel  = EFI_D_ERROR;
 | 
						|
 | 
						|
 | 
						|
//
 | 
						|
// Prototypes
 | 
						|
// Driver model protocol interface
 | 
						|
//
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciDriverBindingSupported (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL     *This,
 | 
						|
  IN EFI_HANDLE                      Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciDriverBindingStart (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL     *This,
 | 
						|
  IN EFI_HANDLE                      Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciDriverBindingStop (
 | 
						|
  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
 | 
						|
  IN  EFI_HANDLE                      Controller,
 | 
						|
  IN  UINTN                           NumberOfChildren,
 | 
						|
  IN  EFI_HANDLE                      *ChildHandleBuffer
 | 
						|
  );
 | 
						|
 | 
						|
//
 | 
						|
// Ehci protocol interface
 | 
						|
//
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciGetCapability (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL   *This,
 | 
						|
  OUT UINT8                  *MaxSpeed,
 | 
						|
  OUT UINT8                  *PortNumber,
 | 
						|
  OUT UINT8                  *Is64BitCapable
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciReset (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL     *This,
 | 
						|
  IN  UINT16                   Attributes
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciGetState (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL     *This,
 | 
						|
  OUT EFI_USB_HC_STATE         *State
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciSetState (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL     *This,
 | 
						|
  IN  EFI_USB_HC_STATE         State
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciControlTransfer (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL                 *This,
 | 
						|
  IN  UINT8                                DeviceAddress,
 | 
						|
  IN  UINT8                                DeviceSpeed,
 | 
						|
  IN  UINTN                                MaximumPacketLength,
 | 
						|
  IN  EFI_USB_DEVICE_REQUEST               *Request,
 | 
						|
  IN  EFI_USB_DATA_DIRECTION               TransferDirection,
 | 
						|
  IN  OUT VOID                             *Data,
 | 
						|
  IN  OUT UINTN                            *DataLength,
 | 
						|
  IN  UINTN                                TimeOut,
 | 
						|
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR   *Translator,
 | 
						|
  OUT UINT32                               *TransferResult
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciBulkTransfer (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL                *This,
 | 
						|
  IN  UINT8                               DeviceAddress,
 | 
						|
  IN  UINT8                               EndPointAddress,
 | 
						|
  IN  UINT8                               DeviceSpeed,
 | 
						|
  IN  UINTN                               MaximumPacketLength,
 | 
						|
  IN  UINT8                               DataBuffersNumber,
 | 
						|
  IN  OUT VOID                            *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
 | 
						|
  IN  OUT UINTN                           *DataLength,
 | 
						|
  IN  OUT UINT8                           *DataToggle,
 | 
						|
  IN  UINTN                               TimeOut,
 | 
						|
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
 | 
						|
  OUT UINT32                              *TransferResult
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciAsyncInterruptTransfer (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL                  * This,
 | 
						|
  IN  UINT8                                 DeviceAddress,
 | 
						|
  IN  UINT8                                 EndPointAddress,
 | 
						|
  IN  UINT8                                 DeviceSpeed,
 | 
						|
  IN  UINTN                                 MaxiumPacketLength,
 | 
						|
  IN  BOOLEAN                               IsNewTransfer,
 | 
						|
  IN  OUT UINT8                             *DataToggle,
 | 
						|
  IN  UINTN                                 PollingInterval,
 | 
						|
  IN  UINTN                                 DataLength,
 | 
						|
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR    *Translator,
 | 
						|
  IN  EFI_ASYNC_USB_TRANSFER_CALLBACK       CallBackFunction,
 | 
						|
  IN  VOID                                  *Context OPTIONAL
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciSyncInterruptTransfer (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL                  *This,
 | 
						|
  IN  UINT8                                 DeviceAddress,
 | 
						|
  IN  UINT8                                 EndPointAddress,
 | 
						|
  IN  UINT8                                 DeviceSpeed,
 | 
						|
  IN  UINTN                                 MaximumPacketLength,
 | 
						|
  IN  OUT VOID                              *Data,
 | 
						|
  IN  OUT UINTN                             *DataLength,
 | 
						|
  IN  OUT UINT8                             *DataToggle,
 | 
						|
  IN  UINTN                                 TimeOut,
 | 
						|
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR    *Translator,
 | 
						|
  OUT UINT32                                *TransferResult
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciIsochronousTransfer (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL                  *This,
 | 
						|
  IN  UINT8                                 DeviceAddress,
 | 
						|
  IN  UINT8                                 EndPointAddress,
 | 
						|
  IN  UINT8                                 DeviceSpeed,
 | 
						|
  IN  UINTN                                 MaximumPacketLength,
 | 
						|
  IN  UINT8                                 DataBuffersNumber,
 | 
						|
  IN  OUT VOID                              *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
 | 
						|
  IN  UINTN                                 DataLength,
 | 
						|
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR    *Translator,
 | 
						|
  OUT UINT32                                *TransferResult
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciAsyncIsochronousTransfer (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL                *This,
 | 
						|
  IN  UINT8                               DeviceAddress,
 | 
						|
  IN  UINT8                               EndPointAddress,
 | 
						|
  IN  UINT8                               DeviceSpeed,
 | 
						|
  IN  UINTN                               MaximumPacketLength,
 | 
						|
  IN  UINT8                               DataBuffersNumber,
 | 
						|
  IN  OUT VOID                            *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
 | 
						|
  IN  UINTN                               DataLength,
 | 
						|
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
 | 
						|
  IN  EFI_ASYNC_USB_TRANSFER_CALLBACK     IsochronousCallBack,
 | 
						|
  IN  VOID                                *Context
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciGetRootHubPortStatus (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL     *This,
 | 
						|
  IN  UINT8                    PortNumber,
 | 
						|
  OUT EFI_USB_PORT_STATUS      *PortStatus
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciSetRootHubPortFeature (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL     *This,
 | 
						|
  IN  UINT8                    PortNumber,
 | 
						|
  IN  EFI_USB_PORT_FEATURE     PortFeature
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciClearRootHubPortFeature (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL     *This,
 | 
						|
  IN  UINT8                    PortNumber,
 | 
						|
  IN  EFI_USB_PORT_FEATURE     PortFeature
 | 
						|
  );
 | 
						|
 | 
						|
//
 | 
						|
// Ehci Driver Global Variables
 | 
						|
//
 | 
						|
EFI_DRIVER_BINDING_PROTOCOL gEhciDriverBinding = {
 | 
						|
  EhciDriverBindingSupported,
 | 
						|
  EhciDriverBindingStart,
 | 
						|
  EhciDriverBindingStop,
 | 
						|
  0x10,
 | 
						|
  NULL,
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
UINT32                      mUsbCapabilityLen;
 | 
						|
UINT32                      mDeviceSpeed[16];
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciDriverBindingSupported (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL *This,
 | 
						|
  IN EFI_HANDLE                  Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Test to see if this driver supports ControllerHandle. Any ControllerHandle
 | 
						|
    that has Usb2HcProtocol installed will be supported.
 | 
						|
 | 
						|
  Arguments:
 | 
						|
  
 | 
						|
    This                - Protocol instance pointer.
 | 
						|
    Controlle           - Handle of device to test
 | 
						|
    RemainingDevicePath - Not used
 | 
						|
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_SUCCESS       This driver supports this device.
 | 
						|
    EFI_UNSUPPORTED   This driver does not support this device.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  EFI_PCI_IO_PROTOCOL *PciIo;
 | 
						|
  USB_CLASSC          UsbClassCReg;
 | 
						|
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Test whether there is PCI IO Protocol attached on the controller handle.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **) &PciIo,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = PciIo->Pci.Read (
 | 
						|
                        PciIo,
 | 
						|
                        EfiPciIoWidthUint8,
 | 
						|
                        CLASSC,
 | 
						|
                        sizeof (USB_CLASSC) / sizeof (UINT8),
 | 
						|
                        &UsbClassCReg
 | 
						|
                        );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    gBS->CloseProtocol (
 | 
						|
          Controller,
 | 
						|
          &gEfiPciIoProtocolGuid,
 | 
						|
          This->DriverBindingHandle,
 | 
						|
          Controller
 | 
						|
          );
 | 
						|
    Status = EFI_UNSUPPORTED;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Test whether the controller belongs to Ehci type
 | 
						|
  //
 | 
						|
  if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
 | 
						|
      (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
 | 
						|
      (UsbClassCReg.PI != PCI_CLASSC_PI_EHCI)
 | 
						|
      ) {
 | 
						|
 | 
						|
    gBS->CloseProtocol (
 | 
						|
           Controller,
 | 
						|
           &gEfiPciIoProtocolGuid,
 | 
						|
           This->DriverBindingHandle,
 | 
						|
           Controller
 | 
						|
           );
 | 
						|
 | 
						|
    Status = EFI_UNSUPPORTED;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->CloseProtocol (
 | 
						|
         Controller,
 | 
						|
         &gEfiPciIoProtocolGuid,
 | 
						|
         This->DriverBindingHandle,
 | 
						|
         Controller
 | 
						|
         );
 | 
						|
 | 
						|
exit:
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciDriverBindingStart (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL *This,
 | 
						|
  IN EFI_HANDLE                  Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Starting the Usb EHCI Driver
 | 
						|
 | 
						|
  Arguments:
 | 
						|
  
 | 
						|
    This                - Protocol instance pointer.
 | 
						|
    Controller          - Handle of device to test
 | 
						|
    RemainingDevicePath - Not used
 | 
						|
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_SUCCESS           supports this device.
 | 
						|
    EFI_UNSUPPORTED       do not support this device.
 | 
						|
    EFI_DEVICE_ERROR      cannot be started due to device Error
 | 
						|
    EFI_OUT_OF_RESOURCES  cannot allocate resources
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  USB2_HC_DEV           *HcDev;
 | 
						|
  EFI_PCI_IO_PROTOCOL   *PciIo;
 | 
						|
  UINT8                 MaxSpeed;
 | 
						|
  UINT8                 PortNumber;
 | 
						|
  UINT8                 Is64BitCapable;
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Open the PciIo Protocol
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **) &PciIo,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Enable the USB Host Controller
 | 
						|
  //
 | 
						|
  Status = PciIo->Attributes (
 | 
						|
                    PciIo,
 | 
						|
                    EfiPciIoAttributeOperationEnable,
 | 
						|
                    EFI_PCI_DEVICE_ENABLE,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto close_pciio_protocol;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Allocate memory for EHC private data structure
 | 
						|
  //
 | 
						|
  HcDev = AllocateZeroPool (sizeof (USB2_HC_DEV));
 | 
						|
  if (NULL == HcDev) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto close_pciio_protocol;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Init EFI_USB2_HC_PROTOCOL interface and private data structure
 | 
						|
  //
 | 
						|
  HcDev->Usb2Hc.GetCapability             = EhciGetCapability;
 | 
						|
  HcDev->Usb2Hc.Reset                     = EhciReset;
 | 
						|
  HcDev->Usb2Hc.GetState                  = EhciGetState;
 | 
						|
  HcDev->Usb2Hc.SetState                  = EhciSetState;
 | 
						|
  HcDev->Usb2Hc.ControlTransfer           = EhciControlTransfer;
 | 
						|
  HcDev->Usb2Hc.BulkTransfer              = EhciBulkTransfer;
 | 
						|
  HcDev->Usb2Hc.AsyncInterruptTransfer    = EhciAsyncInterruptTransfer;
 | 
						|
  HcDev->Usb2Hc.SyncInterruptTransfer     = EhciSyncInterruptTransfer;
 | 
						|
  HcDev->Usb2Hc.IsochronousTransfer       = EhciIsochronousTransfer;
 | 
						|
  HcDev->Usb2Hc.AsyncIsochronousTransfer  = EhciAsyncIsochronousTransfer;
 | 
						|
  HcDev->Usb2Hc.GetRootHubPortStatus      = EhciGetRootHubPortStatus;
 | 
						|
  HcDev->Usb2Hc.SetRootHubPortFeature     = EhciSetRootHubPortFeature;
 | 
						|
  HcDev->Usb2Hc.ClearRootHubPortFeature   = EhciClearRootHubPortFeature;
 | 
						|
  HcDev->Usb2Hc.MajorRevision             = 0x1;
 | 
						|
  HcDev->Usb2Hc.MinorRevision             = 0x1;
 | 
						|
 | 
						|
  HcDev->AsyncRequestList                 = NULL;
 | 
						|
  HcDev->ControllerNameTable              = NULL;
 | 
						|
  HcDev->Signature                        = USB2_HC_DEV_SIGNATURE;
 | 
						|
  HcDev->PciIo = PciIo;
 | 
						|
 | 
						|
  //
 | 
						|
  // Install USB2_HC_PROTOCOL
 | 
						|
  //
 | 
						|
  Status = gBS->InstallProtocolInterface (
 | 
						|
                  &Controller,
 | 
						|
                  &gEfiUsb2HcProtocolGuid,
 | 
						|
                  EFI_NATIVE_INTERFACE,
 | 
						|
                  &HcDev->Usb2Hc
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto free_pool;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Get Capability Register Length
 | 
						|
  //
 | 
						|
  Status = GetCapabilityLen (HcDev);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto uninstall_usb2hc_protocol;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Create and Init Perodic Frame List
 | 
						|
  //
 | 
						|
  Status = EhciGetCapability (
 | 
						|
             &HcDev->Usb2Hc, 
 | 
						|
             &MaxSpeed, 
 | 
						|
             &PortNumber, 
 | 
						|
             &Is64BitCapable
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto uninstall_usb2hc_protocol;
 | 
						|
  }
 | 
						|
  HcDev->Is64BitCapable = Is64BitCapable;
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Create and Init Perodic Frame List
 | 
						|
  //
 | 
						|
  Status = InitialPeriodicFrameList (
 | 
						|
             HcDev, 
 | 
						|
             EHCI_MAX_FRAME_LIST_LENGTH
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto uninstall_usb2hc_protocol;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Init memory pool management
 | 
						|
  //
 | 
						|
  Status = InitialMemoryManagement (HcDev);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto deinit_perodic_frame_list;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Create AsyncRequest Polling Timer
 | 
						|
  //
 | 
						|
  Status = CreatePollingTimer (HcDev, (EFI_EVENT_NOTIFY) AsyncRequestMoniter);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto deinit_memory_management;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Default Maxximum Interrupt Interval is 8, 
 | 
						|
  // it means that 8 micro frame = 1ms
 | 
						|
  //
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Start the Host Controller
 | 
						|
  //
 | 
						|
  if (IsEhcHalted (HcDev)) {
 | 
						|
    Status = StartScheduleExecution (HcDev);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Status = EFI_DEVICE_ERROR;
 | 
						|
      goto deinit_timer;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Set all ports routing to EHC
 | 
						|
  //
 | 
						|
  Status = SetPortRoutingEhc (HcDev);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto deinit_timer;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Component name protocol
 | 
						|
  //
 | 
						|
  Status = AddUnicodeString (
 | 
						|
             "eng",
 | 
						|
             gEhciComponentName.SupportedLanguages,
 | 
						|
             &HcDev->ControllerNameTable,
 | 
						|
             L"Usb Enhanced Host Controller"
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto deinit_timer;
 | 
						|
  }
 | 
						|
 | 
						|
  goto exit;
 | 
						|
 | 
						|
  //
 | 
						|
  // Error handle process
 | 
						|
  //
 | 
						|
deinit_timer:
 | 
						|
  DestoryPollingTimer (HcDev);
 | 
						|
deinit_memory_management:
 | 
						|
  DeinitialMemoryManagement (HcDev);
 | 
						|
deinit_perodic_frame_list:
 | 
						|
  DeinitialPeriodicFrameList (HcDev);
 | 
						|
uninstall_usb2hc_protocol:
 | 
						|
  gBS->UninstallProtocolInterface (
 | 
						|
         Controller,
 | 
						|
         &gEfiUsb2HcProtocolGuid,
 | 
						|
         &HcDev->Usb2Hc
 | 
						|
         );
 | 
						|
free_pool:
 | 
						|
  gBS->FreePool (HcDev);
 | 
						|
close_pciio_protocol:
 | 
						|
  gBS->CloseProtocol (
 | 
						|
         Controller,
 | 
						|
         &gEfiPciIoProtocolGuid,
 | 
						|
         This->DriverBindingHandle,
 | 
						|
         Controller
 | 
						|
         );
 | 
						|
 | 
						|
exit:
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciDriverBindingStop (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL *This,
 | 
						|
  IN EFI_HANDLE                  Controller,
 | 
						|
  IN UINTN                       NumberOfChildren,
 | 
						|
  IN EFI_HANDLE                  *ChildHandleBuffer
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Stop this driver on ControllerHandle. Support stoping any child handles
 | 
						|
    created by this driver.
 | 
						|
 | 
						|
  Arguments:
 | 
						|
  
 | 
						|
    This              - Protocol instance pointer.
 | 
						|
    Controller        - Handle of device to stop driver on
 | 
						|
    NumberOfChildren  - Number of Children in the ChildHandleBuffer
 | 
						|
    ChildHandleBuffer - List of handles for the children we need to stop.
 | 
						|
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_SUCCESS         Success
 | 
						|
    EFI_DEVICE_ERROR    Fail
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  EFI_USB2_HC_PROTOCOL  *Usb2Hc;
 | 
						|
  USB2_HC_DEV           *HcDev;
 | 
						|
 | 
						|
  //
 | 
						|
  // Test whether the Controller handler passed in is a valid
 | 
						|
  // Usb controller handle that should be supported, if not,
 | 
						|
  // return the error status directly
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiUsb2HcProtocolGuid,
 | 
						|
                  (VOID **) &Usb2Hc,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  HcDev = USB2_HC_DEV_FROM_THIS (Usb2Hc);
 | 
						|
 | 
						|
  //
 | 
						|
  // free all the controller related memory and uninstall UHCI Protocol.
 | 
						|
  //
 | 
						|
  Status = gBS->UninstallProtocolInterface (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiUsb2HcProtocolGuid,
 | 
						|
                  Usb2Hc
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Set Host Controller state as halt
 | 
						|
  //
 | 
						|
  Status = Usb2Hc->SetState (
 | 
						|
                     Usb2Hc, 
 | 
						|
                     EfiUsbHcStateHalt
 | 
						|
                     );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Stop AsyncRequest Polling Timer
 | 
						|
  //
 | 
						|
  Status = StopPollingTimer (HcDev);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Destroy Asynchronous Request Event
 | 
						|
  //
 | 
						|
  DestoryPollingTimer (HcDev);
 | 
						|
 | 
						|
  //
 | 
						|
  // Destroy Perodic Frame List
 | 
						|
  //
 | 
						|
  DeinitialPeriodicFrameList (HcDev);
 | 
						|
 | 
						|
  //
 | 
						|
  // Deinit Ehci pool memory management
 | 
						|
  //
 | 
						|
  DeinitialMemoryManagement (HcDev);
 | 
						|
 | 
						|
  //
 | 
						|
  // Denint Unicode String Table
 | 
						|
  //
 | 
						|
  FreeUnicodeStringTable (HcDev->ControllerNameTable);
 | 
						|
 | 
						|
  //
 | 
						|
  // Disable the USB Host Controller
 | 
						|
  //
 | 
						|
  Status = HcDev->PciIo->Attributes (
 | 
						|
                           HcDev->PciIo,
 | 
						|
                           EfiPciIoAttributeOperationDisable,
 | 
						|
                           EFI_PCI_DEVICE_ENABLE,
 | 
						|
                           NULL
 | 
						|
                           );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->FreePool (HcDev);
 | 
						|
 | 
						|
  gBS->CloseProtocol (
 | 
						|
        Controller,
 | 
						|
        &gEfiPciIoProtocolGuid,
 | 
						|
        This->DriverBindingHandle,
 | 
						|
        Controller
 | 
						|
        );
 | 
						|
 | 
						|
exit:
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciGetCapability (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL *This,
 | 
						|
  OUT UINT8                *MaxSpeed,
 | 
						|
  OUT UINT8                *PortNumber,
 | 
						|
  OUT UINT8                *Is64BitCapable
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Retrieves the capablility of root hub ports.
 | 
						|
    
 | 
						|
  Arguments:
 | 
						|
  
 | 
						|
    This            - A pointer to the EFI_USB_HC_PROTOCOL instance.
 | 
						|
    MaxSpeed        - A pointer to the number of the host controller.
 | 
						|
    PortNumber      - A pointer to the number of the root hub ports.
 | 
						|
    Is64BitCapable  - A pointer to the flag for whether controller supports 
 | 
						|
                      64-bit memory addressing.
 | 
						|
    
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_SUCCESS            host controller capability were retrieved successfully.
 | 
						|
    EFI_INVALID_PARAMETER  MaxSpeed or PortNumber or Is64BitCapable is NULL.
 | 
						|
    EFI_DEVICE_ERROR       An error was encountered while attempting to retrieve the capabilities.  
 | 
						|
          
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  USB2_HC_DEV *HcDev;
 | 
						|
  UINT32      HcStructParamsAddr;
 | 
						|
  UINT32      HcStructParamsReg;
 | 
						|
  UINT32      HcCapParamsAddr;
 | 
						|
  UINT32      HcCapParamsReg;
 | 
						|
 | 
						|
  if (MaxSpeed == NULL || PortNumber == NULL || Is64BitCapable == NULL) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  HcStructParamsAddr  = HCSPARAMS;
 | 
						|
  HcCapParamsAddr     = HCCPARAMS;
 | 
						|
  HcDev               = USB2_HC_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  Status = ReadEhcCapabiltiyReg (
 | 
						|
             HcDev,
 | 
						|
             HcStructParamsAddr,
 | 
						|
             &HcStructParamsReg
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = ReadEhcCapabiltiyReg (
 | 
						|
             HcDev,
 | 
						|
             HcCapParamsAddr,
 | 
						|
             &HcCapParamsReg
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  *MaxSpeed       = EFI_USB_SPEED_HIGH;
 | 
						|
  *PortNumber     = (UINT8) (HcStructParamsReg & HCSP_NPORTS);
 | 
						|
  *Is64BitCapable = (UINT8) (HcCapParamsReg & HCCP_64BIT);
 | 
						|
 | 
						|
exit:
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciReset (
 | 
						|
  IN EFI_USB2_HC_PROTOCOL *This,
 | 
						|
  IN UINT16               Attributes
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Provides software reset for the USB host controller.
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
  
 | 
						|
  This        - A pointer to the EFI_USB2_HC_PROTOCOL instance.  
 | 
						|
  Attributes  - A bit mask of the reset operation to perform. 
 | 
						|
                See below for a list of the supported bit mask values.
 | 
						|
  
 | 
						|
  #define EFI_USB_HC_RESET_GLOBAL  0x0001
 | 
						|
  #define EFI_USB_HC_RESET_HOST_CONTROLLER  0x0002
 | 
						|
  #define EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG  0x0004
 | 
						|
  #define EFI_USB_HC_RESET_HOST_WITH_DEBUG  0x0008
 | 
						|
 | 
						|
  EFI_USB_HC_RESET_GLOBAL 
 | 
						|
        If this bit is set, a global reset signal will be sent to the USB bus.
 | 
						|
        This resets all of the USB bus logic, including the USB host 
 | 
						|
        controller hardware and all the devices attached on the USB bus.
 | 
						|
  EFI_USB_HC_RESET_HOST_CONTROLLER  
 | 
						|
        If this bit is set, the USB host controller hardware will be reset. 
 | 
						|
        No reset signal will be sent to the USB bus.
 | 
						|
  EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
 | 
						|
        If this bit is set, a global reset signal will be sent to the USB bus.
 | 
						|
        This resets all of the USB bus logic, including the USB host 
 | 
						|
        controller hardware and all the devices attached on the USB bus. 
 | 
						|
        If this is an EHCI controller and the debug port has configured, then 
 | 
						|
        this is will still reset the host controller.
 | 
						|
  EFI_USB_HC_RESET_HOST_WITH_DEBUG
 | 
						|
        If this bit is set, the USB host controller hardware will be reset. 
 | 
						|
        If this is an EHCI controller and the debug port has been configured,
 | 
						|
        then this will still reset the host controller.
 | 
						|
        
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_SUCCESS 
 | 
						|
        The reset operation succeeded.
 | 
						|
    EFI_INVALID_PARAMETER 
 | 
						|
        Attributes is not valid.
 | 
						|
    EFI_UNSUPPOURTED
 | 
						|
        The type of reset specified by Attributes is not currently supported by
 | 
						|
        the host controller hardware.
 | 
						|
    EFI_ACCESS_DENIED
 | 
						|
        Reset operation is rejected due to the debug port being configured and 
 | 
						|
        active; only EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG or 
 | 
						|
        EFI_USB_HC_RESET_HOST_WITH_DEBUG reset Atrributes can be used to
 | 
						|
        perform reset operation for this host controller.
 | 
						|
    EFI_DEVICE_ERROR  
 | 
						|
        An error was encountered while attempting to perform 
 | 
						|
        the reset operation.
 | 
						|
        
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS        Status;
 | 
						|
  USB2_HC_DEV       *HcDev;
 | 
						|
  UINTN             FrameIndex;
 | 
						|
  FRAME_LIST_ENTRY  *FrameEntryPtr;
 | 
						|
 | 
						|
  HcDev = USB2_HC_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  switch (Attributes) {
 | 
						|
 | 
						|
  case EFI_USB_HC_RESET_GLOBAL:
 | 
						|
    
 | 
						|
    //
 | 
						|
    // Same behavior as Host Controller Reset
 | 
						|
    //
 | 
						|
 | 
						|
  case EFI_USB_HC_RESET_HOST_CONTROLLER:
 | 
						|
  	
 | 
						|
    //
 | 
						|
    // Host Controller must be Halt when Reset it
 | 
						|
    //
 | 
						|
    if (IsEhcHalted (HcDev)) {
 | 
						|
      Status = ResetEhc (HcDev);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        Status = EFI_DEVICE_ERROR;
 | 
						|
        goto exit;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Set to zero by Host Controller when reset process completes
 | 
						|
      //
 | 
						|
      Status = WaitForEhcReset (HcDev, EHCI_GENERIC_TIMEOUT);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        Status = EFI_TIMEOUT;
 | 
						|
        goto exit;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      Status = EFI_DEVICE_ERROR;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // only asynchronous interrupt transfers are always alive on the bus, need to cleanup
 | 
						|
    //
 | 
						|
    CleanUpAllAsyncRequestTransfer (HcDev);
 | 
						|
    Status = ClearEhcAllStatus (HcDev);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Status = EFI_DEVICE_ERROR;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Set appropriate 4G Segment Selector
 | 
						|
    //
 | 
						|
    Status = SetCtrlDataStructSeg (HcDev);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Status = EFI_DEVICE_ERROR;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Init Perodic List Base Addr and Frame List
 | 
						|
    //
 | 
						|
    Status = SetFrameListBaseAddr (
 | 
						|
               HcDev, 
 | 
						|
               (UINT32)GET_0B_TO_31B (HcDev->PeriodicFrameListBuffer)
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Status = EFI_DEVICE_ERROR;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
    FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;
 | 
						|
    for (FrameIndex = 0; FrameIndex < HcDev->PeriodicFrameListLength; FrameIndex++) {
 | 
						|
      FrameEntryPtr->LinkTerminate = TRUE;
 | 
						|
      FrameEntryPtr++;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Start the Host Controller
 | 
						|
    //
 | 
						|
    if (IsEhcHalted (HcDev)) {
 | 
						|
      Status = StartScheduleExecution (HcDev);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        Status = EFI_DEVICE_ERROR;
 | 
						|
        goto exit;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Set all ports routing to EHC
 | 
						|
    //
 | 
						|
    Status = SetPortRoutingEhc (HcDev);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Status = EFI_DEVICE_ERROR;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:
 | 
						|
  	
 | 
						|
    Status = EFI_UNSUPPORTED;
 | 
						|
    break;
 | 
						|
 | 
						|
  case EFI_USB_HC_RESET_HOST_WITH_DEBUG:
 | 
						|
  	
 | 
						|
    Status = EFI_UNSUPPORTED;
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
exit:
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciGetState (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL *This,
 | 
						|
  OUT EFI_USB_HC_STATE     *State
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Retrieves current state of the USB host controller.
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
    
 | 
						|
    This      A pointer to the EFI_USB2_HC_PROTOCOL instance.
 | 
						|
    State     A pointer to the EFI_USB_HC_STATE data structure that 
 | 
						|
              indicates current state of the USB host controller.  
 | 
						|
              Type EFI_USB_HC_STATE is defined below.
 | 
						|
              
 | 
						|
    typedef enum {
 | 
						|
      EfiUsbHcStateHalt,
 | 
						|
      EfiUsbHcStateOperational,
 | 
						|
      EfiUsbHcStateSuspend,
 | 
						|
      EfiUsbHcStateMaximum
 | 
						|
    } EFI_USB_HC_STATE;
 | 
						|
  
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_SUCCESS 
 | 
						|
            The state information of the host controller was returned in State.
 | 
						|
    EFI_INVALID_PARAMETER 
 | 
						|
            State is NULL.
 | 
						|
    EFI_DEVICE_ERROR  
 | 
						|
            An error was encountered while attempting to retrieve the 
 | 
						|
            host controller's current state.  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  USB2_HC_DEV *HcDev;
 | 
						|
  UINT32      UsbStatusAddr;
 | 
						|
  UINT32      UsbStatusReg;
 | 
						|
 | 
						|
  if (State == NULL) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  UsbStatusAddr = USBSTS;
 | 
						|
  HcDev         = USB2_HC_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  Status = ReadEhcOperationalReg (
 | 
						|
             HcDev,
 | 
						|
             UsbStatusAddr,
 | 
						|
             &UsbStatusReg
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (UsbStatusReg & USBSTS_HCH) {
 | 
						|
    *State = EfiUsbHcStateHalt;
 | 
						|
  } else {
 | 
						|
    *State = EfiUsbHcStateOperational;
 | 
						|
  }
 | 
						|
 | 
						|
exit:
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciSetState (
 | 
						|
  IN EFI_USB2_HC_PROTOCOL *This,
 | 
						|
  IN EFI_USB_HC_STATE     State
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Sets the USB host controller to a specific state.
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
    
 | 
						|
    This     - A pointer to the EFI_USB2_HC_PROTOCOL instance.
 | 
						|
    State    - Indicates the state of the host controller that will be set.
 | 
						|
  
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_SUCCESS 
 | 
						|
          The USB host controller was successfully placed in the state 
 | 
						|
          specified by State.
 | 
						|
    EFI_INVALID_PARAMETER 
 | 
						|
          State is invalid.
 | 
						|
    EFI_DEVICE_ERROR  
 | 
						|
          Failed to set the state specified by State due to device error.  
 | 
						|
          
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS        Status;
 | 
						|
  USB2_HC_DEV       *HcDev;
 | 
						|
  UINT32            UsbCommandAddr;
 | 
						|
  UINT32            UsbCommandReg;
 | 
						|
  EFI_USB_HC_STATE  CurrentState;
 | 
						|
 | 
						|
  UsbCommandAddr  = USBCMD;
 | 
						|
  HcDev           = USB2_HC_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  Status          = EhciGetState (This, &CurrentState);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  switch (State) {
 | 
						|
 | 
						|
  case EfiUsbHcStateHalt:
 | 
						|
 | 
						|
    if (EfiUsbHcStateHalt == CurrentState) {
 | 
						|
      Status = EFI_SUCCESS;
 | 
						|
      goto exit;
 | 
						|
    } else if (EfiUsbHcStateOperational == CurrentState) {
 | 
						|
      Status = ReadEhcOperationalReg (
 | 
						|
                 HcDev,
 | 
						|
                 UsbCommandAddr,
 | 
						|
                 &UsbCommandReg
 | 
						|
                 );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        Status = EFI_DEVICE_ERROR;
 | 
						|
        goto exit;
 | 
						|
      }
 | 
						|
 | 
						|
      UsbCommandReg &= ~USBCMD_RS;
 | 
						|
      Status = WriteEhcOperationalReg (
 | 
						|
                 HcDev,
 | 
						|
                 UsbCommandAddr,
 | 
						|
                 UsbCommandReg
 | 
						|
                 );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        Status = EFI_DEVICE_ERROR;
 | 
						|
        goto exit;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Ensure the HC is in halt status after send the stop command
 | 
						|
      //
 | 
						|
      Status = WaitForEhcHalt (HcDev, EHCI_GENERIC_TIMEOUT);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        Status = EFI_TIMEOUT;
 | 
						|
        goto exit;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiUsbHcStateOperational:
 | 
						|
  	
 | 
						|
    if (IsEhcSysError (HcDev)) {
 | 
						|
      Status = EFI_DEVICE_ERROR;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
    if (EfiUsbHcStateOperational == CurrentState) {
 | 
						|
      Status = EFI_SUCCESS;
 | 
						|
      goto exit;
 | 
						|
    } else if (EfiUsbHcStateHalt == CurrentState) {
 | 
						|
      //
 | 
						|
      // Set Host Controller Run
 | 
						|
      //
 | 
						|
      Status = ReadEhcOperationalReg (
 | 
						|
                 HcDev,
 | 
						|
                 UsbCommandAddr,
 | 
						|
                 &UsbCommandReg
 | 
						|
                 );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        return EFI_DEVICE_ERROR;
 | 
						|
      }
 | 
						|
 | 
						|
      UsbCommandReg |= USBCMD_RS;
 | 
						|
      Status = WriteEhcOperationalReg (
 | 
						|
                 HcDev,
 | 
						|
                 UsbCommandAddr,
 | 
						|
                 UsbCommandReg
 | 
						|
                 );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        Status = EFI_DEVICE_ERROR;
 | 
						|
        goto exit;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiUsbHcStateSuspend:
 | 
						|
  	
 | 
						|
    Status = EFI_UNSUPPORTED;
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
  	
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
exit:
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciGetRootHubPortStatus (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL *This,
 | 
						|
  IN  UINT8                PortNumber,
 | 
						|
  OUT EFI_USB_PORT_STATUS  *PortStatus
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Retrieves the current status of a USB root hub port.
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
  
 | 
						|
    This        - A pointer to the EFI_USB2_HC_PROTOCOL.
 | 
						|
    PortNumber  - Specifies the root hub port from which the status 
 | 
						|
                  is to be retrieved.  This value is zero-based. For example, 
 | 
						|
                  if a root hub has two ports, then the first port is numbered 0,
 | 
						|
                  and the second port is numbered 1.
 | 
						|
    PortStatus  - A pointer to the current port status bits and 
 | 
						|
                  port status change bits.  
 | 
						|
  
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_SUCCESS           The status of the USB root hub port specified 
 | 
						|
                          by PortNumber was returned in PortStatus.
 | 
						|
    EFI_INVALID_PARAMETER PortNumber is invalid. 
 | 
						|
    EFI_DEVICE_ERROR      Can't read register     
 | 
						|
    
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  USB2_HC_DEV *HcDev;
 | 
						|
  UINT32      PortStatusControlAddr;
 | 
						|
  UINT32      PortStatusControlReg;
 | 
						|
  UINT8       MaxSpeed;
 | 
						|
  UINT8       TotalPortNumber;
 | 
						|
  UINT8       Is64BitCapable;
 | 
						|
 | 
						|
  if (PortStatus == NULL) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  EhciGetCapability (
 | 
						|
    This, 
 | 
						|
    &MaxSpeed, 
 | 
						|
    &TotalPortNumber, 
 | 
						|
    &Is64BitCapable
 | 
						|
    );
 | 
						|
  
 | 
						|
  if (PortNumber >= TotalPortNumber) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  HcDev                 = USB2_HC_DEV_FROM_THIS (This);
 | 
						|
  PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber));
 | 
						|
 | 
						|
  //
 | 
						|
  // Clear port status
 | 
						|
  //
 | 
						|
  PortStatus->PortStatus        = 0;
 | 
						|
  PortStatus->PortChangeStatus  = 0;
 | 
						|
 | 
						|
  Status = ReadEhcOperationalReg (
 | 
						|
             HcDev,
 | 
						|
             PortStatusControlAddr,
 | 
						|
             &PortStatusControlReg
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  //    Fill Port Status bits
 | 
						|
  //
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Current Connect Status
 | 
						|
  //
 | 
						|
  if (PORTSC_CCS & PortStatusControlReg) {
 | 
						|
    PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Port Enabled/Disabled
 | 
						|
  //
 | 
						|
  if (PORTSC_PED & PortStatusControlReg) {
 | 
						|
    PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Port Suspend
 | 
						|
  //
 | 
						|
  if (PORTSC_SUSP & PortStatusControlReg) {
 | 
						|
    PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Over-current Active
 | 
						|
  //
 | 
						|
  if (PORTSC_OCA & PortStatusControlReg) {
 | 
						|
    PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Port Reset
 | 
						|
  //
 | 
						|
  if (PORTSC_PR & PortStatusControlReg) {
 | 
						|
    PortStatus->PortStatus |= USB_PORT_STAT_RESET;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Port Power
 | 
						|
  //
 | 
						|
  if (PORTSC_PP & PortStatusControlReg) {
 | 
						|
    PortStatus->PortStatus |= USB_PORT_STAT_POWER;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Port Owner
 | 
						|
  //
 | 
						|
  if (PORTSC_PO & PortStatusControlReg) {
 | 
						|
    PortStatus->PortStatus |= USB_PORT_STAT_OWNER;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Identify device speed
 | 
						|
  //
 | 
						|
  if (PORTSC_LS_KSTATE & PortStatusControlReg) {
 | 
						|
    //
 | 
						|
    // Low Speed Device Attached
 | 
						|
    //
 | 
						|
    PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Not Low Speed Device Attached
 | 
						|
    //
 | 
						|
    if ((PORTSC_CCS & PortStatusControlReg) && (PORTSC_CSC & PortStatusControlReg)) {
 | 
						|
      mDeviceSpeed[PortNumber] = IsHighSpeedDevice (This, PortNumber) ? USB_PORT_STAT_HIGH_SPEED : 0;
 | 
						|
    }
 | 
						|
    PortStatus->PortStatus |= mDeviceSpeed[PortNumber];
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Fill Port Status Change bits
 | 
						|
  //
 | 
						|
  //
 | 
						|
  // Connect Status Change
 | 
						|
  //
 | 
						|
  if (PORTSC_CSC & PortStatusControlReg) {
 | 
						|
    PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Port Enabled/Disabled Change
 | 
						|
  //
 | 
						|
  if (PORTSC_PEDC & PortStatusControlReg) {
 | 
						|
    PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Port Over Current Change
 | 
						|
  //
 | 
						|
  if (PORTSC_OCC & PortStatusControlReg) {
 | 
						|
    PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;
 | 
						|
  }
 | 
						|
 | 
						|
exit:
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciSetRootHubPortFeature (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL     *This,
 | 
						|
  IN  UINT8                    PortNumber,
 | 
						|
  IN  EFI_USB_PORT_FEATURE     PortFeature
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Sets a feature for the specified root hub port.
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
  
 | 
						|
    This        - A pointer to the EFI_USB2_HC_PROTOCOL.
 | 
						|
    PortNumber  - Specifies the root hub port whose feature 
 | 
						|
                  is requested to be set.
 | 
						|
    PortFeature - Indicates the feature selector associated 
 | 
						|
                  with the feature set request. 
 | 
						|
  
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_SUCCESS 
 | 
						|
        The feature specified by PortFeature was set for the 
 | 
						|
        USB root hub port specified by PortNumber.
 | 
						|
    EFI_INVALID_PARAMETER 
 | 
						|
        PortNumber is invalid or PortFeature is invalid.
 | 
						|
    EFI_DEVICE_ERROR
 | 
						|
        Can't read register
 | 
						|
        
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  USB2_HC_DEV *HcDev;
 | 
						|
  UINT32      PortStatusControlAddr;
 | 
						|
  UINT32      PortStatusControlReg;
 | 
						|
  UINT8       MaxSpeed;
 | 
						|
  UINT8       TotalPortNumber;
 | 
						|
  UINT8       Is64BitCapable;
 | 
						|
 | 
						|
  EhciGetCapability (
 | 
						|
    This, 
 | 
						|
    &MaxSpeed, 
 | 
						|
    &TotalPortNumber, 
 | 
						|
    &Is64BitCapable
 | 
						|
    );
 | 
						|
 | 
						|
  if (PortNumber >= TotalPortNumber) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  HcDev                 = USB2_HC_DEV_FROM_THIS (This);
 | 
						|
  PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber));
 | 
						|
 | 
						|
  Status = ReadEhcOperationalReg (
 | 
						|
             HcDev,
 | 
						|
             PortStatusControlAddr,
 | 
						|
             &PortStatusControlReg
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  switch (PortFeature) {
 | 
						|
 | 
						|
  case EfiUsbPortEnable:
 | 
						|
  
 | 
						|
    //
 | 
						|
    // Sofeware can't set this bit, Port can only be enable by the Host Controller
 | 
						|
    // as a part of the reset and enable
 | 
						|
    //
 | 
						|
    PortStatusControlReg &= 0xffffffd5;
 | 
						|
    PortStatusControlReg |= PORTSC_PED;
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiUsbPortSuspend:
 | 
						|
  
 | 
						|
    PortStatusControlReg &= 0xffffffd5;
 | 
						|
    PortStatusControlReg |= PORTSC_SUSP;
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiUsbPortReset:
 | 
						|
  
 | 
						|
    //
 | 
						|
    // Make sure Host Controller not halt before reset it
 | 
						|
    //
 | 
						|
    if (IsEhcHalted (HcDev)) {
 | 
						|
      Status = StartScheduleExecution (HcDev);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        Status = EFI_DEVICE_ERROR;
 | 
						|
        goto exit;
 | 
						|
      }
 | 
						|
      Status = WaitForEhcNotHalt (HcDev, EHCI_GENERIC_TIMEOUT);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        DEBUG ((gEHCDebugLevel, "WaitForEhcNotHalt TimeOut\n"));
 | 
						|
        Status = EFI_DEVICE_ERROR;
 | 
						|
        goto exit;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    PortStatusControlReg &= 0xffffffd5;
 | 
						|
    PortStatusControlReg |= PORTSC_PR;
 | 
						|
    //
 | 
						|
    // Set one to PortReset bit must also set zero to PortEnable bit
 | 
						|
    //
 | 
						|
    PortStatusControlReg &= ~PORTSC_PED;
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiUsbPortPower:
 | 
						|
    
 | 
						|
    //
 | 
						|
    // No support, no operation
 | 
						|
    //
 | 
						|
    goto exit;
 | 
						|
 | 
						|
  case EfiUsbPortOwner:
 | 
						|
  
 | 
						|
    PortStatusControlReg &= 0xffffffd5;
 | 
						|
    PortStatusControlReg |= PORTSC_PO;
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
  	
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = WriteEhcOperationalReg (
 | 
						|
             HcDev,
 | 
						|
             PortStatusControlAddr,
 | 
						|
             PortStatusControlReg
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
exit:
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciClearRootHubPortFeature (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL     *This,
 | 
						|
  IN  UINT8                    PortNumber,
 | 
						|
  IN  EFI_USB_PORT_FEATURE     PortFeature
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Clears a feature for the specified root hub port.
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
  
 | 
						|
    This        - A pointer to the EFI_USB2_HC_PROTOCOL instance. 
 | 
						|
    PortNumber  - Specifies the root hub port whose feature 
 | 
						|
                  is requested to be cleared.
 | 
						|
    PortFeature - Indicates the feature selector associated with the 
 | 
						|
                  feature clear request.
 | 
						|
                  
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_SUCCESS 
 | 
						|
        The feature specified by PortFeature was cleared for the 
 | 
						|
        USB root hub port specified by PortNumber.
 | 
						|
    EFI_INVALID_PARAMETER 
 | 
						|
        PortNumber is invalid or PortFeature is invalid.
 | 
						|
    EFI_DEVICE_ERROR
 | 
						|
        Can't read register
 | 
						|
        
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  USB2_HC_DEV *HcDev;
 | 
						|
  UINT32      PortStatusControlAddr;
 | 
						|
  UINT32      PortStatusControlReg;
 | 
						|
  UINT8       MaxSpeed;
 | 
						|
  UINT8       TotalPortNumber;
 | 
						|
  UINT8       Is64BitCapable;
 | 
						|
 | 
						|
  EhciGetCapability (
 | 
						|
    This, 
 | 
						|
    &MaxSpeed, 
 | 
						|
    &TotalPortNumber, 
 | 
						|
    &Is64BitCapable
 | 
						|
    );
 | 
						|
 | 
						|
  if (PortNumber >= TotalPortNumber) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  HcDev                 = USB2_HC_DEV_FROM_THIS (This);
 | 
						|
  PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber));
 | 
						|
 | 
						|
  Status = ReadEhcOperationalReg (
 | 
						|
             HcDev,
 | 
						|
             PortStatusControlAddr,
 | 
						|
             &PortStatusControlReg
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  switch (PortFeature) {
 | 
						|
 | 
						|
  case EfiUsbPortEnable:
 | 
						|
  
 | 
						|
    //
 | 
						|
    // Clear PORT_ENABLE feature means disable port.
 | 
						|
    //
 | 
						|
    PortStatusControlReg &= 0xffffffd5;
 | 
						|
    PortStatusControlReg &= ~PORTSC_PED;
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiUsbPortSuspend:
 | 
						|
  
 | 
						|
    //
 | 
						|
    // A write of zero to this bit is ignored by the host controller.
 | 
						|
    // The host controller will unconditionally set this bit to a zero when:
 | 
						|
    //   1. software sets the Forct Port Resume bit to a zero from a one.
 | 
						|
    //   2. software sets the Port Reset bit to a one frome a zero.
 | 
						|
    //
 | 
						|
    PortStatusControlReg &= 0xffffffd5;
 | 
						|
    PortStatusControlReg &= ~PORTSC_FPR;
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiUsbPortReset:
 | 
						|
  
 | 
						|
    //
 | 
						|
    // Clear PORT_RESET means clear the reset signal.
 | 
						|
    //
 | 
						|
    PortStatusControlReg &= 0xffffffd5;
 | 
						|
    PortStatusControlReg &= ~PORTSC_PR;
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiUsbPortPower:
 | 
						|
  
 | 
						|
    //
 | 
						|
    // No support, no operation
 | 
						|
    //
 | 
						|
    goto exit;
 | 
						|
 | 
						|
  case EfiUsbPortOwner:
 | 
						|
  
 | 
						|
    //
 | 
						|
    // Clear port owner means this port owned by EHC
 | 
						|
    //
 | 
						|
    PortStatusControlReg &= 0xffffffd5;
 | 
						|
    PortStatusControlReg &= ~PORTSC_PO;
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiUsbPortConnectChange:
 | 
						|
  
 | 
						|
    //
 | 
						|
    // Clear connect status change
 | 
						|
    //
 | 
						|
    PortStatusControlReg &= 0xffffffd5;
 | 
						|
    PortStatusControlReg |= PORTSC_CSC;
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiUsbPortEnableChange:
 | 
						|
  
 | 
						|
    //
 | 
						|
    // Clear enable status change
 | 
						|
    //
 | 
						|
    PortStatusControlReg &= 0xffffffd5;
 | 
						|
    PortStatusControlReg |= PORTSC_PEDC;
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiUsbPortSuspendChange:
 | 
						|
  
 | 
						|
    //
 | 
						|
    // No related bit, no operation
 | 
						|
    //
 | 
						|
    goto exit;
 | 
						|
 | 
						|
  case EfiUsbPortOverCurrentChange:
 | 
						|
  
 | 
						|
    //
 | 
						|
    // Clear PortOverCurrent change
 | 
						|
    //
 | 
						|
    PortStatusControlReg &= 0xffffffd5;
 | 
						|
    PortStatusControlReg |= PORTSC_OCC;
 | 
						|
    break;
 | 
						|
 | 
						|
  case EfiUsbPortResetChange:
 | 
						|
  
 | 
						|
    //
 | 
						|
    // No related bit, no operation
 | 
						|
    //
 | 
						|
    goto exit;
 | 
						|
 | 
						|
  default:
 | 
						|
  	
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = WriteEhcOperationalReg (
 | 
						|
             HcDev,
 | 
						|
             PortStatusControlAddr,
 | 
						|
             PortStatusControlReg
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
exit:
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciControlTransfer (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL                 *This,
 | 
						|
  IN  UINT8                                DeviceAddress,
 | 
						|
  IN  UINT8                                DeviceSpeed,
 | 
						|
  IN  UINTN                                MaximumPacketLength,
 | 
						|
  IN  EFI_USB_DEVICE_REQUEST               *Request,
 | 
						|
  IN  EFI_USB_DATA_DIRECTION               TransferDirection,
 | 
						|
  IN  OUT VOID                             *Data,
 | 
						|
  IN  OUT UINTN                            *DataLength,
 | 
						|
  IN  UINTN                                TimeOut,
 | 
						|
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR   *Translator,
 | 
						|
  OUT UINT32                               *TransferResult
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Submits control transfer to a target USB device.
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
    
 | 
						|
    This            - A pointer to the EFI_USB2_HC_PROTOCOL instance.
 | 
						|
    DeviceAddress   - Represents the address of the target device on the USB,
 | 
						|
                      which is assigned during USB enumeration.
 | 
						|
    DeviceSpeed     - Indicates target device speed.
 | 
						|
    MaximumPacketLength - Indicates the maximum packet size that the 
 | 
						|
                         default control transfer endpoint is capable of 
 | 
						|
                         sending or receiving.
 | 
						|
    Request         - A pointer to the USB device request that will be sent 
 | 
						|
                      to the USB device. 
 | 
						|
    TransferDirection - Specifies the data direction for the transfer.
 | 
						|
                        There are three values available, DataIn, DataOut 
 | 
						|
                        and NoData.
 | 
						|
    Data            - A pointer to the buffer of data that will be transmitted 
 | 
						|
                      to USB device or received from USB device.
 | 
						|
    DataLength      - Indicates the size, in bytes, of the data buffer 
 | 
						|
                      specified by Data.
 | 
						|
    TimeOut         - Indicates the maximum time, in microseconds, 
 | 
						|
                      which the transfer is allowed to complete.
 | 
						|
    Translator      - A pointr to the transaction translator data.
 | 
						|
    TransferResult  - A pointer to the detailed result information generated 
 | 
						|
                      by this control transfer.
 | 
						|
                     
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_SUCCESS 
 | 
						|
        The control transfer was completed successfully.
 | 
						|
    EFI_OUT_OF_RESOURCES  
 | 
						|
        The control transfer could not be completed due to a lack of resources.
 | 
						|
    EFI_INVALID_PARAMETER 
 | 
						|
        Some parameters are invalid.
 | 
						|
    EFI_TIMEOUT 
 | 
						|
        The control transfer failed due to timeout.
 | 
						|
    EFI_DEVICE_ERROR  
 | 
						|
        The control transfer failed due to host controller or device error. 
 | 
						|
        Caller should check TranferResult for detailed error information.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS      Status;
 | 
						|
  USB2_HC_DEV     *HcDev;
 | 
						|
  UINT8           PktId;
 | 
						|
  EHCI_QH_ENTITY  *QhPtr;
 | 
						|
  EHCI_QTD_ENTITY *ControlQtdsPtr;
 | 
						|
  UINT8           *DataCursor;
 | 
						|
  VOID            *DataMap;
 | 
						|
  UINT8           *RequestCursor;
 | 
						|
  VOID            *RequestMap;
 | 
						|
 | 
						|
  QhPtr           = NULL;
 | 
						|
  ControlQtdsPtr  = NULL;
 | 
						|
  DataCursor      = NULL;
 | 
						|
  DataMap         = NULL;
 | 
						|
  RequestCursor   = NULL;
 | 
						|
  RequestMap      = NULL;
 | 
						|
  HcDev           = USB2_HC_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Parameters Checking
 | 
						|
  //
 | 
						|
  if (TransferDirection != EfiUsbDataIn &&
 | 
						|
  	TransferDirection != EfiUsbDataOut &&
 | 
						|
  	TransferDirection != EfiUsbNoData
 | 
						|
  	) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EfiUsbNoData == TransferDirection) {
 | 
						|
    if (NULL != Data || 0 != *DataLength) {
 | 
						|
      Status = EFI_INVALID_PARAMETER;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    if (NULL == Data || 0 == *DataLength) {
 | 
						|
      Status = EFI_INVALID_PARAMETER;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (Request == NULL || TransferResult == NULL) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_USB_SPEED_LOW == DeviceSpeed) {
 | 
						|
    if (MaximumPacketLength != 8) {
 | 
						|
      Status = EFI_INVALID_PARAMETER;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
  } else if (MaximumPacketLength != 8 &&
 | 
						|
           MaximumPacketLength != 16 &&
 | 
						|
           MaximumPacketLength != 32 &&
 | 
						|
           MaximumPacketLength != 64
 | 
						|
          ) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // If errors exist that cause host controller halt,
 | 
						|
  // then return EFI_DEVICE_ERROR.
 | 
						|
  //
 | 
						|
  if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
 | 
						|
    ClearEhcAllStatus (HcDev);
 | 
						|
    *TransferResult = EFI_USB_ERR_SYSTEM;
 | 
						|
    Status          = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Map the Request for bus master access.
 | 
						|
  // BusMasterRead means cpu write
 | 
						|
  //
 | 
						|
  Status = MapRequestBuffer (
 | 
						|
             HcDev,
 | 
						|
             Request,
 | 
						|
             &RequestCursor,
 | 
						|
             &RequestMap
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    *TransferResult = EFI_USB_ERR_SYSTEM;
 | 
						|
    Status          = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Map the source data buffer for bus master access.
 | 
						|
  //
 | 
						|
  Status = MapDataBuffer (
 | 
						|
             HcDev,
 | 
						|
             TransferDirection,
 | 
						|
             Data,
 | 
						|
             DataLength,
 | 
						|
             &PktId,
 | 
						|
             &DataCursor,
 | 
						|
             &DataMap
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    *TransferResult = EFI_USB_ERR_SYSTEM;
 | 
						|
    Status          = EFI_DEVICE_ERROR;
 | 
						|
    goto unmap_request;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Create and init control Qh
 | 
						|
  //
 | 
						|
  Status = CreateControlQh (
 | 
						|
             HcDev,
 | 
						|
             DeviceAddress,
 | 
						|
             DeviceSpeed,
 | 
						|
             MaximumPacketLength,
 | 
						|
             Translator,
 | 
						|
             &QhPtr
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    *TransferResult = EFI_USB_ERR_SYSTEM;
 | 
						|
    Status          = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto unmap_data;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Create and init control Qtds
 | 
						|
  //
 | 
						|
  Status = CreateControlQtds (
 | 
						|
             HcDev,
 | 
						|
             PktId,
 | 
						|
             RequestCursor,
 | 
						|
             DataCursor,
 | 
						|
             *DataLength,
 | 
						|
             Translator,
 | 
						|
             &ControlQtdsPtr
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    *TransferResult = EFI_USB_ERR_SYSTEM;
 | 
						|
    Status          = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto destory_qh;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Link Qtds to Qh
 | 
						|
  //
 | 
						|
  LinkQtdToQh (QhPtr, ControlQtdsPtr);
 | 
						|
 | 
						|
  ClearEhcAllStatus (HcDev);
 | 
						|
 | 
						|
  //
 | 
						|
  // Link Qh and Qtds to Async Schedule List
 | 
						|
  //
 | 
						|
  Status = LinkQhToAsyncList (HcDev, QhPtr);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    *TransferResult = EFI_USB_ERR_SYSTEM;
 | 
						|
    Status          = EFI_DEVICE_ERROR;
 | 
						|
    goto destory_qtds;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Poll Qh-Qtds execution and get result.
 | 
						|
  // detail status is returned
 | 
						|
  //
 | 
						|
  Status = ExecuteTransfer (
 | 
						|
             HcDev,
 | 
						|
             TRUE,
 | 
						|
             QhPtr,
 | 
						|
             DataLength,
 | 
						|
             0,
 | 
						|
             TimeOut,
 | 
						|
             TransferResult
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto destory_qtds;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // If has errors that cause host controller halt,
 | 
						|
  // then return EFI_DEVICE_ERROR directly.
 | 
						|
  //
 | 
						|
  if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
 | 
						|
    *TransferResult |= EFI_USB_ERR_SYSTEM;
 | 
						|
  }
 | 
						|
 | 
						|
  ClearEhcAllStatus (HcDev);
 | 
						|
 | 
						|
destory_qtds:
 | 
						|
  UnlinkQhFromAsyncList (HcDev, QhPtr);
 | 
						|
  DestoryQtds (HcDev, ControlQtdsPtr);
 | 
						|
destory_qh:
 | 
						|
  DestoryQh (HcDev, QhPtr);
 | 
						|
unmap_data:
 | 
						|
  HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);
 | 
						|
unmap_request:
 | 
						|
  HcDev->PciIo->Unmap (HcDev->PciIo, RequestMap);
 | 
						|
exit:
 | 
						|
  HcDev->PciIo->Flush (HcDev->PciIo);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciBulkTransfer (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL                *This,
 | 
						|
  IN  UINT8                               DeviceAddress,
 | 
						|
  IN  UINT8                               EndPointAddress,
 | 
						|
  IN  UINT8                               DeviceSpeed,
 | 
						|
  IN  UINTN                               MaximumPacketLength,
 | 
						|
  IN  UINT8                               DataBuffersNumber,
 | 
						|
  IN  OUT VOID                            *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
 | 
						|
  IN  OUT UINTN                           *DataLength,
 | 
						|
  IN  OUT UINT8                           *DataToggle,
 | 
						|
  IN  UINTN                               TimeOut,
 | 
						|
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
 | 
						|
  OUT UINT32                              *TransferResult
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Submits bulk transfer to a bulk endpoint of a USB device.
 | 
						|
    
 | 
						|
  Arguments:
 | 
						|
    
 | 
						|
    This              - A pointer to the EFI_USB2_HC_PROTOCOL instance.
 | 
						|
    DeviceAddress     - Represents the address of the target device on the USB,
 | 
						|
                        which is assigned during USB enumeration.               
 | 
						|
    EndPointAddress   - The combination of an endpoint number and an 
 | 
						|
                        endpoint direction of the target USB device. 
 | 
						|
                        Each endpoint address supports data transfer in 
 | 
						|
                        one direction except the control endpoint 
 | 
						|
                        (whose default endpoint address is 0). 
 | 
						|
                        It is the caller's responsibility to make sure that 
 | 
						|
                        the EndPointAddress represents a bulk endpoint.                  
 | 
						|
    DeviceSpeed       - Indicates device speed. The supported values are EFI_USB_SPEED_FULL
 | 
						|
                        and EFI_USB_SPEED_HIGH.
 | 
						|
    MaximumPacketLength - Indicates the maximum packet size the target endpoint
 | 
						|
                          is capable of sending or receiving.                 
 | 
						|
    DataBuffersNumber - Number of data buffers prepared for the transfer.
 | 
						|
    Data              - Array of pointers to the buffers of data that will be transmitted 
 | 
						|
                        to USB device or received from USB device.              
 | 
						|
    DataLength        - When input, indicates the size, in bytes, of the data buffer
 | 
						|
                        specified by Data. When output, indicates the actually 
 | 
						|
                        transferred data size.              
 | 
						|
    DataToggle        - A pointer to the data toggle value. On input, it indicates 
 | 
						|
                        the initial data toggle value the bulk transfer should adopt;
 | 
						|
                        on output, it is updated to indicate the data toggle value 
 | 
						|
                        of the subsequent bulk transfer. 
 | 
						|
    Translator        - A pointr to the transaction translator data. 
 | 
						|
    TimeOut           - Indicates the maximum time, in microseconds, which the 
 | 
						|
                        transfer is allowed to complete.              
 | 
						|
    TransferResult    - A pointer to the detailed result information of the 
 | 
						|
                        bulk transfer.
 | 
						|
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_SUCCESS 
 | 
						|
        The bulk transfer was completed successfully.
 | 
						|
    EFI_OUT_OF_RESOURCES  
 | 
						|
        The bulk transfer could not be submitted due to lack of resource.
 | 
						|
    EFI_INVALID_PARAMETER 
 | 
						|
        Some parameters are invalid.
 | 
						|
    EFI_TIMEOUT 
 | 
						|
        The bulk transfer failed due to timeout.
 | 
						|
    EFI_DEVICE_ERROR  
 | 
						|
        The bulk transfer failed due to host controller or device error.
 | 
						|
        Caller should check TranferResult for detailed error information.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  USB2_HC_DEV             *HcDev;
 | 
						|
  UINT8                   PktId;
 | 
						|
  EHCI_QH_ENTITY          *QhPtr;
 | 
						|
  EHCI_QTD_ENTITY         *BulkQtdsPtr;
 | 
						|
  UINT8                   *DataCursor;
 | 
						|
  VOID                    *DataMap;
 | 
						|
  EFI_USB_DATA_DIRECTION  TransferDirection;
 | 
						|
 | 
						|
  QhPtr       = NULL;
 | 
						|
  BulkQtdsPtr = NULL;
 | 
						|
  DataCursor  = NULL;
 | 
						|
  DataMap     = NULL;
 | 
						|
  HcDev       = USB2_HC_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Parameters Checking
 | 
						|
  //
 | 
						|
  if (NULL == DataLength ||
 | 
						|
  	NULL == Data || 
 | 
						|
  	NULL == Data[0] || 
 | 
						|
  	NULL == TransferResult
 | 
						|
  	) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (*DataLength == 0) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (1 != *DataToggle && 0 != *DataToggle) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_USB_SPEED_LOW == DeviceSpeed) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_USB_SPEED_FULL == DeviceSpeed) {
 | 
						|
    if (MaximumPacketLength > 64) {
 | 
						|
      Status = EFI_INVALID_PARAMETER;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_USB_SPEED_HIGH == DeviceSpeed) {
 | 
						|
    if (MaximumPacketLength > 512) {
 | 
						|
      Status = EFI_INVALID_PARAMETER;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // if has errors that cause host controller halt,
 | 
						|
  // then return EFI_DEVICE_ERROR directly.
 | 
						|
  //
 | 
						|
  if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
 | 
						|
    ClearEhcAllStatus (HcDev);
 | 
						|
    *TransferResult = EFI_USB_ERR_SYSTEM;
 | 
						|
    Status          = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = ClearEhcAllStatus (HcDev);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // construct QH and TD data structures,
 | 
						|
  // and link them together
 | 
						|
  //
 | 
						|
  if (EndPointAddress & 0x80) {
 | 
						|
    TransferDirection = EfiUsbDataIn;
 | 
						|
  } else {
 | 
						|
    TransferDirection = EfiUsbDataOut;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = MapDataBuffer (
 | 
						|
             HcDev,
 | 
						|
             TransferDirection,
 | 
						|
             Data[0],
 | 
						|
             DataLength,
 | 
						|
             &PktId,
 | 
						|
             &DataCursor,
 | 
						|
             &DataMap
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    *TransferResult = EFI_USB_ERR_SYSTEM;
 | 
						|
    Status          = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Create and init Bulk Qh
 | 
						|
  //
 | 
						|
  Status = CreateBulkQh (
 | 
						|
             HcDev,
 | 
						|
             DeviceAddress,
 | 
						|
             EndPointAddress,
 | 
						|
             DeviceSpeed,
 | 
						|
             *DataToggle,
 | 
						|
             MaximumPacketLength,
 | 
						|
             Translator,
 | 
						|
             &QhPtr
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    *TransferResult = EFI_USB_ERR_SYSTEM;
 | 
						|
    Status          = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto unmap_data;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Create and init Bulk Qtds
 | 
						|
  //
 | 
						|
  Status = CreateBulkOrInterruptQtds (
 | 
						|
             HcDev,
 | 
						|
             PktId,
 | 
						|
             DataCursor,
 | 
						|
             *DataLength,
 | 
						|
             Translator,
 | 
						|
             &BulkQtdsPtr
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    *TransferResult = EFI_USB_ERR_SYSTEM;
 | 
						|
    Status          = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto destory_qh;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Link Qtds to Qh
 | 
						|
  //
 | 
						|
  LinkQtdToQh (QhPtr, BulkQtdsPtr);
 | 
						|
 | 
						|
  ClearEhcAllStatus (HcDev);
 | 
						|
 | 
						|
  //
 | 
						|
  // Link Qh and qtds to Async Schedule List
 | 
						|
  //
 | 
						|
  Status = LinkQhToAsyncList (HcDev, QhPtr);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    *TransferResult = EFI_USB_ERR_SYSTEM;
 | 
						|
    Status          = EFI_DEVICE_ERROR;
 | 
						|
    goto destory_qtds;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Poll QH-TDs execution and get result.
 | 
						|
  // detail status is returned
 | 
						|
  //
 | 
						|
  Status = ExecuteTransfer (
 | 
						|
             HcDev,
 | 
						|
             FALSE,
 | 
						|
             QhPtr,
 | 
						|
             DataLength,
 | 
						|
             DataToggle,
 | 
						|
             TimeOut,
 | 
						|
             TransferResult
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto destory_qtds;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // if has errors that cause host controller halt,
 | 
						|
  // then return EFI_DEVICE_ERROR directly.
 | 
						|
  //
 | 
						|
  if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
 | 
						|
    *TransferResult |= EFI_USB_ERR_SYSTEM;
 | 
						|
  }
 | 
						|
 | 
						|
  ClearEhcAllStatus (HcDev);
 | 
						|
 | 
						|
destory_qtds:
 | 
						|
  UnlinkQhFromAsyncList (HcDev, QhPtr);
 | 
						|
  DestoryQtds (HcDev, BulkQtdsPtr);
 | 
						|
destory_qh:
 | 
						|
  DestoryQh (HcDev, QhPtr);
 | 
						|
unmap_data:
 | 
						|
  HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);
 | 
						|
exit:
 | 
						|
  HcDev->PciIo->Flush (HcDev->PciIo);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciAsyncInterruptTransfer (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL                  * This,
 | 
						|
  IN  UINT8                                 DeviceAddress,
 | 
						|
  IN  UINT8                                 EndPointAddress,
 | 
						|
  IN  UINT8                                 DeviceSpeed,
 | 
						|
  IN  UINTN                                 MaximumPacketLength,
 | 
						|
  IN  BOOLEAN                               IsNewTransfer,
 | 
						|
  IN  OUT UINT8                             *DataToggle,
 | 
						|
  IN  UINTN                                 PollingInterval,
 | 
						|
  IN  UINTN                                 DataLength,
 | 
						|
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR    * Translator,
 | 
						|
  IN  EFI_ASYNC_USB_TRANSFER_CALLBACK       CallBackFunction,
 | 
						|
  IN  VOID                                  *Context OPTIONAL
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Submits an asynchronous interrupt transfer to an 
 | 
						|
    interrupt endpoint of a USB device.
 | 
						|
    Translator parameter doesn't exist in UEFI2.0 spec, but it will be updated 
 | 
						|
    in the following specification version.
 | 
						|
    
 | 
						|
  Arguments:
 | 
						|
    
 | 
						|
    This            - A pointer to the EFI_USB2_HC_PROTOCOL instance.
 | 
						|
    DeviceAddress   - Represents the address of the target device on the USB,
 | 
						|
                      which is assigned during USB enumeration.                
 | 
						|
    EndPointAddress - The combination of an endpoint number and an endpoint 
 | 
						|
                      direction of the target USB device. Each endpoint address 
 | 
						|
                      supports data transfer in one direction except the 
 | 
						|
                      control endpoint (whose default endpoint address is 0). 
 | 
						|
                      It is the caller's responsibility to make sure that 
 | 
						|
                      the EndPointAddress represents an interrupt endpoint.              
 | 
						|
    DeviceSpeed     - Indicates device speed.
 | 
						|
    MaximumPacketLength  - Indicates the maximum packet size the target endpoint
 | 
						|
                           is capable of sending or receiving.                   
 | 
						|
    IsNewTransfer   - If TRUE, an asynchronous interrupt pipe is built between
 | 
						|
                      the host and the target interrupt endpoint. 
 | 
						|
                      If FALSE, the specified asynchronous interrupt pipe 
 | 
						|
                      is canceled.               
 | 
						|
    DataToggle      - A pointer to the data toggle value.  On input, it is valid 
 | 
						|
                      when IsNewTransfer is TRUE, and it indicates the initial 
 | 
						|
                      data toggle value the asynchronous interrupt transfer 
 | 
						|
                      should adopt.  
 | 
						|
                      On output, it is valid when IsNewTransfer is FALSE, 
 | 
						|
                      and it is updated to indicate the data toggle value of 
 | 
						|
                      the subsequent asynchronous interrupt transfer.              
 | 
						|
    PollingInterval - Indicates the interval, in milliseconds, that the 
 | 
						|
                      asynchronous interrupt transfer is polled.  
 | 
						|
                      This parameter is required when IsNewTransfer is TRUE.               
 | 
						|
    DataLength      - Indicates the length of data to be received at the 
 | 
						|
                      rate specified by PollingInterval from the target 
 | 
						|
                      asynchronous interrupt endpoint.  This parameter 
 | 
						|
                      is only required when IsNewTransfer is TRUE.             
 | 
						|
    Translator      - A pointr to the transaction translator data.
 | 
						|
    CallBackFunction  - The Callback function.This function is called at the 
 | 
						|
                        rate specified by PollingInterval.This parameter is 
 | 
						|
                        only required when IsNewTransfer is TRUE.               
 | 
						|
    Context         - The context that is passed to the CallBackFunction.
 | 
						|
                    - This is an optional parameter and may be NULL.
 | 
						|
  
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_SUCCESS 
 | 
						|
        The asynchronous interrupt transfer request has been successfully 
 | 
						|
        submitted or canceled.
 | 
						|
    EFI_INVALID_PARAMETER 
 | 
						|
        Some parameters are invalid.
 | 
						|
    EFI_OUT_OF_RESOURCES  
 | 
						|
        The request could not be completed due to a lack of resources.  
 | 
						|
    EFI_DEVICE_ERROR
 | 
						|
        Can't read register
 | 
						|
        
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  USB2_HC_DEV         *HcDev;
 | 
						|
  UINT8               PktId;
 | 
						|
  EHCI_QH_ENTITY      *QhPtr;
 | 
						|
  EHCI_QTD_ENTITY     *InterruptQtdsPtr;
 | 
						|
  UINT8               *DataPtr;
 | 
						|
  UINT8               *DataCursor;
 | 
						|
  VOID                *DataMap;
 | 
						|
  UINTN               MappedLength;
 | 
						|
  EHCI_ASYNC_REQUEST  *AsyncRequestPtr;
 | 
						|
  EFI_TPL             OldTpl;
 | 
						|
 | 
						|
  QhPtr             = NULL;
 | 
						|
  InterruptQtdsPtr  = NULL;
 | 
						|
  DataPtr           = NULL;
 | 
						|
  DataCursor        = NULL;
 | 
						|
  DataMap           = NULL;
 | 
						|
  AsyncRequestPtr   = NULL;
 | 
						|
  HcDev             = USB2_HC_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Parameters Checking
 | 
						|
  //
 | 
						|
  if (!IsDataInTransfer (EndPointAddress)) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (IsNewTransfer) {
 | 
						|
    if (0 == DataLength) {
 | 
						|
      Status = EFI_INVALID_PARAMETER;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
 | 
						|
    if (*DataToggle != 1 && *DataToggle != 0) {
 | 
						|
      Status = EFI_INVALID_PARAMETER;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
 | 
						|
    if (PollingInterval > 255 || PollingInterval < 1) {
 | 
						|
      Status = EFI_INVALID_PARAMETER;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // if has errors that cause host controller halt,
 | 
						|
  // then return EFI_DEVICE_ERROR directly.
 | 
						|
  //
 | 
						|
  if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
 | 
						|
    ClearEhcAllStatus (HcDev);
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = ClearEhcAllStatus (HcDev);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Delete Async interrupt transfer request
 | 
						|
  //
 | 
						|
  if (!IsNewTransfer) {
 | 
						|
 | 
						|
    OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
 | 
						|
 | 
						|
    Status = DeleteAsyncRequestTransfer (
 | 
						|
               HcDev,
 | 
						|
               DeviceAddress,
 | 
						|
               EndPointAddress,
 | 
						|
               DataToggle
 | 
						|
               );
 | 
						|
 | 
						|
    gBS->RestoreTPL (OldTpl);
 | 
						|
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EhciAllocatePool (
 | 
						|
  	         HcDev, 
 | 
						|
  	         (UINT8 **) &AsyncRequestPtr, 
 | 
						|
  	         sizeof (EHCI_ASYNC_REQUEST)
 | 
						|
  	         );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EhciAllocatePool (HcDev, &DataPtr, DataLength);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto free_request;
 | 
						|
  }
 | 
						|
 | 
						|
  MappedLength = DataLength;
 | 
						|
  Status = MapDataBuffer (
 | 
						|
             HcDev,
 | 
						|
             EfiUsbDataIn,
 | 
						|
             DataPtr,
 | 
						|
             &MappedLength,
 | 
						|
             &PktId,
 | 
						|
             &DataCursor,
 | 
						|
             &DataMap
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto free_data;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Create and init Interrupt Qh
 | 
						|
  //
 | 
						|
  Status = CreateInterruptQh (
 | 
						|
             HcDev,
 | 
						|
             DeviceAddress,
 | 
						|
             EndPointAddress,
 | 
						|
             DeviceSpeed,
 | 
						|
             *DataToggle,
 | 
						|
             MaximumPacketLength,
 | 
						|
             PollingInterval,
 | 
						|
             Translator,
 | 
						|
             &QhPtr
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto unmap_data;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Create and init Interrupt Qtds
 | 
						|
  //
 | 
						|
  Status = CreateBulkOrInterruptQtds (
 | 
						|
             HcDev,
 | 
						|
             PktId,
 | 
						|
             DataCursor,
 | 
						|
             MappedLength,
 | 
						|
             Translator,
 | 
						|
             &InterruptQtdsPtr
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto destory_qh;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Link Qtds to Qh
 | 
						|
  //
 | 
						|
  LinkQtdToQh (QhPtr, InterruptQtdsPtr);
 | 
						|
 | 
						|
  //
 | 
						|
  // Init AsyncRequest Entry
 | 
						|
  //
 | 
						|
  AsyncRequestPtr->Context      = Context;
 | 
						|
  AsyncRequestPtr->CallBackFunc = CallBackFunction;
 | 
						|
  AsyncRequestPtr->TransferType = ASYNC_INTERRUPT_TRANSFER;
 | 
						|
  AsyncRequestPtr->QhPtr        = QhPtr;
 | 
						|
  AsyncRequestPtr->Prev         = NULL;
 | 
						|
  AsyncRequestPtr->Next         = NULL;
 | 
						|
 | 
						|
  if (NULL == HcDev->AsyncRequestList) {
 | 
						|
    Status = StartPollingTimer (HcDev);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Status = EFI_DEVICE_ERROR;
 | 
						|
      CleanUpAllAsyncRequestTransfer (HcDev);
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Link Entry to AsyncRequest List
 | 
						|
  //
 | 
						|
  LinkToAsyncReqeust (HcDev, AsyncRequestPtr);
 | 
						|
 | 
						|
  ClearEhcAllStatus (HcDev);
 | 
						|
 | 
						|
  Status = DisablePeriodicSchedule (HcDev);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_TIMEOUT;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Link Qh and Qtds to Periodic Schedule List
 | 
						|
  //
 | 
						|
  LinkQhToPeriodicList (HcDev, QhPtr);
 | 
						|
 | 
						|
  Status = EnablePeriodicSchedule (HcDev);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_TIMEOUT;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (IsEhcHalted (HcDev)) {
 | 
						|
    Status = StartScheduleExecution (HcDev);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Status = EFI_DEVICE_ERROR;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  HcDev->PciIo->Flush (HcDev->PciIo);
 | 
						|
  goto exit;
 | 
						|
 | 
						|
destory_qh:
 | 
						|
  DestoryQh (HcDev, QhPtr);
 | 
						|
free_data:
 | 
						|
  EhciFreePool (HcDev, DataPtr, DataLength);
 | 
						|
free_request:
 | 
						|
  EhciFreePool (
 | 
						|
  	HcDev, 
 | 
						|
  	(UINT8 *) AsyncRequestPtr, 
 | 
						|
  	sizeof (EHCI_ASYNC_REQUEST)
 | 
						|
  	);
 | 
						|
unmap_data:
 | 
						|
  HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);
 | 
						|
exit:
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciSyncInterruptTransfer (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL                  *This,
 | 
						|
  IN  UINT8                                 DeviceAddress,
 | 
						|
  IN  UINT8                                 EndPointAddress,
 | 
						|
  IN  UINT8                                 DeviceSpeed,
 | 
						|
  IN  UINTN                                 MaximumPacketLength,
 | 
						|
  IN  OUT VOID                              *Data,
 | 
						|
  IN  OUT UINTN                             *DataLength,
 | 
						|
  IN  OUT UINT8                             *DataToggle,
 | 
						|
  IN  UINTN                                 TimeOut,
 | 
						|
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR    *Translator,
 | 
						|
  OUT UINT32                                *TransferResult
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Submits synchronous interrupt transfer to an interrupt endpoint 
 | 
						|
    of a USB device. 
 | 
						|
    Translator parameter doesn't exist in UEFI2.0 spec, but it will be updated 
 | 
						|
    in the following specification version.
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
    
 | 
						|
    This            - A pointer to the EFI_USB2_HC_PROTOCOL instance.
 | 
						|
    DeviceAddress   - Represents the address of the target device on the USB, 
 | 
						|
                      which is assigned during USB enumeration.
 | 
						|
    EndPointAddress - The combination of an endpoint number and an endpoint 
 | 
						|
                      direction of the target USB device. Each endpoint 
 | 
						|
                      address supports data transfer in one direction 
 | 
						|
                      except the control endpoint (whose default 
 | 
						|
                      endpoint address is 0). It is the caller's responsibility
 | 
						|
                      to make sure that the EndPointAddress represents 
 | 
						|
                      an interrupt endpoint. 
 | 
						|
    DeviceSpeed     - Indicates device speed.
 | 
						|
    MaximumPacketLength - Indicates the maximum packet size the target endpoint 
 | 
						|
                          is capable of sending or receiving.
 | 
						|
    Data            - A pointer to the buffer of data that will be transmitted 
 | 
						|
                      to USB device or received from USB device.
 | 
						|
    DataLength      - On input, the size, in bytes, of the data buffer specified 
 | 
						|
                      by Data. On output, the number of bytes transferred.
 | 
						|
    DataToggle      - A pointer to the data toggle value. On input, it indicates
 | 
						|
                      the initial data toggle value the synchronous interrupt 
 | 
						|
                      transfer should adopt; 
 | 
						|
                      on output, it is updated to indicate the data toggle value 
 | 
						|
                      of the subsequent synchronous interrupt transfer. 
 | 
						|
    TimeOut         - Indicates the maximum time, in microseconds, which the 
 | 
						|
                      transfer is allowed to complete.
 | 
						|
    Translator      - A pointr to the transaction translator data.
 | 
						|
    TransferResult  - A pointer to the detailed result information from 
 | 
						|
                      the synchronous interrupt transfer.  
 | 
						|
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_SUCCESS 
 | 
						|
        The synchronous interrupt transfer was completed successfully.
 | 
						|
    EFI_OUT_OF_RESOURCES  
 | 
						|
        The synchronous interrupt transfer could not be submitted due 
 | 
						|
        to lack of resource.
 | 
						|
    EFI_INVALID_PARAMETER 
 | 
						|
        Some parameters are invalid.
 | 
						|
    EFI_TIMEOUT 
 | 
						|
        The synchronous interrupt transfer failed due to timeout.
 | 
						|
    EFI_DEVICE_ERROR  
 | 
						|
        The synchronous interrupt transfer failed due to host controller 
 | 
						|
        or device error. Caller should check TranferResult for detailed 
 | 
						|
        error information.  
 | 
						|
        
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS      Status;
 | 
						|
  USB2_HC_DEV     *HcDev;
 | 
						|
  UINT8           PktId;
 | 
						|
  EHCI_QH_ENTITY  *QhPtr;
 | 
						|
  EHCI_QTD_ENTITY *InterruptQtdsPtr;
 | 
						|
  UINT8           *DataCursor;
 | 
						|
  VOID            *DataMap;
 | 
						|
 | 
						|
  QhPtr             = NULL;
 | 
						|
  InterruptQtdsPtr  = NULL;
 | 
						|
  DataCursor        = NULL;
 | 
						|
  DataMap           = NULL;
 | 
						|
  HcDev             = USB2_HC_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Parameters Checking
 | 
						|
  //
 | 
						|
  if (DataLength == NULL ||
 | 
						|
  	Data == NULL || 
 | 
						|
  	TransferResult == NULL
 | 
						|
  	) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!IsDataInTransfer (EndPointAddress)) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (0 == *DataLength) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (*DataToggle != 1 && *DataToggle != 0) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_USB_SPEED_LOW == DeviceSpeed && 8 != MaximumPacketLength) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_USB_SPEED_FULL == DeviceSpeed && MaximumPacketLength > 64) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_USB_SPEED_HIGH == DeviceSpeed && MaximumPacketLength > 3072) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // if has errors that cause host controller halt,
 | 
						|
  // then return EFI_DEVICE_ERROR directly.
 | 
						|
  //
 | 
						|
  if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
 | 
						|
    ClearEhcAllStatus (HcDev);
 | 
						|
    *TransferResult = EFI_USB_ERR_SYSTEM;
 | 
						|
    Status          = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = ClearEhcAllStatus (HcDev);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = MapDataBuffer (
 | 
						|
             HcDev,
 | 
						|
             EfiUsbDataIn,
 | 
						|
             Data,
 | 
						|
             DataLength,
 | 
						|
             &PktId,
 | 
						|
             &DataCursor,
 | 
						|
             &DataMap
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    *TransferResult = EFI_USB_ERR_SYSTEM;
 | 
						|
    Status          = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Create and init Interrupt Qh
 | 
						|
  //
 | 
						|
  Status = CreateInterruptQh (
 | 
						|
             HcDev,
 | 
						|
             DeviceAddress,
 | 
						|
             EndPointAddress,
 | 
						|
             DeviceSpeed,
 | 
						|
             *DataToggle,
 | 
						|
             MaximumPacketLength,
 | 
						|
             0,
 | 
						|
             Translator,
 | 
						|
             &QhPtr
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto unmap_data;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Create and init Interrupt Qtds
 | 
						|
  //
 | 
						|
  Status = CreateBulkOrInterruptQtds (
 | 
						|
             HcDev,
 | 
						|
             PktId,
 | 
						|
             DataCursor,
 | 
						|
             *DataLength,
 | 
						|
             Translator,
 | 
						|
             &InterruptQtdsPtr
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    *TransferResult = EFI_USB_ERR_SYSTEM;
 | 
						|
    Status          = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto destory_qh;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Link Qtds to Qh
 | 
						|
  //
 | 
						|
  LinkQtdToQh (QhPtr, InterruptQtdsPtr);
 | 
						|
 | 
						|
  ClearEhcAllStatus (HcDev);
 | 
						|
 | 
						|
  Status = DisablePeriodicSchedule (HcDev);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_TIMEOUT;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Link Qh and Qtds to Periodic Schedule List
 | 
						|
  //
 | 
						|
  LinkQhToPeriodicList (HcDev, QhPtr);
 | 
						|
 | 
						|
  Status = EnablePeriodicSchedule (HcDev);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_TIMEOUT;
 | 
						|
    goto exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (IsEhcHalted (HcDev)) {
 | 
						|
    Status = StartScheduleExecution (HcDev);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Status = EFI_DEVICE_ERROR;
 | 
						|
      goto exit;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Poll QH-TDs execution and get result.
 | 
						|
  // detail status is returned
 | 
						|
  //
 | 
						|
  Status = ExecuteTransfer (
 | 
						|
             HcDev,
 | 
						|
             FALSE,
 | 
						|
             QhPtr,
 | 
						|
             DataLength,
 | 
						|
             DataToggle,
 | 
						|
             TimeOut,
 | 
						|
             TransferResult
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto destory_qtds;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // if has errors that cause host controller halt,
 | 
						|
  // then return EFI_DEVICE_ERROR directly.
 | 
						|
  //
 | 
						|
  if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {
 | 
						|
    *TransferResult |= EFI_USB_ERR_SYSTEM;
 | 
						|
  }
 | 
						|
 | 
						|
  ClearEhcAllStatus (HcDev);
 | 
						|
 | 
						|
destory_qtds:
 | 
						|
  UnlinkQhFromPeriodicList (HcDev, QhPtr, 0);
 | 
						|
  DestoryQtds (HcDev, InterruptQtdsPtr);
 | 
						|
destory_qh:
 | 
						|
  DestoryQh (HcDev, QhPtr);
 | 
						|
unmap_data:
 | 
						|
  HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);
 | 
						|
exit:
 | 
						|
  HcDev->PciIo->Flush (HcDev->PciIo);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciIsochronousTransfer (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL                  *This,
 | 
						|
  IN  UINT8                                 DeviceAddress,
 | 
						|
  IN  UINT8                                 EndPointAddress,
 | 
						|
  IN  UINT8                                 DeviceSpeed,
 | 
						|
  IN  UINTN                                 MaximumPacketLength,
 | 
						|
  IN  UINT8                                 DataBuffersNumber,
 | 
						|
  IN  OUT VOID                              *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
 | 
						|
  IN  UINTN                                 DataLength,
 | 
						|
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR    *Translator,
 | 
						|
  OUT UINT32                                *TransferResult
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Submits isochronous transfer to a target USB device.
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
    
 | 
						|
    This             - A pointer to the EFI_USB2_HC_PROTOCOL instance.
 | 
						|
    DeviceAddress    - Represents the address of the target device on the USB,
 | 
						|
                       which is assigned during USB enumeration.
 | 
						|
    EndPointAddress  - End point address
 | 
						|
    DeviceSpeed      - Indicates device speed.
 | 
						|
    MaximumPacketLength    - Indicates the maximum packet size that the 
 | 
						|
                             default control transfer endpoint is capable of 
 | 
						|
                             sending or receiving.
 | 
						|
    DataBuffersNumber - Number of data buffers prepared for the transfer.
 | 
						|
    Data              - Array of pointers to the buffers of data that will be 
 | 
						|
                        transmitted to USB device or received from USB device.
 | 
						|
    DataLength        - Indicates the size, in bytes, of the data buffer 
 | 
						|
                        specified by Data.
 | 
						|
    Translator        - A pointr to the transaction translator data.
 | 
						|
    TransferResult    - A pointer to the detailed result information generated 
 | 
						|
                        by this control transfer.               
 | 
						|
                      
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_UNSUPPORTED 
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EhciAsyncIsochronousTransfer (
 | 
						|
  IN  EFI_USB2_HC_PROTOCOL                *This,
 | 
						|
  IN  UINT8                               DeviceAddress,
 | 
						|
  IN  UINT8                               EndPointAddress,
 | 
						|
  IN  UINT8                               DeviceSpeed,
 | 
						|
  IN  UINTN                               MaximumPacketLength,
 | 
						|
  IN  UINT8                               DataBuffersNumber,
 | 
						|
  IN  OUT VOID                            *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
 | 
						|
  IN  UINTN                               DataLength,
 | 
						|
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
 | 
						|
  IN  EFI_ASYNC_USB_TRANSFER_CALLBACK     IsochronousCallBack,
 | 
						|
  IN  VOID                                *Context
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
  
 | 
						|
    Submits Async isochronous transfer to a target USB device.
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
    
 | 
						|
    This                - A pointer to the EFI_USB2_HC_PROTOCOL instance.
 | 
						|
    DeviceAddress       - Represents the address of the target device on the USB,
 | 
						|
                          which is assigned during USB enumeration.
 | 
						|
    EndPointAddress     - End point address
 | 
						|
    DeviceSpeed         - Indicates device speed.
 | 
						|
    MaximumPacketLength - Indicates the maximum packet size that the 
 | 
						|
                          default control transfer endpoint is capable of 
 | 
						|
                          sending or receiving.
 | 
						|
    DataBuffersNumber   - Number of data buffers prepared for the transfer.
 | 
						|
    Data                - Array of pointers to the buffers of data that will be transmitted 
 | 
						|
                          to USB device or received from USB device.
 | 
						|
    Translator          - A pointr to the transaction translator data.
 | 
						|
    IsochronousCallBack - When the transfer complete, the call back function will be called
 | 
						|
    Context             - Pass to the call back function as parameter
 | 
						|
                    
 | 
						|
  Returns:
 | 
						|
  
 | 
						|
    EFI_UNSUPPORTED 
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 |