ehcisched.c

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

C
2,975
字号
}

BOOLEAN
IsQtdStatusBufferError (
  IN EHCI_QTD_HW  *HwQtdPtr
  )
/*++

Routine Description:

  Whether Qtd status is buffer error or not

Arguments:

  HwQtdPtr - A pointer to hardware Qtd structure

Returns:

  TRUE    Buffer error
  FALSE   No buffer error

--*/
{
  UINT8   QtdStatus;
  BOOLEAN Value;

  QtdStatus = (UINT8) (HwQtdPtr->Status);
  Value     = (BOOLEAN) (QtdStatus & QTD_STATUS_BUFFER_ERR);

  return Value;
}

BOOLEAN
IsQtdStatusBabbleError (
  IN EHCI_QTD_HW  *HwQtdPtr
  )
/*++

Routine Description:

  Whether Qtd status is babble error or not

Arguments:

  HwQtdPtr - A pointer to hardware Qtd structure

Returns:

  TRUE    Babble error
  FALSE   No babble error

--*/
{
  UINT8   QtdStatus;
  BOOLEAN Value;

  QtdStatus = (UINT8) (HwQtdPtr->Status);
  Value     = (BOOLEAN) (QtdStatus & QTD_STATUS_BABBLE_ERR);

  return Value;
}

BOOLEAN
IsQtdStatusTransactionError (
  IN EHCI_QTD_HW  *HwQtdPtr
  )
/*++

Routine Description:

  Whether Qtd status is transaction error or not

Arguments:

  HwQtdPtr - A pointer to hardware Qtd structure

Returns:

  TRUE    Transaction error
  FALSE   No transaction error

--*/
{
  UINT8   QtdStatus;
  BOOLEAN Value;

  QtdStatus = (UINT8) (HwQtdPtr->Status);
  Value     = (BOOLEAN) (QtdStatus & QTD_STATUS_TRANSACTION_ERR);

  return Value;
}

BOOLEAN
IsDataInTransfer (
  IN UINT8     EndPointAddress
  )
/*++

Routine Description:

  Whether is a DataIn direction transfer

Arguments:

  EndPointAddress - address of the endpoint

Returns:

  TRUE    DataIn
  FALSE   DataOut

--*/
{
  BOOLEAN Value;

  if (EndPointAddress & 0x80) {
    Value = TRUE;
  } else {
    Value = FALSE;
  }

  return Value;
}

EFI_STATUS
MapDataBuffer (
  IN  USB2_HC_DEV             *HcDev,
  IN  EFI_USB_DATA_DIRECTION  TransferDirection,
  IN  VOID                    *Data,
  IN  OUT UINTN               *DataLength,
  OUT UINT8                   *PktId,
  OUT UINT8                   **DataCursor,
  OUT VOID                    **DataMap
  )
/*++

Routine Description:

  Map address of user data buffer

Arguments:

  HcDev              - USB2_HC_DEV
  TransferDirection  - direction of transfer
  Data               - A pointer to user data buffer
  DataLength         - length of user data
  PktId              - Packte Identificaion
  DataCursor         - mapped address to return
  DataMap            - identificaion of this mapping to return

Returns:

  EFI_SUCCESS        Success
  EFI_DEVICE_ERROR   Fail

--*/
{
  EFI_STATUS            Status;
  EFI_PHYSICAL_ADDRESS  TempPhysicalAddr;

  Status = EFI_SUCCESS;

  switch (TransferDirection) {

  case EfiUsbDataIn:

    *PktId = INPUT_PACKET_ID;
    //
    // BusMasterWrite means cpu read
    //
    Status = HcDev->PciIo->Map (
                            HcDev->PciIo,
                            EfiPciIoOperationBusMasterWrite,
                            Data,
                            DataLength,
                            &TempPhysicalAddr,
                            DataMap
                            );
    if (EFI_ERROR (Status)) {
      DEBUG ((gEHCDebugLevel, "EHCI: MapDataBuffer Failed\n"));
      Status = EFI_DEVICE_ERROR;
      goto exit;
    }

    *DataCursor = (UINT8 *) ((UINTN) TempPhysicalAddr);
    break;

  case EfiUsbDataOut:

    *PktId = OUTPUT_PACKET_ID;
    //
    // BusMasterRead means cpu write
    //
    Status = HcDev->PciIo->Map (
                            HcDev->PciIo,
                            EfiPciIoOperationBusMasterRead,
                            Data,
                            DataLength,
                            &TempPhysicalAddr,
                            DataMap
                            );
    if (EFI_ERROR (Status)) {
      Status = EFI_DEVICE_ERROR;
      goto exit;
    }

    *DataCursor = (UINT8 *) ((UINTN) TempPhysicalAddr);
    break;

  case EfiUsbNoData:

    *PktId      = OUTPUT_PACKET_ID;
    Data        = NULL;
    *DataLength = 0;
    *DataCursor = NULL;
    *DataMap    = NULL;
    break;

  default:

    Status = EFI_INVALID_PARAMETER;
  }

exit:
  return Status;
}

