]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
1) remove wrong global variable usage because it will bring data corrupt if there...
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / XhciDxe / Xhci.c
index 61c4b2427fa3aebff6d818b85ad4eaee7094883a..bbde0ca0b775a5fbcf52a1ab300aed464a77ceb7 100644 (file)
@@ -14,11 +14,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "Xhci.h"\r
 \r
-//\r
-// The device context array which supports up to 255 devices, entry 0 is reserved and should not be used.\r
-//\r
-USB_DEV_CONTEXT UsbDevContext[256];\r
-\r
 //\r
 // Two arrays used to translate the XHCI port state (change)\r
 // to the UEFI protocol's port state (change).\r
@@ -46,6 +41,27 @@ EFI_DRIVER_BINDING_PROTOCOL  gXhciDriverBinding = {
   NULL\r
 };\r
 \r
+//\r
+// Template for Xhci's Usb2 Host Controller Protocol Instance.\r
+//\r
+EFI_USB2_HC_PROTOCOL gXhciUsb2HcTemplate = {\r
+  XhcGetCapability,\r
+  XhcReset,\r
+  XhcGetState,\r
+  XhcSetState,\r
+  XhcControlTransfer,\r
+  XhcBulkTransfer,\r
+  XhcAsyncInterruptTransfer,\r
+  XhcSyncInterruptTransfer,\r
+  XhcIsochronousTransfer,\r
+  XhcAsyncIsochronousTransfer,\r
+  XhcGetRootHubPortStatus,\r
+  XhcSetRootHubPortFeature,\r
+  XhcClearRootHubPortFeature,\r
+  0x3,\r
+  0x0\r
+};\r
+\r
 /**\r
   Retrieves the capability of root hub ports.\r
 \r
@@ -68,8 +84,8 @@ XhcGetCapability (
   OUT UINT8                 *Is64BitCapable\r
   )\r
 {\r
-  USB_XHCI_DEV    *Xhc;\r
-  EFI_TPL         OldTpl;\r
+  USB_XHCI_INSTANCE  *Xhc;\r
+  EFI_TPL            OldTpl;\r
 \r
   if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -109,9 +125,9 @@ XhcReset (
   IN UINT16                Attributes\r
   )\r
 {\r
-  USB_XHCI_DEV    *Xhc;\r
-  EFI_STATUS      Status;\r
-  EFI_TPL         OldTpl;\r
+  USB_XHCI_INSTANCE  *Xhc;\r
+  EFI_STATUS         Status;\r
+  EFI_TPL            OldTpl;\r
 \r
   OldTpl = gBS->RaiseTPL (XHC_TPL);\r
 \r
@@ -188,8 +204,8 @@ XhcGetState (
   OUT EFI_USB_HC_STATE      *State\r
   )\r
 {\r
-  USB_XHCI_DEV    *Xhc;\r
-  EFI_TPL         OldTpl;\r
+  USB_XHCI_INSTANCE  *Xhc;\r
+  EFI_TPL            OldTpl;\r
 \r
   if (State == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -230,7 +246,7 @@ XhcSetState (
   IN EFI_USB_HC_STATE      State\r
   )\r
 {\r
-  USB_XHCI_DEV        *Xhc;\r
+  USB_XHCI_INSTANCE   *Xhc;\r
   EFI_STATUS          Status;\r
   EFI_USB_HC_STATE    CurState;\r
   EFI_TPL             OldTpl;\r
@@ -309,7 +325,7 @@ XhcGetRootHubPortStatus (
   OUT EFI_USB_PORT_STATUS   *PortStatus\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
   UINT32                  Offset;\r
   UINT32                  State;\r
   UINT32                  TotalPort;\r
@@ -419,7 +435,7 @@ XhcSetRootHubPortFeature (
   IN EFI_USB_PORT_FEATURE  PortFeature\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
   UINT32                  Offset;\r
   UINT32                  State;\r
   UINT32                  TotalPort;\r
@@ -480,15 +496,15 @@ XhcSetRootHubPortFeature (
       }\r
     }\r
 \r
-    RouteChart.Field.RouteString = 0;\r
-    RouteChart.Field.RootPortNum = PortNumber + 1;\r
-    RouteChart.Field.TierNum     = 1;\r
+    RouteChart.Route.RouteString = 0;\r
+    RouteChart.Route.RootPortNum = PortNumber + 1;\r
+    RouteChart.Route.TierNum     = 1;\r
     //\r
-    // BUGBUG: If the port reset operation happens after the usb super speed device is enabled,\r
+    // If the port reset operation happens after the usb super speed device is enabled,\r
     // The subsequent configuration, such as getting device descriptor, will fail.\r
     // So here a workaround is introduced to skip the reset operation if the device is enabled.\r
     //\r
-    SlotId = XhcRouteStringToSlotId (RouteChart);\r
+    SlotId = XhcRouteStringToSlotId (Xhc, RouteChart);\r
     if (SlotId == 0) {\r
       //\r
       // 4.3.1 Resetting a Root Hub Port\r
@@ -549,7 +565,7 @@ XhcClearRootHubPortFeature (
   IN EFI_USB_PORT_FEATURE  PortFeature\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
   UINT32                  Offset;\r
   UINT32                  State;\r
   UINT32                  TotalPort;\r
@@ -674,7 +690,7 @@ ON_EXIT:
   @param  Data                  Data buffer to be transmitted or received from USB\r
                                 device.\r
   @param  DataLength            The size (in bytes) of the data buffer.\r
-  @param  TimeOut               Indicates the maximum timeout, in millisecond.\r
+  @param  Timeout               Indicates the maximum timeout, in millisecond.\r
   @param  Translator            Transaction translator to be used by this device.\r
   @param  TransferResult        Return the result of this control transfer.\r
 \r
@@ -696,12 +712,12 @@ XhcControlTransfer (
   IN     EFI_USB_DATA_DIRECTION              TransferDirection,\r
   IN OUT VOID                                *Data,\r
   IN OUT UINTN                               *DataLength,\r
-  IN     UINTN                               TimeOut,\r
+  IN     UINTN                               Timeout,\r
   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
   OUT    UINT32                              *TransferResult\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
   URB                     *Urb;\r
   UINT8                   Endpoint;\r
   UINT8                   Index;\r
@@ -772,7 +788,7 @@ XhcControlTransfer (
   //\r
   // Check if the device is still enabled before every transaction.\r
   //\r
-  SlotId = XhcBusDevAddrToSlotId (DeviceAddress);\r
+  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
   if (SlotId == 0) {\r
     goto ON_EXIT;\r
   }\r
@@ -780,22 +796,23 @@ XhcControlTransfer (
   //\r
   // Acquire the actual device address assigned by XHCI's Address_Device cmd.\r
   //\r
-  XhciDevAddr = UsbDevContext[SlotId].XhciDevAddr;\r
+  XhciDevAddr = Xhc->UsbDevContext[SlotId].XhciDevAddr;\r
 \r
   //\r
   // Hook the Set_Address request from UsbBus.\r
   // According to XHCI 1.0 spec, the Set_Address request is replaced by XHCI's Address_Device cmd.\r
   //\r
-  if (Request->Request == USB_REQ_SET_ADDRESS) {\r
+  if ((Request->Request     == USB_REQ_SET_ADDRESS) &&\r
+      (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {\r
     //\r
     // Reset the BusDevAddr field of all disabled entries in UsbDevContext array firstly.\r
     // This way is used to clean the history to avoid using wrong device address by XhcAsyncInterruptTransfer().\r
     //\r
     for (Index = 0; Index < 255; Index++) {\r
-      if (!UsbDevContext[Index + 1].Enabled &&\r
-          (UsbDevContext[Index + 1].SlotId != 0) &&\r
-          (UsbDevContext[Index + 1].BusDevAddr == (UINT8)Request->Value)) {\r
-        UsbDevContext[Index + 1].BusDevAddr = 0;\r
+      if (!Xhc->UsbDevContext[Index + 1].Enabled &&\r
+          (Xhc->UsbDevContext[Index + 1].SlotId != 0) &&\r
+          (Xhc->UsbDevContext[Index + 1].BusDevAddr == (UINT8)Request->Value)) {\r
+        Xhc->UsbDevContext[Index + 1].BusDevAddr = 0;\r
       }\r
     }\r
     //\r
@@ -804,18 +821,19 @@ XhcControlTransfer (
     // and the actual device address assigned by XHCI. The the following invocations through EFI_USB2_HC_PROTOCOL interface\r
     // can find out the actual device address by it.\r
     //\r
-    UsbDevContext[SlotId].BusDevAddr = (UINT8)Request->Value;\r
+    Xhc->UsbDevContext[SlotId].BusDevAddr = (UINT8)Request->Value;\r
     Status = EFI_SUCCESS;\r
     goto ON_EXIT;\r
   }\r
   \r
   //\r
-  // BUGBUG: If the port reset operation happens after the usb super speed device is enabled,\r
+  // If the port reset operation happens after the usb super speed device is enabled,\r
   // The subsequent configuration, such as getting device descriptor, will fail.\r
   // So here a workaround is introduced to skip the reset operation if the device is enabled.\r
   //\r
-  if ((Request->Request == USB_REQ_SET_FEATURE) &&\r
-      (Request->Value == EfiUsbPortReset)) {\r
+  if ((Request->Request     == USB_REQ_SET_FEATURE) &&\r
+      (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER)) &&\r
+      (Request->Value       == EfiUsbPortReset)) {\r
     if (DeviceSpeed == EFI_USB_SPEED_SUPER) {\r
       Status = EFI_SUCCESS;\r
       goto ON_EXIT;\r
@@ -829,7 +847,7 @@ XhcControlTransfer (
   // endpoint is bidirectional. XhcCreateUrb expects this\r
   // combination of Ep addr and its direction.\r
   //\r
-  Endpoint = 0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0);\r
+  Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));\r
   Urb = XhcCreateUrb (\r
           Xhc,\r
           XhciDevAddr,\r
@@ -850,7 +868,7 @@ XhcControlTransfer (
     goto ON_EXIT;\r
   }\r
   ASSERT (Urb->EvtRing == &Xhc->CtrlTrEventRing);\r
-  Status = XhcExecTransfer (Xhc, FALSE, Urb, TimeOut);\r
+  Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);\r
 \r
   //\r
   // Get the status from URB. The result is updated in XhcCheckUrbResult\r
@@ -873,42 +891,48 @@ XhcControlTransfer (
   // Hook Get_Status request form UsbBus as we need trace device attach/detach event happened at hub.\r
   // Hook Set_Config request from UsbBus as we need configure device endpoint.\r
   //\r
-  if (Request->Request == USB_REQ_GET_DESCRIPTOR) {\r
+  if ((Request->Request     == USB_REQ_GET_DESCRIPTOR) &&\r
+      (Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {\r
     DescriptorType = (UINT8)(Request->Value >> 8);\r
     if ((DescriptorType == USB_DESC_TYPE_DEVICE) && (*DataLength == sizeof (EFI_USB_DEVICE_DESCRIPTOR))) {\r
+        ASSERT (Data != NULL);\r
         //\r
         // Store a copy of device scriptor as hub device need this info to configure endpoint.\r
         //\r
-        CopyMem (&UsbDevContext[SlotId].DevDesc, Data, *DataLength);\r
-        if (UsbDevContext[SlotId].DevDesc.BcdUSB == 0x0300) {\r
+        CopyMem (&Xhc->UsbDevContext[SlotId].DevDesc, Data, *DataLength);\r
+        if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB == 0x0300) {\r
           //\r
           // If it's a usb3.0 device, then its max packet size is a 2^n.\r
           //\r
-          MaxPacket0 = 1 << UsbDevContext[SlotId].DevDesc.MaxPacketSize0;\r
+          MaxPacket0 = 1 << Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;\r
         } else {\r
-          MaxPacket0 = UsbDevContext[SlotId].DevDesc.MaxPacketSize0;\r
+          MaxPacket0 = Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;\r
         }\r
-        UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));\r
+        Xhc->UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));\r
         Status = XhcEvaluateContext (Xhc, SlotId, MaxPacket0);\r
         ASSERT_EFI_ERROR (Status);\r
-    } else if ((DescriptorType == USB_DESC_TYPE_CONFIG) && (*DataLength == ((UINT16 *)Data)[1])) {\r
-      //\r
-      // Get configuration value from request, Store the configuration descriptor for Configure_Endpoint cmd.\r
-      //\r
-      Index = (UINT8)Request->Value;\r
-      ASSERT (Index < UsbDevContext[SlotId].DevDesc.NumConfigurations);\r
-      UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool(*DataLength);\r
-      CopyMem (UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLength);\r
-    } else if (((DescriptorType == USB_DESC_TYPE_HUB) ||\r
-               (DescriptorType == USB_DESC_TYPE_HUB_SUPER_SPEED))) {\r
+    } else if (DescriptorType == USB_DESC_TYPE_CONFIG) {\r
+      ASSERT (Data != NULL);\r
+      if (*DataLength == ((UINT16 *)Data)[1]) {\r
+        //\r
+        // Get configuration value from request, Store the configuration descriptor for Configure_Endpoint cmd.\r
+        //\r
+        Index = (UINT8)Request->Value;\r
+        ASSERT (Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations);\r
+        Xhc->UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool(*DataLength);\r
+        CopyMem (Xhc->UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLength);\r
+      }\r
+    } else if ((DescriptorType == USB_DESC_TYPE_HUB) ||\r
+               (DescriptorType == USB_DESC_TYPE_HUB_SUPER_SPEED)) {\r
+      ASSERT (Data != NULL);\r
       HubDesc = (EFI_USB_HUB_DESCRIPTOR *)Data;\r
       //\r
       // The bit 5,6 of HubCharacter field of Hub Descriptor is TTT.\r
       //\r
       TTT = (UINT8)((HubDesc->HubCharacter & (BIT5 | BIT6)) >> 5);\r
-      if (UsbDevContext[SlotId].DevDesc.DeviceProtocol == 2) {\r
+      if (Xhc->UsbDevContext[SlotId].DevDesc.DeviceProtocol == 2) {\r
         //\r
-        // BUGBUG: Don't support multi-TT feature for super speed hub.\r
+        // Don't support multi-TT feature for super speed hub now.\r
         //\r
         MTT = 1;\r
         ASSERT (FALSE);\r
@@ -924,17 +948,20 @@ XhcControlTransfer (
                  MTT\r
                  );\r
     }\r
-  } else if (Request->Request == USB_REQ_SET_CONFIG) {\r
+  } else if ((Request->Request     == USB_REQ_SET_CONFIG) &&\r
+             (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {\r
     //\r
     // Hook Set_Config request from UsbBus as we need configure device endpoint.\r
     //\r
-    for (Index = 0; Index < UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {\r
-      if (UsbDevContext[SlotId].ConfDesc[Index]->ConfigurationValue == (UINT8)Request->Value) {\r
-        XhcSetConfigCmd (Xhc, SlotId, DeviceSpeed, UsbDevContext[SlotId].ConfDesc[Index]);\r
+    for (Index = 0; Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {\r
+      if (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->ConfigurationValue == (UINT8)Request->Value) {\r
+        XhcSetConfigCmd (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);\r
         break;\r
       }\r
     }\r
-  } else if (Request->Request == USB_REQ_GET_STATUS) {\r
+  } else if ((Request->Request     == USB_REQ_GET_STATUS) &&\r
+             (Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER))) {\r
+    ASSERT (Data != NULL);\r
     //\r
     // Hook Get_Status request from UsbBus to keep track of the port status change.\r
     //\r
@@ -979,7 +1006,7 @@ XhcControlTransfer (
       }\r
     }\r
 \r
-    XhcPollPortStatusChange (Xhc, UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);\r
+    XhcPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);\r
   }\r
 \r
 FREE_URB:\r
@@ -1014,7 +1041,7 @@ ON_EXIT:
   @param  DataToggle            On input, the initial data toggle for the transfer;\r
                                 On output, it is updated to to next data toggle to\r
                                 use of the subsequent bulk transfer.\r
-  @param  TimeOut               Indicates the maximum time, in millisecond, which\r
+  @param  Timeout               Indicates the maximum time, in millisecond, which\r
                                 the transfer is allowed to complete.\r
   @param  Translator            A pointr to the transaction translator data.\r
   @param  TransferResult        A pointer to the detailed result information of the\r
@@ -1039,12 +1066,12 @@ XhcBulkTransfer (
   IN OUT VOID                                *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
   IN OUT UINTN                               *DataLength,\r
   IN OUT UINT8                               *DataToggle,\r
-  IN     UINTN                               TimeOut,\r
+  IN     UINTN                               Timeout,\r
   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
   OUT    UINT32                              *TransferResult\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
   URB                     *Urb;\r
   UINT8                   XhciDevAddr;\r
   UINT8                   SlotId;\r
@@ -1086,7 +1113,7 @@ XhcBulkTransfer (
   //\r
   // Check if the device is still enabled before every transaction.\r
   //\r
-  SlotId = XhcBusDevAddrToSlotId (DeviceAddress);\r
+  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
   if (SlotId == 0) {\r
     goto ON_EXIT;\r
   }\r
@@ -1094,7 +1121,7 @@ XhcBulkTransfer (
   //\r
   // Acquire the actual device address assigned by XHCI's Address_Device cmd.\r
   //\r
-  XhciDevAddr = UsbDevContext[SlotId].XhciDevAddr;\r
+  XhciDevAddr = Xhc->UsbDevContext[SlotId].XhciDevAddr;\r
 \r
   //\r
   // Create a new URB, insert it into the asynchronous\r
@@ -1122,7 +1149,7 @@ XhcBulkTransfer (
 \r
   ASSERT (Urb->EvtRing == &Xhc->BulkTrEventRing);\r
 \r
-  Status = XhcExecTransfer (Xhc, FALSE, Urb, TimeOut);\r
+  Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);\r
 \r
   *TransferResult = Urb->Result;\r
   *DataLength     = Urb->Completed;\r
@@ -1193,7 +1220,7 @@ XhcAsyncInterruptTransfer (
   IN     VOID                                *Context OPTIONAL\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
   URB                     *Urb;\r
   EFI_STATUS              Status;\r
   UINT8                   XhciDevAddr;\r
@@ -1235,8 +1262,8 @@ XhcAsyncInterruptTransfer (
     // The delete request may happen after device is detached.\r
     //\r
     for (Index = 0; Index < 255; Index++) {\r
-      if ((UsbDevContext[Index + 1].SlotId != 0) &&\r
-          (UsbDevContext[Index + 1].BusDevAddr == DeviceAddress)) {\r
+      if ((Xhc->UsbDevContext[Index + 1].SlotId != 0) &&\r
+          (Xhc->UsbDevContext[Index + 1].BusDevAddr == DeviceAddress)) {\r
         break;\r
       }\r
     }\r
@@ -1249,7 +1276,7 @@ XhcAsyncInterruptTransfer (
     //\r
     // Acquire the actual device address assigned by XHCI's Address_Device cmd.\r
     //\r
-    XhciDevAddr = UsbDevContext[Index + 1].XhciDevAddr;\r
+    XhciDevAddr = Xhc->UsbDevContext[Index + 1].XhciDevAddr;\r
 \r
     Status = XhciDelAsyncIntTransfer (Xhc, XhciDevAddr, EndPointAddress);\r
     DEBUG ((EFI_D_INFO, "XhcAsyncInterruptTransfer: remove old transfer, Status = %r\n", Status));\r
@@ -1267,7 +1294,7 @@ XhcAsyncInterruptTransfer (
   //\r
   // Check if the device is still enabled before every transaction.\r
   //\r
-  SlotId = XhcBusDevAddrToSlotId (DeviceAddress);\r
+  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
   if (SlotId == 0) {\r
     goto ON_EXIT;\r
   }\r
@@ -1275,9 +1302,9 @@ XhcAsyncInterruptTransfer (
   //\r
   // Acquire the actual device address assigned by XHCI's Address_Device cmd.\r
   //\r
-  XhciDevAddr = UsbDevContext[SlotId].XhciDevAddr;\r
+  XhciDevAddr = Xhc->UsbDevContext[SlotId].XhciDevAddr;\r
 \r
-  Data = AllocatePool (DataLength);\r
+  Data = AllocateZeroPool (DataLength);\r
 \r
   if (Data == NULL) {\r
     DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to allocate buffer\n"));\r
@@ -1337,7 +1364,7 @@ ON_EXIT:
                                 output, the number of bytes transferred.\r
   @param  DataToggle            On input, the initial data toggle to use; on output,\r
                                 it is updated to indicate the next data toggle.\r
-  @param  TimeOut               Maximum time, in second, to complete.\r
+  @param  Timeout               Maximum time, in second, to complete.\r
   @param  Translator            Transaction translator to use.\r
   @param  TransferResult        Variable to receive the transfer result.\r
 \r
@@ -1359,12 +1386,12 @@ XhcSyncInterruptTransfer (
   IN OUT VOID                                *Data,\r
   IN OUT UINTN                               *DataLength,\r
   IN OUT UINT8                               *DataToggle,\r
-  IN     UINTN                               TimeOut,\r
+  IN     UINTN                               Timeout,\r
   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
   OUT    UINT32                              *TransferResult\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
   URB                     *Urb;\r
   UINT8                   XhciDevAddr;\r
   UINT8                   SlotId;\r
@@ -1409,7 +1436,7 @@ XhcSyncInterruptTransfer (
   //\r
   // Check if the device is still enabled before every transaction.\r
   //\r
-  SlotId = XhcBusDevAddrToSlotId (DeviceAddress);\r
+  SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
   if (SlotId == 0) {\r
     goto ON_EXIT;\r
   }\r
@@ -1417,7 +1444,7 @@ XhcSyncInterruptTransfer (
   //\r
   // Acquire the actual device address assigned by XHCI's Address_Device cmd.\r
   //\r
-  XhciDevAddr = UsbDevContext[SlotId].XhciDevAddr;\r
+  XhciDevAddr = Xhc->UsbDevContext[SlotId].XhciDevAddr;\r
 \r
   Urb = XhcCreateUrb (\r
           Xhc,\r
@@ -1439,7 +1466,7 @@ XhcSyncInterruptTransfer (
     goto ON_EXIT;\r
   }\r
 \r
-  Status = XhcExecTransfer (Xhc, FALSE, Urb, TimeOut);\r
+  Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);\r
 \r
   *TransferResult = Urb->Result;\r
   *DataLength     = Urb->Completed;\r
@@ -1649,57 +1676,39 @@ ON_EXIT:
 }\r
 \r
 /**\r
-  Create and initialize a USB_XHCI_DEV.\r
+  Create and initialize a USB_XHCI_INSTANCE structure.\r
 \r
   @param  PciIo                  The PciIo on this device.\r
   @param  OriginalPciAttributes  Original PCI attributes.\r
 \r
-  @return The allocated and initialized USB_XHCI_DEV structure if created,\r
+  @return The allocated and initialized USB_XHCI_INSTANCE structure if created,\r
           otherwise NULL.\r
 \r
 **/\r
