summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c')
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c95
1 files changed, 63 insertions, 32 deletions
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
index 443df729d..5ca58fbb9 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
@@ -32,6 +32,13 @@ USB_PORT_STATE_MAP mUsbPortChangeMap[] = {
{XHC_PORTSC_PRC, USB_PORT_STAT_C_RESET}
};
+USB_CLEAR_PORT_MAP mUsbClearPortChangeMap[] = {
+ {XHC_PORTSC_CSC, EfiUsbPortConnectChange},
+ {XHC_PORTSC_PEC, EfiUsbPortEnableChange},
+ {XHC_PORTSC_OCC, EfiUsbPortOverCurrentChange},
+ {XHC_PORTSC_PRC, EfiUsbPortResetChange}
+};
+
USB_PORT_STATE_MAP mUsbHubPortStateMap[] = {
{XHC_HUB_PORTSC_CCS, USB_PORT_STAT_CONNECTION},
{XHC_HUB_PORTSC_PED, USB_PORT_STAT_ENABLE},
@@ -46,6 +53,14 @@ USB_PORT_STATE_MAP mUsbHubPortChangeMap[] = {
{XHC_HUB_PORTSC_PRC, USB_PORT_STAT_C_RESET}
};
+USB_CLEAR_PORT_MAP mUsbHubClearPortChangeMap[] = {
+ {XHC_HUB_PORTSC_CSC, EfiUsbPortConnectChange},
+ {XHC_HUB_PORTSC_PEC, EfiUsbPortEnableChange},
+ {XHC_HUB_PORTSC_OCC, EfiUsbPortOverCurrentChange},
+ {XHC_HUB_PORTSC_PRC, EfiUsbPortResetChange},
+ {XHC_HUB_PORTSC_BHRC, Usb3PortBHPortResetChange}
+};
+
EFI_DRIVER_BINDING_PROTOCOL gXhciDriverBinding = {
XhcDriverBindingSupported,
XhcDriverBindingStart,
@@ -432,6 +447,14 @@ XhcGetRootHubPortStatus (
}
}
+ MapSize = sizeof (mUsbClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);
+
+ for (Index = 0; Index < MapSize; Index++) {
+ if (XHC_BIT_IS_SET (State, mUsbClearPortChangeMap[Index].HwState)) {
+ XhcClearRootHubPortFeature (This, PortNumber, mUsbClearPortChangeMap[Index].Selector);
+ }
+ }
+
//
// Poll the root port status register to enable/disable corresponding device slot if there is a device attached/detached.
// For those devices behind hub, we get its attach/detach event by hooking Get_Port_Status request at control transfer for those hub.
@@ -469,8 +492,6 @@ XhcSetRootHubPortFeature (
UINT32 Offset;
UINT32 State;
UINT32 TotalPort;
- UINT8 SlotId;
- USB_DEV_ROUTE RouteChart;
EFI_STATUS Status;
EFI_TPL OldTpl;
@@ -526,24 +547,13 @@ XhcSetRootHubPortFeature (
}
}
- RouteChart.Route.RouteString = 0;
- RouteChart.Route.RootPortNum = PortNumber + 1;
- RouteChart.Route.TierNum = 1;
//
- // If the port reset operation happens after the usb super speed device is enabled,
- // The subsequent configuration, such as getting device descriptor, will fail.
- // So here a workaround is introduced to skip the reset operation if the device is enabled.
+ // 4.3.1 Resetting a Root Hub Port
+ // 1) Write the PORTSC register with the Port Reset (PR) bit set to '1'.
//
- SlotId = XhcRouteStringToSlotId (Xhc, RouteChart);
- if (SlotId == 0) {
- //
- // 4.3.1 Resetting a Root Hub Port
- // 1) Write the PORTSC register with the Port Reset (PR) bit set to '1'.
- //
- State |= XHC_PORTSC_RESET;
- XhcWriteOpReg (Xhc, Offset, State);
- XhcWaitOpRegBit(Xhc, Offset, XHC_PORTSC_PRC, TRUE, XHC_GENERIC_TIMEOUT);
- }
+ State |= XHC_PORTSC_RESET;
+ XhcWriteOpReg (Xhc, Offset, State);
+ XhcWaitOpRegBit(Xhc, Offset, XHC_PORTSC_PRC, TRUE, XHC_GENERIC_TIMEOUT);
break;
case EfiUsbPortPower:
@@ -763,6 +773,8 @@ XhcControlTransfer (
UINTN MapSize;
EFI_USB_PORT_STATUS PortStatus;
UINT32 State;
+ EFI_USB_DEVICE_REQUEST ClearPortRequest;
+ UINTN Len;
//
// Validate parameters
@@ -808,6 +820,7 @@ XhcControlTransfer (
Status = EFI_DEVICE_ERROR;
*TransferResult = EFI_USB_ERR_SYSTEM;
+ Len = 0;
if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
DEBUG ((EFI_D_ERROR, "XhcControlTransfer: HC halted at entrance\n"));
@@ -839,6 +852,11 @@ XhcControlTransfer (
Xhc->UsbDevContext[Index + 1].BusDevAddr = 0;
}
}
+
+ if (Xhc->UsbDevContext[SlotId].XhciDevAddr == 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
//
// The actual device address has been assigned by XHCI during initializing the device slot.
// So we just need establish the mapping relationship between the device address requested from UsbBus
@@ -849,20 +867,6 @@ XhcControlTransfer (
Status = EFI_SUCCESS;
goto ON_EXIT;
}
-
- //
- // If the port reset operation happens after the usb super speed device is enabled,
- // The subsequent configuration, such as getting device descriptor, will fail.
- // So here a workaround is introduced to skip the reset operation if the device is enabled.
- //
- if ((Request->Request == USB_REQ_SET_FEATURE) &&
- (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER)) &&
- (Request->Value == EfiUsbPortReset)) {
- if (DeviceSpeed == EFI_USB_SPEED_SUPER) {
- Status = EFI_SUCCESS;
- goto ON_EXIT;
- }
- }
//
// Create a new URB, insert it into the asynchronous
@@ -1050,6 +1054,33 @@ XhcControlTransfer (
}
}
+ MapSize = sizeof (mUsbHubClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);
+
+ for (Index = 0; Index < MapSize; Index++) {
+ if (XHC_BIT_IS_SET (State, mUsbHubClearPortChangeMap[Index].HwState)) {
+ ZeroMem (&ClearPortRequest, sizeof (EFI_USB_DEVICE_REQUEST));
+ ClearPortRequest.RequestType = USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER);
+ ClearPortRequest.Request = (UINT8) USB_REQ_CLEAR_FEATURE;
+ ClearPortRequest.Value = mUsbHubClearPortChangeMap[Index].Selector;
+ ClearPortRequest.Index = Request->Index;
+ ClearPortRequest.Length = 0;
+
+ XhcControlTransfer (
+ This,
+ DeviceAddress,
+ DeviceSpeed,
+ MaximumPacketLength,
+ &ClearPortRequest,
+ EfiUsbNoData,
+ NULL,
+ &Len,
+ Timeout,
+ Translator,
+ TransferResult
+ );
+ }
+ }
+
XhcPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);
*(UINT32 *)Data = *(UINT32*)&PortStatus;