+/**\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
+XhcInitializeEndpointContext (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 SlotId,\r
+ IN UINT8 DeviceSpeed,\r
+ IN INPUT_CONTEXT *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
+ 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
+ break;\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
+ default:\r
+ ASSERT (0);\r
+ break;\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 &= ~(0x0F);\r
+ PhyAddr |= ((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
+ 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
+ break;\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
+ default:\r
+ ASSERT (0);\r
+ break;\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 &= ~(0x0F);\r
+ PhyAddr |= ((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