-USB_XHCI_DEV*\r
+USB_XHCI_INSTANCE*\r
 XhcCreateUsbHc (\r
   IN EFI_PCI_IO_PROTOCOL  *PciIo,\r
   IN UINT64               OriginalPciAttributes\r
   )\r
 {\r
-  USB_XHCI_DEV            *Xhc;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
   EFI_STATUS              Status;\r
   UINT32                  PageSize;\r
   UINT16                  ExtCapReg;\r
 \r
-  ZeroMem (UsbDevContext, sizeof (UsbDevContext));\r
-\r
-  Xhc = AllocateZeroPool (sizeof (USB_XHCI_DEV));\r
+  Xhc = AllocateZeroPool (sizeof (USB_XHCI_INSTANCE));\r
 \r
   if (Xhc == NULL) {\r
     return NULL;\r
   }\r
 \r
   //\r
-  // Init EFI_USB2_HC_PROTOCOL interface and private data structure\r
+  // Initialize private data structure\r
   //\r
-  Xhc->Signature                        = USB_XHCI_DEV_SIGNATURE;\r
-\r
-  Xhc->Usb2Hc.GetCapability             = XhcGetCapability;\r
-  Xhc->Usb2Hc.Reset                     = XhcReset;\r
-  Xhc->Usb2Hc.GetState                  = XhcGetState;\r
-  Xhc->Usb2Hc.SetState                  = XhcSetState;\r
-  Xhc->Usb2Hc.ControlTransfer           = XhcControlTransfer;\r
-  Xhc->Usb2Hc.BulkTransfer              = XhcBulkTransfer;\r
-  Xhc->Usb2Hc.AsyncInterruptTransfer    = XhcAsyncInterruptTransfer;\r
-  Xhc->Usb2Hc.SyncInterruptTransfer     = XhcSyncInterruptTransfer;\r
-  Xhc->Usb2Hc.IsochronousTransfer       = XhcIsochronousTransfer;\r
-  Xhc->Usb2Hc.AsyncIsochronousTransfer  = XhcAsyncIsochronousTransfer;\r
-  Xhc->Usb2Hc.GetRootHubPortStatus      = XhcGetRootHubPortStatus;\r
-  Xhc->Usb2Hc.SetRootHubPortFeature     = XhcSetRootHubPortFeature;\r
-  Xhc->Usb2Hc.ClearRootHubPortFeature   = XhcClearRootHubPortFeature;\r
-  Xhc->Usb2Hc.MajorRevision             = 0x3;\r
-  Xhc->Usb2Hc.MinorRevision             = 0x0;\r
-\r
+  Xhc->Signature             = XHCI_INSTANCE_SIG;\r
   Xhc->PciIo                 = PciIo;\r
   Xhc->OriginalPciAttributes = OriginalPciAttributes;\r
+  CopyMem (&Xhc->Usb2Hc, &gXhciUsb2HcTemplate, sizeof (EFI_USB2_HC_PROTOCOL));\r
 \r
   InitializeListHead (&Xhc->AsyncIntTransfers);\r
 \r
@@ -1720,19 +1729,18 @@ XhcCreateUsbHc (
   //\r
   PageSize      = XhcReadOpReg(Xhc, XHC_PAGESIZE_OFFSET) & XHC_PAGESIZE_MASK;\r
   Xhc->PageSize = 1 << (HighBitSet32(PageSize) + 12);\r
-  ASSERT (Xhc->PageSize == 0x1000);\r
 \r
-  ExtCapReg                 = (UINT16) (Xhc->HcCParams.Data.ExtCapReg);\r
-  Xhc->ExtCapRegBase        = ExtCapReg << 2;\r
+  ExtCapReg            = (UINT16) (Xhc->HcCParams.Data.ExtCapReg);\r
+  Xhc->ExtCapRegBase   = ExtCapReg << 2;\r
   Xhc->UsbLegSupOffset = XhcGetLegSupCapAddr (Xhc);\r
 \r
-  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: capability length 0x%x\n", Xhc->CapLength));\r
+  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: Capability length 0x%x\n", Xhc->CapLength));\r
   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcSParams1 0x%x\n", Xhc->HcSParams1));\r
   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcSParams2 0x%x\n", Xhc->HcSParams2));\r
   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcCParams 0x%x\n", Xhc->HcCParams));\r
   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: DBOff 0x%x\n", Xhc->DBOff));\r
   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: RTSOff 0x%x\n", Xhc->RTSOff));\r
-  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: Xhc->UsbLegSupOffset 0x%x\n", Xhc->UsbLegSupOffset));\r
+  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: UsbLegSupOffset 0x%x\n", Xhc->UsbLegSupOffset));\r
 \r
   //\r
   // Create AsyncRequest Polling Timer\r
@@ -1771,17 +1779,17 @@ XhcExitBootService (
   )\r
 \r
 {\r
-  USB_XHCI_DEV         *Xhc;\r
+  USB_XHCI_INSTANCE    *Xhc;\r
   EFI_PCI_IO_PROTOCOL  *PciIo;\r
 \r
-  Xhc = (USB_XHCI_DEV*) Context;\r
+  Xhc = (USB_XHCI_INSTANCE*) Context;\r
   PciIo = Xhc->PciIo;\r
 \r
   //\r
   // Stop AsyncRequest Polling timer then stop the XHCI driver\r
   // and uninstall the XHCI protocl.\r
   //\r
-  gBS->SetTimer (Xhc->PollTimer, TimerCancel, XHC_ASYNC_POLL_INTERVAL);\r
+  gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0);\r
   XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
 \r
   if (Xhc->PollTimer != NULL) {\r
@@ -1827,7 +1835,7 @@ XhcDriverBindingStart (
   UINT64                  Supports;\r
   UINT64                  OriginalPciAttributes;\r
   BOOLEAN                 PciAttributesSaved;\r
-  USB_XHCI_DEV            *Xhc;\r
+  USB_XHCI_INSTANCE       *Xhc;\r
 \r
   //\r
   // Open the PciIo Protocol, then enable the USB host controller\r
@@ -1916,7 +1924,7 @@ XhcDriverBindingStart (
   //\r
   // Start the asynchronous interrupt monitor\r
   //\r
-  Status = gBS->SetTimer (Xhc->PollTimer, TimerPeriodic, XHC_ASYNC_POLL_INTERVAL);\r
+  Status = gBS->SetTimer (Xhc->PollTimer, TimerPeriodic, XHC_ASYNC_TIMER_INTERVAL);\r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to start async interrupt monitor\n"));\r
     XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
@@ -2025,7 +2033,8 @@ XhcDriverBindingStop (
   EFI_STATUS            Status;\r
   EFI_USB2_HC_PROTOCOL  *Usb2Hc;\r
   EFI_PCI_IO_PROTOCOL   *PciIo;\r
-  USB_XHCI_DEV          *Xhc;\r
+  USB_XHCI_INSTANCE     *Xhc;\r
+  UINT8                 Index;\r
 \r
   //\r
   // Test whether the Controller handler passed in is a valid\r
@@ -2052,7 +2061,21 @@ XhcDriverBindingStop (
   // Stop AsyncRequest Polling timer then stop the XHCI driver\r
   // and uninstall the XHCI protocl.\r
   //\r
-  gBS->SetTimer (Xhc->PollTimer, TimerCancel, XHC_ASYNC_POLL_INTERVAL);\r
+  gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0);\r
+\r
+  //\r
+  // Disable the device slots occupied by these devices on its downstream ports.\r
+  // Entry 0 is reserved.\r
+  //\r
+  for (Index = 0; Index < 255; Index++) {\r
+    if (!Xhc->UsbDevContext[Index + 1].Enabled ||\r
+        (Xhc->UsbDevContext[Index + 1].SlotId == 0)) {\r
+      continue;\r
+    }\r
+\r
+    XhcDisableSlotCmd (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);\r
+  }\r
+\r
   XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
   XhcClearBiosOwnership (Xhc);\r
 \r