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
|
@ -32,6 +32,20 @@ USB_PORT_STATE_MAP mUsbPortChangeMap[] = {
|
||||||
{XHC_PORTSC_PRC, USB_PORT_STAT_C_RESET}
|
{XHC_PORTSC_PRC, USB_PORT_STAT_C_RESET}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
USB_PORT_STATE_MAP mUsbHubPortStateMap[] = {
|
||||||
|
{XHC_HUB_PORTSC_CCS, USB_PORT_STAT_CONNECTION},
|
||||||
|
{XHC_HUB_PORTSC_PED, USB_PORT_STAT_ENABLE},
|
||||||
|
{XHC_HUB_PORTSC_OCA, USB_PORT_STAT_OVERCURRENT},
|
||||||
|
{XHC_HUB_PORTSC_RESET, USB_PORT_STAT_RESET}
|
||||||
|
};
|
||||||
|
|
||||||
|
USB_PORT_STATE_MAP mUsbHubPortChangeMap[] = {
|
||||||
|
{XHC_HUB_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION},
|
||||||
|
{XHC_HUB_PORTSC_PEC, USB_PORT_STAT_C_ENABLE},
|
||||||
|
{XHC_HUB_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT},
|
||||||
|
{XHC_HUB_PORTSC_PRC, USB_PORT_STAT_C_RESET}
|
||||||
|
};
|
||||||
|
|
||||||
EFI_DRIVER_BINDING_PROTOCOL gXhciDriverBinding = {
|
EFI_DRIVER_BINDING_PROTOCOL gXhciDriverBinding = {
|
||||||
XhcDriverBindingSupported,
|
XhcDriverBindingSupported,
|
||||||
XhcDriverBindingStart,
|
XhcDriverBindingStart,
|
||||||
|
@ -861,7 +875,7 @@ XhcControlTransfer (
|
||||||
Status = EFI_OUT_OF_RESOURCES;
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
goto ON_EXIT;
|
goto ON_EXIT;
|
||||||
}
|
}
|
||||||
ASSERT (Urb->EvtRing == &Xhc->EventRing);
|
|
||||||
Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
|
Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -998,21 +1012,23 @@ XhcControlTransfer (
|
||||||
//
|
//
|
||||||
// Convert the XHCI port/port change state to UEFI status
|
// Convert the XHCI port/port change state to UEFI status
|
||||||
//
|
//
|
||||||
MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
|
MapSize = sizeof (mUsbHubPortStateMap) / sizeof (USB_PORT_STATE_MAP);
|
||||||
for (Index = 0; Index < MapSize; Index++) {
|
for (Index = 0; Index < MapSize; Index++) {
|
||||||
if (XHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
|
if (XHC_BIT_IS_SET (State, mUsbHubPortStateMap[Index].HwState)) {
|
||||||
PortStatus.PortStatus = (UINT16) (PortStatus.PortStatus | mUsbPortStateMap[Index].UefiState);
|
PortStatus.PortStatus = (UINT16) (PortStatus.PortStatus | mUsbHubPortStateMap[Index].UefiState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
|
|
||||||
|
|
||||||
|
MapSize = sizeof (mUsbHubPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
|
||||||
for (Index = 0; Index < MapSize; Index++) {
|
for (Index = 0; Index < MapSize; Index++) {
|
||||||
if (XHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
|
if (XHC_BIT_IS_SET (State, mUsbHubPortChangeMap[Index].HwState)) {
|
||||||
PortStatus.PortChangeStatus = (UINT16) (PortStatus.PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
|
PortStatus.PortChangeStatus = (UINT16) (PortStatus.PortChangeStatus | mUsbHubPortChangeMap[Index].UefiState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XhcPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);
|
XhcPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);
|
||||||
|
|
||||||
|
*(UINT32 *)Data = *(UINT32*)&PortStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
FREE_URB:
|
FREE_URB:
|
||||||
|
@ -1147,8 +1163,6 @@ XhcBulkTransfer (
|
||||||
goto ON_EXIT;
|
goto ON_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT (Urb->EvtRing == &Xhc->EventRing);
|
|
||||||
|
|
||||||
Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
|
Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
|
||||||
|
|
||||||
*TransferResult = Urb->Result;
|
*TransferResult = Urb->Result;
|
||||||
|
@ -1272,7 +1286,7 @@ XhcAsyncInterruptTransfer (
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = XhciDelAsyncIntTransfer (Xhc, DeviceAddress, EndPointAddress);
|
Status = XhciDelAsyncIntTransfer (Xhc, DeviceAddress, EndPointAddress);
|
||||||
DEBUG ((EFI_D_INFO, "XhcAsyncInterruptTransfer: remove old transfer, Status = %r\n", Status));
|
DEBUG ((EFI_D_INFO, "XhcAsyncInterruptTransfer: remove old transfer for addr %d, Status = %r\n", DeviceAddress, Status));
|
||||||
goto ON_EXIT;
|
goto ON_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1321,8 +1335,6 @@ XhcAsyncInterruptTransfer (
|
||||||
goto ON_EXIT;
|
goto ON_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT (Urb->EvtRing == &Xhc->EventRing);
|
|
||||||
|
|
||||||
InsertHeadList (&Xhc->AsyncIntTransfers, &Urb->UrbList);
|
InsertHeadList (&Xhc->AsyncIntTransfers, &Urb->UrbList);
|
||||||
//
|
//
|
||||||
// Ring the doorbell
|
// Ring the doorbell
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
Provides some data structure definitions used by the XHCI host controller driver.
|
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
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
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 XHC_TPL TPL_NOTIFY
|
||||||
|
|
||||||
#define CMD_RING_TRB_NUMBER 0x40
|
#define CMD_RING_TRB_NUMBER 0x100
|
||||||
#define TR_RING_TRB_NUMBER 0x40
|
#define TR_RING_TRB_NUMBER 0x100
|
||||||
#define ERST_NUMBER 0x01
|
#define ERST_NUMBER 0x01
|
||||||
#define EVENT_RING_TRB_NUMBER 0x80
|
#define EVENT_RING_TRB_NUMBER 0x200
|
||||||
|
|
||||||
#define CMD_INTER 0
|
#define CMD_INTER 0
|
||||||
#define CTRL_INTER 1
|
#define CTRL_INTER 1
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
This file contains the register definition of XHCI host controller.
|
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
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
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_CEC BIT23 // Port Config Error Change
|
||||||
#define XHC_PORTSC_CAS BIT24 // Cold Attach Status
|
#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_IP BIT0 // Interrupt Pending
|
||||||
#define XHC_IMAN_IE BIT1 // Interrupt Enable
|
#define XHC_IMAN_IE BIT1 // Interrupt Enable
|
||||||
|
|
||||||
|
|
|
@ -47,10 +47,6 @@ XhcCreateCmdTrb (
|
||||||
Urb->TrbStart->CycleBit = Urb->Ring->RingPCS & BIT0;
|
Urb->TrbStart->CycleBit = Urb->Ring->RingPCS & BIT0;
|
||||||
Urb->TrbEnd = Urb->TrbStart;
|
Urb->TrbEnd = Urb->TrbStart;
|
||||||
|
|
||||||
Urb->EvtRing = &Xhc->EventRing;
|
|
||||||
XhcSyncEventRing (Xhc, Urb->EvtRing);
|
|
||||||
Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;
|
|
||||||
|
|
||||||
return Urb;
|
return Urb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,10 +102,8 @@ XhcCmdTransfer (
|
||||||
goto ON_EXIT;
|
goto ON_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT (Urb->EvtRing == &Xhc->EventRing);
|
|
||||||
|
|
||||||
Status = XhcExecTransfer (Xhc, TRUE, Urb, Timeout);
|
Status = XhcExecTransfer (Xhc, TRUE, Urb, Timeout);
|
||||||
*EvtTrb = Urb->EvtTrbStart;
|
*EvtTrb = Urb->EvtTrb;
|
||||||
|
|
||||||
if (Urb->Result == EFI_USB_NOERROR) {
|
if (Urb->Result == EFI_USB_NOERROR) {
|
||||||
Status = EFI_SUCCESS;
|
Status = EFI_SUCCESS;
|
||||||
|
@ -216,6 +210,12 @@ XhcCreateTransferTrb (
|
||||||
return EFI_DEVICE_ERROR;
|
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));
|
Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));
|
||||||
ASSERT (Dci < 32);
|
ASSERT (Dci < 32);
|
||||||
EPRing = (TRANSFER_RING *)(UINTN) Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1];
|
EPRing = (TRANSFER_RING *)(UINTN) Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1];
|
||||||
|
@ -234,9 +234,6 @@ XhcCreateTransferTrb (
|
||||||
Urb->TrbStart = EPRing->RingEnqueue;
|
Urb->TrbStart = EPRing->RingEnqueue;
|
||||||
switch (EPType) {
|
switch (EPType) {
|
||||||
case ED_CONTROL_BIDIR:
|
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.
|
// For control transfer, create SETUP_STAGE_TRB first.
|
||||||
//
|
//
|
||||||
|
@ -325,10 +322,6 @@ XhcCreateTransferTrb (
|
||||||
|
|
||||||
case ED_BULK_OUT:
|
case ED_BULK_OUT:
|
||||||
case ED_BULK_IN:
|
case ED_BULK_IN:
|
||||||
Urb->EvtRing = &Xhc->EventRing;
|
|
||||||
XhcSyncEventRing (Xhc, Urb->EvtRing);
|
|
||||||
Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;
|
|
||||||
|
|
||||||
TotalLen = 0;
|
TotalLen = 0;
|
||||||
Len = 0;
|
Len = 0;
|
||||||
TrbNum = 0;
|
TrbNum = 0;
|
||||||
|
@ -364,10 +357,6 @@ XhcCreateTransferTrb (
|
||||||
|
|
||||||
case ED_INTERRUPT_OUT:
|
case ED_INTERRUPT_OUT:
|
||||||
case ED_INTERRUPT_IN:
|
case ED_INTERRUPT_IN:
|
||||||
Urb->EvtRing = &Xhc->EventRing;
|
|
||||||
XhcSyncEventRing (Xhc, Urb->EvtRing);
|
|
||||||
Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;
|
|
||||||
|
|
||||||
TotalLen = 0;
|
TotalLen = 0;
|
||||||
Len = 0;
|
Len = 0;
|
||||||
TrbNum = 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 Xhc The XHCI Instance.
|
||||||
@param Trb The TRB to check if it's in the transfer ring
|
@param Trb The TRB to be checked.
|
||||||
|
@param Urb The pointer to the matched Urb.
|
||||||
|
|
||||||
@retval TRUE It is in the ring
|
@retval TRUE The Trb is matched with a transaction of the URBs in the async list.
|
||||||
@retval FALSE It is not in the ring
|
@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
|
BOOLEAN
|
||||||
IsTransferRingTrb (
|
IsTransferRingTrb (
|
||||||
IN TRANSFER_RING *Ring,
|
IN TRB_TEMPLATE *Trb,
|
||||||
IN TRB_TEMPLATE *Trb
|
IN URB *Urb
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
BOOLEAN Flag;
|
TRB_TEMPLATE *CheckedTrb;
|
||||||
TRB_TEMPLATE *Trb1;
|
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
|
|
||||||
Trb1 = Ring->RingSeg0;
|
CheckedTrb = Urb->Ring->RingSeg0;
|
||||||
Flag = FALSE;
|
|
||||||
|
|
||||||
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++) {
|
for (Index = 0; Index < Urb->Ring->TrbNumber; Index++) {
|
||||||
if (Trb == Trb1) {
|
if (Trb == CheckedTrb) {
|
||||||
Flag = TRUE;
|
return TRUE;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
Trb1++;
|
CheckedTrb++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Flag;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -880,19 +908,25 @@ XhcCheckUrbResult (
|
||||||
IN URB *Urb
|
IN URB *Urb
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
BOOLEAN StartDone;
|
|
||||||
BOOLEAN EndDone;
|
|
||||||
EVT_TRB_TRANSFER *EvtTrb;
|
EVT_TRB_TRANSFER *EvtTrb;
|
||||||
TRB_TEMPLATE *TRBPtr;
|
TRB_TEMPLATE *TRBPtr;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
UINT8 TRBType;
|
UINT8 TRBType;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
|
URB *AsyncUrb;
|
||||||
|
URB *CheckedUrb;
|
||||||
|
UINT64 XhcDequeue;
|
||||||
|
UINT32 High;
|
||||||
|
UINT32 Low;
|
||||||
|
|
||||||
ASSERT ((Xhc != NULL) && (Urb != NULL));
|
ASSERT ((Xhc != NULL) && (Urb != NULL));
|
||||||
|
|
||||||
Urb->Completed = 0;
|
|
||||||
Urb->Result = EFI_USB_NOERROR;
|
|
||||||
Status = EFI_SUCCESS;
|
Status = EFI_SUCCESS;
|
||||||
|
|
||||||
|
if (Urb->Finished) {
|
||||||
|
goto EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
EvtTrb = NULL;
|
EvtTrb = NULL;
|
||||||
|
|
||||||
if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
|
if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
|
||||||
|
@ -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;
|
XhcSyncEventRing (Xhc, &Xhc->EventRing);
|
||||||
EndDone = FALSE;
|
for (Index = 0; Index < Xhc->EventRing.TrbNumber; Index++) {
|
||||||
Urb->EvtRing->EventRingDequeue = Urb->EvtTrbStart;
|
Status = XhcCheckNewEvent (Xhc, &Xhc->EventRing, ((TRB_TEMPLATE **)&EvtTrb));
|
||||||
for (Index = 0; Index < Urb->EvtRing->TrbNumber; Index++) {
|
|
||||||
XhcSyncEventRing (Xhc, Urb->EvtRing);
|
|
||||||
Status = XhcCheckNewEvent (Xhc, Urb->EvtRing, ((TRB_TEMPLATE **)&EvtTrb));
|
|
||||||
if (Status == EFI_NOT_READY) {
|
if (Status == EFI_NOT_READY) {
|
||||||
Urb->Result |= EFI_USB_ERR_TIMEOUT;
|
//
|
||||||
|
// All new events are handled, return directly.
|
||||||
|
//
|
||||||
goto EXIT;
|
goto EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,34 +956,44 @@ XhcCheckUrbResult (
|
||||||
}
|
}
|
||||||
|
|
||||||
TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32));
|
TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32));
|
||||||
if (IsTransferRingTrb (Urb->Ring, TRBPtr)) {
|
|
||||||
|
//
|
||||||
|
// 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) {
|
switch (EvtTrb->Completecode) {
|
||||||
case TRB_COMPLETION_STALL_ERROR:
|
case TRB_COMPLETION_STALL_ERROR:
|
||||||
Urb->Result |= EFI_USB_ERR_STALL;
|
CheckedUrb->Result |= EFI_USB_ERR_STALL;
|
||||||
Status = EFI_DEVICE_ERROR;
|
CheckedUrb->Finished = TRUE;
|
||||||
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: STALL_ERROR! Completecode = %x\n",EvtTrb->Completecode));
|
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: STALL_ERROR! Completecode = %x\n",EvtTrb->Completecode));
|
||||||
goto EXIT;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TRB_COMPLETION_BABBLE_ERROR:
|
case TRB_COMPLETION_BABBLE_ERROR:
|
||||||
Urb->Result |= EFI_USB_ERR_BABBLE;
|
CheckedUrb->Result |= EFI_USB_ERR_BABBLE;
|
||||||
Status = EFI_DEVICE_ERROR;
|
CheckedUrb->Finished = TRUE;
|
||||||
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: BABBLE_ERROR! Completecode = %x\n",EvtTrb->Completecode));
|
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: BABBLE_ERROR! Completecode = %x\n",EvtTrb->Completecode));
|
||||||
goto EXIT;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TRB_COMPLETION_DATA_BUFFER_ERROR:
|
case TRB_COMPLETION_DATA_BUFFER_ERROR:
|
||||||
Urb->Result |= EFI_USB_ERR_BUFFER;
|
CheckedUrb->Result |= EFI_USB_ERR_BUFFER;
|
||||||
Status = EFI_DEVICE_ERROR;
|
CheckedUrb->Finished = TRUE;
|
||||||
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: ERR_BUFFER! Completecode = %x\n",EvtTrb->Completecode));
|
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: ERR_BUFFER! Completecode = %x\n",EvtTrb->Completecode));
|
||||||
goto EXIT;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TRB_COMPLETION_USB_TRANSACTION_ERROR:
|
case TRB_COMPLETION_USB_TRANSACTION_ERROR:
|
||||||
Urb->Result |= EFI_USB_ERR_TIMEOUT;
|
CheckedUrb->Result |= EFI_USB_ERR_TIMEOUT;
|
||||||
Status = EFI_DEVICE_ERROR;
|
CheckedUrb->Finished = TRUE;
|
||||||
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: TRANSACTION_ERROR! Completecode = %x\n",EvtTrb->Completecode));
|
DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: TRANSACTION_ERROR! Completecode = %x\n",EvtTrb->Completecode));
|
||||||
goto EXIT;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TRB_COMPLETION_SHORT_PACKET:
|
case TRB_COMPLETION_SHORT_PACKET:
|
||||||
|
@ -963,38 +1006,56 @@ XhcCheckUrbResult (
|
||||||
if ((TRBType == TRB_TYPE_DATA_STAGE) ||
|
if ((TRBType == TRB_TYPE_DATA_STAGE) ||
|
||||||
(TRBType == TRB_TYPE_NORMAL) ||
|
(TRBType == TRB_TYPE_NORMAL) ||
|
||||||
(TRBType == TRB_TYPE_ISOCH)) {
|
(TRBType == TRB_TYPE_ISOCH)) {
|
||||||
Urb->Completed += (Urb->DataLen - EvtTrb->Lenth);
|
CheckedUrb->Completed += (CheckedUrb->DataLen - EvtTrb->Lenth);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = EFI_SUCCESS;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG ((EFI_D_ERROR, "Transfer Default Error Occur! Completecode = 0x%x!\n",EvtTrb->Completecode));
|
DEBUG ((EFI_D_ERROR, "Transfer Default Error Occur! Completecode = 0x%x!\n",EvtTrb->Completecode));
|
||||||
Urb->Result |= EFI_USB_ERR_TIMEOUT;
|
CheckedUrb->Result |= EFI_USB_ERR_TIMEOUT;
|
||||||
Status = EFI_DEVICE_ERROR;
|
CheckedUrb->Finished = TRUE;
|
||||||
goto EXIT;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Only check first and end Trb event address
|
// Only check first and end Trb event address
|
||||||
//
|
//
|
||||||
if (TRBPtr == Urb->TrbStart) {
|
if (TRBPtr == CheckedUrb->TrbStart) {
|
||||||
StartDone = TRUE;
|
CheckedUrb->StartDone = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TRBPtr == Urb->TrbEnd) {
|
if (TRBPtr == CheckedUrb->TrbEnd) {
|
||||||
EndDone = TRUE;
|
CheckedUrb->EndDone = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StartDone && EndDone) {
|
if (CheckedUrb->StartDone && CheckedUrb->EndDone) {
|
||||||
break;
|
CheckedUrb->Finished = TRUE;
|
||||||
}
|
CheckedUrb->EvtTrb = (TRB_TEMPLATE *)EvtTrb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EXIT:
|
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;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1048,12 +1109,16 @@ XhcExecTransfer (
|
||||||
|
|
||||||
for (Index = 0; Index < Loop; Index++) {
|
for (Index = 0; Index < Loop; Index++) {
|
||||||
Status = XhcCheckUrbResult (Xhc, Urb);
|
Status = XhcCheckUrbResult (Xhc, Urb);
|
||||||
if ((Status != EFI_NOT_READY)) {
|
if (Urb->Finished) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gBS->Stall (XHC_POLL_DELAY);
|
gBS->Stall (XHC_POLL_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Index == Loop) {
|
||||||
|
Urb->Result = EFI_USB_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1196,7 +1261,7 @@ XhcMonitorAsyncRequests (
|
||||||
//
|
//
|
||||||
Status = XhcCheckUrbResult (Xhc, Urb);
|
Status = XhcCheckUrbResult (Xhc, Urb);
|
||||||
|
|
||||||
if (Status == EFI_NOT_READY) {
|
if (!Urb->Finished) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1219,8 +1284,6 @@ XhcMonitorAsyncRequests (
|
||||||
CopyMem (ProcBuf, Urb->Data, Urb->Completed);
|
CopyMem (ProcBuf, Urb->Data, Urb->Completed);
|
||||||
}
|
}
|
||||||
|
|
||||||
XhcUpdateAsyncRequest (Xhc, Urb);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Leave error recovery to its related device driver. A
|
// Leave error recovery to its related device driver. A
|
||||||
// common case of the error recovery is to re-submit the
|
// common case of the error recovery is to re-submit the
|
||||||
|
@ -1244,6 +1307,8 @@ XhcMonitorAsyncRequests (
|
||||||
if (ProcBuf != NULL) {
|
if (ProcBuf != NULL) {
|
||||||
gBS->FreePool (ProcBuf);
|
gBS->FreePool (ProcBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XhcUpdateAsyncRequest (Xhc, Urb);
|
||||||
}
|
}
|
||||||
gBS->RestoreTPL (OldTpl);
|
gBS->RestoreTPL (OldTpl);
|
||||||
}
|
}
|
||||||
|
@ -1445,10 +1510,6 @@ XhcSyncEventRing (
|
||||||
{
|
{
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
TRB_TEMPLATE *EvtTrb1;
|
TRB_TEMPLATE *EvtTrb1;
|
||||||
TRB_TEMPLATE *EvtTrb2;
|
|
||||||
UINT64 XhcDequeue;
|
|
||||||
UINT32 High;
|
|
||||||
UINT32 Low;
|
|
||||||
|
|
||||||
ASSERT (EvtRing != NULL);
|
ASSERT (EvtRing != NULL);
|
||||||
|
|
||||||
|
@ -1456,41 +1517,25 @@ XhcSyncEventRing (
|
||||||
// Calculate the EventRingEnqueue and EventRingCCS.
|
// Calculate the EventRingEnqueue and EventRingCCS.
|
||||||
// Note: only support single Segment
|
// Note: only support single Segment
|
||||||
//
|
//
|
||||||
EvtTrb1 = EvtRing->EventRingSeg0;
|
EvtTrb1 = EvtRing->EventRingDequeue;
|
||||||
EvtTrb2 = EvtRing->EventRingSeg0;
|
|
||||||
|
|
||||||
for (Index = 0; Index < EvtRing->TrbNumber; Index++) {
|
for (Index = 0; Index < EvtRing->TrbNumber; Index++) {
|
||||||
if (EvtTrb1->CycleBit != EvtTrb2->CycleBit) {
|
if (EvtTrb1->CycleBit != EvtRing->EventRingCCS) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
EvtTrb1++;
|
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) {
|
if (Index < EvtRing->TrbNumber) {
|
||||||
EvtRing->EventRingEnqueue = EvtTrb1;
|
EvtRing->EventRingEnqueue = EvtTrb1;
|
||||||
EvtRing->EventRingCCS = (EvtTrb2->CycleBit) ? 1 : 0;
|
|
||||||
} else {
|
} else {
|
||||||
EvtRing->EventRingEnqueue = EvtTrb2;
|
ASSERT (FALSE);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
@ -1593,10 +1638,6 @@ XhcCheckNewEvent (
|
||||||
|
|
||||||
Status = EFI_SUCCESS;
|
Status = EFI_SUCCESS;
|
||||||
|
|
||||||
if (((EvtTrb->Status >> 24) & 0xFF) != TRB_COMPLETION_SUCCESS) {
|
|
||||||
Status = EFI_DEVICE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
EvtRing->EventRingDequeue++;
|
EvtRing->EventRingDequeue++;
|
||||||
//
|
//
|
||||||
// If the dequeue pointer is beyond the ring, then roll-back it to the begining of the ring.
|
// If the dequeue pointer is beyond the ring, then roll-back it to the begining of the ring.
|
||||||
|
@ -1845,7 +1886,7 @@ XhcInitializeDeviceSlot (
|
||||||
ASSERT (!EFI_ERROR(Status));
|
ASSERT (!EFI_ERROR(Status));
|
||||||
|
|
||||||
DeviceAddress = (UINT8) ((DEVICE_CONTEXT *) OutputContext)->Slot.DeviceAddress;
|
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;
|
Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;
|
||||||
|
|
||||||
|
@ -2038,7 +2079,7 @@ XhcInitializeDeviceSlot64 (
|
||||||
ASSERT (!EFI_ERROR(Status));
|
ASSERT (!EFI_ERROR(Status));
|
||||||
|
|
||||||
DeviceAddress = (UINT8) ((DEVICE_CONTEXT_64 *) OutputContext)->Slot.DeviceAddress;
|
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;
|
Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
This file contains the definition for XHCI host controller schedule routines.
|
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
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
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 *TrbStart;
|
||||||
TRB_TEMPLATE *TrbEnd;
|
TRB_TEMPLATE *TrbEnd;
|
||||||
UINTN TrbNum;
|
UINTN TrbNum;
|
||||||
EVENT_RING *EvtRing;
|
BOOLEAN StartDone;
|
||||||
TRB_TEMPLATE *EvtTrbStart;
|
BOOLEAN EndDone;
|
||||||
|
BOOLEAN Finished;
|
||||||
|
|
||||||
|
TRB_TEMPLATE *EvtTrb;
|
||||||
} URB;
|
} URB;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -862,7 +862,7 @@ UsbEnumeratePort (
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG (( EFI_D_INFO, "UsbEnumeratePort: port %d state - %02x, change - %02x on %p\n",
|
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
|
// This driver only process two kinds of events now: over current and
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
Unified interface for RootHub and Hub.
|
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
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
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);
|
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;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue