ehcireg.c

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

C
1,733
字号
/*++

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:

    Ehchlp.c

Abstract:


Revision History
--*/

#include "Tiano.h"
#include "EfiDriverLib.h"
#include "Ehci.h"


VOID
HostReset (
  IN USB2_HC_DEV    *HcDev
  )
{
  UINT32  Value;
  UINT32  TimeOut;
 
  ReadEhcOperationalReg (
    HcDev,
    USBCMD,
    &Value
    );

  Value = Value & (~USBCMD_RS);
  WriteEhcOperationalReg (
    HcDev,
    USBCMD,
    Value
    );

  TimeOut = 40;
  while (TimeOut --) {
    gBS->Stall (500);
    ReadEhcOperationalReg (
      HcDev,
      USBSTS,
      &Value
      );
    if ((Value & USBSTS_HCH) != 0) {
      break;
    }
  }

  if (TimeOut == 0) {
    DEBUG((gEHCErrorLevel, "TimeOut for clearing Run/Stop bit\n"));
  }

  ReadEhcOperationalReg (
    HcDev,
    USBCMD,
    &Value
    );
  Value = Value | USBCMD_HCRESET;
  WriteEhcOperationalReg (
    HcDev,
    USBCMD,
    Value
    );

  TimeOut = 40;
  while (TimeOut --) {
    gBS->Stall (500);
    ReadEhcOperationalReg (
      HcDev,
      USBCMD,
      &Value
      );
    if ((Value & USBCMD_HCRESET) == 0) {
      break;
    }
  }

  if (TimeOut == 0) {
    DEBUG((gEHCErrorLevel, "TimeOut for Host Reset\n"));
  }

}

EFI_STATUS
ReadEhcCapabiltiyReg (
  IN USB2_HC_DEV             *HcDev,
  IN UINT32                  CapabiltiyRegAddr,
  IN OUT UINT32              *Data
  )
/*++

Routine Description:

  Read  Ehc Capabitlity register

Arguments:

  HcDev              - USB2_HC_DEV
  CapabiltiyRegAddr  - Ehc Capability register address
  Data               - A pointer to data read from register

Returns:

  EFI_SUCCESS        Success
  EFI_DEVICE_ERROR   Fail

--*/
{
  return HcDev->PciIo->Mem.Read (
                             HcDev->PciIo,
                             EfiPciIoWidthUint32,
                             USB_BAR_INDEX,
                             (UINT64) CapabiltiyRegAddr,
                             1,
                             Data
                             );
}

EFI_STATUS
ReadEhcOperationalReg (
  IN USB2_HC_DEV             *HcDev,
  IN UINT32                  OperationalRegAddr,
  IN OUT UINT32              *Data
  )
/*++

Routine Description:

  Read  Ehc Operation register

Arguments:

  HcDev                - USB2_HC_DEV
  OperationalRegAddr   - Ehc Operation register address
  Data                 - A pointer to data read from register

Returns:

  EFI_SUCCESS        Success
  EFI_DEVICE_ERROR   Fail

--*/
{
  ASSERT (HcDev->UsbCapabilityLen);
  return HcDev->PciIo->Mem.Read (
                             HcDev->PciIo,
                             EfiPciIoWidthUint32,
                             USB_BAR_INDEX,
                             (UINT64) (OperationalRegAddr + HcDev->UsbCapabilityLen),
                             1,
                             Data
                             );
}

EFI_STATUS
WriteEhcOperationalReg (
  IN USB2_HC_DEV             *HcDev,
  IN UINT32                  OperationalRegAddr,
  IN UINT32                  Data
  )
/*++

Routine Description:

  Write  Ehc Operation register

Arguments:

  HcDev                - USB2_HC_DEV
  OperationalRegAddr   - Ehc Operation register address
  Data                 - 32bit write to register

Returns:

  EFI_SUCCESS        Success
  EFI_DEVICE_ERROR   Fail

--*/
{
  ASSERT (HcDev->UsbCapabilityLen);
  return HcDev->PciIo->Mem.Write (
                             HcDev->PciIo,
                             EfiPciIoWidthUint32,
                             USB_BAR_INDEX,
                             (UINT64) (OperationalRegAddr + HcDev->UsbCapabilityLen),
                             1,
                             &Data
                             );
}



VOID
ClearLegacySupport (
  IN USB2_HC_DEV     *HcDev
  )
