ehcisched.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,975 行 · 第 1/5 页
C
2,975 行
HcDev,
StatusPktId,
&StatusQtdPtr
);
if (EFI_ERROR (Status)) {
Status = EFI_OUT_OF_RESOURCES;
goto destory_qtds;
}
//
// Link setup Qtd -> data Qtds -> status Qtd
//
if (FirstDataQtdPtr != NULL) {
LinkQtdToQtd (SetupQtdPtr, FirstDataQtdPtr);
LinkQtdToQtd (LastDataQtdPtr, StatusQtdPtr);
} else {
LinkQtdToQtd (SetupQtdPtr, StatusQtdPtr);
}
*ControlQtdsHead = SetupQtdPtr;
goto exit;
destory_qtds:
DestoryQtds (HcDev, FirstDataQtdPtr);
destory_setup_qtd:
DestoryQtds (HcDev, SetupQtdPtr);
exit:
return Status;
}
EFI_STATUS
CreateBulkOrInterruptQtds (
IN USB2_HC_DEV *HcDev,
IN UINT8 PktId,
IN UINT8 *DataCursor,
IN UINTN DataLen,
IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
OUT EHCI_QTD_ENTITY **QtdsHead
)
/*++
Routine Description:
Create Qtds list for Bulk or Interrupt Transfer
Arguments:
HcDev - USB2_HC_DEV
PktId - Packet Identification of Qtds
DataCursor - A pointer to user data buffer to transfer
DataLen - Length of user data to transfer
DataToggle - Data Toggle to start
Translator - Translator Transaction for SplitX
QtdsHead - 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 *FirstQtdPtr;
EHCI_QTD_ENTITY *AltQtdPtr;
UINTN DataCount;
UINTN CapacityOfQtd;
UINTN SizePerQtd;
Status = EFI_SUCCESS;
QtdPtr = NULL;
PreQtdPtr = NULL;
FirstQtdPtr = NULL;
AltQtdPtr = NULL;
CapacityOfQtd = 0;
DataCount = DataLen;
while (DataCount > 0) {
CapacityOfQtd = GetCapacityOfQtd (DataCursor);
SizePerQtd = DataCount;
if (DataCount > CapacityOfQtd) {
SizePerQtd = CapacityOfQtd;
}
Status = CreateDataQtd (
HcDev,
DataCursor,
SizePerQtd,
PktId,
0,
&QtdPtr
);
if (EFI_ERROR (Status)) {
Status = EFI_OUT_OF_RESOURCES;
if (NULL == FirstQtdPtr) {
goto exit;
} else {
goto destory_qtds;
}
}
if (NULL == FirstQtdPtr) {
FirstQtdPtr = QtdPtr;
} else {
LinkQtdToQtd (PreQtdPtr, QtdPtr);
}
PreQtdPtr = QtdPtr;
DataCursor += SizePerQtd;
DataCount -= SizePerQtd;
}
//
// Set Alternate Qtd
//
if (INPUT_PACKET_ID == PktId && 0 < GetNumberOfQtd (FirstQtdPtr)) {
Status = CreateAltQtd (
HcDev,
PktId,
&AltQtdPtr
);
if (EFI_ERROR (Status)) {
Status = EFI_OUT_OF_RESOURCES;
goto destory_qtds;
}
LinkQtdsToAltQtd (FirstQtdPtr, AltQtdPtr);
}
*QtdsHead = FirstQtdPtr;
goto exit;
destory_qtds:
DestoryQtds (HcDev, FirstQtdPtr);
exit:
return Status;
}
VOID
DestoryQtds (
IN USB2_HC_DEV *HcDev,
IN EHCI_QTD_ENTITY *FirstQtdPtr
)
/*++
Routine Description:
Destory all Qtds in the list
Arguments:
HcDev - USB2_HC_DEV
FirstQtdPtr - A pointer to first Qtd in the list
Returns:
VOID
--*/
{
EHCI_QTD_ENTITY *PrevQtd;
EHCI_QTD_ENTITY *NextQtd;
if (!FirstQtdPtr) {
goto exit;
}
PrevQtd = FirstQtdPtr;
//
// Delete all the Qtds.
//
do {
NextQtd = PrevQtd->Next;
EhciFreePool (HcDev, (UINT8 *) PrevQtd, sizeof (EHCI_QTD_ENTITY));
PrevQtd = NextQtd;
} while (NULL != PrevQtd);
exit:
return ;
}
UINTN
GetNumberOfQtd (
IN EHCI_QTD_ENTITY *FirstQtdPtr
)
/*++
Routine Description:
Number of Qtds in the list
Arguments:
FirstQtdPtr - A pointer to first Qtd in the list
Returns:
Number of Qtds in the list
--*/
{
UINTN Count;
EHCI_QTD_ENTITY *QtdPtr;
Count = 0;
QtdPtr = FirstQtdPtr;
while (NULL != QtdPtr) {
Count++;
QtdPtr = QtdPtr->Next;
}
return Count;
}
UINTN
GetCapacityOfQtd (
IN UINT8 *BufferCursor
)
/*++
Routine Description:
Get Size of First Qtd
Arguments:
BufferCursor - BufferCursor of the Qtd
Returns:
Size of First Qtd
--*/
{
if (EFI_PAGE_MASK & GET_0B_TO_31B (BufferCursor)) {
return EFI_PAGE_SIZE * 4;
} else {
return EFI_PAGE_SIZE * 5;
}
}
UINTN
GetApproxiOfInterval (
IN UINTN Interval
)
/*++
Routine Description:
Get the approximate value in the 2 index sequence
Arguments:
Interval - the value of interval
Returns:
approximate value of interval in the 2 index sequence
--*/
{
UINTN Orignate;
UINTN Approxi;
Orignate = Interval;
Approxi = 1;
while (Orignate != 1 && Orignate != 0) {
Orignate = Orignate >> 1;
Approxi = Approxi << 1;
}
if (Interval & (Approxi >> 1)) {
Approxi = Approxi << 1;
}
return Approxi;
}
EHCI_QTD_HW *
GetQtdAlternateNextPointer (
IN EHCI_QTD_HW *HwQtdPtr
)
/*++
Routine Description:
Get Qtd alternate next pointer field
Arguments:
HwQtdPtr - A pointer to hardware Qtd structure
Returns:
A pointer to hardware alternate Qtd
--*/
{
EHCI_QTD_HW *Value;
Value = NULL;
if (!HwQtdPtr->AltNextQtdTerminate) {
Value = (EHCI_QTD_HW *) GET_0B_TO_31B (HwQtdPtr->AltNextQtdPointer << 5);
}
return Value;
}
EHCI_QTD_HW *
GetQtdNextPointer (
IN EHCI_QTD_HW *HwQtdPtr
)
/*++
Routine Description:
Get Qtd next pointer field
Arguments:
HwQtdPtr - A pointer to hardware Qtd structure
Returns:
A pointer to next hardware Qtd structure
--*/
{
EHCI_QTD_HW *Value;
Value = NULL;
if (!HwQtdPtr->NextQtdTerminate) {
Value = (EHCI_QTD_HW *) GET_0B_TO_31B (HwQtdPtr->NextQtdPointer << 5);
}
return Value;
}
VOID
LinkQtdToQtd (
IN EHCI_QTD_ENTITY * PreQtdPtr,
IN EHCI_QTD_ENTITY * QtdPtr
)
/*++
Routine Description:
Link Qtds together
Arguments:
PreQtdPtr - A pointer to pre Qtd
QtdPtr - A pointer to next Qtd
Returns:
VOID
--*/
{
EHCI_QTD_HW *QtdHwPtr;
ASSERT(PreQtdPtr);
ASSERT(QtdPtr);
//
// Software link
//
PreQtdPtr->Next = QtdPtr;
QtdPtr->Prev = PreQtdPtr;
//
// Hardware link
//
QtdHwPtr = &(QtdPtr->Qtd);
PreQtdPtr->Qtd.NextQtdPointer = (UINT32) (GET_0B_TO_31B(QtdHwPtr) >> 5);
PreQtdPtr->Qtd.NextQtdTerminate = FALSE;
return ;
}
VOID
LinkQtdsToAltQtd (
IN EHCI_QTD_ENTITY * FirstQtdPtr,
IN EHCI_QTD_ENTITY * AltQtdPtr
)
/*++
Routine Description:
Link AlterQtds together
Arguments:
FirstQtdPtr - A pointer to first Qtd in the list
AltQtdPtr - A pointer to alternative Qtd
Returns:
VOID
--*/
{
EHCI_QTD_ENTITY *QtdPtr;
EHCI_QTD_HW *AltQtdHwPtr;
ASSERT(FirstQtdPtr);
ASSERT(AltQtdPtr);
AltQtdHwPtr = &(AltQtdPtr->Qtd);
QtdPtr = FirstQtdPtr;
while (NULL != QtdPtr) {
//
// Software link
//
QtdPtr->AltNext = AltQtdPtr;
//
// Hardware link
//
QtdPtr->Qtd.AltNextQtdPointer = (UINT32) (GET_0B_TO_31B(AltQtdHwPtr) >> 5);
QtdPtr->Qtd.AltNextQtdTerminate = FALSE;
QtdPtr = QtdPtr->Next;
}
return ;
}
VOID
LinkQtdToQh (
IN EHCI_QH_ENTITY *QhPtr,
IN EHCI_QTD_ENTITY *QtdPtr
)
/*++
Routine Description:
Link Qtds list to Qh
Arguments:
QhPtr - A pointer to Qh
QtdPtr - A pointer to first Qtd in the list
Returns:
VOID
--*/
{
EHCI_QTD_ENTITY *Cursor;
EHCI_QTD_HW *QtdHwPtr;
ASSERT (QhPtr);
ASSERT (QtdPtr);
QhPtr->FirstQtdPtr = QtdPtr;
if (NULL != QtdPtr->AltNext) {
QhPtr->AltQtdPtr = QtdPtr->AltNext;
}
Cursor = QtdPtr;
while (NULL != Cursor) {
Cursor->SelfQh = QhPtr;
if (NULL == Cursor->Next) {
QhPtr->LastQtdPtr = Cursor;
}
Cursor = Cursor->Next;
}
QtdHwPtr = &(QtdPtr->Qtd);
QhPtr->Qh.NextQtdPointer = (UINT32) (GET_0B_TO_31B (QtdHwPtr) >> 5);
QhPtr->Qh.NextQtdTerminate = FALSE;
QhPtr->Qh.AltNextQtdPointer = 0;
QhPtr->Qh.AltNextQtdTerminate = TRUE;
if ((QtdPtr->Qtd.PidCode == OUTPUT_PACKET_PID_CODE) &&
(QhPtr->TransferType == BULK_TRANSFER)) {
//
//Start PING first
//
QhPtr->Qh.Status |= QTD_STATUS_DO_PING;
}
return ;
}
EFI_STATUS
LinkQhToAsyncList (
IN USB2_HC_DEV *HcDev,
IN EHCI_QH_ENTITY *QhPtr
)
/*++
Routine Description:
Link Qh to Async Schedule List
Arguments:
HcDev - USB2_HC_DEV
QhPtr - A pointer to Qh
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
EFI_STATUS Status;
ASSERT (HcDev);
ASSERT (QhPtr);
//
// NULL QH created before
//
HcDev->NULLQH->Next = QhPtr;
HcDev->NULLQH->Prev = QhPtr;
QhPtr->Next = HcDev->NULLQH;
QhPtr->Prev = HcDev->NULLQH;
HcDev->NULLQH->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&(QhPtr->Qh) >> 5));
QhPtr->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&(HcDev->NULLQH->Qh) >> 5));
Status = SetAsyncListAddr (HcDev, HcDev->NULLQH);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
if (!IsAsyncScheduleEnabled (HcDev)) {
Status = EnableAsynchronousSchedule (HcDev);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto exit;
}
Status = WaitForAsyncScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);
if (EFI_ERROR (Status)) {
DEBUG ((gEHCDebugLevel, "EHCI: WaitForAsyncScheduleEnable TimeOut"));
Status = EFI_TIMEOUT;
goto exit;
}
if (IsEhcHalted (HcDev)) {
Status = StartScheduleExecution (HcDev);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
}
}
}
exit:
return Status;
}
EFI_STATUS
UnlinkQhFromAsyncList (
IN USB2_HC_DEV *HcDev,
IN EHCI_QH_ENTITY *QhPtr
)
/*++
Routine Description:
Unlink Qh from Async Schedule List
Arguments:
HcDev - USB2_HC_DEV
QhPtr - A pointer to Qh
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?