+ // 2) Initialize the Input Control Context (6.2.5.1) of the Input Context by setting the A0 and A1\r
+ // flags to '1'. These flags indicate that the Slot Context and the Endpoint 0 Context of the Input\r
+ // Context are affected by the command.\r
+ //\r
+ InputContext->InputControlContext.Dword2 |= (BIT0 | BIT1);\r
+\r
+ //\r
+ // 3) Initialize the Input Slot Context data structure\r
+ //\r
+ InputContext->Slot.RouteString = RouteChart.Route.RouteString;\r
+ InputContext->Slot.Speed = DeviceSpeed + 1;\r
+ InputContext->Slot.ContextEntries = 1;\r
+ InputContext->Slot.RootHubPortNum = RouteChart.Route.RootPortNum;\r
+\r
+ if (RouteChart.Route.RouteString) {\r
+ //\r
+ // The device is behind of hub device.\r
+ //\r
+ ParentSlotId = XhcRouteStringToSlotId(Xhc, ParentRouteChart);\r
+ ASSERT (ParentSlotId != 0);\r
+ //\r
+ //if the Full/Low device attached to a High Speed Hub, Init the TTPortNum and TTHubSlotId field of slot context\r
+ //\r
+ ParentDeviceContext = (DEVICE_CONTEXT_64 *)Xhc->UsbDevContext[ParentSlotId].OutputContext;\r
+ if ((ParentDeviceContext->Slot.TTPortNum == 0) &&\r
+ (ParentDeviceContext->Slot.TTHubSlotId == 0)) {\r
+ if ((ParentDeviceContext->Slot.Speed == (EFI_USB_SPEED_HIGH + 1)) && (DeviceSpeed < EFI_USB_SPEED_HIGH)) {\r
+ //\r
+ // Full/Low device attached to High speed hub port that isolates the high speed signaling\r
+ // environment from Full/Low speed signaling environment for a device\r
+ //\r
+ InputContext->Slot.TTPortNum = ParentPort;\r
+ InputContext->Slot.TTHubSlotId = ParentSlotId;\r
+ }\r
+ } else {\r
+ //\r
+ // Inherit the TT parameters from parent device.\r
+ //\r
+ InputContext->Slot.TTPortNum = ParentDeviceContext->Slot.TTPortNum;\r
+ InputContext->Slot.TTHubSlotId = ParentDeviceContext->Slot.TTHubSlotId;\r
+ //\r
+ // If the device is a High speed device then down the speed to be the same as its parent Hub\r
+ //\r
+ if (DeviceSpeed == EFI_USB_SPEED_HIGH) {\r
+ InputContext->Slot.Speed = ParentDeviceContext->Slot.Speed;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // 4) Allocate and initialize the Transfer Ring for the Default Control Endpoint.\r
+ //\r
+ EndpointTransferRing = AllocateZeroPool (sizeof (TRANSFER_RING));\r
+ Xhc->UsbDevContext[SlotId].EndpointTransferRing[0] = EndpointTransferRing;\r
+ CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0]);\r
+ //\r
+ // 5) Initialize the Input default control Endpoint 0 Context (6.2.3).\r
+ //\r
+ InputContext->EP[0].EPType = ED_CONTROL_BIDIR;\r
+\r
+ if (DeviceSpeed == EFI_USB_SPEED_SUPER) {\r
+ InputContext->EP[0].MaxPacketSize = 512;\r
+ } else if (DeviceSpeed == EFI_USB_SPEED_HIGH) {\r
+ InputContext->EP[0].MaxPacketSize = 64;\r
+ } else {\r
+ InputContext->EP[0].MaxPacketSize = 8;\r
+ }\r
+ //\r
+ // Initial value of Average TRB Length for Control endpoints would be 8B, Interrupt endpoints\r
+ // 1KB, and Bulk and Isoch endpoints 3KB.\r
+ //\r
+ InputContext->EP[0].AverageTRBLength = 8;\r
+ InputContext->EP[0].MaxBurstSize = 0;\r
+ InputContext->EP[0].Interval = 0;\r
+ InputContext->EP[0].MaxPStreams = 0;\r
+ InputContext->EP[0].Mult = 0;\r
+ InputContext->EP[0].CErr = 3;\r
+\r
+ //\r
+ // Init the DCS(dequeue cycle state) as the transfer ring's CCS\r
+ //\r
+ InputContext->EP[0].PtrLo = XHC_LOW_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0) | BIT0;\r
+ InputContext->EP[0].PtrHi = XHC_HIGH_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0);\r
+\r
+ //\r
+ // 6) Allocate the Output Device Context data structure (6.2.1) and initialize it to '0'.\r
+ //\r
+ OutputContext = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (DEVICE_CONTEXT_64)));\r
+ ASSERT (OutputContext != NULL);\r
+ ASSERT (((UINTN) OutputContext & 0x3F) == 0);\r
+ ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT_64));\r
+\r
+ Xhc->UsbDevContext[SlotId].OutputContext = OutputContext;\r
+ //\r
+ // 7) Load the appropriate (Device Slot ID) entry in the Device Context Base Address Array (5.4.6) with\r
+ // a pointer to the Output Device Context data structure (6.2.1).\r
+ //\r
+ Xhc->DCBAA[SlotId] = (UINT64) (UINTN) OutputContext;\r
+\r
+ //\r
+ // 8) Issue an Address Device Command for the Device Slot, where the command points to the Input\r
+ // Context data structure described above.\r
+ //\r
+ ZeroMem (&CmdTrbAddr, sizeof (CmdTrbAddr));\r
+ CmdTrbAddr.PtrLo = XHC_LOW_32BIT (Xhc->UsbDevContext[SlotId].InputContext);\r
+ CmdTrbAddr.PtrHi = XHC_HIGH_32BIT (Xhc->UsbDevContext[SlotId].InputContext);\r
+ CmdTrbAddr.CycleBit = 1;\r
+ CmdTrbAddr.Type = TRB_TYPE_ADDRESS_DEV;\r
+ CmdTrbAddr.SlotId = Xhc->UsbDevContext[SlotId].SlotId;\r
+ Status = XhcCmdTransfer (\r
+ Xhc,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbAddr,\r
+ XHC_GENERIC_TIMEOUT,\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+ );\r
+ ASSERT (!EFI_ERROR(Status));\r
+\r
+ DeviceAddress = (UINT8) ((DEVICE_CONTEXT_64 *) OutputContext)->Slot.DeviceAddress;\r
+ DEBUG ((EFI_D_INFO, " Address %d assigned successfully\n", DeviceAddress));\r
+\r
+ Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Disable the specified device slot.\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param SlotId The slot id to be disabled.\r
+\r
+ @retval EFI_SUCCESS Successfully disable the device slot.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcDisableSlotCmd (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 SlotId\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ TRB_TEMPLATE *EvtTrb;\r
+ CMD_TRB_DISABLE_SLOT CmdTrbDisSlot;\r
+ UINT8 Index;\r
+ VOID *RingSeg;\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
+ (Xhc->UsbDevContext[Index + 1].ParentRouteString.Dword != Xhc->UsbDevContext[SlotId].RouteString.Dword)) {\r
+ continue;\r
+ }\r
+\r
+ Status = XhcDisableSlotCmd (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcDisableSlotCmd: failed to disable child, ignore error\n"));\r
+ Xhc->UsbDevContext[Index + 1].SlotId = 0;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Construct the disable slot command\r
+ //\r
+ DEBUG ((EFI_D_INFO, "Disable device slot %d!\n", SlotId));\r
+\r
+ ZeroMem (&CmdTrbDisSlot, sizeof (CmdTrbDisSlot));\r
+ CmdTrbDisSlot.CycleBit = 1;\r
+ CmdTrbDisSlot.Type = TRB_TYPE_DIS_SLOT;\r
+ CmdTrbDisSlot.SlotId = SlotId;\r
+ Status = XhcCmdTransfer (\r
+ Xhc,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbDisSlot,\r
+ XHC_GENERIC_TIMEOUT,\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+ );\r
+ ASSERT_EFI_ERROR(Status);\r
+ //\r
+ // Free the slot's device context entry\r
+ //\r
+ Xhc->DCBAA[SlotId] = 0;\r
+\r
+ //\r
+ // Free the slot related data structure\r
+ //\r
+ for (Index = 0; Index < 31; Index++) {\r
+ if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] != NULL) {\r
+ RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index])->RingSeg0;\r
+ if (RingSeg != NULL) {\r
+ FreePages (RingSeg, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER));\r
+ }\r
+ FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index]);\r
+ }\r
+ }\r
+\r
+ for (Index = 0; Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {\r
+ if (Xhc->UsbDevContext[SlotId].ConfDesc[Index] != NULL) {\r
+ FreePool (Xhc->UsbDevContext[SlotId].ConfDesc[Index]);\r
+ }\r
+ }\r
+\r
+ if (Xhc->UsbDevContext[SlotId].InputContext != NULL) {\r
+ FreePages (Xhc->UsbDevContext[SlotId].InputContext, EFI_SIZE_TO_PAGES (sizeof (INPUT_CONTEXT)));\r
+ }\r
+\r
+ if (Xhc->UsbDevContext[SlotId].OutputContext != NULL) {\r
+ FreePages (Xhc->UsbDevContext[SlotId].OutputContext, EFI_SIZE_TO_PAGES (sizeof (DEVICE_CONTEXT)));\r
+ }\r
+ //\r
+ // Doesn't zero the entry because XhcAsyncInterruptTransfer() may be invoked to remove the established\r
+ // asynchronous interrupt pipe after the device is disabled. It needs the device address mapping info to\r
+ // remove urb from XHCI's asynchronous transfer list.\r
+ //\r
+ Xhc->UsbDevContext[SlotId].Enabled = FALSE;\r
+ Xhc->UsbDevContext[SlotId].SlotId = 0;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Disable the specified device slot.\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param SlotId The slot id to be disabled.\r
+\r
+ @retval EFI_SUCCESS Successfully disable the device slot.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcDisableSlotCmd64 (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 SlotId\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ TRB_TEMPLATE *EvtTrb;\r
+ CMD_TRB_DISABLE_SLOT CmdTrbDisSlot;\r
+ UINT8 Index;\r
+ VOID *RingSeg;\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
+ (Xhc->UsbDevContext[Index + 1].ParentRouteString.Dword != Xhc->UsbDevContext[SlotId].RouteString.Dword)) {\r
+ continue;\r
+ }\r
+\r
+ Status = XhcDisableSlotCmd64 (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcDisableSlotCmd: failed to disable child, ignore error\n"));\r
+ Xhc->UsbDevContext[Index + 1].SlotId = 0;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Construct the disable slot command\r