ehcisched.c

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

C
2,975
字号
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_OUT_OF_RESOURCES;
    goto exit;
  }
  //
  // Software field
  //
  (*QhPtrPtr)->Next         = (*QhPtrPtr);
  (*QhPtrPtr)->Prev         = (*QhPtrPtr);
  (*QhPtrPtr)->TransferType = CONTROL_TRANSFER;

  //
  // Hardware field
  //
  // Control Transfer use DataToggleControl
  //
  (*QhPtrPtr)->Qh.DataToggleControl   = TRUE;
  (*QhPtrPtr)->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&((*QhPtrPtr)->Qh)) >> 5);
  (*QhPtrPtr)->Qh.SelectType          = QH_SELECT_TYPE;
  (*QhPtrPtr)->Qh.QhTerminate         = FALSE;
  if (EFI_USB_SPEED_HIGH != DeviceSpeed)  {
    (*QhPtrPtr)->Qh.ControlEndpointFlag = TRUE;
  }
  (*QhPtrPtr)->Qh.NakCountReload      = NAK_COUNT_RELOAD;
  if (NULL != Translator) {
    (*QhPtrPtr)->Qh.PortNum = Translator->TranslatorPortNumber;
    (*QhPtrPtr)->Qh.HubAddr = Translator->TranslatorHubAddress;
    (*QhPtrPtr)->Qh.Status |= QTD_STATUS_DO_START_SPLIT;
  }

exit:
  return Status;
}

EFI_STATUS
CreateBulkQh (
  IN  USB2_HC_DEV                         *HcDev,
  IN  UINT8                               DeviceAddr,
  IN  UINT8                               EndPointAddr,
  IN  UINT8                               DeviceSpeed,
  IN  UINT8                               DataToggle,
  IN  UINTN                               MaxPacketLen,
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
  OUT EHCI_QH_ENTITY                      **QhPtrPtr
  )
/*++

Routine Description:

  Create Qh for Bulk Transfer

Arguments:

  HcDev        - USB2_HC_DEV
  DeviceAddr   - Address of Device
  EndPointAddr - Address of Endpoint
  DeviceSpeed  - Device Speed
  MaxPacketLen - Max Length of one Packet
  Translator   - Translator Transaction for SplitX
  QhPtrPtr     - A pointer of pointer to Qh for return

Returns:

  EFI_SUCCESS            Success
  EFI_OUT_OF_RESOURCES   Cannot allocate resources

--*/
{
  EFI_STATUS  Status;

  //
  // Create and init Bulk Qh
  //
  Status = CreateQh (
             HcDev,
             DeviceAddr,
             EndPointAddr,
             DeviceSpeed,
             MaxPacketLen,
             QhPtrPtr
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_OUT_OF_RESOURCES;
    goto exit;
  }

  //
  // Software fields
  //
  (*QhPtrPtr)->Next         = (*QhPtrPtr);
  (*QhPtrPtr)->Prev         = (*QhPtrPtr);
  (*QhPtrPtr)->TransferType = BULK_TRANSFER;

  //
  // Hardware fields
  //
  // BulkTransfer don't use DataToggleControl
  //
  (*QhPtrPtr)->Qh.DataToggleControl   = FALSE;
  (*QhPtrPtr)->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&((*QhPtrPtr)->Qh)) >> 5);
  (*QhPtrPtr)->Qh.SelectType          = QH_SELECT_TYPE;
  (*QhPtrPtr)->Qh.QhTerminate         = FALSE;
  (*QhPtrPtr)->Qh.NakCountReload      = NAK_COUNT_RELOAD;
  (*QhPtrPtr)->Qh.DataToggle          = DataToggle;
  if (NULL != Translator) {
    (*QhPtrPtr)->Qh.PortNum = Translator->TranslatorPortNumber;
    (*QhPtrPtr)->Qh.HubAddr = Translator->TranslatorHubAddress;
    (*QhPtrPtr)->Qh.Status |= QTD_STATUS_DO_START_SPLIT;
  }

exit:
  return Status;
}

EFI_STATUS
CreateInterruptQh (
  IN  USB2_HC_DEV                         *HcDev,
  IN  UINT8                               DeviceAddr,
  IN  UINT8                               EndPointAddr,
  IN  UINT8                               DeviceSpeed,
  IN  UINT8                               DataToggle,
  IN  UINTN                               MaxPacketLen,
  IN  UINTN                               Interval,
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
  OUT EHCI_QH_ENTITY                      **QhPtrPtr
  )
