uhchlp.c

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

C
3,348
字号
  ptrTDStruct->TDData.TDBufferPtr = (UINT32) ((UINTN) (ptrTDStruct->pTDBuffer));
}

BOOLEAN
IsTDStatusActive (
  IN TD_STRUCT     *ptrTDStruct
  )
{
  UINT8 TDStatus;

  //
  // Detect whether the TD is active.
  //
  TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
  return (BOOLEAN) (TDStatus & 0x80);
}

BOOLEAN
IsTDStatusStalled (
  IN TD_STRUCT     *ptrTDStruct
  )
{
  UINT8 TDStatus;

  //
  // Detect whether the device/endpoint addressed by this TD is stalled.
  //
  TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
  return (BOOLEAN) (TDStatus & 0x40);
}

BOOLEAN
IsTDStatusBufferError (
  IN TD_STRUCT     *ptrTDStruct
  )
{
  UINT8 TDStatus;
  //
  // Detect whether Data Buffer Error is happened.
  //
  TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
  return (BOOLEAN) (TDStatus & 0x20);
}

BOOLEAN
IsTDStatusBabbleError (
  IN TD_STRUCT     *ptrTDStruct
  )
{
  UINT8 TDStatus;

  //
  // Detect whether Babble Error is happened.
  //
  TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
  return (BOOLEAN) (TDStatus & 0x10);
}

BOOLEAN
IsTDStatusNAKReceived (
  IN TD_STRUCT     *ptrTDStruct
  )
{
  UINT8 TDStatus;

  //
  // Detect whether NAK is received.
  //
  TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
  return (BOOLEAN) (TDStatus & 0x08);
}

BOOLEAN
IsTDStatusCRCTimeOutError (
  IN TD_STRUCT     *ptrTDStruct
  )
{
  UINT8 TDStatus;

  //
  // Detect whether CRC/Time Out Error is encountered.
  //
  TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
  return (BOOLEAN) (TDStatus & 0x04);
}

BOOLEAN
IsTDStatusBitStuffError (
  IN TD_STRUCT     *ptrTDStruct
  )
{
  UINT8 TDStatus;

  //
  // Detect whether Bitstuff Error is received.
  //
  TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
  return (BOOLEAN) (TDStatus & 0x02);
}

UINT16
GetTDStatusActualLength (
  IN TD_STRUCT     *ptrTDStruct
  )
{
  //
  // Retrieve the actual number of bytes that were tansferred.
  // the value is encoded as n-1. so return the decoded value.
  //
  return (UINT16) ((ptrTDStruct->TDData.TDStatusActualLength) + 1);
}

UINT16
GetTDTokenMaxLength (
  IN TD_STRUCT     *ptrTDStruct
  )
{
  //
  // Retrieve the maximum number of data bytes allowed for the trnasfer.
  //
  return (UINT16) ((ptrTDStruct->TDData.TDTokenMaxLen) + 1);
}

UINT8
GetTDTokenEndPoint (
  IN TD_STRUCT     *ptrTDStruct
  )
{
  //
  // Retrieve the endpoint number the transaction is targeting at.
  //
  return (UINT8) (ptrTDStruct->TDData.TDTokenEndPt);
}

UINT8
GetTDTokenDeviceAddress (
  IN TD_STRUCT     *ptrTDStruct
  )
{
  //
  // Retrieve the device address the transaction is targeting at.
  //
  return (UINT8) (ptrTDStruct->TDData.TDTokenDevAddr);
}

UINT8
GetTDTokenPacketID (
  IN  TD_STRUCT *ptrTDStruct
  )
{
  //
  // Retrieve the Packet Identification information.
  //
  return (UINT8) (ptrTDStruct->TDData.TDTokenPID);
}

UINT8 *
GetTDDataBuffer (
  IN TD_STRUCT    *ptrTDStruct
  )
{
  //
  // Retrieve the beginning address of the data buffer
  // that involved in this transaction.
  //
  return ptrTDStruct->pTDBuffer;
}

