)\r
{\r
EFI_STATUS Status;\r
- EVT_TRB_COMMAND_COMPLETION *EvtTrb;\r
- CMD_TRB_RESET_ENDPOINT CmdTrbResetED;\r
- CMD_SET_TR_DEQ_POINTER CmdSetTRDeq;\r
UINT8 Dci;\r
UINT8 SlotId;\r
- EFI_PHYSICAL_ADDRESS PhyAddr;\r
\r
Status = EFI_SUCCESS;\r
SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);\r
//\r
// 1) Send Reset endpoint command to transit from halt 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
+ Status = XhcResetEndpoint(Xhc, SlotId, Dci);\r
if (EFI_ERROR(Status)) {\r
DEBUG ((EFI_D_ERROR, "XhcRecoverHaltedEndpoint: Reset Endpoint Failed, Status = %r\n", Status));\r
goto Done;\r
//\r
// 2)Set dequeue pointer\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
+ Status = XhcSetTrDequeuePointer(Xhc, SlotId, Dci, Urb);\r
if (EFI_ERROR(Status)) {\r
- DEBUG ((EFI_D_ERROR, "XhcRecoverHaltedEndpoint: Set Dequeue Pointer Failed, Status = %r\n", Status));\r
+ DEBUG ((EFI_D_ERROR, "XhcRecoverHaltedEndpoint: Set Transfer Ring Dequeue Pointer Failed, Status = %r\n", Status));\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // 3)Ring the doorbell to transit from stop to active\r
+ //\r
+ XhcRingDoorBell (Xhc, SlotId, Dci);\r
+\r
+Done:\r
+ return Status;\r
+}\r
+\r
+/**\r
+ System software shall use a Stop Endpoint Command (section 4.6.9) and the Set TR Dequeue Pointer\r
+ Command (section 4.6.10) to remove the timed-out TDs from the xHC transfer ring. The next write to\r
+ the Doorbell of the Endpoint will transition the Endpoint Context from the Stopped to the Running\r
+ state.\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param Urb The urb which doesn't get completed in a specified timeout range.\r
+\r
+ @retval EFI_SUCCESS The dequeuing of the TDs is successful.\r
+ @retval Others Failed to stop the endpoint and dequeue the TDs.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcDequeueTrbFromEndpoint (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN URB *Urb\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 Dci;\r
+ UINT8 SlotId;\r
+\r
+ Status = EFI_SUCCESS;\r
+ SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);\r
+ if (SlotId == 0) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));\r
+ ASSERT (Dci < 32);\r
+ \r
+ DEBUG ((EFI_D_INFO, "Stop Slot = %x,Dci = %x\n", SlotId, Dci));\r
+\r
+ //\r
+ // 1) Send Stop endpoint command to stop xHC from executing of the TDs on the endpoint\r
+ //\r
+ Status = XhcStopEndpoint(Xhc, SlotId, Dci);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcDequeueTrbFromEndpoint: Stop Endpoint Failed, Status = %r\n", Status));\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // 2)Set dequeue pointer\r
+ //\r
+ Status = XhcSetTrDequeuePointer(Xhc, SlotId, Dci, Urb);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcDequeueTrbFromEndpoint: Set Transfer Ring Dequeue Pointer Failed, Status = %r\n", Status));\r
goto Done;\r
}\r
\r
return TRUE;\r
}\r
CheckedTrb++;\r
- if ((UINTN)CheckedTrb >= ((UINTN) CheckedUrb->Ring->RingSeg0 + sizeof (TRB_TEMPLATE) * CheckedUrb->Ring->TrbNumber)) {\r
+ //\r
+ // If the checked TRB is the link TRB at the end of the transfer ring,\r
+ // recircle it to the head of the ring.\r
+ //\r
+ if (CheckedTrb->Type == TRB_TYPE_LINK) {\r
CheckedTrb = (TRB_TEMPLATE*) CheckedUrb->Ring->RingSeg0;\r
}\r
}\r
case TRB_COMPLETION_SHORT_PACKET:\r
case TRB_COMPLETION_SUCCESS:\r
if (EvtTrb->Completecode == TRB_COMPLETION_SHORT_PACKET) {\r
- DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: short packet happens!\n"));\r
+ DEBUG ((EFI_D_VERBOSE, "XhcCheckUrbResult: short packet happens!\n"));\r
}\r
\r
TRBType = (UINT8) (TRBPtr->Type);\r
{\r
EFI_STATUS Status;\r
UINTN Index;\r
- UINTN Loop;\r
+ UINT64 Loop;\r
UINT8 SlotId;\r
UINT8 Dci;\r
BOOLEAN Finished;\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
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
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
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
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
\r
IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);\r
while ((UINTN) IfDesc < ((UINTN) ConfigDesc + ConfigDesc->TotalLength)) {\r
- if (IfDesc->DescriptorType == USB_DESC_TYPE_INTERFACE) {\r
+ if ((IfDesc->DescriptorType == USB_DESC_TYPE_INTERFACE) && (IfDesc->Length >= sizeof (USB_INTERFACE_DESCRIPTOR))) {\r
if (IfDesc->InterfaceNumber == (UINT8) Request->Index) {\r
if (IfDesc->AlternateSetting == Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[IfDesc->InterfaceNumber]) {\r
//\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
\r
IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);\r
while ((UINTN) IfDesc < ((UINTN) ConfigDesc + ConfigDesc->TotalLength)) {\r
- if (IfDesc->DescriptorType == USB_DESC_TYPE_INTERFACE) {\r
+ if ((IfDesc->DescriptorType == USB_DESC_TYPE_INTERFACE) && (IfDesc->Length >= sizeof (USB_INTERFACE_DESCRIPTOR))) {\r
if (IfDesc->InterfaceNumber == (UINT8) Request->Index) {\r
if (IfDesc->AlternateSetting == Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[IfDesc->InterfaceNumber]) {\r
//\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