EFI_STATUS
MapRequestBuffer (
  IN  USB2_HC_DEV             *HcDev,
  IN  OUT VOID                *Request,
  OUT UINT8                   **RequestCursor,
  OUT VOID                    **RequestMap
  )
/*++

Routine Description:

  Map address of request structure buffer

Arguments:

  HcDev           - USB2_HC_DEV
  Request         - A pointer to request structure
  RequestCursor   - Mapped address of request structure to return
  RequestMap      - Identificaion of this mapping to return

Returns:

  EFI_SUCCESS        Success
  EFI_DEVICE_ERROR   Fail

--*/
{
  EFI_STATUS            Status;
  UINTN                 RequestLen;
  EFI_PHYSICAL_ADDRESS  TempPhysicalAddr;

  RequestLen = sizeof (EFI_USB_DEVICE_REQUEST);
  Status = HcDev->PciIo->Map (
                           HcDev->PciIo,
                           EfiPciIoOperationBusMasterRead,
                           (UINT8 *) Request,
                           (UINTN *) &RequestLen,
                           &TempPhysicalAddr,
                           RequestMap
                           );
  if (EFI_ERROR (Status)) {
    Status = EFI_DEVICE_ERROR;
    goto exit;
  }

  *RequestCursor = (UINT8 *) ((UINTN) TempPhysicalAddr);

exit:
  return Status;
}

EFI_STATUS
DeleteAsyncRequestTransfer (
  IN  USB2_HC_DEV     *HcDev,
  IN  UINT8           DeviceAddress,
  IN  UINT8           EndPointAddress,
  OUT UINT8           *DataToggle
  )