BOOLEAN
GetTDLinkPtrValidorInvalid (
  IN TD_STRUCT     *ptrTDStruct
  )
{
  //
  // Retrieve the information of whether the Link Pointer field
  // is valid or not.
  //
  if (ptrTDStruct->TDData.TDLinkPtrTerminate) {
    return FALSE;
  } else {
    return TRUE;
  }

}

UINTN
CountTDsNumber (
  IN TD_STRUCT     *PtrFirstTD
  )
{
  UINTN     Number;
  TD_STRUCT *ptr;
  //
  // Count the queued TDs number.
  //
  Number  = 0;
  ptr     = PtrFirstTD;
  while (ptr) {
    ptr = (TD_STRUCT *) ptr->ptrNextTD;
    Number++;
  }

  return Number;
}



VOID
LinkTDToQH (
  IN QH_STRUCT     *PtrQH,
  IN TD_STRUCT     *PtrTD
  )
/*++

Routine Description:

  Link TD To QH

Arguments:

  PtrQH - QH_STRUCT
  PtrTD - TD_STRUCT
Returns:

  VOID

--*/
{
  if (PtrQH == NULL || PtrTD == NULL) {
    return ;
  }
  //
  //  Validate QH Vertical Ptr field
  //
  SetQHVerticalValidorInvalid (PtrQH, TRUE);

  //
  //  Vertical Ptr pointing to TD structure
  //
  SetQHVerticalQHorTDSelect (PtrQH, FALSE);

  SetQHVerticalLinkPtr (PtrQH, (VOID *) PtrTD);

  PtrQH->ptrDown = (VOID *) PtrTD;
}

VOID
LinkTDToTD (
  IN TD_STRUCT     *ptrPreTD,
  IN TD_STRUCT     *PtrTD
  )
/*++

Routine Description:

  Link TD To TD

Arguments:

  ptrPreTD - Previous TD_STRUCT to be linked
  PtrTD    - TD_STRUCT to link
Returns:

  VOID

--*/
{
  if (ptrPreTD == NULL || PtrTD == NULL) {
    return ;
  }
  //
  // Depth first fashion
  //
  SetTDLinkPtrDepthorBreadth (ptrPreTD, TRUE);

  //
  // Link pointer pointing to TD struct
  //
  SetTDLinkPtrQHorTDSelect (ptrPreTD, FALSE);

  //
  // Validate the link pointer valid bit
  //
  SetTDLinkPtrValidorInvalid (ptrPreTD, TRUE);

  SetTDLinkPtr (ptrPreTD, PtrTD);

  ptrPreTD->ptrNextTD = (VOID *) PtrTD;
}
//
// Transfer Schedule related Helper Functions
//
VOID
SetorClearCurFrameListTerminate (
  IN FRAMELIST_ENTRY     *pCurEntry,
  IN BOOLEAN             IsSet
  )
{
  //
  // If TRUE, empty the frame. If FALSE, indicate the Pointer field is valid.
  //
  pCurEntry->FrameListPtrTerminate = (IsSet ? 1 : 0);
}

VOID
SetCurFrameListQHorTD (
  IN FRAMELIST_ENTRY     *pCurEntry,
  IN BOOLEAN             IsQH
  )
{
  //
  // This bit indicates to the hardware whether the item referenced by the
  // link pointer is a TD or a QH.
  //
  pCurEntry->FrameListPtrQSelect = (IsQH ? 1 : 0);
}

BOOLEAN
IsCurFrameListQHorTD (
  IN FRAMELIST_ENTRY     *pCurEntry
  )
{
  //
  // TRUE is QH
  // FALSE is TD
  //
  return (BOOLEAN) (pCurEntry->FrameListPtrQSelect);
}

BOOLEAN
GetCurFrameListTerminate (
  IN FRAMELIST_ENTRY     *pCurEntry
  )
{
  //
  // TRUE means the frame is empty,
  // FALSE means the link pointer field is valid.
  //
  return (BOOLEAN) (pCurEntry->FrameListPtrTerminate);
}

