ehci.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,436 行 · 第 1/5 页

C
2,436
字号
/*++

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"

#ifdef EFI_DEBUG
UINTN                       gEHCDebugLevel  = EFI_D_INFO;
UINTN                       gEHCErrorLevel  = EFI_D_ERROR;
#endif

//
// Prototypes
// Driver model protocol interface
//
EFI_STATUS
EFIAPI
EhciDriverEntryPoint (
  IN EFI_HANDLE           ImageHandle,
  IN EFI_SYSTEM_TABLE     *SystemTable
  );

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
};

EFI_DRIVER_ENTRY_POINT (EhciDriverEntryPoint)

EFI_STATUS
EFIAPI
EhciDriverEntryPoint (
  IN EFI_HANDLE           ImageHandle,
  IN EFI_SYSTEM_TABLE     *SystemTable
  )
/*++

Routine Description:

  Entry point for EFI drivers.

Arguments:

  ImageHandle - EFI_HANDLE
  SystemTable - EFI_SYSTEM_TABLE

Returns:

  EFI_SUCCESS         Success
  EFI_DEVICE_ERROR    Fail

--*/
{
  return EfiLibInstallAllDriverProtocols (
          ImageHandle,
          SystemTable,
          &gEhciDriverBinding,
          ImageHandle,
          &gEhciComponentName,
          NULL,
          NULL
          );
}

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,
                  &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,
                  &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 = EfiLibAllocateZeroPool (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;
  }

  ClearLegacySupport (HcDev);
  HostReset (HcDev);

  DEBUG_CODE (
   DumpEHCIPortsStatus (HcDev);
  )

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?