/*++

Routine Description:

  Create Qh for Control Transfer

Arguments:

  HcDev        - USB2_HC_DEV
  DeviceAddr   - Address of Device
  EndPointAddr - Address of Endpoint
  DeviceSpeed  - Device Speed
  MaxPacketLen - Max Length of one Packet
  Interval     - value of interval
  Translator   - Translator Transaction for SplitX
  QhPtrPtr     - A pointer of pointer to Qh for return

Returns:

  EFI_SUCCESS            Success
  EFI_OUT_OF_RESOURCES   Cannot allocate resources

--*/
{
  EFI_STATUS  Status;

  //
  // Create and init InterruptQh
  //
  Status = CreateQh (
             HcDev,
             DeviceAddr,
             EndPointAddr,
             DeviceSpeed,
             MaxPacketLen,
             QhPtrPtr
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_OUT_OF_RESOURCES;
    goto exit;
  }

  //
  // Software fields
  //
  if (Interval == 0) {
    (*QhPtrPtr)->TransferType = SYNC_INTERRUPT_TRANSFER;
  } else {
    (*QhPtrPtr)->TransferType = ASYNC_INTERRUPT_TRANSFER;
  }
  (*QhPtrPtr)->Interval = GetApproxiOfInterval (Interval);

  //
  // Hardware fields
  //
  // InterruptTranfer don't use DataToggleControl
  //
  (*QhPtrPtr)->Qh.DataToggleControl     = FALSE;
  (*QhPtrPtr)->Qh.QhHorizontalPointer   = 0;
  (*QhPtrPtr)->Qh.QhTerminate           = TRUE;
  (*QhPtrPtr)->Qh.NakCountReload        = 0;
  (*QhPtrPtr)->Qh.InerruptScheduleMask  = MICRO_FRAME_0_CHANNEL;
  (*QhPtrPtr)->Qh.SplitComletionMask    = (MICRO_FRAME_2_CHANNEL | MICRO_FRAME_3_CHANNEL | MICRO_FRAME_4_CHANNEL);
  (*QhPtrPtr)->Qh.DataToggle            = DataToggle;
  if (NULL != Translator) {
    (*QhPtrPtr)->Qh.PortNum = Translator->TranslatorPortNumber;
    (*QhPtrPtr)->Qh.HubAddr = Translator->TranslatorHubAddress;
    (*QhPtrPtr)->Qh.Status |= QTD_STATUS_DO_START_SPLIT;
  }

exit:
  return Status;
}

EFI_STATUS
CreateQtd (
  IN  USB2_HC_DEV          *HcDev,
  IN  UINT8                *DataPtr,
  IN  UINTN                DataLen,
  IN  UINT8                PktId,
  IN  UINT8                Toggle,
  IN  UINT8                QtdStatus,
  OUT EHCI_QTD_ENTITY      **QtdPtrPtr
  )