VOID
SetCurFrameListPointer (
  IN FRAMELIST_ENTRY     *pCurEntry,
  IN UINT8               *ptr
  )
{
  //
  // Set the pointer field of the frame.
  //
  pCurEntry->FrameListPtr = (UINT32) ((UINTN) ptr >> 4);
}

VOID *
GetCurFrameListPointer (
  IN FRAMELIST_ENTRY     *pCurEntry
  )
{
  //
  // Get the link pointer of the frame.
  //
  return (VOID *) ((UINTN) (pCurEntry->FrameListPtr << 4));

}

VOID
LinkQHToFrameList (
  IN FRAMELIST_ENTRY     *pEntry,
  IN UINT16              FrameListIndex,
  IN QH_STRUCT           *PtrQH
  )
/*++

Routine Description:

  Link QH To Frame List

Arguments:

  pEntry           - FRAMELIST_ENTRY
  FrameListIndex   - Frame List Index
  PtrQH            - QH to link 
Returns:

  VOID

--*/
{
  FRAMELIST_ENTRY *pCurFrame;
  QH_STRUCT       *TempQH;
  QH_STRUCT       *NextTempQH;
  TD_STRUCT       *TempTD;
  BOOLEAN         LINK;

  //
  // Get frame list entry that the link process will begin from.
  //
  pCurFrame = pEntry + FrameListIndex;

  //
  // if current frame is empty
  // then link the specified QH directly to the Frame List.
  //
  if (GetCurFrameListTerminate (pCurFrame)) {
    
    //
    // Link new QH to the frame list entry.
    //
    SetCurFrameListQHorTD (pCurFrame, TRUE);

    SetCurFrameListPointer (pCurFrame, (UINT8 *) PtrQH);

    //
    // clear T bit in the Frame List, indicating that the frame list entry
    // is no longer empty.
    //
    SetorClearCurFrameListTerminate (pCurFrame, FALSE);

    return ;

  } else {
    //
    // current frame list has link pointer
    //
    if (!IsCurFrameListQHorTD (pCurFrame)) {
      //
      //  a TD is linked to the framelist entry
      //
      TempTD = (TD_STRUCT *) GetCurFrameListPointer (pCurFrame);

      while (GetTDLinkPtrValidorInvalid (TempTD)) {

        if (IsTDLinkPtrQHOrTD (TempTD)) {
          //
          // QH linked next to the TD
          //
          break;
        }

        TempTD = (TD_STRUCT *) GetTDLinkPtr (TempTD);
      }
      
      //
      // either no ptr linked next to the TD or QH is linked next to the TD
      //
      if (!GetTDLinkPtrValidorInvalid (TempTD)) {
        
        //
        // no ptr linked next to the TD
        //
        TempTD->ptrNextQH = PtrQH;
        SetTDLinkPtrQHorTDSelect (TempTD, TRUE);
        SetTDLinkPtr (TempTD, PtrQH);
        SetTDLinkPtrValidorInvalid (TempTD, TRUE);
        return ;

      } else {
        //
        //  QH is linked next to the TD
        //
        TempQH = (QH_STRUCT *) GetTDLinkPtr (TempTD);
      }
    } else {
      //
      // a QH is linked to the framelist entry
      //
      TempQH = (QH_STRUCT *) GetCurFrameListPointer (pCurFrame);
    }
    
    //
    // Set up Flag
    //
    LINK = TRUE;

    //
    // Avoid the same qh repeated linking in one frame entry
    //
    if (TempQH == PtrQH) {
      LINK = FALSE;
      return ;
    }
    //
    // if current QH has next QH connected
    //
    while (GetQHHorizontalValidorInvalid (TempQH)) {
      //
      // Get next QH pointer
      //
      NextTempQH = (QH_STRUCT *) GetQHHorizontalLinkPtr (TempQH);

      //
      // Bulk transfer qh may be self-linked,
      // so, the code below is to aVOID dead-loop when meeting self-linked qh
      //
      if (NextTempQH == TempQH) {
        LINK = FALSE;
        break;
      }

      TempQH = NextTempQH;

      //
      // Avoid the same qh repeated linking in one frame entry
      //
      if (TempQH == PtrQH) {
        LINK = FALSE;
      }
    }

    if (LINK) {
      TempQH->ptrNext = PtrQH;
      SetQHHorizontalQHorTDSelect (TempQH, TRUE);
      SetQHHorizontalLinkPtr (TempQH, PtrQH);
      SetQHHorizontalValidorInvalid (TempQH, TRUE);
    }

    return ;
  }
}