/*++

Routine Description:

  Delete all asynchronous request transfer

Arguments:

  HcDev           - USB2_HC_DEV
  DeviceAddress   - address of usb device
  EndPointAddress - address of endpoint
  DataToggle      - stored data toggle

Returns:

  EFI_SUCCESS        Success
  EFI_DEVICE_ERROR   Fail

--*/
{
  EFI_STATUS          Status;
  EHCI_ASYNC_REQUEST  *AsyncRequestPtr;
  EHCI_ASYNC_REQUEST  *MatchPtr;
  EHCI_QH_HW          *QhHwPtr;
  UINT8               EndPointNum;

  if (NULL == HcDev->AsyncRequestList) {
    Status = EFI_INVALID_PARAMETER;
    goto exit;
  }

  MatchPtr        = NULL;
  QhHwPtr         = NULL;
  EndPointNum     = EndPointAddress & 0x0f;
  AsyncRequestPtr = HcDev->AsyncRequestList;

  //
  // Find QH of AsyncRequest by DeviceAddress and EndPointNum
  //
  do {

    QhHwPtr = &(AsyncRequestPtr->QhPtr->Qh);
    if (QhHwPtr->DeviceAddr == DeviceAddress && QhHwPtr->EndpointNum == EndPointNum) {
      MatchPtr = AsyncRequestPtr;
      break;
    }

    AsyncRequestPtr = AsyncRequestPtr->Next;

  } while (NULL != AsyncRequestPtr);

  if (NULL == MatchPtr) {
    Status = EFI_INVALID_PARAMETER;
    goto exit;
  }

  Status = DisablePeriodicSchedule (HcDev);
  if (EFI_ERROR (Status)) {
    Status = EFI_DEVICE_ERROR;
    goto exit;
  }

  Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
  if (EFI_ERROR (Status)) {
    DEBUG ((gEHCErrorLevel, "EHCI: WaitForPeriodicScheduleDisable TimeOut\n"));
    Status = EFI_TIMEOUT;
    goto exit;
  }

  *DataToggle = (UINT8) MatchPtr->QhPtr->Qh.DataToggle;
  UnlinkQhFromPeriodicList (HcDev, MatchPtr->QhPtr, MatchPtr->QhPtr->Interval);
  UnlinkFromAsyncReqeust (HcDev, MatchPtr);

  if (NULL == HcDev->AsyncRequestList) {

    Status = StopPollingTimer (HcDev);
    if (EFI_ERROR (Status)) {
      Status = EFI_DEVICE_ERROR;
      goto exit;
    }

  } else {

    Status = EnablePeriodicSchedule (HcDev);
    if (EFI_ERROR (Status)) {
      Status = EFI_DEVICE_ERROR;
      goto exit;
    }

    Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);
    if (EFI_ERROR (Status)) {
      DEBUG ((gEHCErrorLevel, "EHCI: WaitForPeriodicScheduleEnable TimeOut\n"));
      Status = EFI_TIMEOUT;
      goto exit;
    }

    if (IsEhcHalted (HcDev)) {
      Status = StartScheduleExecution (HcDev);
      if (EFI_ERROR (Status)) {
        Status = EFI_DEVICE_ERROR;
        goto exit;
      }
    }

  }

  DestoryQtds (HcDev, MatchPtr->QhPtr->FirstQtdPtr);
  DestoryQh (HcDev, MatchPtr->QhPtr);
  EhciFreePool (HcDev, (UINT8 *) MatchPtr, sizeof (EHCI_ASYNC_REQUEST));

exit:
  return Status;
}

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

Routine Description:

  Clean up all asynchronous request transfer

Arguments:

  HcDev - USB2_HC_DEV

Returns:

  VOID

--*/
{
  EHCI_ASYNC_REQUEST  *AsyncRequestPtr;
  EHCI_ASYNC_REQUEST  *FreePtr;

  AsyncRequestPtr = NULL;
  FreePtr         = NULL;

  StopPollingTimer (HcDev);

  AsyncRequestPtr = HcDev->AsyncRequestList;
  while (NULL != AsyncRequestPtr) {

    FreePtr         = AsyncRequestPtr;
    AsyncRequestPtr = AsyncRequestPtr->Next;
    UnlinkFromAsyncReqeust (HcDev, FreePtr);
    UnlinkQhFromPeriodicList (HcDev, FreePtr->QhPtr, FreePtr->QhPtr->Interval);
    DestoryQtds (HcDev, FreePtr->QhPtr->FirstQtdPtr);
    DestoryQh (HcDev, FreePtr->QhPtr);
    EhciFreePool (HcDev, (UINT8 *) FreePtr, sizeof (EHCI_ASYNC_REQUEST));

  }

  return ;
}

VOID
ZeroOutQhOverlay (
  IN EHCI_QH_ENTITY  *QhPtr
  )