/*++

Routine Description:

  Create Qtd Structure and Pre-Initialize it

Arguments:

  HcDev       - USB2_HC_DEV
  DataPtr     - A pointer to user data buffer to transfer
  DataLen     - Length of user data to transfer
  PktId       - Packet Identification of this Qtd
  Toggle      - Data Toggle of this Qtd
  QtdStatus   - Default value of status of this Qtd
  QtdPtrPtr   - A pointer of pointer to Qtd for return

Returns:

  EFI_SUCCESS            Success
  EFI_OUT_OF_RESOURCES   Cannot allocate resources

--*/
{
  EFI_STATUS  Status;
  EHCI_QTD_HW *QtdHwPtr;

  ASSERT (HcDev);
  ASSERT (QtdPtrPtr);

  //
  // Create memory for Qtd structure
  //
  Status = EhciAllocatePool (
             HcDev,
             (UINT8 **) QtdPtrPtr,
             sizeof (EHCI_QTD_ENTITY)
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_OUT_OF_RESOURCES;
    goto exit;
  }

  //
  // Software field
  //
  (*QtdPtrPtr)->TotalBytes        = (UINT32) DataLen;
  (*QtdPtrPtr)->StaticTotalBytes  = (UINT32) DataLen;
  (*QtdPtrPtr)->Prev              = NULL;
  (*QtdPtrPtr)->Next              = NULL;

  //
  // Hardware field
  //
  QtdHwPtr                      = &((*QtdPtrPtr)->Qtd);
  QtdHwPtr->NextQtdPointer      = 0;
  QtdHwPtr->NextQtdTerminate    = TRUE;
  QtdHwPtr->AltNextQtdPointer   = 0;
  QtdHwPtr->AltNextQtdTerminate = TRUE;
  QtdHwPtr->DataToggle          = Toggle;
  QtdHwPtr->TotalBytes          = (UINT32) DataLen;
  QtdHwPtr->CurrentPage         = 0;
  QtdHwPtr->ErrorCount          = QTD_ERROR_COUNTER;
  QtdHwPtr->Status              = QtdStatus;
  QtdHwPtr->Rsvd1               = 0;
  QtdHwPtr->Rsvd2               = 0;
  QtdHwPtr->Rsvd3               = 0;
  QtdHwPtr->Rsvd4               = 0;
  QtdHwPtr->Rsvd5               = 0;
  QtdHwPtr->Rsvd6               = 0;

  //
  // Set PacketID [Setup/Data/Status]
  //
  switch (PktId) {
  case SETUP_PACKET_ID:
    QtdHwPtr->PidCode = SETUP_PACKET_PID_CODE;
    break;

  case INPUT_PACKET_ID:
    QtdHwPtr->PidCode = INPUT_PACKET_PID_CODE;
    break;

  case OUTPUT_PACKET_ID:
    QtdHwPtr->PidCode = OUTPUT_PACKET_PID_CODE;
    break;

  default:
    Status = EFI_INVALID_PARAMETER;
    goto exit;
  }

  //
  // Set Data Buffer Pointers
  //
  if (NULL != DataPtr) {
    SetQtdBufferPointer (
      QtdHwPtr,
      DataPtr,
      DataLen
      );
    (*QtdPtrPtr)->StaticCurrentOffset = QtdHwPtr->CurrentOffset;
  }

exit:
  return Status;
}

EFI_STATUS
CreateSetupQtd (
  IN  USB2_HC_DEV          *HcDev,
  IN  UINT8                *DevReqPtr,
  OUT EHCI_QTD_ENTITY      **QtdPtrPtr
  )
/*++

Routine Description:

  Create Qtd Structure for Setup

Arguments:

  HcDev      - USB2_HC_DEV
  DevReqPtr  - A pointer to Device Request Data
  QtdPtrPtr  - A pointer of pointer to Qtd for return

Returns:

  EFI_SUCCESS            Success
  EFI_OUT_OF_RESOURCES   Cannot allocate resources

--*/
{
  return CreateQtd (
           HcDev,
           DevReqPtr,
           sizeof (EFI_USB_DEVICE_REQUEST),
           SETUP_PACKET_ID,
           DATA0,
           QTD_STATUS_ACTIVE,
           QtdPtrPtr
           );
}

EFI_STATUS
CreateDataQtd (
  IN  USB2_HC_DEV           *HcDev,
  IN  UINT8                 *DataPtr,
  IN  UINTN                 DataLen,
  IN  UINT8                 PktId,
  IN  UINT8                 Toggle,
  OUT EHCI_QTD_ENTITY       **QtdPtrPtr
  )
/*++

Routine Description:

  Create Qtd Structure for data

Arguments:

  HcDev       - USB2_HC_DEV
  DataPtr     - A pointer to user data buffer to transfer
  DataLen     - Length of user data to transfer
  PktId       - Packet Identification of this Qtd
  Toggle      - Data Toggle of this Qtd
  QtdPtrPtr   - A pointer of pointer to Qtd for return

Returns:

  EFI_SUCCESS            Success
  EFI_OUT_OF_RESOURCES   Cannot allocate resources

--*/
{
  return CreateQtd (
           HcDev,
           DataPtr,
           DataLen,
           PktId,
           Toggle,
           QTD_STATUS_ACTIVE,
           QtdPtrPtr
           );
}

EFI_STATUS
CreateAltQtd (
  IN  USB2_HC_DEV           *HcDev,
  IN  UINT8                 PktId,
  OUT EHCI_QTD_ENTITY       **QtdPtrPtr
  )
/*++

Routine Description:

  Create Qtd Structure for Alternative

Arguments:

  HcDev      - USB2_HC_DEV
  PktId      - Packet Identification of this Qtd
  QtdPtrPtr  - A pointer of pointer to Qtd for return

Returns:

  EFI_SUCCESS            Success
  EFI_OUT_OF_RESOURCES   Cannot allocate resources

--*/
{
  return CreateQtd (
           HcDev,
           NULL,
           0,
           PktId,
           0,
           QTD_STATUS_ACTIVE,
           QtdPtrPtr
           );
}