EFI_STATUS
ExecuteControlTransfer (
  IN  USB_HC_DEV     *HcDev,
  IN  TD_STRUCT      *PtrTD,
  IN  UINT32         wIndex,
  OUT UINTN          *ActualLen,
  IN  UINTN          TimeOut,
  OUT UINT32         *TransferResult
  )
/*++

Routine Description:

  Execute Control Transfer

Arguments:

  HcDev            - USB_HC_DEV
  PtrTD            - TD_STRUCT
  wIndex           - No use
  ActualLen        - Actual transfered Len 
  TimeOut          - TimeOut value in milliseconds
  TransferResult   - Transfer result
Returns:

  EFI_SUCCESS      - Sucess
  EFI_DEVICE_ERROR - Error
  

--*/
{
  UINTN   ErrTDPos;
  UINTN   Delay;
  UINTN   RequiredLen;
  BOOLEAN TransferFinished;

  ErrTDPos        = 0;
  *TransferResult = EFI_USB_NOERROR;
  RequiredLen     = *ActualLen;
  *ActualLen      = 0;

  Delay           = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1;

  do {
    TransferFinished = CheckTDsResults (
                         PtrTD,
                         RequiredLen,
                         TransferResult,
                         &ErrTDPos,
                         ActualLen
                         );

    if (TransferFinished) {
      break;
    }
       
    //
    // TD is inactive, which means the control transfer is end.
    //
    if ((*TransferResult & EFI_USB_ERR_NOTEXECUTE) != EFI_USB_ERR_NOTEXECUTE) {
      break;
    } 

    gBS->Stall (50);

  } while (Delay--);

  if (*TransferResult != EFI_USB_NOERROR) {
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}

EFI_STATUS
ExecBulkorSyncInterruptTransfer (
  IN  USB_HC_DEV     *HcDev,
  IN  TD_STRUCT      *PtrTD,
  IN  UINT32         wIndex,
  OUT UINTN          *ActualLen,
  OUT UINT8          *DataToggle,
  IN  UINTN          TimeOut,
  OUT UINT32         *TransferResult
  )
/*++

Routine Description:

  Execute Bulk or SyncInterrupt Transfer

Arguments:

  HcDev            - USB_HC_DEV
  PtrTD            - TD_STRUCT
  wIndex           - No use
  ActualLen        - Actual transfered Len 
  DataToggle       - Data Toggle
  TimeOut          - TimeOut value in milliseconds
  TransferResult   - Transfer result
Returns:

  EFI_SUCCESS      - Sucess
  EFI_DEVICE_ERROR - Error
--*/
{
  UINTN   ErrTDPos;
  UINTN   ScrollNum;
  UINTN   Delay;
  UINTN   RequiredLen;
  BOOLEAN TransferFinished;

  ErrTDPos        = 0;
  *TransferResult = EFI_USB_NOERROR;
  RequiredLen     = *ActualLen;
  *ActualLen      = 0;

  Delay           = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1;

  do {

    TransferFinished = CheckTDsResults (
                         PtrTD,
                         RequiredLen,
                         TransferResult,
                         &ErrTDPos,
                         ActualLen
                         );
                        
    if (TransferFinished) {
      break;
    }
       
    //
    // TD is inactive, which means bulk or interrupt transfer's end.
    //    
    if ((*TransferResult & EFI_USB_ERR_NOTEXECUTE) != EFI_USB_ERR_NOTEXECUTE) {
      break;
    }

    gBS->Stall (50);

  } while (Delay--);

  //
  // has error
  //
  if (*TransferResult != EFI_USB_NOERROR) {
  
    //
    // scroll the Data Toggle back to the last success TD

⌨️ 快捷键说明

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