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 + -
显示快捷键?