+ MaxDci = 0;\r
+\r
+ NumEp = IfDesc->NumEndpoints;\r
+\r
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);\r
+ for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {\r
+ while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {\r
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+ }\r
+\r
+ if (EpDesc->Length < sizeof (USB_ENDPOINT_DESCRIPTOR)) {\r
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+ continue;\r
+ }\r
+\r
+ EpAddr = (UINT8)(EpDesc->EndpointAddress & 0x0F);\r
+ Direction = (UINT8)((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut);\r
+\r
+ Dci = XhcEndpointToDci (EpAddr, Direction);\r
+ ASSERT (Dci < 32);\r
+ if (Dci > MaxDci) {\r
+ MaxDci = Dci;\r
+ }\r
+\r
+ InputContext->InputControlContext.Dword2 |= (BIT0 << Dci);\r
+ InputContext->EP[Dci-1].MaxPacketSize = EpDesc->MaxPacketSize;\r
+\r
+ if (DeviceSpeed == EFI_USB_SPEED_SUPER) {\r
+ //\r
+ // 6.2.3.4, shall be set to the value defined in the bMaxBurst field of the SuperSpeed Endpoint Companion Descriptor.\r
+ //\r
+ InputContext->EP[Dci-1].MaxBurstSize = 0x0;\r
+ } else {\r
+ InputContext->EP[Dci-1].MaxBurstSize = 0x0;\r
+ }\r
+\r
+ switch (EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK) {\r
+ case USB_ENDPOINT_BULK:\r
+ if (Direction == EfiUsbDataIn) {\r
+ InputContext->EP[Dci-1].CErr = 3;\r
+ InputContext->EP[Dci-1].EPType = ED_BULK_IN;\r
+ } else {\r
+ InputContext->EP[Dci-1].CErr = 3;\r
+ InputContext->EP[Dci-1].EPType = ED_BULK_OUT;\r
+ }\r
+\r
+ InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
+ if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {\r
+ EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING));\r
+ Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;\r
+ CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]);\r
+ }\r
+\r
+ break;\r
+ case USB_ENDPOINT_ISO:\r
+ if (Direction == EfiUsbDataIn) {\r
+ InputContext->EP[Dci-1].CErr = 0;\r
+ InputContext->EP[Dci-1].EPType = ED_ISOCH_IN;\r
+ } else {\r
+ InputContext->EP[Dci-1].CErr = 0;\r
+ InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;\r
+ }\r
+ //\r
+ // Get the bInterval from descriptor and init the the interval field of endpoint context.\r
+ // Refer to XHCI 1.1 spec section 6.2.3.6.\r
+ //\r
+ if (DeviceSpeed == EFI_USB_SPEED_FULL) {\r
+ Interval = EpDesc->Interval;\r
+ ASSERT (Interval >= 1 && Interval <= 16);\r
+ InputContext->EP[Dci-1].Interval = Interval + 2;\r
+ } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {\r
+ Interval = EpDesc->Interval;\r
+ ASSERT (Interval >= 1 && Interval <= 16);\r
+ InputContext->EP[Dci-1].Interval = Interval - 1;\r
+ }\r
+\r
+ //\r
+ // Do not support isochronous transfer now.\r
+ //\r
+ DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext: Unsupport ISO EP found, Transfer ring is not allocated.\n"));\r
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+ continue;\r
+ case USB_ENDPOINT_INTERRUPT:\r
+ if (Direction == EfiUsbDataIn) {\r
+ InputContext->EP[Dci-1].CErr = 3;\r
+ InputContext->EP[Dci-1].EPType = ED_INTERRUPT_IN;\r
+ } else {\r
+ InputContext->EP[Dci-1].CErr = 3;\r
+ InputContext->EP[Dci-1].EPType = ED_INTERRUPT_OUT;\r
+ }\r
+ InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
+ InputContext->EP[Dci-1].MaxESITPayload = EpDesc->MaxPacketSize;\r
+ //\r
+ // Get the bInterval from descriptor and init the the interval field of endpoint context\r
+ //\r
+ if ((DeviceSpeed == EFI_USB_SPEED_FULL) || (DeviceSpeed == EFI_USB_SPEED_LOW)) {\r
+ Interval = EpDesc->Interval;\r
+ //\r
+ // Calculate through the bInterval field of Endpoint descriptor.\r
+ //\r
+ ASSERT (Interval != 0);\r
+ InputContext->EP[Dci-1].Interval = (UINT32)HighBitSet32((UINT32)Interval) + 3;\r
+ } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {\r
+ Interval = EpDesc->Interval;\r
+ ASSERT (Interval >= 1 && Interval <= 16);\r
+ //\r
+ // Refer to XHCI 1.0 spec section 6.2.3.6, table 61\r
+ //\r
+ InputContext->EP[Dci-1].Interval = Interval - 1;\r
+ InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
+ InputContext->EP[Dci-1].MaxESITPayload = 0x0002;\r
+ InputContext->EP[Dci-1].MaxBurstSize = 0x0;\r
+ InputContext->EP[Dci-1].CErr = 3;\r
+ }\r
+\r
+ if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {\r
+ EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING));\r
+ Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;\r
+ CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]);\r
+ }\r
+ break;\r
+\r
+ case USB_ENDPOINT_CONTROL:\r
+ //\r
+ // Do not support control transfer now.\r
+ //\r
+ DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext: Unsupport Control EP found, Transfer ring is not allocated.\n"));\r
+ default:\r
+ DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext: Unknown EP found, Transfer ring is not allocated.\n"));\r
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+ continue;\r
+ }\r
+\r
+ PhyAddr = UsbHcGetPciAddrForHostAddr (\r
+ Xhc->MemPool,\r
+ ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0,\r
+ sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER\r
+ );\r
+ PhyAddr &= ~((EFI_PHYSICAL_ADDRESS)0x0F);\r
+ PhyAddr |= (EFI_PHYSICAL_ADDRESS)((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;\r
+ InputContext->EP[Dci-1].PtrLo = XHC_LOW_32BIT (PhyAddr);\r
+ InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (PhyAddr);\r
+\r
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+ }\r
+\r
+ return MaxDci;\r
+}\r
+\r
+/**\r
+ Initialize endpoint context in input context.\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param SlotId The slot id to be configured.\r
+ @param DeviceSpeed The device's speed.\r
+ @param InputContext The pointer to the input context.\r
+ @param IfDesc The pointer to the usb device interface descriptor.\r
+\r
+ @return The maximum device context index of endpoint.\r
+\r
+**/\r
+UINT8\r
+EFIAPI\r
+XhcInitializeEndpointContext64 (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 SlotId,\r
+ IN UINT8 DeviceSpeed,\r
+ IN INPUT_CONTEXT_64 *InputContext,\r
+ IN USB_INTERFACE_DESCRIPTOR *IfDesc\r
+ )\r
+{\r
+ USB_ENDPOINT_DESCRIPTOR *EpDesc;\r
+ UINTN NumEp;\r
+ UINTN EpIndex;\r
+ UINT8 EpAddr;\r
+ UINT8 Direction;\r
+ UINT8 Dci;\r
+ UINT8 MaxDci;\r
+ EFI_PHYSICAL_ADDRESS PhyAddr;\r
+ UINT8 Interval;\r
+ TRANSFER_RING *EndpointTransferRing;\r
+\r
+ MaxDci = 0;\r
+\r
+ NumEp = IfDesc->NumEndpoints;\r
+\r
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);\r
+ for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {\r
+ while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {\r
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+ }\r
+\r
+ if (EpDesc->Length < sizeof (USB_ENDPOINT_DESCRIPTOR)) {\r
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+ continue;\r
+ }\r
+\r
+ EpAddr = (UINT8)(EpDesc->EndpointAddress & 0x0F);\r
+ Direction = (UINT8)((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut);\r
+\r
+ Dci = XhcEndpointToDci (EpAddr, Direction);\r
+ ASSERT (Dci < 32);\r
+ if (Dci > MaxDci) {\r
+ MaxDci = Dci;\r
+ }\r
+\r
+ InputContext->InputControlContext.Dword2 |= (BIT0 << Dci);\r
+ InputContext->EP[Dci-1].MaxPacketSize = EpDesc->MaxPacketSize;\r
+\r
+ if (DeviceSpeed == EFI_USB_SPEED_SUPER) {\r
+ //\r
+ // 6.2.3.4, shall be set to the value defined in the bMaxBurst field of the SuperSpeed Endpoint Companion Descriptor.\r
+ //\r
+ InputContext->EP[Dci-1].MaxBurstSize = 0x0;\r
+ } else {\r
+ InputContext->EP[Dci-1].MaxBurstSize = 0x0;\r
+ }\r
+\r
+ switch (EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK) {\r
+ case USB_ENDPOINT_BULK:\r
+ if (Direction == EfiUsbDataIn) {\r
+ InputContext->EP[Dci-1].CErr = 3;\r
+ InputContext->EP[Dci-1].EPType = ED_BULK_IN;\r
+ } else {\r
+ InputContext->EP[Dci-1].CErr = 3;\r
+ InputContext->EP[Dci-1].EPType = ED_BULK_OUT;\r
+ }\r
+\r
+ InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
+ if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {\r
+ EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING));\r
+ Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;\r
+ CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]);\r
+ }\r
+\r
+ break;\r
+ case USB_ENDPOINT_ISO:\r
+ if (Direction == EfiUsbDataIn) {\r
+ InputContext->EP[Dci-1].CErr = 0;\r
+ InputContext->EP[Dci-1].EPType = ED_ISOCH_IN;\r
+ } else {\r
+ InputContext->EP[Dci-1].CErr = 0;\r
+ InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;\r
+ }\r
+ //\r
+ // Get the bInterval from descriptor and init the the interval field of endpoint context.\r
+ // Refer to XHCI 1.1 spec section 6.2.3.6.\r
+ //\r
+ if (DeviceSpeed == EFI_USB_SPEED_FULL) {\r
+ Interval = EpDesc->Interval;\r
+ ASSERT (Interval >= 1 && Interval <= 16);\r
+ InputContext->EP[Dci-1].Interval = Interval + 2;\r
+ } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {\r
+ Interval = EpDesc->Interval;\r
+ ASSERT (Interval >= 1 && Interval <= 16);\r
+ InputContext->EP[Dci-1].Interval = Interval - 1;\r
+ }\r
+\r
+ //\r
+ // Do not support isochronous transfer now.\r
+ //\r
+ DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext64: Unsupport ISO EP found, Transfer ring is not allocated.\n"));\r
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+ continue;\r
+ case USB_ENDPOINT_INTERRUPT:\r
+ if (Direction == EfiUsbDataIn) {\r
+ InputContext->EP[Dci-1].CErr = 3;\r
+ InputContext->EP[Dci-1].EPType = ED_INTERRUPT_IN;\r
+ } else {\r
+ InputContext->EP[Dci-1].CErr = 3;\r
+ InputContext->EP[Dci-1].EPType = ED_INTERRUPT_OUT;\r
+ }\r
+ InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
+ InputContext->EP[Dci-1].MaxESITPayload = EpDesc->MaxPacketSize;\r
+ //\r
+ // Get the bInterval from descriptor and init the the interval field of endpoint context\r
+ //\r
+ if ((DeviceSpeed == EFI_USB_SPEED_FULL) || (DeviceSpeed == EFI_USB_SPEED_LOW)) {\r
+ Interval = EpDesc->Interval;\r
+ //\r
+ // Calculate through the bInterval field of Endpoint descriptor.\r
+ //\r
+ ASSERT (Interval != 0);\r
+ InputContext->EP[Dci-1].Interval = (UINT32)HighBitSet32((UINT32)Interval) + 3;\r
+ } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {\r
+ Interval = EpDesc->Interval;\r
+ ASSERT (Interval >= 1 && Interval <= 16);\r
+ //\r
+ // Refer to XHCI 1.0 spec section 6.2.3.6, table 61\r
+ //\r
+ InputContext->EP[Dci-1].Interval = Interval - 1;\r
+ InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
+ InputContext->EP[Dci-1].MaxESITPayload = 0x0002;\r
+ InputContext->EP[Dci-1].MaxBurstSize = 0x0;\r
+ InputContext->EP[Dci-1].CErr = 3;\r
+ }\r
+\r
+ if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {\r
+ EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING));\r
+ Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;\r
+ CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]);\r
+ }\r
+ break;\r
+\r
+ case USB_ENDPOINT_CONTROL:\r
+ //\r
+ // Do not support control transfer now.\r
+ //\r
+ DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext64: Unsupport Control EP found, Transfer ring is not allocated.\n"));\r
+ default:\r
+ DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext64: Unknown EP found, Transfer ring is not allocated.\n"));\r
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+ continue;\r
+ }\r
+\r
+ PhyAddr = UsbHcGetPciAddrForHostAddr (\r
+ Xhc->MemPool,\r
+ ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0,\r
+ sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER\r
+ );\r
+ PhyAddr &= ~((EFI_PHYSICAL_ADDRESS)0x0F);\r
+ PhyAddr |= (EFI_PHYSICAL_ADDRESS)((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;\r
+ InputContext->EP[Dci-1].PtrLo = XHC_LOW_32BIT (PhyAddr);\r
+ InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (PhyAddr);\r
+\r
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
+ }\r
+\r
+ return MaxDci;\r
+}\r
+\r
+/**\r
+ Configure all the device endpoints through XHCI's Configure_Endpoint cmd.\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param SlotId The slot id to be configured.\r
+ @param DeviceSpeed The device's speed.\r
+ @param ConfigDesc The pointer to the usb device configuration descriptor.\r
+\r
+ @retval EFI_SUCCESS Successfully configure all the device endpoints.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcSetConfigCmd (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 SlotId,\r
+ IN UINT8 DeviceSpeed,\r
+ IN USB_CONFIG_DESCRIPTOR *ConfigDesc\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ USB_INTERFACE_DESCRIPTOR *IfDesc;\r
+ UINT8 Index;\r
+ UINT8 Dci;\r
+ UINT8 MaxDci;\r
+ EFI_PHYSICAL_ADDRESS PhyAddr;\r
+\r
+ CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;\r
+ INPUT_CONTEXT *InputContext;\r
+ DEVICE_CONTEXT *OutputContext;\r
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;\r
+ //\r
+ // 4.6.6 Configure Endpoint\r
+ //\r
+ InputContext = Xhc->UsbDevContext[SlotId].InputContext;\r
+ OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;\r
+ ZeroMem (InputContext, sizeof (INPUT_CONTEXT));\r
+ CopyMem (&InputContext->Slot, &OutputContext->Slot, sizeof (SLOT_CONTEXT));\r
+\r
+ ASSERT (ConfigDesc != NULL);\r
+\r
+ MaxDci = 0;\r
+\r
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);\r
+ for (Index = 0; Index < ConfigDesc->NumInterfaces; Index++) {\r
+ while ((IfDesc->DescriptorType != USB_DESC_TYPE_INTERFACE) || (IfDesc->AlternateSetting != 0)) {\r
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+ }\r
+\r
+ if (IfDesc->Length < sizeof (USB_INTERFACE_DESCRIPTOR)) {\r
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+ continue;\r
+ }\r
+\r
+ Dci = XhcInitializeEndpointContext (Xhc, SlotId, DeviceSpeed, InputContext, IfDesc);\r
+ if (Dci > MaxDci) {\r
+ MaxDci = Dci;\r
+ }\r
+\r
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+ }\r
+\r
+ InputContext->InputControlContext.Dword2 |= BIT0;\r
+ InputContext->Slot.ContextEntries = MaxDci;\r
+ //\r
+ // configure endpoint\r
+ //\r
+ ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));\r
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT));\r
+ CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (PhyAddr);\r
+ CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (PhyAddr);\r
+ CmdTrbCfgEP.CycleBit = 1;\r
+ CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT;\r
+ CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId;\r
+ DEBUG ((EFI_D_INFO, "Configure Endpoint\n"));\r
+ Status = XhcCmdTransfer (\r
+ Xhc,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP,\r
+ XHC_GENERIC_TIMEOUT,\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcSetConfigCmd: Config Endpoint Failed, Status = %r\n", Status));\r
+ } else {\r
+ Xhc->UsbDevContext[SlotId].ActiveConfiguration = ConfigDesc->ConfigurationValue;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Configure all the device endpoints through XHCI's Configure_Endpoint cmd.\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param SlotId The slot id to be configured.\r
+ @param DeviceSpeed The device's speed.\r
+ @param ConfigDesc The pointer to the usb device configuration descriptor.\r
+\r
+ @retval EFI_SUCCESS Successfully configure all the device endpoints.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcSetConfigCmd64 (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 SlotId,\r
+ IN UINT8 DeviceSpeed,\r
+ IN USB_CONFIG_DESCRIPTOR *ConfigDesc\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ USB_INTERFACE_DESCRIPTOR *IfDesc;\r
+ UINT8 Index;\r
+ UINT8 Dci;\r
+ UINT8 MaxDci;\r
+ EFI_PHYSICAL_ADDRESS PhyAddr;\r
+\r
+ CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;\r
+ INPUT_CONTEXT_64 *InputContext;\r
+ DEVICE_CONTEXT_64 *OutputContext;\r
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;\r
+ //\r
+ // 4.6.6 Configure Endpoint\r
+ //\r
+ InputContext = Xhc->UsbDevContext[SlotId].InputContext;\r
+ OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;\r
+ ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64));\r
+ CopyMem (&InputContext->Slot, &OutputContext->Slot, sizeof (SLOT_CONTEXT_64));\r
+\r
+ ASSERT (ConfigDesc != NULL);\r
+\r
+ MaxDci = 0;\r
+\r
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);\r
+ for (Index = 0; Index < ConfigDesc->NumInterfaces; Index++) {\r
+ while ((IfDesc->DescriptorType != USB_DESC_TYPE_INTERFACE) || (IfDesc->AlternateSetting != 0)) {\r
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+ }\r
+\r
+ if (IfDesc->Length < sizeof (USB_INTERFACE_DESCRIPTOR)) {\r
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+ continue;\r
+ }\r
+\r
+ Dci = XhcInitializeEndpointContext64 (Xhc, SlotId, DeviceSpeed, InputContext, IfDesc);\r
+ if (Dci > MaxDci) {\r
+ MaxDci = Dci;\r
+ }\r
+ \r
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+ }\r
+\r
+ InputContext->InputControlContext.Dword2 |= BIT0;\r
+ InputContext->Slot.ContextEntries = MaxDci;\r
+ //\r
+ // configure endpoint\r
+ //\r
+ ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));\r
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64));\r
+ CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (PhyAddr);\r
+ CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (PhyAddr);\r
+ CmdTrbCfgEP.CycleBit = 1;\r
+ CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT;\r
+ CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId;\r
+ DEBUG ((EFI_D_INFO, "Configure Endpoint\n"));\r
+ Status = XhcCmdTransfer (\r
+ Xhc,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP,\r
+ XHC_GENERIC_TIMEOUT,\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcSetConfigCmd64: Config Endpoint Failed, Status = %r\n", Status));\r
+ } else {\r
+ Xhc->UsbDevContext[SlotId].ActiveConfiguration = ConfigDesc->ConfigurationValue;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Stop endpoint through XHCI's Stop_Endpoint cmd.\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param SlotId The slot id to be configured.\r
+ @param Dci The device context index of endpoint.\r
+\r
+ @retval EFI_SUCCESS Stop endpoint successfully.\r
+ @retval Others Failed to stop endpoint.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcStopEndpoint (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 SlotId,\r
+ IN UINT8 Dci\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;\r
+ CMD_TRB_STOP_ENDPOINT CmdTrbStopED;\r
+\r
+ DEBUG ((EFI_D_INFO, "XhcStopEndpoint: Slot = 0x%x, Dci = 0x%x\n", SlotId, Dci));\r
+\r
+ //\r
+ // Send stop endpoint command to transit Endpoint from running to stop state\r
+ //\r
+ ZeroMem (&CmdTrbStopED, sizeof (CmdTrbStopED));\r
+ CmdTrbStopED.CycleBit = 1;\r
+ CmdTrbStopED.Type = TRB_TYPE_STOP_ENDPOINT;\r
+ CmdTrbStopED.EDID = Dci;\r
+ CmdTrbStopED.SlotId = SlotId;\r
+ Status = XhcCmdTransfer (\r
+ Xhc,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbStopED,\r
+ XHC_GENERIC_TIMEOUT,\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcStopEndpoint: Stop Endpoint Failed, Status = %r\n", Status));\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Reset endpoint through XHCI's Reset_Endpoint cmd.\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param SlotId The slot id to be configured.\r
+ @param Dci The device context index of endpoint.\r
+\r
+ @retval EFI_SUCCESS Reset endpoint successfully.\r
+ @retval Others Failed to reset endpoint.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcResetEndpoint (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 SlotId,\r
+ IN UINT8 Dci\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;\r
+ CMD_TRB_RESET_ENDPOINT CmdTrbResetED;\r
+\r
+ DEBUG ((EFI_D_INFO, "XhcResetEndpoint: Slot = 0x%x, Dci = 0x%x\n", SlotId, Dci));\r
+\r
+ //\r
+ // Send stop endpoint command to transit Endpoint from running to stop state\r
+ //\r
+ ZeroMem (&CmdTrbResetED, sizeof (CmdTrbResetED));\r
+ CmdTrbResetED.CycleBit = 1;\r
+ CmdTrbResetED.Type = TRB_TYPE_RESET_ENDPOINT;\r
+ CmdTrbResetED.EDID = Dci;\r
+ CmdTrbResetED.SlotId = SlotId;\r
+ Status = XhcCmdTransfer (\r
+ Xhc,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbResetED,\r
+ XHC_GENERIC_TIMEOUT,\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcResetEndpoint: Reset Endpoint Failed, Status = %r\n", Status));\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Set transfer ring dequeue pointer through XHCI's Set_Tr_Dequeue_Pointer cmd.\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param SlotId The slot id to be configured.\r
+ @param Dci The device context index of endpoint.\r
+ @param Urb The dequeue pointer of the transfer ring specified\r
+ by the urb to be updated.\r
+\r
+ @retval EFI_SUCCESS Set transfer ring dequeue pointer succeeds.\r
+ @retval Others Failed to set transfer ring dequeue pointer.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcSetTrDequeuePointer (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 SlotId,\r
+ IN UINT8 Dci,\r
+ IN URB *Urb\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;\r
+ CMD_SET_TR_DEQ_POINTER CmdSetTRDeq;\r
+ EFI_PHYSICAL_ADDRESS PhyAddr;\r
+\r
+ DEBUG ((EFI_D_INFO, "XhcSetTrDequeuePointer: Slot = 0x%x, Dci = 0x%x, Urb = 0x%x\n", SlotId, Dci, Urb));\r
+\r
+ //\r
+ // Send stop endpoint command to transit Endpoint from running to stop state\r
+ //\r
+ ZeroMem (&CmdSetTRDeq, sizeof (CmdSetTRDeq));\r
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Urb->Ring->RingEnqueue, sizeof (CMD_SET_TR_DEQ_POINTER));\r
+ CmdSetTRDeq.PtrLo = XHC_LOW_32BIT (PhyAddr) | Urb->Ring->RingPCS;\r
+ CmdSetTRDeq.PtrHi = XHC_HIGH_32BIT (PhyAddr);\r
+ CmdSetTRDeq.CycleBit = 1;\r
+ CmdSetTRDeq.Type = TRB_TYPE_SET_TR_DEQUE;\r
+ CmdSetTRDeq.Endpoint = Dci;\r
+ CmdSetTRDeq.SlotId = SlotId;\r
+ Status = XhcCmdTransfer (\r
+ Xhc,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdSetTRDeq,\r
+ XHC_GENERIC_TIMEOUT,\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcSetTrDequeuePointer: Set TR Dequeue Pointer Failed, Status = %r\n", Status));\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Set interface through XHCI's Configure_Endpoint cmd.\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param SlotId The slot id to be configured.\r
+ @param DeviceSpeed The device's speed.\r
+ @param ConfigDesc The pointer to the usb device configuration descriptor.\r
+ @param Request USB device request to send.\r
+\r
+ @retval EFI_SUCCESS Successfully set interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcSetInterface (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 SlotId,\r
+ IN UINT8 DeviceSpeed,\r
+ IN USB_CONFIG_DESCRIPTOR *ConfigDesc,\r
+ IN EFI_USB_DEVICE_REQUEST *Request\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ USB_INTERFACE_DESCRIPTOR *IfDescActive;\r
+ USB_INTERFACE_DESCRIPTOR *IfDescSet;\r
+ USB_INTERFACE_DESCRIPTOR *IfDesc;\r
+ USB_ENDPOINT_DESCRIPTOR *EpDesc;\r
+ UINTN NumEp;\r
+ UINTN EpIndex;\r
+ UINT8 EpAddr;\r
+ UINT8 Direction;\r
+ UINT8 Dci;\r
+ UINT8 MaxDci;\r
+ EFI_PHYSICAL_ADDRESS PhyAddr;\r
+ VOID *RingSeg;\r