ehcisched.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,975 行 · 第 1/5 页
C
2,975 行
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
Status = EFI_SUCCESS;
ASSERT (HcDev);
ASSERT (QhPtr);
HcDev->NULLQH->Next = HcDev->NULLQH;
HcDev->NULLQH->Prev = HcDev->NULLQH;
QhPtr->Next = QhPtr;
QhPtr->Prev = QhPtr;
HcDev->NULLQH->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&(HcDev->NULLQH->Qh) >> 5));
SetAndWaitDoorBell (HcDev, 2 * EHCI_GENERIC_TIMEOUT);
QhPtr->Qh.QhTerminate = 1;
QhPtr->Qh.QhHorizontalPointer = 0;
Status = DisableAsynchronousSchedule (HcDev);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
Status = WaitForAsyncScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
if (EFI_ERROR (Status)) {
DEBUG ((gEHCErrorLevel, "EHCI: WaitForAsyncScheduleDisable TimeOut\n"));
Status = EFI_TIMEOUT;
goto exit;
}
exit:
return Status;
}
VOID
LinkQhToPeriodicList (
IN USB2_HC_DEV *HcDev,
IN EHCI_QH_ENTITY *QhPtr
)
/*++
Routine Description:
Link Qh to Periodic Schedule List
Arguments:
HcDev - USB2_HC_DEV
QhPtr - A pointer to Qh
Returns:
VOID
--*/
{
FRAME_LIST_ENTRY *FrameEntryPtr;
EHCI_QH_ENTITY *FindQhPtr;
EHCI_QH_HW *FindQhHwPtr;
UINTN FrameIndex;
ASSERT (HcDev);
ASSERT (QhPtr);
FindQhPtr = NULL;
FindQhHwPtr = NULL;
FrameIndex = 0;
FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;
QhPtr->Qh.HeadReclamationFlag = FALSE;
if (QhPtr->TransferType == ASYNC_INTERRUPT_TRANSFER) {
//
// AsyncInterruptTransfer Qh
//
//
// Link to Frame[0] List
//
if (!FrameEntryPtr->LinkTerminate) {
//
// Not Null FrameList
//
FindQhHwPtr = (EHCI_QH_HW *) GET_0B_TO_31B (FrameEntryPtr->LinkPointer << 5);
FindQhPtr = (EHCI_QH_ENTITY *) GET_QH_ENTITY_ADDR (FindQhHwPtr);
//
// FindQh is Left/Right to Qh
//
while ((NULL != FindQhPtr->Next) && (FindQhPtr->Interval > QhPtr->Interval)) {
FindQhPtr = FindQhPtr->Next;
}
if (FindQhPtr->Interval == QhPtr->Interval) {
//
// Link Qh after FindQh
//
if (NULL != FindQhPtr->Next) {
FindQhPtr->Next->Prev = QhPtr;
QhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(FindQhPtr->Next->Qh) >> 5);
QhPtr->Qh.SelectType = QH_SELECT_TYPE;
QhPtr->Qh.QhTerminate = FALSE;
}
FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
FindQhPtr->Qh.SelectType = QH_SELECT_TYPE;
FindQhPtr->Qh.QhTerminate = FALSE;
QhPtr->Prev = FindQhPtr;
QhPtr->Next = FindQhPtr->Next;
FindQhPtr->Next = QhPtr;
} else if (FindQhPtr->Interval < QhPtr->Interval) {
//
// Link Qh before FindQh
//
if (NULL == FindQhPtr->Prev) {
//
// Qh is the First one in Frame[0] List
//
FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
FrameEntryPtr->SelectType = QH_SELECT_TYPE;
FrameEntryPtr->LinkTerminate = FALSE;
} else {
//
// Qh is not the First one in Frame[0] List
//
FindQhPtr->Prev->Next = QhPtr;
FindQhPtr->Prev->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
FindQhPtr->Prev->Qh.SelectType = QH_SELECT_TYPE;
FindQhPtr->Prev->Qh.QhTerminate = FALSE;
}
QhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(FindQhPtr->Qh) >> 5);
QhPtr->Qh.SelectType = QH_SELECT_TYPE;
QhPtr->Qh.QhTerminate = FALSE;
QhPtr->Next = FindQhPtr;
QhPtr->Prev = FindQhPtr->Prev;
FindQhPtr->Prev = QhPtr;
} else {
//
// Link Qh after FindQh, Qh is the Last one
//
FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
FindQhPtr->Prev->Qh.SelectType = QH_SELECT_TYPE;
FindQhPtr->Qh.QhTerminate = FALSE;
QhPtr->Prev = FindQhPtr;
QhPtr->Next = NULL;
FindQhPtr->Next = QhPtr;
}
} else {
//
// Null FrameList
//
FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
FrameEntryPtr->SelectType = QH_SELECT_TYPE;
FrameEntryPtr->LinkTerminate = FALSE;
}
//
// Other Frame[X]
//
if (NULL == QhPtr->Prev) {
//
// Qh is the First one in Frame[0] List
//
FrameIndex += QhPtr->Interval;
while (FrameIndex < HcDev->PeriodicFrameListLength) {
FrameEntryPtr = (FRAME_LIST_ENTRY *) (FrameEntryPtr + QhPtr->Interval);
FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
FrameEntryPtr->SelectType = QH_SELECT_TYPE;
FrameEntryPtr->LinkTerminate = FALSE;
FrameIndex += QhPtr->Interval;
}
} else if (QhPtr->Interval < QhPtr->Prev->Interval) {
//
// Qh is not the First one in Frame[0] List, and Prev.interval > Qh.interval
//
FrameIndex += QhPtr->Interval;
while (FrameIndex < HcDev->PeriodicFrameListLength) {
FrameEntryPtr = (FRAME_LIST_ENTRY *) (FrameEntryPtr + QhPtr->Interval);
if ((FrameIndex % QhPtr->Prev->Interval) != 0) {
FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
FrameEntryPtr->SelectType = QH_SELECT_TYPE;
FrameEntryPtr->LinkTerminate = FALSE;
}
FrameIndex += QhPtr->Interval;
}
}
} else {
//
// SyncInterruptTransfer Qh
//
if (!FrameEntryPtr->LinkTerminate) {
//
// Not Null FrameList
//
FindQhHwPtr = (EHCI_QH_HW *) GET_0B_TO_31B (FrameEntryPtr->LinkPointer << 5);
FindQhPtr = (EHCI_QH_ENTITY *) GET_QH_ENTITY_ADDR (FindQhHwPtr);
//
// FindQh is Last Qh in the Asynchronous List, Link Qh after FindQh
//
while (NULL != FindQhPtr->Next) {
FindQhPtr = FindQhPtr->Next;
}
FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
FindQhPtr->Qh.SelectType = QH_SELECT_TYPE;
FindQhPtr->Qh.QhTerminate = FALSE;
FindQhPtr->Next = QhPtr;
QhPtr->Prev = FindQhPtr;
} else {
//
// Null FrameList
//
FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
FrameEntryPtr->SelectType = QH_SELECT_TYPE;
FrameEntryPtr->LinkTerminate = FALSE;
}
}
return ;
}
VOID
UnlinkQhFromPeriodicList (
IN USB2_HC_DEV *HcDev,
IN EHCI_QH_ENTITY *QhPtr,
IN UINTN Interval
)
/*++
Routine Description:
Unlink Qh from Periodic Schedule List
Arguments:
HcDev - USB2_HC_DEV
QhPtr - A pointer to Qh
Interval - Interval of this periodic transfer
Returns:
VOID
--*/
{
FRAME_LIST_ENTRY *FrameEntryPtr;
UINTN FrameIndex;
FrameIndex = 0;
ASSERT (HcDev);
ASSERT (QhPtr);
FrameIndex = 0;
FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;
if (QhPtr->TransferType == ASYNC_INTERRUPT_TRANSFER) {
//
// AsyncInterruptTransfer Qh
//
if (NULL == QhPtr->Prev) {
//
// Qh is the First one on Frame[0] List
//
if (NULL == QhPtr->Next) {
//
// Only one on Frame[0] List
//
while (FrameIndex < HcDev->PeriodicFrameListLength) {
FrameEntryPtr->LinkPointer = 0;
FrameEntryPtr->SelectType = 0;
FrameEntryPtr->LinkTerminate = TRUE;
FrameEntryPtr += Interval;
FrameIndex += Interval;
}
} else {
while (FrameIndex < HcDev->PeriodicFrameListLength) {
FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Next->Qh) >> 5);
FrameEntryPtr->SelectType = QH_SELECT_TYPE;
FrameEntryPtr->LinkTerminate = FALSE;
FrameEntryPtr += Interval;
FrameIndex += Interval;
}
}
} else {
//
// Not First one on Frame[0] List
//
if (NULL == QhPtr->Next) {
//
// Qh is the Last one on Frame[0] List
//
QhPtr->Prev->Qh.QhHorizontalPointer = 0;
QhPtr->Prev->Qh.SelectType = 0;
QhPtr->Prev->Qh.QhTerminate = TRUE;
} else {
QhPtr->Prev->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Next->Qh) >> 5);
QhPtr->Prev->Qh.SelectType = QH_SELECT_TYPE;
QhPtr->Prev->Qh.QhTerminate = FALSE;
}
if (Interval == QhPtr->Prev->Interval) {
//
// Interval is the same as Prev
// Not involed Frame[X]
//
} else {
//
// Other Frame[X]
//
while (FrameIndex < HcDev->PeriodicFrameListLength) {
if ((FrameIndex % QhPtr->Prev->Interval) != 0) {
FrameEntryPtr->LinkPointer = QhPtr->Prev->Qh.QhHorizontalPointer;
FrameEntryPtr->SelectType = QhPtr->Prev->Qh.SelectType;
FrameEntryPtr->LinkTerminate = QhPtr->Prev->Qh.QhTerminate;
}
FrameEntryPtr += Interval;
FrameIndex += Interval;
}
}
}
if (NULL != QhPtr->Next) {
QhPtr->Next->Prev = QhPtr->Prev;
}
if (NULL != QhPtr->Prev) {
QhPtr->Prev->Next = QhPtr->Next;
}
} else {
//
// SyncInterruptTransfer Qh
//
if (NULL == QhPtr->Prev) {
//
// Qh is the only one Qh on Frame[0] List
//
FrameEntryPtr->LinkPointer = 0;
FrameEntryPtr->SelectType = 0;
FrameEntryPtr->LinkTerminate = TRUE;
} else {
QhPtr->Prev->Qh.QhHorizontalPointer = 0;
QhPtr->Prev->Qh.SelectType = 0;
QhPtr->Prev->Qh.QhTerminate = TRUE;
}
if (NULL != QhPtr->Prev) {
QhPtr->Prev->Next = NULL;
}
}
return ;
}
VOID
LinkToAsyncReqeust (
IN USB2_HC_DEV *HcDev,
IN EHCI_ASYNC_REQUEST *AsyncRequestPtr
)
/*++
Routine Description:
Llink AsyncRequest Entry to Async Request List
Arguments:
HcDev - USB2_HC_DEV
AsyncRequestPtr - A pointer to Async Request Entry
Returns:
VOID
--*/
{
EHCI_ASYNC_REQUEST *CurrentPtr;
CurrentPtr = HcDev->AsyncRequestList;
HcDev->AsyncRequestList = AsyncRequestPtr;
AsyncRequestPtr->Prev = NULL;
AsyncRequestPtr->Next = CurrentPtr;
if (NULL != CurrentPtr) {
CurrentPtr->Prev = AsyncRequestPtr;
}
return ;
}
VOID
UnlinkFromAsyncReqeust (
IN USB2_HC_DEV *HcDev,
IN EHCI_ASYNC_REQUEST *AsyncRequestPtr
)
/*++
Routine Description:
Unlink AsyncRequest Entry from Async Request List
Arguments:
HcDev - USB2_HC_DEV
AsyncRequestPtr - A pointer to Async Request Entry
Returns:
VOID
--*/
{
if (NULL == AsyncRequestPtr->Prev) {
HcDev->AsyncRequestList = AsyncRequestPtr->Next;
if (NULL != AsyncRequestPtr->Next) {
AsyncRequestPtr->Next->Prev = NULL;
}
} else {
AsyncRequestPtr->Prev->Next = AsyncRequestPtr->Next;
if (NULL != AsyncRequestPtr->Next) {
AsyncRequestPtr->Next->Prev = AsyncRequestPtr->Prev;
}
}
return ;
}
VOID
SetQtdBufferPointer (
IN EHCI_QTD_HW *QtdHwPtr,
IN VOID *DataPtr,
IN UINTN DataLen
)
/*++
Routine Description:
Set data buffer pointers in Qtd
Arguments:
QtdHwPtr - A pointer to Qtd hardware structure
DataPtr - A pointer to user data buffer
DataLen - Length of the user data buffer
Returns:
VOID
--*/
{
UINTN RemainLen;
ASSERT (QtdHwPtr);
ASSERT (DataLen <= 5 * EFI_PAGE_SIZE);
RemainLen = DataLen;
//
// Allow buffer address range across 4G.
// But EFI_USB_MAX_BULK_BUFFER_NUM = 1, so don't allow
// seperate buffer array.
//
//
// Set BufferPointer0, ExtBufferPointer0 and Offset
//
QtdHwPtr->BufferPointer0 = (UINT32) (GET_0B_TO_31B (DataPtr) >> EFI_PAGE_SHIFT);
QtdHwPtr->CurrentOffset = (UINT32) (GET_0B_TO_31B (DataPtr) & EFI_PAGE_MASK);
//
// Set BufferPointer1 and ExtBufferPointer1
//
RemainLen = RemainLen > (EFI_PAGE_SIZE - QtdHwPtr->CurrentOffset) ? (RemainLen - (EFI_PAGE_SIZE - QtdHwPtr->CurrentOffset)) : 0;
if (RemainLen == 0) {
goto exit;
}
QtdHwPtr->BufferPointer1 = QtdHwPtr->BufferPointer0 + 1;
//
// Set BufferPointer2 and ExtBufferPointer2
//
RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0;
if (RemainLen == 0) {
goto exit;
}
QtdHwPtr->BufferPointer2 = QtdHwPtr->BufferPointer1 + 1;
//
// Set BufferPointer3 and ExtBufferPointer3
//
RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0;
if (RemainLen == 0) {
goto exit;
}
QtdHwPtr->BufferPointer3 = QtdHwPtr->BufferPointer2 + 1;
//
// Set BufferPointer4 and ExtBufferPointer4
//
RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0;
if (RemainLen == 0) {
goto exit;
}
QtdHwPtr->BufferPointer4 = QtdHwPtr->BufferPointer3 + 1;
exit:
return ;
}
BOOLEAN
IsQtdStatusActive (
IN EHCI_QTD_HW *HwQtdPtr
)
/*++
Routine Description:
Whether Qtd status is active or not
Arguments:
HwQtdPtr - A pointer to hardware Qtd structure
Returns:
TRUE Active
FALSE Inactive
--*/
{
UINT8 QtdStatus;
BOOLEAN Value;
QtdStatus = (UINT8) (HwQtdPtr->Status);
Value = (BOOLEAN) (QtdStatus & QTD_STATUS_ACTIVE);
return Value;
}
BOOLEAN
IsQtdStatusHalted (
IN EHCI_QTD_HW *HwQtdPtr
)
/*++
Routine Description:
Whether Qtd status is halted or not
Arguments:
HwQtdPtr - A pointer to hardware Qtd structure
Returns:
TRUE Halted
FALSE Not halted
--*/
{
UINT8 QtdStatus;
BOOLEAN Value;
QtdStatus = (UINT8) (HwQtdPtr->Status);
Value = (BOOLEAN) (QtdStatus & QTD_STATUS_HALTED);
return Value;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?