X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FBus%2FPci%2FXhciDxe%2FXhci.c;h=43c53bad4e4a654f4ca10c9d50a6a6d85327054e;hb=9d510e61fceee7b92955ef9a3c20343752d8ce3f;hp=3224202bfe45c8d2cf6b4bfbc3699e8fd87a48f4;hpb=6e1e5405544724406f07344a5911298c3df44129;p=mirror_edk2.git
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
index 3224202bfe..43c53bad4e 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
@@ -1,14 +1,8 @@
/** @file
The XHCI controller driver.
-Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -125,7 +119,7 @@ XhcGetCapability (
Xhc = XHC_FROM_THIS (This);
*MaxSpeed = EFI_USB_SPEED_SUPER;
*PortNumber = (UINT8) (Xhc->HcSParams1.Data.MaxPorts);
- *Is64BitCapable = (UINT8) (Xhc->HcCParams.Data.Ac64);
+ *Is64BitCapable = (UINT8) Xhc->Support64BitDma;
DEBUG ((EFI_D_INFO, "XhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));
gBS->RestoreTPL (OldTpl);
@@ -159,7 +153,7 @@ XhcReset (
EFI_TPL OldTpl;
Xhc = XHC_FROM_THIS (This);
-
+
if (Xhc->DevicePath != NULL) {
//
// Report Status Code to indicate reset happens
@@ -169,7 +163,7 @@ XhcReset (
(EFI_IO_BUS_USB | EFI_IOB_PC_RESET),
Xhc->DevicePath
);
- }
+ }
OldTpl = gBS->RaiseTPL (XHC_TPL);
@@ -403,7 +397,8 @@ XhcGetRootHubPortStatus (
State = XhcReadOpReg (Xhc, Offset);
//
- // According to XHCI 1.0 spec, bit 10~13 of the root port status register identifies the speed of the attached device.
+ // According to XHCI 1.1 spec November 2017,
+ // bit 10~13 of the root port status register identifies the speed of the attached device.
//
switch ((State & XHC_PORTSC_PS) >> 10) {
case 2:
@@ -415,6 +410,7 @@ XhcGetRootHubPortStatus (
break;
case 4:
+ case 5:
PortStatus->PortStatus |= USB_PORT_STAT_SUPER_SPEED;
break;
@@ -716,6 +712,103 @@ ON_EXIT:
return Status;
}
+/**
+ Submits a new transaction to a target USB device.
+
+ @param Xhc The XHCI Instance.
+ @param DeviceAddress The target device address.
+ @param EndPointAddress Endpoint number and its direction encoded in bit 7
+ @param DeviceSpeed Target device speed.
+ @param MaximumPacketLength Maximum packet size the default control transfer
+ endpoint is capable of sending or receiving.
+ @param Type The transaction type.
+ @param Request USB device request to send.
+ @param Data Data buffer to be transmitted or received from USB
+ device.
+ @param DataLength The size (in bytes) of the data buffer.
+ @param Timeout Indicates the maximum timeout, in millisecond.
+ @param TransferResult Return the result of this control transfer.
+
+ @retval EFI_SUCCESS Transfer was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+ @retval EFI_TIMEOUT Transfer failed due to timeout.
+ @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
+**/
+EFI_STATUS
+XhcTransfer (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINTN Type,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN Timeout,
+ OUT UINT32 *TransferResult
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS RecoveryStatus;
+ URB *Urb;
+
+ ASSERT ((Type == XHC_CTRL_TRANSFER) || (Type == XHC_BULK_TRANSFER) || (Type == XHC_INT_TRANSFER_SYNC));
+ Urb = XhcCreateUrb (
+ Xhc,
+ DeviceAddress,
+ EndPointAddress,
+ DeviceSpeed,
+ MaximumPacketLength,
+ Type,
+ Request,
+ Data,
+ *DataLength,
+ NULL,
+ NULL
+ );
+
+ if (Urb == NULL) {
+ DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: failed to create URB!\n", Type));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
+
+ if (Status == EFI_TIMEOUT) {
+ //
+ // The transfer timed out. Abort the transfer by dequeueing of the TD.
+ //
+ RecoveryStatus = XhcDequeueTrbFromEndpoint(Xhc, Urb);
+ if (RecoveryStatus == EFI_ALREADY_STARTED) {
+ //
+ // The URB is finished just before stopping endpoint.
+ // Change returning status from EFI_TIMEOUT to EFI_SUCCESS.
+ //
+ ASSERT (Urb->Result == EFI_USB_NOERROR);
+ Status = EFI_SUCCESS;
+ DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: pending URB is finished, Length = %d.\n", Type, Urb->Completed));
+ } else if (EFI_ERROR(RecoveryStatus)) {
+ DEBUG((DEBUG_ERROR, "XhcTransfer[Type=%d]: XhcDequeueTrbFromEndpoint failed!\n", Type));
+ }
+ }
+
+ *TransferResult = Urb->Result;
+ *DataLength = Urb->Completed;
+
+ if ((*TransferResult == EFI_USB_ERR_STALL) || (*TransferResult == EFI_USB_ERR_BABBLE)) {
+ ASSERT (Status == EFI_DEVICE_ERROR);
+ RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
+ if (EFI_ERROR (RecoveryStatus)) {
+ DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: XhcRecoverHaltedEndpoint failed!\n", Type));
+ }
+ }
+
+ Xhc->PciIo->Flush (Xhc->PciIo);
+ XhcFreeUrb (Xhc, Urb);
+ return Status;
+}
/**
Submits control transfer to a target USB device.
@@ -758,7 +851,6 @@ XhcControlTransfer (
)
{
USB_XHCI_INSTANCE *Xhc;
- URB *Urb;
UINT8 Endpoint;
UINT8 Index;
UINT8 DescriptorType;
@@ -769,7 +861,6 @@ XhcControlTransfer (
EFI_USB_HUB_DESCRIPTOR *HubDesc;
EFI_TPL OldTpl;
EFI_STATUS Status;
- EFI_STATUS RecoveryStatus;
UINTN MapSize;
EFI_USB_PORT_STATUS PortStatus;
UINT32 State;
@@ -876,66 +967,31 @@ XhcControlTransfer (
// combination of Ep addr and its direction.
//
Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
- Urb = XhcCreateUrb (
- Xhc,
- DeviceAddress,
- Endpoint,
- DeviceSpeed,
- MaximumPacketLength,
- XHC_CTRL_TRANSFER,
- Request,
- Data,
- *DataLength,
- NULL,
- NULL
- );
+ Status = XhcTransfer (
+ Xhc,
+ DeviceAddress,
+ Endpoint,
+ DeviceSpeed,
+ MaximumPacketLength,
+ XHC_CTRL_TRANSFER,
+ Request,
+ Data,
+ DataLength,
+ Timeout,
+ TransferResult
+ );
- if (Urb == NULL) {
- DEBUG ((EFI_D_ERROR, "XhcControlTransfer: failed to create URB"));
- Status = EFI_OUT_OF_RESOURCES;
+ if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
- Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
-
- //
- // Get the status from URB. The result is updated in XhcCheckUrbResult
- // which is called by XhcExecTransfer
- //
- *TransferResult = Urb->Result;
- *DataLength = Urb->Completed;
-
- if (*TransferResult == EFI_USB_NOERROR) {
- Status = EFI_SUCCESS;
- } else if (*TransferResult == EFI_USB_ERR_STALL) {
- RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
- if (EFI_ERROR (RecoveryStatus)) {
- DEBUG ((EFI_D_ERROR, "XhcControlTransfer: XhcRecoverHaltedEndpoint failed\n"));
- }
- Status = EFI_DEVICE_ERROR;
- goto FREE_URB;
- } else {
- goto FREE_URB;
- }
-
- Xhc->PciIo->Flush (Xhc->PciIo);
-
- if (Urb->DataMap != NULL) {
- Status = Xhc->PciIo->Unmap (Xhc->PciIo, Urb->DataMap);
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- goto FREE_URB;
- }
- }
-
//
// Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.
// Hook Get_Status request form UsbBus as we need trace device attach/detach event happened at hub.
// Hook Set_Config request from UsbBus as we need configure device endpoint.
//
if ((Request->Request == USB_REQ_GET_DESCRIPTOR) &&
- ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)) ||
+ ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)) ||
((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_DEVICE))))) {
DescriptorType = (UINT8)(Request->Value >> 8);
if ((DescriptorType == USB_DESC_TYPE_DEVICE) && ((*DataLength == sizeof (EFI_USB_DEVICE_DESCRIPTOR)) || ((DeviceSpeed == EFI_USB_SPEED_FULL) && (*DataLength == 8)))) {
@@ -944,7 +1000,7 @@ XhcControlTransfer (
// Store a copy of device scriptor as hub device need this info to configure endpoint.
//
CopyMem (&Xhc->UsbDevContext[SlotId].DevDesc, Data, *DataLength);
- if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB == 0x0300) {
+ if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB >= 0x0300) {
//
// If it's a usb3.0 device, then its max packet size is a 2^n.
//
@@ -1084,7 +1140,7 @@ XhcControlTransfer (
ClearPortRequest.Length = 0;
XhcControlTransfer (
- This,
+ This,
DeviceAddress,
DeviceSpeed,
MaximumPacketLength,
@@ -1104,11 +1160,7 @@ XhcControlTransfer (
*(UINT32 *)Data = *(UINT32*)&PortStatus;
}
-FREE_URB:
- FreePool (Urb);
-
ON_EXIT:
-
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
}
@@ -1167,10 +1219,8 @@ XhcBulkTransfer (
)
{
USB_XHCI_INSTANCE *Xhc;
- URB *Urb;
UINT8 SlotId;
EFI_STATUS Status;
- EFI_STATUS RecoveryStatus;
EFI_TPL OldTpl;
//
@@ -1216,46 +1266,21 @@ XhcBulkTransfer (
// Create a new URB, insert it into the asynchronous
// schedule list, then poll the execution status.
//
- Urb = XhcCreateUrb (
- Xhc,
- DeviceAddress,
- EndPointAddress,
- DeviceSpeed,
- MaximumPacketLength,
- XHC_BULK_TRANSFER,
- NULL,
- Data[0],
- *DataLength,
- NULL,
- NULL
- );
-
- if (Urb == NULL) {
- DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: failed to create URB\n"));
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_EXIT;
- }
-
- Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
-
- *TransferResult = Urb->Result;
- *DataLength = Urb->Completed;
-
- if (*TransferResult == EFI_USB_NOERROR) {
- Status = EFI_SUCCESS;
- } else if (*TransferResult == EFI_USB_ERR_STALL) {
- RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
- if (EFI_ERROR (RecoveryStatus)) {
- DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: XhcRecoverHaltedEndpoint failed\n"));
- }
- Status = EFI_DEVICE_ERROR;
- }
-
- Xhc->PciIo->Flush (Xhc->PciIo);
- XhcFreeUrb (Xhc, Urb);
+ Status = XhcTransfer (
+ Xhc,
+ DeviceAddress,
+ EndPointAddress,
+ DeviceSpeed,
+ MaximumPacketLength,
+ XHC_BULK_TRANSFER,
+ NULL,
+ Data[0],
+ DataLength,
+ Timeout,
+ TransferResult
+ );
ON_EXIT:
-
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
}
@@ -1315,7 +1340,6 @@ XhcAsyncInterruptTransfer (
EFI_STATUS Status;
UINT8 SlotId;
UINT8 Index;
- UINT8 *Data;
EFI_TPL OldTpl;
//
@@ -1382,36 +1406,21 @@ XhcAsyncInterruptTransfer (
goto ON_EXIT;
}
- Data = AllocateZeroPool (DataLength);
-
- if (Data == NULL) {
- DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to allocate buffer\n"));
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_EXIT;
- }
-
- Urb = XhcCreateUrb (
+ Urb = XhciInsertAsyncIntTransfer (
Xhc,
DeviceAddress,
EndPointAddress,
DeviceSpeed,
MaximumPacketLength,
- XHC_INT_TRANSFER_ASYNC,
- NULL,
- Data,
DataLength,
CallBackFunction,
Context
);
-
if (Urb == NULL) {
- DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to create URB\n"));
- FreePool (Data);
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
- InsertHeadList (&Xhc->AsyncIntTransfers, &Urb->UrbList);
//
// Ring the doorbell
//
@@ -1469,10 +1478,8 @@ XhcSyncInterruptTransfer (
)
{
USB_XHCI_INSTANCE *Xhc;
- URB *Urb;
UINT8 SlotId;
EFI_STATUS Status;
- EFI_STATUS RecoveryStatus;
EFI_TPL OldTpl;
//
@@ -1483,10 +1490,6 @@ XhcSyncInterruptTransfer (
return EFI_INVALID_PARAMETER;
}
- if (!XHCI_IS_DATAIN (EndPointAddress)) {
- return EFI_INVALID_PARAMETER;
- }
-
if ((*DataToggle != 1) && (*DataToggle != 0)) {
return EFI_INVALID_PARAMETER;
}
@@ -1517,43 +1520,19 @@ XhcSyncInterruptTransfer (
goto ON_EXIT;
}
- Urb = XhcCreateUrb (
- Xhc,
- DeviceAddress,
- EndPointAddress,
- DeviceSpeed,
- MaximumPacketLength,
- XHC_INT_TRANSFER_SYNC,
- NULL,
- Data,
- *DataLength,
- NULL,
- NULL
- );
-
- if (Urb == NULL) {
- DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: failed to create URB\n"));
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_EXIT;
- }
-
- Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
-
- *TransferResult = Urb->Result;
- *DataLength = Urb->Completed;
-
- if (*TransferResult == EFI_USB_NOERROR) {
- Status = EFI_SUCCESS;
- } else if (*TransferResult == EFI_USB_ERR_STALL) {
- RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
- if (EFI_ERROR (RecoveryStatus)) {
- DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: XhcRecoverHaltedEndpoint failed\n"));
- }
- Status = EFI_DEVICE_ERROR;
- }
-
- Xhc->PciIo->Flush (Xhc->PciIo);
- XhcFreeUrb (Xhc, Urb);
+ Status = XhcTransfer (
+ Xhc,
+ DeviceAddress,
+ EndPointAddress,
+ DeviceSpeed,
+ MaximumPacketLength,
+ XHC_INT_TRANSFER_SYNC,
+ NULL,
+ Data,
+ DataLength,
+ Timeout,
+ TransferResult
+ );
ON_EXIT:
if (EFI_ERROR (Status)) {
@@ -1771,6 +1750,7 @@ XhcCreateUsbHc (
EFI_STATUS Status;
UINT32 PageSize;
UINT16 ExtCapReg;
+ UINT8 ReleaseNumber;
Xhc = AllocateZeroPool (sizeof (USB_XHCI_INSTANCE));
@@ -1787,6 +1767,19 @@ XhcCreateUsbHc (
Xhc->OriginalPciAttributes = OriginalPciAttributes;
CopyMem (&Xhc->Usb2Hc, &gXhciUsb2HcTemplate, sizeof (EFI_USB2_HC_PROTOCOL));
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ XHC_PCI_SBRN_OFFSET,
+ 1,
+ &ReleaseNumber
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Xhc->Usb2Hc.MajorRevision = (ReleaseNumber & 0xF0) >> 4;
+ Xhc->Usb2Hc.MinorRevision = (ReleaseNumber & 0x0F);
+ }
+
InitializeListHead (&Xhc->AsyncIntTransfers);
//
@@ -1826,7 +1819,7 @@ XhcCreateUsbHc (
//
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
+ TPL_NOTIFY,
XhcMonitorAsyncRequests,
Xhc,
&Xhc->PollTimer
@@ -1993,6 +1986,26 @@ XhcDriverBindingStart (
return EFI_OUT_OF_RESOURCES;
}
+ //
+ // Enable 64-bit DMA support in the PCI layer if this controller
+ // supports it.
+ //
+ if (Xhc->HcCParams.Data.Ac64 != 0) {
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
+ NULL
+ );
+ if (!EFI_ERROR (Status)) {
+ Xhc->Support64BitDma = TRUE;
+ } else {
+ DEBUG ((EFI_D_WARN,
+ "%a: failed to enable 64-bit DMA on 64-bit capable controller @ %p (%r)\n",
+ __FUNCTION__, Controller, Status));
+ }
+ }
+
XhcSetBiosOwnership (Xhc);
XhcResetHC (Xhc, XHC_RESET_TIMEOUT);
@@ -2102,7 +2115,7 @@ CLOSE_PCIIO:
/**
- Stop this driver on ControllerHandle. Support stoping any child handles
+ Stop this driver on ControllerHandle. Support stopping any child handles
created by this driver.
@param This Protocol instance pointer.