EFI_STATUS
CreateStatusQtd (
  IN  USB2_HC_DEV           *HcDev,
  IN  UINT8                 PktId,
  OUT EHCI_QTD_ENTITY       **QtdPtrPtr
  )
/*++

Routine Description:

  Create Qtd Structure for status

Arguments:

  HcDev       - USB2_HC_DEV
  PktId       - Packet Identification of this Qtd
  QtdPtrPtr   - A pointer of pointer to Qtd for return

Returns:

  EFI_SUCCESS            Success
  EFI_OUT_OF_RESOURCES   Cannot allocate resources

--*/
{
  return CreateQtd (
           HcDev,
           NULL,
           0,
           PktId,
           DATA1,
           QTD_STATUS_ACTIVE,
           QtdPtrPtr
           );
}

EFI_STATUS
CreateControlQtds (
  IN  USB2_HC_DEV                         *HcDev,
  IN UINT8                                DataPktId,
  IN UINT8                                *RequestCursor,
  IN UINT8                                *DataCursor,
  IN UINTN                                DataLen,
  IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
  OUT EHCI_QTD_ENTITY                     **ControlQtdsHead
  )
/*++

Routine Description:

  Create Qtds list for Control Transfer

Arguments:

  HcDev           - USB2_HC_DEV
  DataPktId       - Packet Identification of Data Qtds
  RequestCursor   - A pointer to request structure buffer to transfer
  DataCursor      - A pointer to user data buffer to transfer
  DataLen         - Length of user data to transfer
  ControlQtdsHead - A pointer of pointer to first Qtd for control tranfer for return

Returns:

  EFI_SUCCESS            Success
  EFI_OUT_OF_RESOURCES   Cannot allocate resources

--*/
{
  EFI_STATUS      Status;
  EHCI_QTD_ENTITY *QtdPtr;
  EHCI_QTD_ENTITY *PreQtdPtr;
  EHCI_QTD_ENTITY *SetupQtdPtr;
  EHCI_QTD_ENTITY *FirstDataQtdPtr;
  EHCI_QTD_ENTITY *LastDataQtdPtr;
  EHCI_QTD_ENTITY *StatusQtdPtr;
  UINT8           DataToggle;
  UINT8           StatusPktId;
  UINTN           CapacityOfQtd;
  UINTN           SizePerQtd;
  UINTN           DataCount;

  QtdPtr          = NULL;
  PreQtdPtr       = NULL;
  SetupQtdPtr     = NULL;
  FirstDataQtdPtr = NULL;
  LastDataQtdPtr  = NULL;
  StatusQtdPtr    = NULL;
  CapacityOfQtd   = 0;

  //
  //  Setup Stage of Control Transfer
  //
  Status = CreateSetupQtd (
             HcDev,
             RequestCursor,
             &SetupQtdPtr
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_OUT_OF_RESOURCES;
    goto exit;
  }

  //
  //  Data Stage of Control Transfer
  //
  DataToggle  = 1;
  DataCount   = DataLen;

  //
  // Create Qtd structure and link together
  //
  while (DataCount > 0) {
    //
    // PktSize is the data load size that each Qtd.
    //
    CapacityOfQtd = GetCapacityOfQtd (DataCursor);
    SizePerQtd    = DataCount;
    if (DataCount > CapacityOfQtd) {
      SizePerQtd = CapacityOfQtd;
    }

    Status = CreateDataQtd (
               HcDev,
               DataCursor,
               SizePerQtd,
               DataPktId,
               DataToggle,
               &QtdPtr
               );
    if (EFI_ERROR (Status)) {
      Status = EFI_OUT_OF_RESOURCES;
      if (NULL == FirstDataQtdPtr) {
        goto destory_setup_qtd;
      } else {
        goto destory_qtds;
      }
    }

    if (NULL == FirstDataQtdPtr) {
      FirstDataQtdPtr = QtdPtr;
    } else {
      LinkQtdToQtd (PreQtdPtr, QtdPtr);
    }

    DataToggle ^= 1;
  
    PreQtdPtr = QtdPtr;
    DataCursor += SizePerQtd;
    DataCount -= SizePerQtd;
  }

  LastDataQtdPtr = QtdPtr;

  //
  // Status Stage of Control Transfer
  //
  if (OUTPUT_PACKET_ID == DataPktId) {
    StatusPktId = INPUT_PACKET_ID;
  } else {
    StatusPktId = OUTPUT_PACKET_ID;
  }

  Status = CreateStatusQtd (

⌨️ 快捷键说明

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