mirror of https://github.com/acidanthera/audk.git
MdeModulePkg/XhciDxe: Event Ring traverse algorithm enhancement to avoid that those completed async transfer events don't get handled in time and are flushed by newer coming events.
Signed-off-by: erictian Reviewed-by: li-elvin git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13145 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
ecc722ad41
commit
a50f7c4c09
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,7 @@
|
|||
|
||||
Provides some data structure definitions used by the XHCI host controller driver.
|
||||
|
||||
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -71,10 +71,10 @@ typedef struct _USB_DEV_CONTEXT USB_DEV_CONTEXT;
|
|||
//
|
||||
#define XHC_TPL TPL_NOTIFY
|
||||
|
||||
#define CMD_RING_TRB_NUMBER 0x40
|
||||
#define TR_RING_TRB_NUMBER 0x40
|
||||
#define CMD_RING_TRB_NUMBER 0x100
|
||||
#define TR_RING_TRB_NUMBER 0x100
|
||||
#define ERST_NUMBER 0x01
|
||||
#define EVENT_RING_TRB_NUMBER 0x80
|
||||
#define EVENT_RING_TRB_NUMBER 0x200
|
||||
|
||||
#define CMD_INTER 0
|
||||
#define CTRL_INTER 1
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
This file contains the register definition of XHCI host controller.
|
||||
|
||||
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -172,6 +172,15 @@ typedef union {
|
|||
#define XHC_PORTSC_CEC BIT23 // Port Config Error Change
|
||||
#define XHC_PORTSC_CAS BIT24 // Cold Attach Status
|
||||
|
||||
#define XHC_HUB_PORTSC_CCS BIT0 // Hub's Current Connect Status
|
||||
#define XHC_HUB_PORTSC_PED BIT1 // Hub's Port Enabled/Disabled
|
||||
#define XHC_HUB_PORTSC_OCA BIT3 // Hub's Over-current Active
|
||||
#define XHC_HUB_PORTSC_RESET BIT4 // Hub's Port Reset
|
||||
#define XHC_HUB_PORTSC_PP BIT9 // Hub's Port Power
|
||||
#define XHC_HUB_PORTSC_CSC BIT16 // Hub's Connect Status Change
|
||||
#define XHC_HUB_PORTSC_PEC BIT17 // Hub's Port Enabled/Disabled Change
|
||||
#define XHC_HUB_PORTSC_OCC BIT19 // Hub's Over-Current Change
|
||||
#define XHC_HUB_PORTSC_PRC BIT20 // Hub's Port Reset Change
|
||||
#define XHC_IMAN_IP BIT0 // Interrupt Pending
|
||||
#define XHC_IMAN_IE BIT1 // Interrupt Enable
|
||||
|
||||
|
|
|
@ -47,10 +47,6 @@ XhcCreateCmdTrb (
|
|||
Urb->TrbStart->CycleBit = Urb->Ring->RingPCS & BIT0;
|
||||
Urb->TrbEnd = Urb->TrbStart;
|
||||
|
||||
Urb->EvtRing = &Xhc->EventRing;
|
||||
XhcSyncEventRing (Xhc, Urb->EvtRing);
|
||||
Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;
|
||||
|
||||
return Urb;
|
||||
}
|
||||
|
||||
|
@ -106,10 +102,8 @@ XhcCmdTransfer (
|
|||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
ASSERT (Urb->EvtRing == &Xhc->EventRing);
|
||||
|
||||
Status = XhcExecTransfer (Xhc, TRUE, Urb, Timeout);
|
||||
*EvtTrb = Urb->EvtTrbStart;
|
||||
*EvtTrb = Urb->EvtTrb;
|
||||
|
||||
if (Urb->Result == EFI_USB_NOERROR) {
|
||||
Status = EFI_SUCCESS;
|
||||
|
@ -216,6 +210,12 @@ XhcCreateTransferTrb (
|
|||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Urb->Finished = FALSE;
|
||||
Urb->StartDone = FALSE;
|
||||
Urb->EndDone = FALSE;
|
||||
Urb->Completed = 0;
|
||||
Urb->Result = EFI_USB_NOERROR;
|
||||
|
||||
Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));
|
||||
ASSERT (Dci < 32);
|
||||
EPRing = (TRANSFER_RING *)(UINTN) Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1];
|
||||
|
@ -234,9 +234,6 @@ XhcCreateTransferTrb (
|
|||
Urb->TrbStart = EPRing->RingEnqueue;
|
||||
switch (EPType) {
|
||||
case ED_CONTROL_BIDIR:
|
||||
Urb->EvtRing = &Xhc->EventRing;
|
||||
XhcSyncEventRing (Xhc, Urb->EvtRing);
|
||||
Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;
|
||||
//
|
||||
// For control transfer, create SETUP_STAGE_TRB first.
|
||||
//
|
||||
|
@ -325,10 +322,6 @@ XhcCreateTransferTrb (
|
|||
|
||||
case ED_BULK_OUT:
|
||||
case ED_BULK_IN:
|
||||
Urb->EvtRing = &Xhc->EventRing;
|
||||
XhcSyncEventRing (Xhc, Urb->EvtRing);
|
||||
Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;
|
||||
|
||||
TotalLen = 0;
|
||||
Len = 0;
|
||||
TrbNum = 0;
|
||||
|
@ -364,10 +357,6 @@ XhcCreateTransferTrb (
|
|||
|
||||
case ED_INTERRUPT_OUT:
|
||||
case ED_INTERRUPT_IN:
|
||||
Urb->EvtRing = &Xhc->EventRing;
|
||||
XhcSyncEventRing (Xhc, Urb->EvtRing);
|
||||
Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;
|
||||
|
||||
TotalLen = 0;
|
||||
Len = 0;
|
||||
TrbNum = 0;
|
||||
|
@ -829,39 +818,78 @@ XhcFreeSched (
|
|||
}
|
||||
|
||||
/**
|
||||
Check if it is ring TRB.
|
||||
Check if the Trb is a transaction of the URBs in XHCI's asynchronous transfer list.
|
||||
|
||||
@param Ring The transfer ring
|
||||
@param Trb The TRB to check if it's in the transfer ring
|
||||
@param Xhc The XHCI Instance.
|
||||
@param Trb The TRB to be checked.
|
||||
@param Urb The pointer to the matched Urb.
|
||||
|
||||
@retval TRUE It is in the ring
|
||||
@retval FALSE It is not in the ring
|
||||
@retval TRUE The Trb is matched with a transaction of the URBs in the async list.
|
||||
@retval FALSE The Trb is not matched with any URBs in the async list.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsAsyncIntTrb (
|
||||
IN USB_XHCI_INSTANCE *Xhc,
|
||||
IN TRB_TEMPLATE *Trb,
|
||||
OUT URB **Urb
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *Next;
|
||||
TRB_TEMPLATE *CheckedTrb;
|
||||
URB *CheckedUrb;
|
||||
UINTN Index;
|
||||
|
||||
EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) {
|
||||
CheckedUrb = EFI_LIST_CONTAINER (Entry, URB, UrbList);
|
||||
CheckedTrb = CheckedUrb->TrbStart;
|
||||
for (Index = 0; Index < CheckedUrb->TrbNum; Index++) {
|
||||
if (Trb == CheckedTrb) {
|
||||
*Urb = CheckedUrb;
|
||||
return TRUE;
|
||||
}
|
||||
CheckedTrb++;
|
||||
if ((UINTN)CheckedTrb >= ((UINTN) CheckedUrb->Ring->RingSeg0 + sizeof (TRB_TEMPLATE) * CheckedUrb->Ring->TrbNumber)) {
|
||||
CheckedTrb = (TRB_TEMPLATE*) CheckedUrb->Ring->RingSeg0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Check if the Trb is a transaction of the URB.
|
||||
|
||||
@param Trb The TRB to be checked
|
||||
@param Urb The transfer ring to be checked.
|
||||
|
||||
@retval TRUE It is a transaction of the URB.
|
||||
@retval FALSE It is not any transaction of the URB.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsTransferRingTrb (
|
||||
IN TRANSFER_RING *Ring,
|
||||
IN TRB_TEMPLATE *Trb
|
||||
IN TRB_TEMPLATE *Trb,
|
||||
IN URB *Urb
|
||||
)
|
||||
{
|
||||
BOOLEAN Flag;
|
||||
TRB_TEMPLATE *Trb1;
|
||||
TRB_TEMPLATE *CheckedTrb;
|
||||
UINTN Index;
|
||||
|
||||
Trb1 = Ring->RingSeg0;
|
||||
Flag = FALSE;
|
||||
CheckedTrb = Urb->Ring->RingSeg0;
|
||||
|
||||
ASSERT (Ring->TrbNumber == CMD_RING_TRB_NUMBER || Ring->TrbNumber == TR_RING_TRB_NUMBER);
|
||||
ASSERT (Urb->Ring->TrbNumber == CMD_RING_TRB_NUMBER || Urb->Ring->TrbNumber == TR_RING_TRB_NUMBER);
|
||||
|
||||
for (Index = 0; Index < Ring->TrbNumber; Index++) {
|
||||
if (Trb == Trb1) {
|
||||
Flag = TRUE;
|
||||
break;
|
||||
for (Index = 0; Index < Urb->Ring->TrbNumber; Index++) {
|
||||
if (Trb == CheckedTrb) {
|
||||
return TRUE;
|
||||
}
|
||||
Trb1++;
|
||||
CheckedTrb++;
|
||||
}
|
||||
|
||||
return Flag;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -880,20 +908,26 @@ XhcCheckUrbResult (
|
|||
IN URB *Urb
|
||||
)
|
||||
{
|
||||
BOOLEAN StartDone;
|
||||
BOOLEAN EndDone;
|
||||
EVT_TRB_TRANSFER *EvtTrb;
|
||||
TRB_TEMPLATE *TRBPtr;
|
||||
UINTN Index;
|
||||
UINT8 TRBType;
|
||||
EFI_STATUS Status;
|
||||
URB *AsyncUrb;
|
||||
URB *CheckedUrb;
|
||||
UINT64 XhcDequeue;
|
||||
UINT32 High;
|
||||
UINT32 Low;
|
||||
|
||||
ASSERT ((Xhc != NULL) && (Urb != NULL));
|
||||
|
||||
Urb->Completed = 0;
|
||||
Urb->Result = EFI_USB_NOERROR;
|
||||
Status = EFI_SUCCESS;
|
||||
EvtTrb = NULL;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
if (Urb->Finished) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
EvtTrb = NULL;
|
||||
|
||||
if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
|
||||
Urb->Result |= EFI_USB_ERR_SYSTEM;
|
||||
|
@ -902,16 +936,15 @@ XhcCheckUrbResult (
|
|||
}
|
||||
|
||||
//
|
||||
// Restore the EventRingDequeue and poll the transfer event ring from beginning
|
||||
// Traverse the event ring to find out all new events from the previous check.
|
||||
//
|
||||
StartDone = FALSE;
|
||||
EndDone = FALSE;
|
||||
Urb->EvtRing->EventRingDequeue = Urb->EvtTrbStart;
|
||||
for (Index = 0; Index < Urb->EvtRing->TrbNumber; Index++) {
|
||||
XhcSyncEventRing (Xhc, Urb->EvtRing);
|
||||
Status = XhcCheckNewEvent (Xhc, Urb->EvtRing, ((TRB_TEMPLATE **)&EvtTrb));
|
||||
XhcSyncEventRing (Xhc, &Xhc->EventRing);
|
||||
for (Index = 0; Index < Xhc->EventRing.TrbNumber; Index++) {
|
||||
Status = XhcCheckNewEvent (Xhc, &Xhc->EventRing, ((TRB_TEMPLATE **)&EvtTrb));
|
||||
if (Status == EFI_NOT_READY) {
|
||||
Urb->Result |= EFI_USB_ERR_TIMEOUT;
|
||||
//
|
||||
// All new events are handled, return directly.
|
||||
//
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
|
@ -923,78 +956,106 @@ XhcCheckUrbResult (
|
|||
}
|
||||
|
||||
TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32));
|
||||
if (IsTransferRingTrb (Urb->Ring, TRBPtr)) {
|
||||
switch (EvtTrb->Completecode) {
|
||||
case TRB_COMPLETION_STALL_ERROR:
|
||||
Urb->Result |= EFI_USB_ERR_STALL;
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: STALL_ERROR! Completecode = %x\n",EvtTrb->Completecode));
|
||||
goto EXIT;
|
||||
break;
|
||||
|
||||
case TRB_COMPLETION_BABBLE_ERROR:
|
||||
Urb->Result |= EFI_USB_ERR_BABBLE;
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: BABBLE_ERROR! Completecode = %x\n",EvtTrb->Completecode));
|
||||
goto EXIT;
|
||||
break;
|
||||
|
||||
case TRB_COMPLETION_DATA_BUFFER_ERROR:
|
||||
Urb->Result |= EFI_USB_ERR_BUFFER;
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: ERR_BUFFER! Completecode = %x\n",EvtTrb->Completecode));
|
||||
goto EXIT;
|
||||
break;
|
||||
|
||||
case TRB_COMPLETION_USB_TRANSACTION_ERROR:
|
||||
Urb->Result |= EFI_USB_ERR_TIMEOUT;
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: TRANSACTION_ERROR! Completecode = %x\n",EvtTrb->Completecode));
|
||||
goto EXIT;
|
||||
break;
|
||||
|
||||
case TRB_COMPLETION_SHORT_PACKET:
|
||||
case TRB_COMPLETION_SUCCESS:
|
||||
if (EvtTrb->Completecode == TRB_COMPLETION_SHORT_PACKET) {
|
||||
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: short packet happens!\n"));
|
||||
}
|
||||
|
||||
TRBType = (UINT8) (TRBPtr->Type);
|
||||
if ((TRBType == TRB_TYPE_DATA_STAGE) ||
|
||||
(TRBType == TRB_TYPE_NORMAL) ||
|
||||
(TRBType == TRB_TYPE_ISOCH)) {
|
||||
Urb->Completed += (Urb->DataLen - EvtTrb->Lenth);
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG ((EFI_D_ERROR, "Transfer Default Error Occur! Completecode = 0x%x!\n",EvtTrb->Completecode));
|
||||
Urb->Result |= EFI_USB_ERR_TIMEOUT;
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto EXIT;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Only check first and end Trb event address
|
||||
//
|
||||
if (TRBPtr == Urb->TrbStart) {
|
||||
StartDone = TRUE;
|
||||
}
|
||||
|
||||
if (TRBPtr == Urb->TrbEnd) {
|
||||
EndDone = TRUE;
|
||||
}
|
||||
|
||||
if (StartDone && EndDone) {
|
||||
//
|
||||
// Update the status of Urb according to the finished event regardless of whether
|
||||
// the urb is current checked one or in the XHCI's async transfer list.
|
||||
// This way is used to avoid that those completed async transfer events don't get
|
||||
// handled in time and are flushed by newer coming events.
|
||||
//
|
||||
if (IsTransferRingTrb (TRBPtr, Urb)) {
|
||||
CheckedUrb = Urb;
|
||||
} else if (IsAsyncIntTrb (Xhc, TRBPtr, &AsyncUrb)) {
|
||||
CheckedUrb = AsyncUrb;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (EvtTrb->Completecode) {
|
||||
case TRB_COMPLETION_STALL_ERROR:
|
||||
CheckedUrb->Result |= EFI_USB_ERR_STALL;
|
||||
CheckedUrb->Finished = TRUE;
|
||||
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: STALL_ERROR! Completecode = %x\n",EvtTrb->Completecode));
|
||||
break;
|
||||
}
|
||||
|
||||
case TRB_COMPLETION_BABBLE_ERROR:
|
||||
CheckedUrb->Result |= EFI_USB_ERR_BABBLE;
|
||||
CheckedUrb->Finished = TRUE;
|
||||
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: BABBLE_ERROR! Completecode = %x\n",EvtTrb->Completecode));
|
||||
break;
|
||||
|
||||
case TRB_COMPLETION_DATA_BUFFER_ERROR:
|
||||
CheckedUrb->Result |= EFI_USB_ERR_BUFFER;
|
||||
CheckedUrb->Finished = TRUE;
|
||||
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: ERR_BUFFER! Completecode = %x\n",EvtTrb->Completecode));
|
||||
break;
|
||||
|
||||
case TRB_COMPLETION_USB_TRANSACTION_ERROR:
|
||||
CheckedUrb->Result |= EFI_USB_ERR_TIMEOUT;
|
||||
CheckedUrb->Finished = TRUE;
|
||||
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: TRANSACTION_ERROR! Completecode = %x\n",EvtTrb->Completecode));
|
||||
break;
|
||||
|
||||
case TRB_COMPLETION_SHORT_PACKET:
|
||||
case TRB_COMPLETION_SUCCESS:
|
||||
if (EvtTrb->Completecode == TRB_COMPLETION_SHORT_PACKET) {
|
||||
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: short packet happens!\n"));
|
||||
}
|
||||
|
||||
TRBType = (UINT8) (TRBPtr->Type);
|
||||
if ((TRBType == TRB_TYPE_DATA_STAGE) ||
|
||||
(TRBType == TRB_TYPE_NORMAL) ||
|
||||
(TRBType == TRB_TYPE_ISOCH)) {
|
||||
CheckedUrb->Completed += (CheckedUrb->DataLen - EvtTrb->Lenth);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG ((EFI_D_ERROR, "Transfer Default Error Occur! Completecode = 0x%x!\n",EvtTrb->Completecode));
|
||||
CheckedUrb->Result |= EFI_USB_ERR_TIMEOUT;
|
||||
CheckedUrb->Finished = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Only check first and end Trb event address
|
||||
//
|
||||
if (TRBPtr == CheckedUrb->TrbStart) {
|
||||
CheckedUrb->StartDone = TRUE;
|
||||
}
|
||||
|
||||
if (TRBPtr == CheckedUrb->TrbEnd) {
|
||||
CheckedUrb->EndDone = TRUE;
|
||||
}
|
||||
|
||||
if (CheckedUrb->StartDone && CheckedUrb->EndDone) {
|
||||
CheckedUrb->Finished = TRUE;
|
||||
CheckedUrb->EvtTrb = (TRB_TEMPLATE *)EvtTrb;
|
||||
}
|
||||
}
|
||||
|
||||
EXIT:
|
||||
|
||||
//
|
||||
// Advance event ring to last available entry
|
||||
//
|
||||
// Some 3rd party XHCI external cards don't support single 64-bytes width register access,
|
||||
// So divide it to two 32-bytes width register access.
|
||||
//
|
||||
Low = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET);
|
||||
High = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4);
|
||||
XhcDequeue = (UINT64)(LShiftU64((UINT64)High, 32) | Low);
|
||||
|
||||
if ((XhcDequeue & (~0x0F)) != ((UINT64)(UINTN)Xhc->EventRing.EventRingDequeue & (~0x0F))) {
|
||||
//
|
||||
// Some 3rd party XHCI external cards don't support single 64-bytes width register access,
|
||||
// So divide it to two 32-bytes width register access.
|
||||
//
|
||||
XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET, XHC_LOW_32BIT (Xhc->EventRing.EventRingDequeue) | BIT3);
|
||||
XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4, XHC_HIGH_32BIT (Xhc->EventRing.EventRingDequeue));
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -1048,12 +1109,16 @@ XhcExecTransfer (
|
|||
|
||||
for (Index = 0; Index < Loop; Index++) {
|
||||
Status = XhcCheckUrbResult (Xhc, Urb);
|
||||
if ((Status != EFI_NOT_READY)) {
|
||||
if (Urb->Finished) {
|
||||
break;
|
||||
}
|
||||
gBS->Stall (XHC_POLL_DELAY);
|
||||
}
|
||||
|
||||
if (Index == Loop) {
|
||||
Urb->Result = EFI_USB_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -1196,7 +1261,7 @@ XhcMonitorAsyncRequests (
|
|||
//
|
||||
Status = XhcCheckUrbResult (Xhc, Urb);
|
||||
|
||||
if (Status == EFI_NOT_READY) {
|
||||
if (!Urb->Finished) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1219,8 +1284,6 @@ XhcMonitorAsyncRequests (
|
|||
CopyMem (ProcBuf, Urb->Data, Urb->Completed);
|
||||
}
|
||||
|
||||
XhcUpdateAsyncRequest (Xhc, Urb);
|
||||
|
||||
//
|
||||
// Leave error recovery to its related device driver. A
|
||||
// common case of the error recovery is to re-submit the
|
||||
|
@ -1244,6 +1307,8 @@ XhcMonitorAsyncRequests (
|
|||
if (ProcBuf != NULL) {
|
||||
gBS->FreePool (ProcBuf);
|
||||
}
|
||||
|
||||
XhcUpdateAsyncRequest (Xhc, Urb);
|
||||
}
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
}
|
||||
|
@ -1445,10 +1510,6 @@ XhcSyncEventRing (
|
|||
{
|
||||
UINTN Index;
|
||||
TRB_TEMPLATE *EvtTrb1;
|
||||
TRB_TEMPLATE *EvtTrb2;
|
||||
UINT64 XhcDequeue;
|
||||
UINT32 High;
|
||||
UINT32 Low;
|
||||
|
||||
ASSERT (EvtRing != NULL);
|
||||
|
||||
|
@ -1456,41 +1517,25 @@ XhcSyncEventRing (
|
|||
// Calculate the EventRingEnqueue and EventRingCCS.
|
||||
// Note: only support single Segment
|
||||
//
|
||||
EvtTrb1 = EvtRing->EventRingSeg0;
|
||||
EvtTrb2 = EvtRing->EventRingSeg0;
|
||||
EvtTrb1 = EvtRing->EventRingDequeue;
|
||||
|
||||
for (Index = 0; Index < EvtRing->TrbNumber; Index++) {
|
||||
if (EvtTrb1->CycleBit != EvtTrb2->CycleBit) {
|
||||
if (EvtTrb1->CycleBit != EvtRing->EventRingCCS) {
|
||||
break;
|
||||
}
|
||||
|
||||
EvtTrb1++;
|
||||
|
||||
if ((UINTN)EvtTrb1 >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {
|
||||
EvtTrb1 = EvtRing->EventRingSeg0;
|
||||
EvtRing->EventRingCCS = (EvtRing->EventRingCCS) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Index < EvtRing->TrbNumber) {
|
||||
EvtRing->EventRingEnqueue = EvtTrb1;
|
||||
EvtRing->EventRingCCS = (EvtTrb2->CycleBit) ? 1 : 0;
|
||||
} else {
|
||||
EvtRing->EventRingEnqueue = EvtTrb2;
|
||||
EvtRing->EventRingCCS = (EvtTrb2->CycleBit) ? 0 : 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Apply the EventRingDequeue to Xhc
|
||||
//
|
||||
// Some 3rd party XHCI external cards don't support single 64-bytes width register access,
|
||||
// So divide it to two 32-bytes width register access.
|
||||
//
|
||||
Low = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET);
|
||||
High = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4);
|
||||
XhcDequeue = (UINT64)(LShiftU64((UINT64)High, 32) | Low);
|
||||
|
||||
if ((XhcDequeue & (~0x0F)) != ((UINT64)(UINTN)EvtRing->EventRingDequeue & (~0x0F))) {
|
||||
//
|
||||
// Some 3rd party XHCI external cards don't support single 64-bytes width register access,
|
||||
// So divide it to two 32-bytes width register access.
|
||||
//
|
||||
XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET, XHC_LOW_32BIT (EvtRing->EventRingDequeue) | BIT3);
|
||||
XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4, XHC_HIGH_32BIT (EvtRing->EventRingDequeue));
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
@ -1579,8 +1624,8 @@ XhcCheckNewEvent (
|
|||
OUT TRB_TEMPLATE **NewEvtTrb
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
TRB_TEMPLATE*EvtTrb;
|
||||
EFI_STATUS Status;
|
||||
TRB_TEMPLATE *EvtTrb;
|
||||
|
||||
ASSERT (EvtRing != NULL);
|
||||
|
||||
|
@ -1593,15 +1638,11 @@ XhcCheckNewEvent (
|
|||
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
if (((EvtTrb->Status >> 24) & 0xFF) != TRB_COMPLETION_SUCCESS) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
EvtRing->EventRingDequeue++;
|
||||
//
|
||||
// If the dequeue pointer is beyond the ring, then roll-back it to the begining of the ring.
|
||||
//
|
||||
if ((UINTN)EvtRing->EventRingDequeue >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {
|
||||
if ((UINTN)EvtRing->EventRingDequeue >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {
|
||||
EvtRing->EventRingDequeue = EvtRing->EventRingSeg0;
|
||||
}
|
||||
|
||||
|
@ -1845,7 +1886,7 @@ XhcInitializeDeviceSlot (
|
|||
ASSERT (!EFI_ERROR(Status));
|
||||
|
||||
DeviceAddress = (UINT8) ((DEVICE_CONTEXT *) OutputContext)->Slot.DeviceAddress;
|
||||
DEBUG ((EFI_D_INFO, " Address %d assigned succeefully\n", DeviceAddress));
|
||||
DEBUG ((EFI_D_INFO, " Address %d assigned successfully\n", DeviceAddress));
|
||||
|
||||
Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;
|
||||
|
||||
|
@ -2038,7 +2079,7 @@ XhcInitializeDeviceSlot64 (
|
|||
ASSERT (!EFI_ERROR(Status));
|
||||
|
||||
DeviceAddress = (UINT8) ((DEVICE_CONTEXT_64 *) OutputContext)->Slot.DeviceAddress;
|
||||
DEBUG ((EFI_D_INFO, " Address %d assigned succeefully\n", DeviceAddress));
|
||||
DEBUG ((EFI_D_INFO, " Address %d assigned successfully\n", DeviceAddress));
|
||||
|
||||
Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
This file contains the definition for XHCI host controller schedule routines.
|
||||
|
||||
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -189,8 +189,11 @@ typedef struct _URB {
|
|||
TRB_TEMPLATE *TrbStart;
|
||||
TRB_TEMPLATE *TrbEnd;
|
||||
UINTN TrbNum;
|
||||
EVENT_RING *EvtRing;
|
||||
TRB_TEMPLATE *EvtTrbStart;
|
||||
BOOLEAN StartDone;
|
||||
BOOLEAN EndDone;
|
||||
BOOLEAN Finished;
|
||||
|
||||
TRB_TEMPLATE *EvtTrb;
|
||||
} URB;
|
||||
|
||||
//
|
||||
|
|
|
@ -862,7 +862,7 @@ UsbEnumeratePort (
|
|||
}
|
||||
|
||||
DEBUG (( EFI_D_INFO, "UsbEnumeratePort: port %d state - %02x, change - %02x on %p\n",
|
||||
Port, PortState.PortChangeStatus, PortState.PortStatus, HubIf));
|
||||
Port, PortState.PortStatus, PortState.PortChangeStatus, HubIf));
|
||||
|
||||
//
|
||||
// This driver only process two kinds of events now: over current and
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Unified interface for RootHub and Hub.
|
||||
|
||||
Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -844,12 +844,6 @@ UsbHubGetPortStatus (
|
|||
|
||||
Status = UsbHubCtrlGetPortStatus (HubIf->Device, Port, PortState);
|
||||
|
||||
//
|
||||
// Mark the USB_PORT_STAT_SUPER_SPEED bit if SuperSpeed
|
||||
//
|
||||
if (HubIf->Device->Speed == EFI_USB_SPEED_SUPER) {
|
||||
PortState->PortStatus |= USB_PORT_STAT_SUPER_SPEED;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue