summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c93
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h22
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c103
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h45
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c942
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h245
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c1
7 files changed, 1049 insertions, 402 deletions
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
index 5ccb78e55b..8cbb7bab07 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
@@ -721,7 +721,6 @@ XhcControlTransfer (
URB *Urb;
UINT8 Endpoint;
UINT8 Index;
- UINT8 XhciDevAddr;
UINT8 DescriptorType;
UINT8 SlotId;
UINT8 TTT;
@@ -794,11 +793,6 @@ XhcControlTransfer (
}
//
- // Acquire the actual device address assigned by XHCI's Address_Device cmd.
- //
- XhciDevAddr = Xhc->UsbDevContext[SlotId].XhciDevAddr;
-
- //
// Hook the Set_Address request from UsbBus.
// According to XHCI 1.0 spec, the Set_Address request is replaced by XHCI's Address_Device cmd.
//
@@ -810,7 +804,7 @@ XhcControlTransfer (
//
for (Index = 0; Index < 255; Index++) {
if (!Xhc->UsbDevContext[Index + 1].Enabled &&
- (Xhc->UsbDevContext[Index + 1].SlotId != 0) &&
+ (Xhc->UsbDevContext[Index + 1].SlotId == 0) &&
(Xhc->UsbDevContext[Index + 1].BusDevAddr == (UINT8)Request->Value)) {
Xhc->UsbDevContext[Index + 1].BusDevAddr = 0;
}
@@ -850,7 +844,7 @@ XhcControlTransfer (
Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
Urb = XhcCreateUrb (
Xhc,
- XhciDevAddr,
+ DeviceAddress,
Endpoint,
DeviceSpeed,
MaximumPacketLength,
@@ -867,7 +861,7 @@ XhcControlTransfer (
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
- ASSERT (Urb->EvtRing == &Xhc->CtrlTrEventRing);
+ ASSERT (Urb->EvtRing == &Xhc->EventRing);
Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
//
@@ -909,7 +903,11 @@ XhcControlTransfer (
MaxPacket0 = Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;
}
Xhc->UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));
- Status = XhcEvaluateContext (Xhc, SlotId, MaxPacket0);
+ if (Xhc->HcCParams.Data.Csz == 0) {
+ Status = XhcEvaluateContext (Xhc, SlotId, MaxPacket0);
+ } else {
+ Status = XhcEvaluateContext64 (Xhc, SlotId, MaxPacket0);
+ }
ASSERT_EFI_ERROR (Status);
} else if (DescriptorType == USB_DESC_TYPE_CONFIG) {
ASSERT (Data != NULL);
@@ -940,13 +938,12 @@ XhcControlTransfer (
MTT = 0;
}
- Status = XhcConfigHubContext (
- Xhc,
- SlotId,
- HubDesc->NumPorts,
- TTT,
- MTT
- );
+ if (Xhc->HcCParams.Data.Csz == 0) {
+ Status = XhcConfigHubContext (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);
+ } else {
+ Status = XhcConfigHubContext64 (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);
+ }
+ ASSERT_EFI_ERROR (Status);
}
} else if ((Request->Request == USB_REQ_SET_CONFIG) &&
(Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {
@@ -955,7 +952,12 @@ XhcControlTransfer (
//
for (Index = 0; Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {
if (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->ConfigurationValue == (UINT8)Request->Value) {
- XhcSetConfigCmd (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
+ if (Xhc->HcCParams.Data.Csz == 0) {
+ Status = XhcSetConfigCmd (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
+ } else {
+ Status = XhcSetConfigCmd64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
+ }
+ ASSERT_EFI_ERROR (Status);
break;
}
}
@@ -1073,7 +1075,6 @@ XhcBulkTransfer (
{
USB_XHCI_INSTANCE *Xhc;
URB *Urb;
- UINT8 XhciDevAddr;
UINT8 SlotId;
EFI_STATUS Status;
EFI_STATUS RecoveryStatus;
@@ -1119,17 +1120,12 @@ XhcBulkTransfer (
}
//
- // Acquire the actual device address assigned by XHCI's Address_Device cmd.
- //
- XhciDevAddr = Xhc->UsbDevContext[SlotId].XhciDevAddr;
-
- //
// Create a new URB, insert it into the asynchronous
// schedule list, then poll the execution status.
//
Urb = XhcCreateUrb (
Xhc,
- XhciDevAddr,
+ DeviceAddress,
EndPointAddress,
DeviceSpeed,
MaximumPacketLength,
@@ -1147,7 +1143,7 @@ XhcBulkTransfer (
goto ON_EXIT;
}
- ASSERT (Urb->EvtRing == &Xhc->BulkTrEventRing);
+ ASSERT (Urb->EvtRing == &Xhc->EventRing);
Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
@@ -1223,7 +1219,6 @@ XhcAsyncInterruptTransfer (
USB_XHCI_INSTANCE *Xhc;
URB *Urb;
EFI_STATUS Status;
- UINT8 XhciDevAddr;
UINT8 SlotId;
UINT8 Index;
UINT8 *Data;
@@ -1262,8 +1257,7 @@ XhcAsyncInterruptTransfer (
// The delete request may happen after device is detached.
//
for (Index = 0; Index < 255; Index++) {
- if ((Xhc->UsbDevContext[Index + 1].SlotId != 0) &&
- (Xhc->UsbDevContext[Index + 1].BusDevAddr == DeviceAddress)) {
+ if (Xhc->UsbDevContext[Index + 1].BusDevAddr == DeviceAddress) {
break;
}
}
@@ -1273,12 +1267,7 @@ XhcAsyncInterruptTransfer (
goto ON_EXIT;
}
- //
- // Acquire the actual device address assigned by XHCI's Address_Device cmd.
- //
- XhciDevAddr = Xhc->UsbDevContext[Index + 1].XhciDevAddr;
-
- Status = XhciDelAsyncIntTransfer (Xhc, XhciDevAddr, EndPointAddress);
+ Status = XhciDelAsyncIntTransfer (Xhc, DeviceAddress, EndPointAddress);
DEBUG ((EFI_D_INFO, "XhcAsyncInterruptTransfer: remove old transfer, Status = %r\n", Status));
goto ON_EXIT;
}
@@ -1299,11 +1288,6 @@ XhcAsyncInterruptTransfer (
goto ON_EXIT;
}
- //
- // Acquire the actual device address assigned by XHCI's Address_Device cmd.
- //
- XhciDevAddr = Xhc->UsbDevContext[SlotId].XhciDevAddr;
-
Data = AllocateZeroPool (DataLength);
if (Data == NULL) {
@@ -1314,7 +1298,7 @@ XhcAsyncInterruptTransfer (
Urb = XhcCreateUrb (
Xhc,
- XhciDevAddr,
+ DeviceAddress,
EndPointAddress,
DeviceSpeed,
MaximumPacketLength,
@@ -1333,7 +1317,7 @@ XhcAsyncInterruptTransfer (
goto ON_EXIT;
}
- ASSERT (Urb->EvtRing == &Xhc->AsynIntTrEventRing);
+ ASSERT (Urb->EvtRing == &Xhc->EventRing);
InsertHeadList (&Xhc->AsyncIntTransfers, &Urb->UrbList);
//
@@ -1393,7 +1377,6 @@ XhcSyncInterruptTransfer (
{
USB_XHCI_INSTANCE *Xhc;
URB *Urb;
- UINT8 XhciDevAddr;
UINT8 SlotId;
EFI_STATUS Status;
EFI_STATUS RecoveryStatus;
@@ -1441,14 +1424,9 @@ XhcSyncInterruptTransfer (
goto ON_EXIT;
}
- //
- // Acquire the actual device address assigned by XHCI's Address_Device cmd.
- //
- XhciDevAddr = Xhc->UsbDevContext[SlotId].XhciDevAddr;
-
Urb = XhcCreateUrb (
Xhc,
- XhciDevAddr,
+ DeviceAddress,
EndPointAddress,
DeviceSpeed,
MaximumPacketLength,
@@ -2072,8 +2050,11 @@ XhcDriverBindingStop (
(Xhc->UsbDevContext[Index + 1].SlotId == 0)) {
continue;
}
-
- XhcDisableSlotCmd (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);
+ if (Xhc->HcCParams.Data.Csz == 0) {
+ XhcDisableSlotCmd (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);
+ } else {
+ XhcDisableSlotCmd64 (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);
+ }
}
XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
@@ -2108,11 +2089,11 @@ XhcDriverBindingStop (
// Restore original PCI attributes
//
PciIo->Attributes (
- PciIo,
- EfiPciIoAttributeOperationSet,
- Xhc->OriginalPciAttributes,
- NULL
- );
+ PciIo,
+ EfiPciIoAttributeOperationSet,
+ Xhc->OriginalPciAttributes,
+ NULL
+ );
gBS->CloseProtocol (
Controller,
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
index 3793d9c1c2..f6da016bfb 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
@@ -93,7 +93,7 @@ typedef struct _USB_DEV_CONTEXT USB_DEV_CONTEXT;
#define EFI_LIST_CONTAINER(Entry, Type, Field) BASE_CR(Entry, Type, Field)
#define XHC_LOW_32BIT(Addr64) ((UINT32)(((UINTN)(Addr64)) & 0xFFFFFFFF))
-#define XHC_HIGH_32BIT(Addr64) ((UINT32)(RShiftU64((UINTN)(Addr64), 32) & 0xFFFFFFFF))
+#define XHC_HIGH_32BIT(Addr64) ((UINT32)(RShiftU64((UINT64)(UINTN)(Addr64), 32) & 0xFFFFFFFF))
#define XHC_BIT_IS_SET(Data, Bit) ((BOOLEAN)(((Data) & (Bit)) == (Bit)))
#define XHC_REG_BIT_IS_SET(Xhc, Offset, Bit) \
@@ -228,25 +228,9 @@ struct _USB_XHCI_INSTANCE {
//
TRANSFER_RING CmdRing;
//
- // CmdEventRing
+ // EventRing
//
- EVENT_RING CmdEventRing;
- //
- // ControlTREventRing
- //
- EVENT_RING CtrlTrEventRing;
- //
- // BulkTREventRing
- //
- EVENT_RING BulkTrEventRing;
- //
- // IntTREventRing
- //
- EVENT_RING IntTrEventRing;
- //
- // AsyncIntTREventRing
- //
- EVENT_RING AsynIntTrEventRing;
+ EVENT_RING EventRing;
//
// Misc
//
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
index 874967974c..9d50ef8242 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
@@ -192,39 +192,6 @@ XhcWriteOpReg16 (
}
/**
- Write the data to the 8-bytes width XHCI operational register.
-
- @param Xhc The XHCI Instance.
- @param Offset The offset of the 8-bytes width operational register.
- @param Data The data to write.
-
-**/
-VOID
-XhcWriteOpReg64 (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset,
- IN UINT64 Data
- )
-{
- EFI_STATUS Status;
-
- ASSERT (Xhc->CapLength != 0);
-
- Status = Xhc->PciIo->Mem.Write (
- Xhc->PciIo,
- EfiPciIoWidthUint64,
- XHC_BAR_INDEX,
- (UINT64) (Xhc->CapLength + Offset),
- 1,
- &Data
- );
-
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "XhcWriteOpReg64: Pci Io Write error: %r at %d\n", Status, Offset));
- }
-}
-
-/**
Read XHCI door bell register.
@param Xhc The XHCI Instance.
@@ -332,43 +299,6 @@ XhcReadRuntimeReg (
}
/**
- Read 8-bytes width XHCI runtime register.
-
- @param Xhc The XHCI Instance.
- @param Offset The offset of the 8-bytes width runtime register.
-
- @return The register content read
-
-**/
-UINT64
-XhcReadRuntimeReg64 (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset
- )
-{
- UINT64 Data;
- EFI_STATUS Status;
-
- ASSERT (Xhc->RTSOff != 0);
-
- Status = Xhc->PciIo->Mem.Read (
- Xhc->PciIo,
- EfiPciIoWidthUint64,
- XHC_BAR_INDEX,
- (UINT64) (Xhc->RTSOff + Offset),
- 1,
- &Data
- );
-
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "XhcReadRuntimeReg64: Pci Io Read error - %r at %d\n", Status, Offset));
- Data = 0xFFFFFFFFFFFFFFFFULL;
- }
-
- return Data;
-}
-
-/**
Write the data to the XHCI runtime register.
@param Xhc The XHCI Instance.
@@ -402,39 +332,6 @@ XhcWriteRuntimeReg (
}
/**
- Write the data to the 8-bytes width XHCI runtime register.
-
- @param Xhc The XHCI Instance.
- @param Offset The offset of the 8-bytes width runtime register.
- @param Data The data to write.
-
-**/
-VOID
-XhcWriteRuntimeReg64 (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset,
- IN UINT64 Data
- )
-{
- EFI_STATUS Status;
-
- ASSERT (Xhc->RTSOff != 0);
-
- Status = Xhc->PciIo->Mem.Write (
- Xhc->PciIo,
- EfiPciIoWidthUint64,
- XHC_BAR_INDEX,
- (UINT64) (Xhc->RTSOff + Offset),
- 1,
- &Data
- );
-
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "XhcWriteRuntimeReg64: Pci Io Write error: %r at %d\n", Status, Offset));
- }
-}
-
-/**
Read XHCI extended capability register.
@param Xhc The XHCI Instance.
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h
index c1c086cf28..26ead70bb4 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h
@@ -266,21 +266,6 @@ XhcWriteOpReg16 (
);
/**
- Write the data to the 8-bytes width XHCI operational register.
-
- @param Xhc The XHCI Instance.
- @param Offset The offset of the 8-bytes width operational register.
- @param Data The data to write.
-
-**/
-VOID
-XhcWriteOpReg64 (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset,
- IN UINT64 Data
- );
-
-/**
Read XHCI runtime register.
@param Xhc The XHCI Instance.
@@ -296,21 +281,6 @@ XhcReadRuntimeReg (
);
/**
- Read 8-bytes width XHCI runtime register.
-
- @param Xhc The XHCI Instance.
- @param Offset The offset of the 8-bytes width runtime register.
-
- @return The register content read
-
-**/
-UINT64
-XhcReadRuntimeReg64 (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset
- );
-
-/**
Write the data to the XHCI runtime register.
@param Xhc The XHCI Instance.
@@ -326,21 +296,6 @@ XhcWriteRuntimeReg (
);
/**
- Write the data to the 8-bytes width XHCI runtime register.
-
- @param Xhc The XHCI Instance.
- @param Offset The offset of the 8-bytes width runtime register.
- @param Data The data to write.
-
-**/
-VOID
-XhcWriteRuntimeReg64 (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset,
- IN UINT64 Data
- );
-
-/**
Read XHCI door bell register.
@param Xhc The XHCI Instance.
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
index 49cc2619eb..d0b616582e 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
@@ -47,7 +47,7 @@ XhcCreateCmdTrb (
Urb->TrbStart->CycleBit = Urb->Ring->RingPCS & BIT0;
Urb->TrbEnd = Urb->TrbStart;
- Urb->EvtRing = &Xhc->CmdEventRing;
+ Urb->EvtRing = &Xhc->EventRing;
XhcSyncEventRing (Xhc, Urb->EvtRing);
Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;
@@ -106,7 +106,7 @@ XhcCmdTransfer (
goto ON_EXIT;
}
- ASSERT (Urb->EvtRing == &Xhc->CmdEventRing);
+ ASSERT (Urb->EvtRing == &Xhc->EventRing);
Status = XhcExecTransfer (Xhc, TRUE, Urb, Timeout);
*EvtTrb = Urb->EvtTrbStart;
@@ -125,7 +125,7 @@ ON_EXIT:
Create a new URB for a new transaction.
@param Xhc The XHCI Instance
- @param DevAddr The device address
+ @param BusAddr The logical device address assigned by UsbBus driver
@param EpAddr Endpoint addrress
@param DevSpeed The device speed
@param MaxPacket The max packet length of the endpoint
@@ -142,7 +142,7 @@ ON_EXIT:
URB*
XhcCreateUrb (
IN USB_XHCI_INSTANCE *Xhc,
- IN UINT8 DevAddr,
+ IN UINT8 BusAddr,
IN UINT8 EpAddr,
IN UINT8 DevSpeed,
IN UINTN MaxPacket,
@@ -167,7 +167,7 @@ XhcCreateUrb (
InitializeListHead (&Urb->UrbList);
Ep = &Urb->Ep;
- Ep->DevAddr = DevAddr;
+ Ep->BusAddr = BusAddr;
Ep->EpAddr = (UINT8)(EpAddr & 0x0F);
Ep->Direction = ((EpAddr & 0x80) != 0) ? EfiUsbDataIn : EfiUsbDataOut;
Ep->DevSpeed = DevSpeed;
@@ -201,7 +201,7 @@ XhcCreateTransferTrb (
IN URB *Urb
)
{
- DEVICE_CONTEXT *OutputContext;
+ VOID *OutputContext;
TRANSFER_RING *EPRing;
UINT8 EPType;
UINT8 SlotId;
@@ -211,13 +211,21 @@ XhcCreateTransferTrb (
UINTN Len;
UINTN TrbNum;
- SlotId = XhcDevAddrToSlotId(Xhc, Urb->Ep.DevAddr);
+ SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);
+ if (SlotId == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));
ASSERT (Dci < 32);
EPRing = (TRANSFER_RING *)(UINTN) Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1];
Urb->Ring = EPRing;
- OutputContext = (DEVICE_CONTEXT *)(UINTN) Xhc->DCBAA[SlotId];
- EPType = (UINT8) OutputContext->EP[Dci-1].EPType;
+ OutputContext = (VOID *)(UINTN)Xhc->DCBAA[SlotId];
+ if (Xhc->HcCParams.Data.Csz == 0) {
+ EPType = (UINT8) ((DEVICE_CONTEXT *)OutputContext)->EP[Dci-1].EPType;
+ } else {
+ EPType = (UINT8) ((DEVICE_CONTEXT_64 *)OutputContext)->EP[Dci-1].EPType;
+ }
//
// Construct the TRB
@@ -226,7 +234,7 @@ XhcCreateTransferTrb (
Urb->TrbStart = EPRing->RingEnqueue;
switch (EPType) {
case ED_CONTROL_BIDIR:
- Urb->EvtRing = &Xhc->CtrlTrEventRing;
+ Urb->EvtRing = &Xhc->EventRing;
XhcSyncEventRing (Xhc, Urb->EvtRing);
Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;
//
@@ -239,7 +247,7 @@ XhcCreateTransferTrb (
TrbStart->TrbCtrSetup.wIndex = Urb->Request->Index;
TrbStart->TrbCtrSetup.wLength = Urb->Request->Length;
TrbStart->TrbCtrSetup.Lenth = 8;
- TrbStart->TrbCtrSetup.IntTarget = Urb->EvtRing->EventInterrupter;
+ TrbStart->TrbCtrSetup.IntTarget = 0;
TrbStart->TrbCtrSetup.IOC = 1;
TrbStart->TrbCtrSetup.IDT = 1;
TrbStart->TrbCtrSetup.Type = TRB_TYPE_SETUP_STAGE;
@@ -266,7 +274,7 @@ XhcCreateTransferTrb (
TrbStart->TrbCtrData.TRBPtrHi = XHC_HIGH_32BIT(Urb->Data);
TrbStart->TrbCtrData.Lenth = (UINT32) Urb->DataLen;
TrbStart->TrbCtrData.TDSize = 0;
- TrbStart->TrbCtrData.IntTarget = Urb->EvtRing->EventInterrupter;
+ TrbStart->TrbCtrData.IntTarget = 0;
TrbStart->TrbCtrData.ISP = 1;
TrbStart->TrbCtrData.IOC = 1;
TrbStart->TrbCtrData.IDT = 0;
@@ -291,7 +299,7 @@ XhcCreateTransferTrb (
//
XhcSyncTrsRing (Xhc, EPRing);
TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;
- TrbStart->TrbCtrStatus.IntTarget = Urb->EvtRing->EventInterrupter;
+ TrbStart->TrbCtrStatus.IntTarget = 0;
TrbStart->TrbCtrStatus.IOC = 1;
TrbStart->TrbCtrStatus.CH = 0;
TrbStart->TrbCtrStatus.Type = TRB_TYPE_STATUS_STAGE;
@@ -317,7 +325,7 @@ XhcCreateTransferTrb (
case ED_BULK_OUT:
case ED_BULK_IN:
- Urb->EvtRing = &Xhc->BulkTrEventRing;
+ Urb->EvtRing = &Xhc->EventRing;
XhcSyncEventRing (Xhc, Urb->EvtRing);
Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;
@@ -336,7 +344,7 @@ XhcCreateTransferTrb (
TrbStart->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT((UINT8 *) Urb->Data + TotalLen);
TrbStart->TrbNormal.Lenth = (UINT32) Len;
TrbStart->TrbNormal.TDSize = 0;
- TrbStart->TrbNormal.IntTarget = Urb->EvtRing->EventInterrupter;
+ TrbStart->TrbNormal.IntTarget = 0;
TrbStart->TrbNormal.ISP = 1;
TrbStart->TrbNormal.IOC = 1;
TrbStart->TrbNormal.Type = TRB_TYPE_NORMAL;
@@ -356,14 +364,7 @@ XhcCreateTransferTrb (
case ED_INTERRUPT_OUT:
case ED_INTERRUPT_IN:
- if (Urb->Ep.Type == XHC_INT_TRANSFER_ASYNC) {
- Urb->EvtRing = &Xhc->AsynIntTrEventRing;
- } else if(Urb->Ep.Type == XHC_INT_TRANSFER_SYNC){
- Urb->EvtRing = &Xhc->IntTrEventRing;
- } else {
- DEBUG ((EFI_D_ERROR, "EP Interrupt type error!\n"));
- ASSERT(FALSE);
- }
+ Urb->EvtRing = &Xhc->EventRing;
XhcSyncEventRing (Xhc, Urb->EvtRing);
Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;
@@ -382,7 +383,7 @@ XhcCreateTransferTrb (
TrbStart->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT((UINT8 *) Urb->Data + TotalLen);
TrbStart->TrbNormal.Lenth = (UINT32) Len;
TrbStart->TrbNormal.TDSize = 0;
- TrbStart->TrbNormal.IntTarget = Urb->EvtRing->EventInterrupter;
+ TrbStart->TrbNormal.IntTarget = 0;
TrbStart->TrbNormal.ISP = 1;
TrbStart->TrbNormal.IOC = 1;
TrbStart->TrbNormal.Type = TRB_TYPE_NORMAL;
@@ -481,7 +482,12 @@ XhcInitSched (
// a 64-bit address pointing to where the Device Context Base Address Array is located.
//
Xhc->DCBAA = (UINT64 *)(UINTN)Dcbaa;
- XhcWriteOpReg64 (Xhc, XHC_DCBAAP_OFFSET, (UINT64)(UINTN)Xhc->DCBAA);
+ //
+ // 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.
+ //
+ XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET, XHC_LOW_32BIT(Xhc->DCBAA));
+ XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET + 4, XHC_HIGH_32BIT (Xhc->DCBAA));
DEBUG ((EFI_D_INFO, "XhcInitSched:DCBAA=0x%x\n", (UINT64)(UINTN)Xhc->DCBAA));
//
@@ -499,7 +505,12 @@ XhcInitSched (
CmdRing = (UINT64)(UINTN)Xhc->CmdRing.RingSeg0;
ASSERT ((CmdRing & 0x3F) == 0);
CmdRing |= XHC_CRCR_RCS;
- XhcWriteOpReg64 (Xhc, XHC_CRCR_OFFSET, CmdRing);
+ //
+ // 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.
+ //
+ XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET, XHC_LOW_32BIT(CmdRing));
+ XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET + 4, XHC_HIGH_32BIT (CmdRing));
DEBUG ((EFI_D_INFO, "XhcInitSched:XHC_CRCR=0x%x\n", Xhc->CmdRing.RingSeg0));
@@ -516,11 +527,8 @@ XhcInitSched (
//
// Allocate EventRing for Cmd, Ctrl, Bulk, Interrupt, AsynInterrupt transfer
//
- CreateEventRing (Xhc, CMD_INTER, &Xhc->CmdEventRing);
- CreateEventRing (Xhc, CTRL_INTER, &Xhc->CtrlTrEventRing);
- CreateEventRing (Xhc, BULK_INTER, &Xhc->BulkTrEventRing);
- CreateEventRing (Xhc, INT_INTER, &Xhc->IntTrEventRing);
- CreateEventRing (Xhc, INT_INTER_ASYNC, &Xhc->AsynIntTrEventRing);
+ CreateEventRing (Xhc, &Xhc->EventRing);
+ DEBUG ((EFI_D_INFO, "XhcInitSched:XHC_EVENTRING=0x%x\n", Xhc->EventRing.EventRingSeg0));
}
/**
@@ -551,10 +559,14 @@ XhcRecoverHaltedEndpoint (
UINT8 Dci;
UINT8 SlotId;
- Status = EFI_SUCCESS;
- SlotId = XhcDevAddrToSlotId(Xhc, Urb->Ep.DevAddr);
- Dci = XhcEndpointToDci(Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));
-
+ Status = EFI_SUCCESS;
+ SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);
+ if (SlotId == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));
+ ASSERT (Dci < 32);
+
DEBUG ((EFI_D_INFO, "Recovery Halted Slot = %x,Dci = %x\n", SlotId, Dci));
//
@@ -603,14 +615,12 @@ XhcRecoverHaltedEndpoint (
Create XHCI event ring.
@param Xhc The XHCI Instance.
- @param EventInterrupter The interrupter of event.
@param EventRing The created event ring.
**/
VOID
CreateEventRing (
IN USB_XHCI_INSTANCE *Xhc,
- IN UINT8 EventInterrupter,
OUT EVENT_RING *EventRing
)
{
@@ -625,7 +635,6 @@ CreateEventRing (
ZeroMem (Buf, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
EventRing->EventRingSeg0 = Buf;
- EventRing->EventInterrupter = EventInterrupter;
EventRing->TrbNumber = EVENT_RING_TRB_NUMBER;
EventRing->EventRingDequeue = (TRB_TEMPLATE *) EventRing->EventRingSeg0;
EventRing->EventRingEnqueue = (TRB_TEMPLATE *) EventRing->EventRingSeg0;
@@ -651,29 +660,45 @@ CreateEventRing (
//
XhcWriteRuntimeReg (
Xhc,
- XHC_ERSTSZ_OFFSET + (32 * EventRing->EventInterrupter),
+ XHC_ERSTSZ_OFFSET,
ERST_NUMBER
);
//
// Program the Interrupter Event Ring Dequeue Pointer (ERDP) register (5.5.2.3.3)
//
- XhcWriteRuntimeReg64 (
+ // 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 + (32 * EventRing->EventInterrupter),
- (UINT64)(UINTN)EventRing->EventRingDequeue
+ XHC_ERDP_OFFSET,
+ XHC_LOW_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)
+ );
+ XhcWriteRuntimeReg (
+ Xhc,
+ XHC_ERDP_OFFSET + 4,
+ XHC_HIGH_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)
);
//
// Program the Interrupter Event Ring Segment Table Base Address (ERSTBA) register(5.5.2.3.2)
//
- XhcWriteRuntimeReg64 (
+ // 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_ERSTBA_OFFSET,
+ XHC_LOW_32BIT((UINT64)(UINTN)ERSTBase)
+ );
+ XhcWriteRuntimeReg (
Xhc,
- XHC_ERSTBA_OFFSET + (32 * EventRing->EventInterrupter),
- (UINT64)(UINTN)ERSTBase
+ XHC_ERSTBA_OFFSET + 4,
+ XHC_HIGH_32BIT((UINT64)(UINTN)ERSTBase)
);
//
// Need set IMAN IE bit to enble the ring interrupt
//
- XhcSetRuntimeRegBit (Xhc, XHC_IMAN_OFFSET + (32 * EventRing->EventInterrupter), XHC_IMAN_IE);
+ XhcSetRuntimeRegBit (Xhc, XHC_IMAN_OFFSET, XHC_IMAN_IE);
}
/**
@@ -800,11 +825,7 @@ XhcFreeSched (
Xhc->CmdRing.RingSeg0 = NULL;
}
- XhcFreeEventRing (Xhc,&Xhc->CmdEventRing);
- XhcFreeEventRing (Xhc,&Xhc->CtrlTrEventRing);
- XhcFreeEventRing (Xhc,&Xhc->BulkTrEventRing);
- XhcFreeEventRing (Xhc,&Xhc->AsynIntTrEventRing);
- XhcFreeEventRing (Xhc,&Xhc->IntTrEventRing);
+ XhcFreeEventRing (Xhc,&Xhc->EventRing);
}
/**
@@ -894,74 +915,82 @@ XhcCheckUrbResult (
goto EXIT;
}
- TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | (UINT64) EvtTrb->TRBPtrHi << 32);
+ //
+ // Only handle COMMAND_COMPLETETION_EVENT and TRANSFER_EVENT.
+ //
+ if ((EvtTrb->Type != TRB_TYPE_COMMAND_COMPLT_EVENT) && (EvtTrb->Type != TRB_TYPE_TRANS_EVENT)) {
+ continue;
+ }
- 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;
+ TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | (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_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_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_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 (IsTransferRingTrb (Urb->Ring, TRBPtr)) {
+ 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;
- }
+ Status = EFI_SUCCESS;
+ break;
- //
- // Only check first and end Trb event address
- //
- if (TRBPtr == Urb->TrbStart) {
- StartDone = TRUE;
- }
+ 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;
+ }
- if (TRBPtr == Urb->TrbEnd) {
- EndDone = TRUE;
- }
+ //
+ // Only check first and end Trb event address
+ //
+ if (TRBPtr == Urb->TrbStart) {
+ StartDone = TRUE;
+ }
- if (StartDone && EndDone) {
- break;
+ if (TRBPtr == Urb->TrbEnd) {
+ EndDone = TRUE;
+ }
+
+ if (StartDone && EndDone) {
+ break;
+ }
}
}
@@ -1001,8 +1030,12 @@ XhcExecTransfer (
SlotId = 0;
Dci = 0;
} else {
- SlotId = XhcDevAddrToSlotId(Xhc, Urb->Ep.DevAddr);
- Dci = XhcEndpointToDci(Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));
+ SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);
+ if (SlotId == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));
+ ASSERT (Dci < 32);
}
Status = EFI_SUCCESS;
@@ -1029,7 +1062,7 @@ XhcExecTransfer (
the device and endpoint.
@param Xhc The XHCI Instance.
- @param DevAddr The address of the target device.
+ @param BusAddr The logical device address assigned by UsbBus driver.
@param EpNum The endpoint of the target.
@retval EFI_SUCCESS An asynchronous transfer is removed.
@@ -1039,7 +1072,7 @@ XhcExecTransfer (
EFI_STATUS
XhciDelAsyncIntTransfer (
IN USB_XHCI_INSTANCE *Xhc,
- IN UINT8 DevAddr,
+ IN UINT8 BusAddr,
IN UINT8 EpNum
)
{
@@ -1051,11 +1084,11 @@ XhciDelAsyncIntTransfer (
Direction = ((EpNum & 0x80) != 0) ? EfiUsbDataIn : EfiUsbDataOut;
EpNum &= 0x0F;
- Urb = NULL;
+ Urb = NULL;
EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) {
Urb = EFI_LIST_CONTAINER (Entry, URB, UrbList);
- if ((Urb->Ep.DevAddr == DevAddr) &&
+ if ((Urb->Ep.BusAddr == BusAddr) &&
(Urb->Ep.EpAddr == EpNum) &&
(Urb->Ep.Direction == Direction)) {
RemoveEntryList (&Urb->UrbList);
@@ -1108,9 +1141,13 @@ XhcUpdateAsyncRequest (
if (Urb->Result == EFI_USB_NOERROR) {
Status = XhcCreateTransferTrb (Xhc, Urb);
- ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
Status = RingIntTransferDoorBell (Xhc, Urb);
- ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
}
}
@@ -1148,7 +1185,7 @@ XhcMonitorAsyncRequests (
//
// Make sure that the device is available before every check.
//
- SlotId = XhcDevAddrToSlotId(Xhc, Urb->Ep.DevAddr);
+ SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);
if (SlotId == 0) {
continue;
}
@@ -1271,7 +1308,11 @@ XhcPollPortStatusChange (
//
SlotId = XhcRouteStringToSlotId (Xhc, RouteChart);
if (SlotId == 0) {
- Status = XhcInitializeDeviceSlot (Xhc, ParentRouteChart, Port, RouteChart, Speed);
+ if (Xhc->HcCParams.Data.Csz == 0) {
+ Status = XhcInitializeDeviceSlot (Xhc, ParentRouteChart, Port, RouteChart, Speed);
+ } else {
+ Status = XhcInitializeDeviceSlot64 (Xhc, ParentRouteChart, Port, RouteChart, Speed);
+ }
ASSERT_EFI_ERROR (Status);
}
} else if ((PortState->PortStatus & USB_PORT_STAT_CONNECTION) == 0) {
@@ -1280,7 +1321,11 @@ XhcPollPortStatusChange (
//
SlotId = XhcRouteStringToSlotId (Xhc, RouteChart);
if (SlotId != 0) {
- Status = XhcDisableSlotCmd (Xhc, SlotId);
+ if (Xhc->HcCParams.Data.Csz == 0) {
+ Status = XhcDisableSlotCmd (Xhc, SlotId);
+ } else {
+ Status = XhcDisableSlotCmd64 (Xhc, SlotId);
+ }
ASSERT_EFI_ERROR (Status);
}
}
@@ -1317,38 +1362,6 @@ XhcEndpointToDci (
}
/**
- Find out the slot id according to device address assigned by XHCI's Address_Device cmd.
-
- @param Xhc The XHCI Instance.
- @param DevAddr The device address of the target device.
-
- @return The slot id used by the device.
-
-**/
-UINT8
-XhcDevAddrToSlotId (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT8 DevAddr
- )
-{
- UINT8 Index;
-
- for (Index = 0; Index < 255; Index++) {
- if (Xhc->UsbDevContext[Index + 1].Enabled &&
- (Xhc->UsbDevContext[Index + 1].SlotId != 0) &&
- (Xhc->UsbDevContext[Index + 1].XhciDevAddr == DevAddr)) {
- break;
- }
- }
-
- if (Index == 255) {
- return 0;
- }
-
- return Xhc->UsbDevContext[Index + 1].SlotId;
-}
-
-/**
Find out the actual device address according to the requested device address from UsbBus.
@param Xhc The XHCI Instance.
@@ -1433,7 +1446,9 @@ XhcSyncEventRing (
UINTN Index;
TRB_TEMPLATE *EvtTrb1;
TRB_TEMPLATE *EvtTrb2;
- TRB_TEMPLATE *XhcDequeue;
+ UINT64 XhcDequeue;
+ UINT32 High;
+ UINT32 Low;
ASSERT (EvtRing != NULL);
@@ -1462,17 +1477,20 @@ XhcSyncEventRing (
//
// Apply the EventRingDequeue to Xhc
//
- XhcDequeue = (TRB_TEMPLATE *)(UINTN) XhcReadRuntimeReg64 (
- Xhc,
- XHC_ERDP_OFFSET + (32 * EvtRing->EventInterrupter)
- );
-
- if (((UINT64)(UINTN)XhcDequeue & (~0x0F)) != ((UINT64)(UINTN)EvtRing->EventRingDequeue & (~0x0F))) {
- XhcWriteRuntimeReg64 (
- Xhc,
- XHC_ERDP_OFFSET + (32 * EvtRing->EventInterrupter),
- (UINT64)(UINTN)EvtRing->EventRingDequeue | BIT3
- );
+ // 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, Low | BIT3);
+ XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4, High);
}
return EFI_SUCCESS;
@@ -1635,8 +1653,8 @@ RingIntTransferDoorBell (
UINT8 SlotId;
UINT8 Dci;
- SlotId = XhcDevAddrToSlotId(Xhc, Urb->Ep.DevAddr);
- Dci = XhcEndpointToDci(Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));
+ SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);
+ Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));
XhcRingDoorBell (Xhc, SlotId, Dci);
return EFI_SUCCESS;
}
@@ -1835,6 +1853,200 @@ XhcInitializeDeviceSlot (
}
/**
+ Assign and initialize the device slot for a new device.
+
+ @param Xhc The XHCI Instance.
+ @param ParentRouteChart The route string pointed to the parent device.
+ @param ParentPort The port at which the device is located.
+ @param RouteChart The route string pointed to the device.
+ @param DeviceSpeed The device speed.
+
+ @retval EFI_SUCCESS Successfully assign a slot to the device and assign an address to it.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcInitializeDeviceSlot64 (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN USB_DEV_ROUTE ParentRouteChart,
+ IN UINT16 ParentPort,
+ IN USB_DEV_ROUTE RouteChart,
+ IN UINT8 DeviceSpeed
+ )
+{
+ EFI_STATUS Status;
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;
+ INPUT_CONTEXT_64 *InputContext;
+ DEVICE_CONTEXT_64 *OutputContext;
+ TRANSFER_RING *EndpointTransferRing;
+ CMD_TRB_ADDRESS_DEVICE CmdTrbAddr;
+ UINT8 DeviceAddress;
+ CMD_TRB_ENABLE_SLOT CmdTrb;
+ UINT8 SlotId;
+ UINT8 ParentSlotId;
+ DEVICE_CONTEXT_64 *ParentDeviceContext;
+
+ ZeroMem (&CmdTrb, sizeof (CMD_TRB_ENABLE_SLOT));
+ CmdTrb.CycleBit = 1;
+ CmdTrb.Type = TRB_TYPE_EN_SLOT;
+
+ Status = XhcCmdTransfer (
+ Xhc,
+ (TRB_TEMPLATE *) (UINTN) &CmdTrb,
+ XHC_GENERIC_TIMEOUT,
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb
+ );
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (EvtTrb->SlotId <= Xhc->MaxSlotsEn);
+ DEBUG ((EFI_D_INFO, "Enable Slot Successfully, The Slot ID = 0x%x\n", EvtTrb->SlotId));
+ SlotId = (UINT8)EvtTrb->SlotId;
+ ASSERT (SlotId != 0);
+
+ ZeroMem (&Xhc->UsbDevContext[SlotId], sizeof (USB_DEV_CONTEXT));
+ Xhc->UsbDevContext[SlotId].Enabled = TRUE;
+ Xhc->UsbDevContext[SlotId].SlotId = SlotId;
+ Xhc->UsbDevContext[SlotId].RouteString.Dword = RouteChart.Dword;
+ Xhc->UsbDevContext[SlotId].ParentRouteString.Dword = ParentRouteChart.Dword;
+
+ //
+ // 4.3.3 Device Slot Initialization
+ // 1) Allocate an Input Context data structure (6.2.5) and initialize all fields to '0'.
+ //
+ InputContext = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (INPUT_CONTEXT_64)));
+ ASSERT (InputContext != NULL);
+ ASSERT (((UINTN) InputContext & 0x3F) == 0);
+ ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64));
+
+ Xhc->UsbDevContext[SlotId].InputContext = (VOID *) InputContext;
+
+ //
+ // 2) Initialize the Input Control Context (6.2.5.1) of the Input Context by setting the A0 and A1
+ // flags to '1'. These flags indicate that the Slot Context and the Endpoint 0 Context of the Input
+ // Context are affected by the command.
+ //
+ InputContext->InputControlContext.Dword2 |= (BIT0 | BIT1);
+
+ //
+ // 3) Initialize the Input Slot Context data structure
+ //
+ InputContext->Slot.RouteString = RouteChart.Route.RouteString;
+ InputContext->Slot.Speed = DeviceSpeed + 1;
+ InputContext->Slot.ContextEntries = 1;
+ InputContext->Slot.RootHubPortNum = RouteChart.Route.RootPortNum;
+
+ if (RouteChart.Route.RouteString) {
+ //
+ // The device is behind of hub device.
+ //
+ ParentSlotId = XhcRouteStringToSlotId(Xhc, ParentRouteChart);
+ ASSERT (ParentSlotId != 0);
+ //
+ //if the Full/Low device attached to a High Speed Hub, Init the TTPortNum and TTHubSlotId field of slot context
+ //
+ ParentDeviceContext = (DEVICE_CONTEXT_64 *)Xhc->UsbDevContext[ParentSlotId].OutputContext;
+ if ((ParentDeviceContext->Slot.TTPortNum == 0) &&
+ (ParentDeviceContext->Slot.TTHubSlotId == 0)) {
+ if ((ParentDeviceContext->Slot.Speed == (EFI_USB_SPEED_HIGH + 1)) && (DeviceSpeed < EFI_USB_SPEED_HIGH)) {
+ //
+ // Full/Low device attached to High speed hub port that isolates the high speed signaling
+ // environment from Full/Low speed signaling environment for a device
+ //
+ InputContext->Slot.TTPortNum = ParentPort;
+ InputContext->Slot.TTHubSlotId = ParentSlotId;
+ }
+ } else {
+ //
+ // Inherit the TT parameters from parent device.
+ //
+ InputContext->Slot.TTPortNum = ParentDeviceContext->Slot.TTPortNum;
+ InputContext->Slot.TTHubSlotId = ParentDeviceContext->Slot.TTHubSlotId;
+ //
+ // If the device is a High speed device then down the speed to be the same as its parent Hub
+ //
+ if (DeviceSpeed == EFI_USB_SPEED_HIGH) {
+ InputContext->Slot.Speed = ParentDeviceContext->Slot.Speed;
+ }
+ }
+ }
+
+ //
+ // 4) Allocate and initialize the Transfer Ring for the Default Control Endpoint.
+ //
+ EndpointTransferRing = AllocateZeroPool (sizeof (TRANSFER_RING));
+ Xhc->UsbDevContext[SlotId].EndpointTransferRing[0] = EndpointTransferRing;
+ CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0]);
+ //
+ // 5) Initialize the Input default control Endpoint 0 Context (6.2.3).
+ //
+ InputContext->EP[0].EPType = ED_CONTROL_BIDIR;
+
+ if (DeviceSpeed == EFI_USB_SPEED_SUPER) {
+ InputContext->EP[0].MaxPacketSize = 512;
+ } else if (DeviceSpeed == EFI_USB_SPEED_HIGH) {
+ InputContext->EP[0].MaxPacketSize = 64;
+ } else {
+ InputContext->EP[0].MaxPacketSize = 8;
+ }
+ //
+ // Initial value of Average TRB Length for Control endpoints would be 8B, Interrupt endpoints
+ // 1KB, and Bulk and Isoch endpoints 3KB.
+ //
+ InputContext->EP[0].AverageTRBLength = 8;
+ InputContext->EP[0].MaxBurstSize = 0;
+ InputContext->EP[0].Interval = 0;
+ InputContext->EP[0].MaxPStreams = 0;
+ InputContext->EP[0].Mult = 0;
+ InputContext->EP[0].CErr = 3;
+
+ //
+ // Init the DCS(dequeue cycle state) as the transfer ring's CCS
+ //
+ InputContext->EP[0].PtrLo = XHC_LOW_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0) | BIT0;
+ InputContext->EP[0].PtrHi = XHC_HIGH_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0);
+
+ //
+ // 6) Allocate the Output Device Context data structure (6.2.1) and initialize it to '0'.
+ //
+ OutputContext = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (DEVICE_CONTEXT_64)));
+ ASSERT (OutputContext != NULL);
+ ASSERT (((UINTN) OutputContext & 0x3F) == 0);
+ ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT_64));
+
+ Xhc->UsbDevContext[SlotId].OutputContext = OutputContext;
+ //
+ // 7) Load the appropriate (Device Slot ID) entry in the Device Context Base Address Array (5.4.6) with
+ // a pointer to the Output Device Context data structure (6.2.1).
+ //
+ Xhc->DCBAA[SlotId] = (UINT64) (UINTN) OutputContext;
+
+ //
+ // 8) Issue an Address Device Command for the Device Slot, where the command points to the Input
+ // Context data structure described above.
+ //
+ ZeroMem (&CmdTrbAddr, sizeof (CmdTrbAddr));
+ CmdTrbAddr.PtrLo = XHC_LOW_32BIT (Xhc->UsbDevContext[SlotId].InputContext);
+ CmdTrbAddr.PtrHi = XHC_HIGH_32BIT (Xhc->UsbDevContext[SlotId].InputContext);
+ CmdTrbAddr.CycleBit = 1;
+ CmdTrbAddr.Type = TRB_TYPE_ADDRESS_DEV;
+ CmdTrbAddr.SlotId = Xhc->UsbDevContext[SlotId].SlotId;
+ Status = XhcCmdTransfer (
+ Xhc,
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbAddr,
+ XHC_GENERIC_TIMEOUT,
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb
+ );
+ ASSERT (!EFI_ERROR(Status));
+
+ DeviceAddress = (UINT8) ((DEVICE_CONTEXT_64 *) OutputContext)->Slot.DeviceAddress;
+ DEBUG ((EFI_D_INFO, " Address %d assigned succeefully\n", DeviceAddress));
+
+ Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;
+
+ return Status;
+}
+
+
+/**
Disable the specified device slot.
@param Xhc The XHCI Instance.
@@ -1928,11 +2140,112 @@ XhcDisableSlotCmd (
// remove urb from XHCI's asynchronous transfer list.
//
Xhc->UsbDevContext[SlotId].Enabled = FALSE;
+ Xhc->UsbDevContext[SlotId].SlotId = 0;
return Status;
}
/**
+ Disable the specified device slot.
+
+ @param Xhc The XHCI Instance.
+ @param SlotId The slot id to be disabled.
+
+ @retval EFI_SUCCESS Successfully disable the device slot.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcDisableSlotCmd64 (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN UINT8 SlotId
+ )
+{
+ EFI_STATUS Status;
+ TRB_TEMPLATE *EvtTrb;
+ CMD_TRB_DISABLE_SLOT CmdTrbDisSlot;
+ UINT8 Index;
+ VOID *RingSeg;
+
+ //
+ // Disable the device slots occupied by these devices on its downstream ports.
+ // Entry 0 is reserved.
+ //
+ for (Index = 0; Index < 255; Index++) {
+ if (!Xhc->UsbDevContext[Index + 1].Enabled ||
+ (Xhc->UsbDevContext[Index + 1].SlotId == 0) ||
+ (Xhc->UsbDevContext[Index + 1].ParentRouteString.Dword != Xhc->UsbDevContext[SlotId].RouteString.Dword)) {
+ continue;
+ }
+
+ Status = XhcDisableSlotCmd64 (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "XhcDisableSlotCmd: failed to disable child, ignore error\n"));
+ Xhc->UsbDevContext[Index + 1].SlotId = 0;
+ }
+ }
+
+ //
+ // Construct the disable slot command
+ //
+ DEBUG ((EFI_D_INFO, "Disable device slot %d!\n", SlotId));
+
+ ZeroMem (&CmdTrbDisSlot, sizeof (CmdTrbDisSlot));
+ CmdTrbDisSlot.CycleBit = 1;
+ CmdTrbDisSlot.Type = TRB_TYPE_DIS_SLOT;
+ CmdTrbDisSlot.SlotId = SlotId;
+ Status = XhcCmdTransfer (
+ Xhc,
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbDisSlot,
+ XHC_GENERIC_TIMEOUT,
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb
+ );
+ ASSERT_EFI_ERROR(Status);
+ //
+ // Free the slot's device context entry
+ //
+ Xhc->DCBAA[SlotId] = 0;
+
+ //
+ // Free the slot related data structure
+ //
+ for (Index = 0; Index < 31; Index++) {
+ if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] != NULL) {
+ RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index])->RingSeg0;
+ if (RingSeg != NULL) {
+ FreePages (RingSeg, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER));
+ }
+ FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index]);
+ }
+ }
+
+ for (Index = 0; Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {
+ if (Xhc->UsbDevContext[SlotId].ConfDesc[Index] != NULL) {
+ FreePool (Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
+ }
+ }
+
+ if (Xhc->UsbDevContext[SlotId].InputContext != NULL) {
+ FreePages (Xhc->UsbDevContext[SlotId].InputContext, EFI_SIZE_TO_PAGES (sizeof (INPUT_CONTEXT_64)));
+ }
+
+ if (Xhc->UsbDevContext[SlotId].OutputContext != NULL) {
+ FreePages (Xhc->UsbDevContext[SlotId].OutputContext, EFI_SIZE_TO_PAGES (sizeof (DEVICE_CONTEXT_64)));
+ }
+ //
+ // Doesn't zero the entry because XhcAsyncInterruptTransfer() may be invoked to remove the established
+ // asynchronous interrupt pipe after the device is disabled. It needs the device address mapping info to
+ // remove urb from XHCI's asynchronous transfer list.
+ //
+ Xhc->UsbDevContext[SlotId].Enabled = FALSE;
+ Xhc->UsbDevContext[SlotId].SlotId = 0;
+
+ return Status;
+}
+
+
+/**
Configure all the device endpoints through XHCI's Configure_Endpoint cmd.
@param Xhc The XHCI Instance.
@@ -2125,6 +2438,199 @@ XhcSetConfigCmd (
}
/**
+ Configure all the device endpoints through XHCI's Configure_Endpoint cmd.
+
+ @param Xhc The XHCI Instance.
+ @param SlotId The slot id to be configured.
+ @param DeviceSpeed The device's speed.
+ @param ConfigDesc The pointer to the usb device configuration descriptor.
+
+ @retval EFI_SUCCESS Successfully configure all the device endpoints.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcSetConfigCmd64 (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN UINT8 SlotId,
+ IN UINT8 DeviceSpeed,
+ IN USB_CONFIG_DESCRIPTOR *ConfigDesc
+ )
+{
+ EFI_STATUS Status;
+
+ USB_INTERFACE_DESCRIPTOR *IfDesc;
+ USB_ENDPOINT_DESCRIPTOR *EpDesc;
+ UINT8 Index;
+ UINTN NumEp;
+ UINTN EpIndex;
+ UINT8 EpAddr;
+ UINT8 Direction;
+ UINT8 Dci;
+ UINT8 MaxDci;
+ UINT32 PhyAddr;
+ UINT8 Interval;
+
+ TRANSFER_RING *EndpointTransferRing;
+ CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;
+ INPUT_CONTEXT_64 *InputContext;
+ DEVICE_CONTEXT_64 *OutputContext;
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;
+ //
+ // 4.6.6 Configure Endpoint
+ //
+ InputContext = Xhc->UsbDevContext[SlotId].InputContext;
+ OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;
+ ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64));
+ CopyMem (&InputContext->Slot, &OutputContext->Slot, sizeof (SLOT_CONTEXT_64));
+
+ ASSERT (ConfigDesc != NULL);
+
+ MaxDci = 0;
+
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);
+ for (Index = 0; Index < ConfigDesc->NumInterfaces; Index++) {
+ while (IfDesc->DescriptorType != USB_DESC_TYPE_INTERFACE) {
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
+ }
+
+ NumEp = IfDesc->NumEndpoints;
+
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);
+ for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {
+ while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
+ }
+
+ EpAddr = (UINT8)(EpDesc->EndpointAddress & 0x0F);
+ Direction = (UINT8)((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut);
+
+ Dci = XhcEndpointToDci (EpAddr, Direction);
+ ASSERT (Dci < 32);
+ if (Dci > MaxDci) {
+ MaxDci = Dci;
+ }
+
+ InputContext->InputControlContext.Dword2 |= (BIT0 << Dci);
+ InputContext->EP[Dci-1].MaxPacketSize = EpDesc->MaxPacketSize;
+
+ if (DeviceSpeed == EFI_USB_SPEED_SUPER) {
+ //
+ // 6.2.3.4, shall be set to the value defined in the bMaxBurst field of the SuperSpeed Endpoint Companion Descriptor.
+ //
+ InputContext->EP[Dci-1].MaxBurstSize = 0x0;
+ } else {
+ InputContext->EP[Dci-1].MaxBurstSize = 0x0;
+ }
+
+ switch (EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK) {
+ case USB_ENDPOINT_BULK:
+ if (Direction == EfiUsbDataIn) {
+ InputContext->EP[Dci-1].CErr = 3;
+ InputContext->EP[Dci-1].EPType = ED_BULK_IN;
+ } else {
+ InputContext->EP[Dci-1].CErr = 3;
+ InputContext->EP[Dci-1].EPType = ED_BULK_OUT;
+ }
+
+ InputContext->EP[Dci-1].AverageTRBLength = 0x1000;
+ if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {
+ EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING));
+ Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;
+ CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]);
+ }
+
+ break;
+ case USB_ENDPOINT_ISO:
+ if (Direction == EfiUsbDataIn) {
+ InputContext->EP[Dci-1].CErr = 0;
+ InputContext->EP[Dci-1].EPType = ED_ISOCH_IN;
+ } else {
+ InputContext->EP[Dci-1].CErr = 0;
+ InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;
+ }
+ break;
+ case USB_ENDPOINT_INTERRUPT:
+ if (Direction == EfiUsbDataIn) {
+ InputContext->EP[Dci-1].CErr = 3;
+ InputContext->EP[Dci-1].EPType = ED_INTERRUPT_IN;
+ } else {
+ InputContext->EP[Dci-1].CErr = 3;
+ InputContext->EP[Dci-1].EPType = ED_INTERRUPT_OUT;
+ }
+ InputContext->EP[Dci-1].AverageTRBLength = 0x1000;
+ InputContext->EP[Dci-1].MaxESITPayload = EpDesc->MaxPacketSize;
+ //
+ // Get the bInterval from descriptor and init the the interval field of endpoint context
+ //
+ if ((DeviceSpeed == EFI_USB_SPEED_FULL) || (DeviceSpeed == EFI_USB_SPEED_LOW)) {
+ Interval = EpDesc->Interval;
+ //
+ // Hard code the interval to MAX first, need calculate through the bInterval field of Endpoint descriptor.
+ //
+ InputContext->EP[Dci-1].Interval = 6;
+ } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {
+ Interval = EpDesc->Interval;
+ ASSERT (Interval >= 1 && Interval <= 16);
+ //
+ // Refer to XHCI 1.0 spec section 6.2.3.6, table 61
+ //
+ InputContext->EP[Dci-1].Interval = Interval - 1;
+ InputContext->EP[Dci-1].AverageTRBLength = 0x1000;
+ InputContext->EP[Dci-1].MaxESITPayload = 0x0002;
+ InputContext->EP[Dci-1].MaxBurstSize = 0x0;
+ InputContext->EP[Dci-1].CErr = 3;
+ }
+
+ if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {
+ EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING));
+ Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;
+ CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]);
+ }
+ break;
+
+ case USB_ENDPOINT_CONTROL:
+ default:
+ ASSERT (0);
+ break;
+ }
+
+ PhyAddr = XHC_LOW_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0);
+ PhyAddr &= ~(0x0F);
+ PhyAddr |= ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;
+ InputContext->EP[Dci-1].PtrLo = PhyAddr;
+ InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0);
+
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
+ }
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
+ }
+
+ InputContext->InputControlContext.Dword2 |= BIT0;
+ InputContext->Slot.ContextEntries = MaxDci;
+ //
+ // configure endpoint
+ //
+ ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));
+ CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (InputContext);
+ CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (InputContext);
+ CmdTrbCfgEP.CycleBit = 1;
+ CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT;
+ CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId;
+ DEBUG ((EFI_D_INFO, "Configure Endpoint\n"));
+ Status = XhcCmdTransfer (
+ Xhc,
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP,
+ XHC_GENERIC_TIMEOUT,
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+
+/**
Evaluate the endpoint 0 context through XHCI's Evaluate_Context cmd.
@param Xhc The XHCI Instance.
@@ -2177,6 +2683,59 @@ XhcEvaluateContext (
}
/**
+ Evaluate the endpoint 0 context through XHCI's Evaluate_Context cmd.
+
+ @param Xhc The XHCI Instance.
+ @param SlotId The slot id to be evaluated.
+ @param MaxPacketSize The max packet size supported by the device control transfer.
+
+ @retval EFI_SUCCESS Successfully evaluate the device endpoint 0.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcEvaluateContext64 (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN UINT8 SlotId,
+ IN UINT32 MaxPacketSize
+ )
+{
+ EFI_STATUS Status;
+ CMD_TRB_EVALUATE_CONTEXT CmdTrbEvalu;
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;
+ INPUT_CONTEXT_64 *InputContext;
+
+ ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);
+
+ //
+ // 4.6.7 Evaluate Context
+ //
+ InputContext = Xhc->UsbDevContext[SlotId].InputContext;
+ ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64));
+
+ InputContext->InputControlContext.Dword2 |= BIT1;
+ InputContext->EP[0].MaxPacketSize = MaxPacketSize;
+
+ ZeroMem (&CmdTrbEvalu, sizeof (CmdTrbEvalu));
+ CmdTrbEvalu.PtrLo = XHC_LOW_32BIT (InputContext);
+ CmdTrbEvalu.PtrHi = XHC_HIGH_32BIT (InputContext);
+ CmdTrbEvalu.CycleBit = 1;
+ CmdTrbEvalu.Type = TRB_TYPE_EVALU_CONTXT;
+ CmdTrbEvalu.SlotId = Xhc->UsbDevContext[SlotId].SlotId;
+ DEBUG ((EFI_D_INFO, "Evaluate context\n"));
+ Status = XhcCmdTransfer (
+ Xhc,
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbEvalu,
+ XHC_GENERIC_TIMEOUT,
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb
+ );
+ ASSERT (!EFI_ERROR(Status));
+
+ return Status;
+}
+
+
+/**
Evaluate the slot context for hub device through XHCI's Configure_Endpoint cmd.
@param Xhc The XHCI Instance.
@@ -2242,3 +2801,70 @@ XhcConfigHubContext (
return Status;
}
+/**
+ Evaluate the slot context for hub device through XHCI's Configure_Endpoint cmd.
+
+ @param Xhc The XHCI Instance.
+ @param SlotId The slot id to be configured.
+ @param PortNum The total number of downstream port supported by the hub.
+ @param TTT The TT think time of the hub device.
+ @param MTT The multi-TT of the hub device.
+
+ @retval EFI_SUCCESS Successfully configure the hub device's slot context.
+
+**/
+EFI_STATUS
+XhcConfigHubContext64 (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN UINT8 SlotId,
+ IN UINT8 PortNum,
+ IN UINT8 TTT,
+ IN UINT8 MTT
+ )
+{
+ EFI_STATUS Status;
+
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;
+ INPUT_CONTEXT_64 *InputContext;
+ DEVICE_CONTEXT_64 *OutputContext;
+ CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;
+
+ ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);
+ InputContext = Xhc->UsbDevContext[SlotId].InputContext;
+ OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;
+
+ //
+ // 4.6.7 Evaluate Context
+ //
+ ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64));
+
+ InputContext->InputControlContext.Dword2 |= BIT0;
+
+ //
+ // Copy the slot context from OutputContext to Input context
+ //
+ CopyMem(&(InputContext->Slot), &(OutputContext->Slot), sizeof (SLOT_CONTEXT_64));
+ InputContext->Slot.Hub = 1;
+ InputContext->Slot.PortNum = PortNum;
+ InputContext->Slot.TTT = TTT;
+ InputContext->Slot.MTT = MTT;
+
+ ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));
+ CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (InputContext);
+ CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (InputContext);
+ CmdTrbCfgEP.CycleBit = 1;
+ CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT;
+ CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId;
+ DEBUG ((EFI_D_INFO, "Configure Hub Slot Context\n"));
+ Status = XhcCmdTransfer (
+ Xhc,
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP,
+ XHC_GENERIC_TIMEOUT,
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb
+ );
+ ASSERT (!EFI_ERROR(Status));
+
+ return Status;
+}
+
+
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
index 2090644e04..f319c56c60 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
@@ -111,6 +111,12 @@ typedef union _USB_DEV_ROUTE {
// Endpoint address and its capabilities
//
typedef struct _USB_ENDPOINT {
+ //
+ // Store logical device address assigned by UsbBus
+ // It's because some XHCI host controllers may assign the same physcial device
+ // address for those devices inserted at different root port.
+ //
+ UINT8 BusAddr;
UINT8 DevAddr;
UINT8 EpAddr;
EFI_USB_DATA_DIRECTION Direction;
@@ -144,7 +150,6 @@ typedef struct _TRANSFER_RING {
} TRANSFER_RING;
typedef struct _EVENT_RING {
- UINT32 EventInterrupter;
VOID *ERSTBase;
VOID *EventRingSeg0;
UINTN TrbNumber;
@@ -577,6 +582,46 @@ typedef struct _SLOT_CONTEXT {
UINT32 RsvdZ7;
} SLOT_CONTEXT;
+typedef struct _SLOT_CONTEXT_64 {
+ UINT32 RouteString:20;
+ UINT32 Speed:4;
+ UINT32 RsvdZ1:1;
+ UINT32 MTT:1;
+ UINT32 Hub:1;
+ UINT32 ContextEntries:5;
+
+ UINT32 MaxExitLatency:16;
+ UINT32 RootHubPortNum:8;
+ UINT32 PortNum:8;
+
+ UINT32 TTHubSlotId:8;
+ UINT32 TTPortNum:8;
+ UINT32 TTT:2;
+ UINT32 RsvdZ2:4;
+ UINT32 InterTarget:10;
+
+ UINT32 DeviceAddress:8;
+ UINT32 RsvdZ3:19;
+ UINT32 SlotState:5;
+
+ UINT32 RsvdZ4;
+ UINT32 RsvdZ5;
+ UINT32 RsvdZ6;
+ UINT32 RsvdZ7;
+
+ UINT32 RsvdZ8;
+ UINT32 RsvdZ9;
+ UINT32 RsvdZ10;
+ UINT32 RsvdZ11;
+
+ UINT32 RsvdZ12;
+ UINT32 RsvdZ13;
+ UINT32 RsvdZ14;
+ UINT32 RsvdZ15;
+
+} SLOT_CONTEXT_64;
+
+
//
// 6.2.3 Endpoint Context
//
@@ -609,6 +654,47 @@ typedef struct _ENDPOINT_CONTEXT {
UINT32 RsvdZ7;
} ENDPOINT_CONTEXT;
+typedef struct _ENDPOINT_CONTEXT_64 {
+ UINT32 EPState:3;
+ UINT32 RsvdZ1:5;
+ UINT32 Mult:2;
+ UINT32 MaxPStreams:5;
+ UINT32 LSA:1;
+ UINT32 Interval:8;
+ UINT32 RsvdZ2:8;
+
+ UINT32 RsvdZ3:1;
+ UINT32 CErr:2;
+ UINT32 EPType:3;
+ UINT32 RsvdZ4:1;
+ UINT32 HID:1;
+ UINT32 MaxBurstSize:8;
+ UINT32 MaxPacketSize:16;
+
+ UINT32 PtrLo;
+
+ UINT32 PtrHi;
+
+ UINT32 AverageTRBLength:16;
+ UINT32 MaxESITPayload:16;
+
+ UINT32 RsvdZ5;
+ UINT32 RsvdZ6;
+ UINT32 RsvdZ7;
+
+ UINT32 RsvdZ8;
+ UINT32 RsvdZ9;
+ UINT32 RsvdZ10;
+ UINT32 RsvdZ11;
+
+ UINT32 RsvdZ12;
+ UINT32 RsvdZ13;
+ UINT32 RsvdZ14;
+ UINT32 RsvdZ15;
+
+} ENDPOINT_CONTEXT_64;
+
+
//
// 6.2.5.1 Input Control Context
//
@@ -623,6 +709,25 @@ typedef struct _INPUT_CONTRL_CONTEXT {
UINT32 RsvdZ6;
} INPUT_CONTRL_CONTEXT;
+typedef struct _INPUT_CONTRL_CONTEXT_64 {
+ UINT32 Dword1;
+ UINT32 Dword2;
+ UINT32 RsvdZ1;
+ UINT32 RsvdZ2;
+ UINT32 RsvdZ3;
+ UINT32 RsvdZ4;
+ UINT32 RsvdZ5;
+ UINT32 RsvdZ6;
+ UINT32 RsvdZ7;
+ UINT32 RsvdZ8;
+ UINT32 RsvdZ9;
+ UINT32 RsvdZ10;
+ UINT32 RsvdZ11;
+ UINT32 RsvdZ12;
+ UINT32 RsvdZ13;
+ UINT32 RsvdZ14;
+} INPUT_CONTRL_CONTEXT_64;
+
//
// 6.2.1 Device Context
//
@@ -631,6 +736,11 @@ typedef struct _DEVICE_CONTEXT {
ENDPOINT_CONTEXT EP[31];
} DEVICE_CONTEXT;
+typedef struct _DEVICE_CONTEXT_64 {
+ SLOT_CONTEXT_64 Slot;
+ ENDPOINT_CONTEXT_64 EP[31];
+} DEVICE_CONTEXT_64;
+
//
// 6.2.5 Input Context
//
@@ -640,6 +750,13 @@ typedef struct _INPUT_CONTEXT {
ENDPOINT_CONTEXT EP[31];
} INPUT_CONTEXT;
+typedef struct _INPUT_CONTEXT_64 {
+ INPUT_CONTRL_CONTEXT_64 InputControlContext;
+ SLOT_CONTEXT_64 Slot;
+ ENDPOINT_CONTEXT_64 EP[31];
+} INPUT_CONTEXT_64;
+
+
/**
Initialize the XHCI host controller for schedule.
@@ -703,7 +820,7 @@ XhcExecTransfer (
the device and endpoint.
@param Xhc The XHCI Instance.
- @param DevAddr The address of the target device.
+ @param BusAddr The logical device address assigned by UsbBus driver.
@param EpNum The endpoint of the target.
@retval EFI_SUCCESS An asynchronous transfer is removed.
@@ -713,7 +830,7 @@ XhcExecTransfer (
EFI_STATUS
XhciDelAsyncIntTransfer (
IN USB_XHCI_INSTANCE *Xhc,
- IN UINT8 DevAddr,
+ IN UINT8 BusAddr,
IN UINT8 EpNum
);
@@ -751,21 +868,6 @@ XhcClearBiosOwnership (
);
/**
- Find out the slot id according to device address assigned by XHCI's Address_Device cmd.
-
- @param Xhc The XHCI Instance.
- @param DevAddr The device address of the target device.
-
- @return The slot id used by the device.
-
-**/
-UINT8
-XhcDevAddrToSlotId (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT8 DevAddr
- );
-
-/**
Find out the slot id according to the device's route string.
@param Xhc The XHCI Instance.
@@ -870,6 +972,29 @@ XhcConfigHubContext (
IN UINT8 MTT
);
+
+/**
+ Evaluate the slot context for hub device through XHCI's Configure_Endpoint cmd.
+
+ @param Xhc The XHCI Instance.
+ @param SlotId The slot id to be configured.
+ @param PortNum The total number of downstream port supported by the hub.
+ @param TTT The TT think time of the hub device.
+ @param MTT The multi-TT of the hub device.
+
+ @retval EFI_SUCCESS Successfully configure the hub device's slot context.
+
+**/
+EFI_STATUS
+XhcConfigHubContext64 (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN UINT8 SlotId,
+ IN UINT8 PortNum,
+ IN UINT8 TTT,
+ IN UINT8 MTT
+ );
+
+
/**
Configure all the device endpoints through XHCI's Configure_Endpoint cmd.
@@ -890,6 +1015,28 @@ XhcSetConfigCmd (
IN USB_CONFIG_DESCRIPTOR *ConfigDesc
);
+
+/**
+ Configure all the device endpoints through XHCI's Configure_Endpoint cmd.
+
+ @param Xhc The XHCI Instance.
+ @param SlotId The slot id to be configured.
+ @param DeviceSpeed The device's speed.
+ @param ConfigDesc The pointer to the usb device configuration descriptor.
+
+ @retval EFI_SUCCESS Successfully configure all the device endpoints.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcSetConfigCmd64 (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN UINT8 SlotId,
+ IN UINT8 DeviceSpeed,
+ IN USB_CONFIG_DESCRIPTOR *ConfigDesc
+ );
+
+
/**
Find out the actual device address according to the requested device address from UsbBus.
@@ -929,6 +1076,28 @@ XhcInitializeDeviceSlot (
);
/**
+ Assign and initialize the device slot for a new device.
+
+ @param Xhc The XHCI Instance.
+ @param ParentRouteChart The route string pointed to the parent device.
+ @param ParentPort The port at which the device is located.
+ @param RouteChart The route string pointed to the device.
+ @param DeviceSpeed The device speed.
+
+ @retval EFI_SUCCESS Successfully assign a slot to the device and assign an address to it.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcInitializeDeviceSlot64 (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN USB_DEV_ROUTE ParentRouteChart,
+ IN UINT16 ParentPort,
+ IN USB_DEV_ROUTE RouteChart,
+ IN UINT8 DeviceSpeed
+ );
+
+/**
Evaluate the endpoint 0 context through XHCI's Evaluate_Context cmd.
@param Xhc The XHCI Instance.
@@ -946,6 +1115,26 @@ XhcEvaluateContext (
IN UINT32 MaxPacketSize
);
+
+/**
+ Evaluate the endpoint 0 context through XHCI's Evaluate_Context cmd.
+
+ @param Xhc The XHCI Instance.
+ @param SlotId The slot id to be evaluated.
+ @param MaxPacketSize The max packet size supported by the device control transfer.
+
+ @retval EFI_SUCCESS Successfully evaluate the device endpoint 0.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcEvaluateContext64 (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN UINT8 SlotId,
+ IN UINT32 MaxPacketSize
+ );
+
+
/**
Disable the specified device slot.
@@ -962,6 +1151,24 @@ XhcDisableSlotCmd (
IN UINT8 SlotId
);
+
+/**
+ Disable the specified device slot.
+
+ @param Xhc The XHCI Instance.
+ @param SlotId The slot id to be disabled.
+
+ @retval EFI_SUCCESS Successfully disable the device slot.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcDisableSlotCmd64 (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN UINT8 SlotId
+ );
+
+
/**
Synchronize the specified transfer ring to update the enqueue and dequeue pointer.
@@ -1032,14 +1239,12 @@ CreateTransferRing (
Create XHCI event ring.
@param Xhc The XHCI Instance.
- @param EventInterrupter The interrupter of event.
@param EventRing The created event ring.
**/
VOID
CreateEventRing (
IN USB_XHCI_INSTANCE *Xhc,
- IN UINT8 EventInterrupter,
OUT EVENT_RING *EventRing
);
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
index 30bf43cb36..e8f9ed5018 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
@@ -1431,7 +1431,6 @@ UsbBusControllerDriverStop (
// BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
//
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- UsbHcSetState (Bus, EfiUsbHcStateHalt);
RootHub = Bus->Devices[0];
RootIf = RootHub->Interfaces[0];