/*++

Routine Description:

  Stop the legacy USB SMI

Arguments:

  HcDev - USB2_HC_DEV

Returns:

  EFI_SUCCESS       Success
  EFI_DEVICE_ERROR  Fail

--*/
{
  UINT32  EECP;
  UINT32  Value;
  UINT32  TimeOut;

  ReadEhcCapabiltiyReg (
    HcDev,
    HCCPARAMS,
    &EECP
    );

  EECP = (EECP >> 8) & 0xFF;

  DEBUG ((gEHCDebugLevel, "EHCI: EECPBase = 0x%x\n", EECP));


  HcDev->PciIo->Pci.Read (
                     HcDev->PciIo,
                     EfiPciIoWidthUint32,
                     EECP,
                     1,
                     &Value 
                     );

  DEBUG((gEHCDebugLevel, "EECP[0] = 0x%x\n", Value));

  HcDev->PciIo->Pci.Read (
                     HcDev->PciIo,
                     EfiPciIoWidthUint32,
                     EECP + 0x4,
                     1,
                     &Value 
                     );

  DEBUG((gEHCDebugLevel, "EECP[4] = 0x%x\n", Value));

  HcDev->PciIo->Pci.Read (
                     HcDev->PciIo,
                     EfiPciIoWidthUint32,
                     EECP,
                     1,
                     &Value 
                     );

  Value = Value | (0x1 << 24);
  DEBUG((gEHCErrorLevel, "Value Written = 0x%x\n", Value));

  HcDev->PciIo->Pci.Write (
                     HcDev->PciIo,
                     EfiPciIoWidthUint32,
                     EECP,
                     1,
                     &Value 
                     );

 TimeOut = 40;
 while (TimeOut --) {
   gBS->Stall (500);

   HcDev->PciIo->Pci.Read (
                      HcDev->PciIo,
                      EfiPciIoWidthUint32,
                      EECP,
                      1,
                      &Value 
                      );
  if ((Value & 0x01010000) == 0x01000000) {
    break;
  }
 }

  if (TimeOut == 0) {
    DEBUG((gEHCErrorLevel, "Timeout for getting HC OS Owned Semaphore\n" ));
  } 
  
  DEBUG((gEHCErrorLevel, "After Release Value\n" ));

  HcDev->PciIo->Pci.Read (
                     HcDev->PciIo,
                     EfiPciIoWidthUint32,
                     EECP,
                     1,
                     &Value 
                     );

  DEBUG((gEHCDebugLevel, "EECP[0] = 0x%x\n", Value));

  HcDev->PciIo->Pci.Read (
                     HcDev->PciIo,
                     EfiPciIoWidthUint32,
                     EECP + 0x4,
                     1,
                     &Value 
                     );

  DEBUG((gEHCDebugLevel, "EECP[4] = 0x%x\n", Value));


}

EFI_STATUS
GetCapabilityLen (
  IN USB2_HC_DEV     *HcDev
  )
/*++

Routine Description:

  Get the length of capability register

Arguments:

  HcDev - USB2_HC_DEV

Returns:

  EFI_SUCCESS       Success
  EFI_DEVICE_ERROR  Fail

--*/
{
  EFI_STATUS  Status;
  UINT32      CapabilityLenAddr;

  CapabilityLenAddr = CAPLENGTH;

  Status = ReadEhcCapabiltiyReg (
             HcDev,
             CapabilityLenAddr,
             &(HcDev->UsbCapabilityLen)
             );
  HcDev->UsbCapabilityLen = (UINT8) HcDev->UsbCapabilityLen;

  return Status;
}

EFI_STATUS
SetFrameListLen (
  IN USB2_HC_DEV     *HcDev,
  IN UINTN           Length
  )
/*++

Routine Description:

  Set the length of Frame List

Arguments:

  HcDev    - USB2_HC_DEV
  Length   - the required length of frame list

Returns:

  EFI_SUCCESS            Success
  EFI_INVALID_PARAMETER  Invalid parameter
  EFI_DEVICE_ERROR       Fail

--*/
{
  EFI_STATUS  Status;
  UINT32      UsbCommandAddr;
  UINT32      UsbCommandReg;

  UsbCommandAddr = USBCMD;

  if (256 != Length && 512 != Length) {
    Status = EFI_INVALID_PARAMETER;
    goto exit;
  }

  Status = ReadEhcOperationalReg (
             HcDev,
             UsbCommandAddr,
             &UsbCommandReg
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_DEVICE_ERROR;
    goto exit;
  }

  if (256 == Length) {
    UsbCommandReg |= USBCMD_FLS_256;
  } else {
    UsbCommandReg |= USBCMD_FLS_512;
  }

  Status = WriteEhcOperationalReg (
             HcDev,
             UsbCommandAddr,
             UsbCommandReg
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_DEVICE_ERROR;
  }

exit:
  return Status;
}

EFI_STATUS
SetFrameListBaseAddr (
  IN USB2_HC_DEV     *HcDev,
  IN UINT32          FrameBuffer
  )
/*++

Routine Description:

  Set base address of frame list first entry

Arguments:

  HcDev        - USB2_HC_DEV
  FrameBuffer  - base address of first entry of frame list

Returns:

--*/
{
  EFI_STATUS  Status;
  UINT32      PeriodicListBaseAddr;
  UINT32      PeriodicListBaseReg;

  Status                = EFI_SUCCESS;
  PeriodicListBaseAddr  = PERIODICLISTBASE;
  PeriodicListBaseReg   = FrameBuffer & 0xfffff000;

  if (IsEhcHalted (HcDev)) {

    Status = WriteEhcOperationalReg (
               HcDev,
               PeriodicListBaseAddr,
               PeriodicListBaseReg
               );
    if (EFI_ERROR (Status)) {
      Status = EFI_DEVICE_ERROR;
      goto exit;
    }

  }

exit:
  return Status;
}

EFI_STATUS
SetAsyncListAddr (
  IN USB2_HC_DEV        *HcDev,
  IN EHCI_QH_ENTITY     *QhPtr
  )
/*++

Routine Description:

  Set address of first Async schedule Qh

Arguments:

  HcDev   - USB2_HC_DEV
  QhPtr   - A pointer to first Qh in the Async schedule

Returns:

  EFI_SUCCESS       Success
  EFI_DEVICE_ERROR  Fail

--*/
{
  EFI_STATUS  Status;
  UINT32      AsyncListAddr;
  UINT32      AsyncListReg;

  AsyncListAddr = ASYNCLISTADDR;
  AsyncListReg  = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh));

  Status = WriteEhcOperationalReg (
             HcDev,
             AsyncListAddr,
             AsyncListReg
             );

  return Status;
}

EFI_STATUS
SetCtrlDataStructSeg (
  IN USB2_HC_DEV     *HcDev
  )
/*++

Routine Description:

  Set register of control and data structure segment

Arguments:

  HcDev  - USB2_HC_DEV

Returns:

  EFI_SUCCESS       Success
  EFI_DEVICE_ERROR  Fail


--*/
{
  EFI_STATUS  Status;
  UINT32      CtrlDsSegmentAddr;
  UINT32      CtrlDsSegmentReg;

  CtrlDsSegmentAddr = CTRLDSSGMENT;
  CtrlDsSegmentReg  = HcDev->High32BitAddr;

  Status = WriteEhcOperationalReg (
             HcDev,
             CtrlDsSegmentAddr,
             CtrlDsSegmentReg
             );

  return Status;
}

EFI_STATUS
SetPortRoutingEhc (
  IN USB2_HC_DEV     *HcDev
  )
/*++

Routine Description:

  Set Ehc port routing bit

Arguments:

  HcDev - USB2_HC_DEV

Returns:

  EFI_SUCCESS       Success
  EFI_DEVICE_ERROR  Fail

--*/
{
  EFI_STATUS  Status;
  UINT32      ConfigFlagAddr;
  UINT32      ConfigFlagReg;

  ConfigFlagAddr = CONFIGFLAG;

  Status = ReadEhcOperationalReg (
             HcDev,
             ConfigFlagAddr,
             &ConfigFlagReg
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_DEVICE_ERROR;
    goto exit;
  }

  ConfigFlagReg |= CONFIGFLAG_CF;
  Status = WriteEhcOperationalReg (
             HcDev,
             ConfigFlagAddr,
             ConfigFlagReg
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_DEVICE_ERROR;
  }

exit:
  return Status;
}

EFI_STATUS
SetEhcDoorbell (
  IN  USB2_HC_DEV     *HcDev
  )
/*++

Routine Description:

  Set Ehc door bell bit

Arguments:

  HcDev - USB2_HC_DEV

Returns:

  EFI_SUCCESS       Success
  EFI_DEVICE_ERROR  Fail

--*/
{
  EFI_STATUS  Status;
  UINT32      UsbCommandAddr;
  UINT32      UsbCommandReg;

  UsbCommandAddr = USBCMD;

  Status = ReadEhcOperationalReg (
             HcDev,
             UsbCommandAddr,
             &UsbCommandReg
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_DEVICE_ERROR;
    goto exit;
  }

  UsbCommandReg |= USBCMD_IAAD;
  Status = WriteEhcOperationalReg (
             HcDev,
             UsbCommandAddr,
             UsbCommandReg
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_DEVICE_ERROR;
  }

exit:
  return Status;
}

