ehci.c

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

C
2,436
字号
      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)) {
      HcDev->DeviceSpeed[PortNumber] = IsHighSpeedDevice (This, PortNumber) ? USB_PORT_STAT_HIGH_SPEED : 0;
    }
    PortStatus->PortStatus |= HcDev->DeviceSpeed[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, "EHCI: WaitForEhcNotHalt TimeOut\n"));

⌨️ 快捷键说明

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