/*++

Routine Description:

  Zero out the fields in Qh structure

Arguments:

  QhPtr - A pointer to Qh structure

Returns:

  VOID

--*/
{
  QhPtr->Qh.CurrentQtdPointer   = 0;
  QhPtr->Qh.AltNextQtdPointer   = 0;
  QhPtr->Qh.NakCount            = 0;
  QhPtr->Qh.AltNextQtdTerminate = 0;
  QhPtr->Qh.TotalBytes          = 0;
  QhPtr->Qh.InterruptOnComplete = 0;
  QhPtr->Qh.CurrentPage         = 0;
  QhPtr->Qh.ErrorCount          = 0;
  QhPtr->Qh.PidCode             = 0;
  QhPtr->Qh.Status              = 0;
  QhPtr->Qh.BufferPointer0      = 0;
  QhPtr->Qh.CurrentOffset       = 0;
  QhPtr->Qh.BufferPointer1      = 0;
  QhPtr->Qh.CompleteSplitMask   = 0;
  QhPtr->Qh.BufferPointer2      = 0;
  QhPtr->Qh.SplitBytes          = 0;
  QhPtr->Qh.FrameTag            = 0;
  QhPtr->Qh.BufferPointer3      = 0;
  QhPtr->Qh.BufferPointer4      = 0;
}

VOID
UpdateAsyncRequestTransfer (
  IN EHCI_ASYNC_REQUEST *AsyncRequestPtr,
  IN UINT32             TransferResult,
  IN UINTN              ErrQtdPos
  )
/*++

Routine Description:

  Update asynchronous request transfer

Arguments:

  AsyncRequestPtr  - A pointer to async request
  TransferResult   - transfer result
  ErrQtdPos        - postion of error Qtd

Returns:

  VOID

--*/
{
  EHCI_QTD_ENTITY *QtdPtr;

  QtdPtr      = NULL;

  if (EFI_USB_NOERROR == TransferResult) {

    //
    // Update Qh for next trigger
    //

    QtdPtr = AsyncRequestPtr->QhPtr->FirstQtdPtr;

    //
    // Update fields in Qh
    //

    //
    // Get DataToggle from Overlay in Qh
    //
    // ZeroOut Overlay in Qh except DataToggle, HostController will update this field
    //
    ZeroOutQhOverlay (AsyncRequestPtr->QhPtr);
    AsyncRequestPtr->QhPtr->Qh.NextQtdPointer   = (UINT32) (GET_0B_TO_31B (&(QtdPtr->Qtd)) >> 5);
    AsyncRequestPtr->QhPtr->Qh.NextQtdTerminate = FALSE;

    //
    // Update fields in Qtd
    //
    while (NULL != QtdPtr) {
      QtdPtr->Qtd.TotalBytes    = QtdPtr->StaticTotalBytes;
      QtdPtr->Qtd.CurrentOffset = QtdPtr->StaticCurrentOffset;
      QtdPtr->Qtd.CurrentPage   = 0;
      QtdPtr->Qtd.ErrorCount    = QTD_ERROR_COUNTER;
      QtdPtr->Qtd.Status        = QTD_STATUS_ACTIVE;

      QtdPtr->TotalBytes        = QtdPtr->StaticTotalBytes;
      QtdPtr                    = QtdPtr->Next;
    }
  }

  return ;
}

BOOLEAN
CheckQtdsTransferResult (
  IN  BOOLEAN            IsControl,
  IN  EHCI_QH_ENTITY     *QhPtr,
  OUT UINT32             *Result,
  OUT UINTN              *ErrQtdPos,
  OUT UINTN              *ActualLen
  )
/*++

Routine Description:

  Check transfer result of Qtds

Arguments:

  IsControl    - Is control transfer or not
  QhPtr        - A pointer to Qh
  Result       - Transfer result
  ErrQtdPos    - Error TD Position
  ActualLen    - Actual Transfer Size

Returns:

  TRUE    Qtds finished
  FALSE   Not finish

--*/
{
  UINTN           ActualLenPerQtd;
  EHCI_QTD_ENTITY *QtdPtr;
  EHCI_QTD_HW     *QtdHwPtr;
  BOOLEAN         Value;

  ASSERT (QhPtr);
  ASSERT (Result);
  ASSERT (ErrQtdPos);
  ASSERT (ActualLen);

  Value     = TRUE;
  QtdPtr    = QhPtr->FirstQtdPtr;
  QtdHwPtr  = &(QtdPtr->Qtd);

  while (NULL !

⌨️ 快捷键说明

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