EFI_STATUS
ClearEhcAllStatus (
  IN  USB2_HC_DEV     *HcDev
  )
/*++

Routine Description:

  Clear Ehc all status bits

Arguments:

  HcDev - USB2_HC_DEV

Returns:

  EFI_SUCCESS       Success
  EFI_DEVICE_ERROR  Fail

--*/
{
  UINT32  UsbStatusAddr;

  UsbStatusAddr = USBSTS;

  return WriteEhcOperationalReg (
           HcDev,
           UsbStatusAddr,
           0x003F
           );
}

EFI_STATUS
EnablePeriodicSchedule (
  IN  USB2_HC_DEV     *HcDev
  )
/*++

Routine Description:

  Enable periodic schedule

Arguments:

  HcDev - USB2_HC_DEV

Returns:

  EFI_SUCCESS       Success
  EFI_DEVICE_ERROR  Fail

--*/
{
  EFI_STATUS  Status;
  UINT32      UsbCommandAddr;
  UINT32      UsbCommandReg;

  UsbCommandAddr = USBCMD;

  Status = ReadEhcOperationalReg (
             HcDev,
             UsbCommandAddr,
             &UsbCommandReg
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_DEVICE_ERROR;
    goto exit;
  }

  UsbCommandReg |= USBCMD_PSE;
  Status = WriteEhcOperationalReg (
             HcDev,
             UsbCommandAddr,
             UsbCommandReg
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_DEVICE_ERROR;
  }

exit:
  return Status;
}

EFI_STATUS
DisablePeriodicSchedule (
  IN  USB2_HC_DEV     *HcDev
  )
/*++

Routine Description:

  Disable periodic schedule

Arguments:

  HcDev - USB2_HC_DEV

Returns:

  EFI_SUCCESS       Success
  EFI_DEVICE_ERROR  Fail

--*/
{
  EFI_STATUS  Status;
  UINT32      UsbCommandAddr;
  UINT32      UsbCommandReg;

  UsbCommandAddr = USBCMD;

  Status = ReadEhcOperationalReg (
             HcDev,
             UsbCommandAddr,
             &UsbCommandReg
             );
  if (EFI_ERROR (Status)) {
    return EFI_DEVICE_ERROR;
  }

  UsbCommandReg &= ~USBCMD_PSE;
  Status = WriteEhcOperationalReg (
             HcDev,
             UsbCommandAddr,
             UsbCommandReg
             );
  if (EFI_ERROR (Status)) {
    return EFI_DEVICE_ERROR;
  }

  return Status;
}

EFI_STATUS
EnableAsynchronousSchedule (
  IN  USB2_HC_DEV     *HcDev
  )
/*++

Routine Description:

  Enable asynchrounous schedule

Arguments:

  HcDev - USB2_HC_DEV

Returns:

  EFI_SUCCESS       Success
  EFI_DEVICE_ERROR  Fail

--*/
{
  EFI_STATUS  Status;
  UINT32      UsbCommandAddr;
  UINT32      UsbCommandReg;

  UsbCommandAddr = USBCMD;

  Status = ReadEhcOperationalReg (
             HcDev,
             UsbCommandAddr,
             &UsbCommandReg
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_DEVICE_ERROR;
    goto exit;
  }

  UsbCommandReg |= USBCMD_ASE;
  Status = WriteEhcOperationalReg (
             HcDev,
             UsbCommandAddr,
             UsbCommandReg
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_DEVICE_ERROR;
  }

exit:
  return Status;
}

EFI_STATUS
DisableAsynchronousSchedule (
  IN  USB2_HC_DEV     *HcDev
  )
/*++

Routine Description:

  Disable asynchrounous schedule

Arguments:

  HcDev - USB2_HC_DEV

Returns:

  EFI_SUCCESS       Success
  EFI_DEVICE_ERROR  Fail

--*/
{
  EFI_STATUS  Status;
  UINT32      UsbCommandAddr;
  UINT32      UsbCommandReg;

  UsbCommandAddr = USBCMD;

  Status = ReadEhcOperationalReg (
             HcDev,
             UsbCommandAddr,
             &UsbCommandReg
             );
  if (EFI_ERROR (Status)) {
    return EFI_DEVICE_ERROR;
  }

⌨️ 快捷键说明

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