Urb->TrbStart->CycleBit = Urb->Ring->RingPCS & BIT0;\r
Urb->TrbEnd = Urb->TrbStart;\r
\r
- Urb->EvtRing = &Xhc->CmdEventRing;\r
+ Urb->EvtRing = &Xhc->EventRing;\r
XhcSyncEventRing (Xhc, Urb->EvtRing);\r
Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
\r
goto ON_EXIT;\r
}\r
\r
- ASSERT (Urb->EvtRing == &Xhc->CmdEventRing);\r
+ ASSERT (Urb->EvtRing == &Xhc->EventRing);\r
\r
Status = XhcExecTransfer (Xhc, TRUE, Urb, Timeout);\r
*EvtTrb = Urb->EvtTrbStart;\r
Create a new URB for a new transaction.\r
\r
@param Xhc The XHCI Instance\r
- @param DevAddr The device address\r
+ @param BusAddr The logical device address assigned by UsbBus driver\r
@param EpAddr Endpoint addrress\r
@param DevSpeed The device speed\r
@param MaxPacket The max packet length of the endpoint\r
URB*\r
XhcCreateUrb (\r
IN USB_XHCI_INSTANCE *Xhc,\r
- IN UINT8 DevAddr,\r
+ IN UINT8 BusAddr,\r
IN UINT8 EpAddr,\r
IN UINT8 DevSpeed,\r
IN UINTN MaxPacket,\r
InitializeListHead (&Urb->UrbList);\r
\r
Ep = &Urb->Ep;\r
- Ep->DevAddr = DevAddr;\r
+ Ep->BusAddr = BusAddr;\r
Ep->EpAddr = (UINT8)(EpAddr & 0x0F);\r
Ep->Direction = ((EpAddr & 0x80) != 0) ? EfiUsbDataIn : EfiUsbDataOut;\r
Ep->DevSpeed = DevSpeed;\r
IN URB *Urb\r
)\r
{\r
- DEVICE_CONTEXT *OutputContext;\r
+ VOID *OutputContext;\r
TRANSFER_RING *EPRing;\r
UINT8 EPType;\r
UINT8 SlotId;\r
UINTN Len;\r
UINTN TrbNum;\r
\r
- SlotId = XhcDevAddrToSlotId(Xhc, Urb->Ep.DevAddr);\r
+ SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);\r
+ if (SlotId == 0) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));\r
ASSERT (Dci < 32);\r
EPRing = (TRANSFER_RING *)(UINTN) Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1];\r
Urb->Ring = EPRing;\r
- OutputContext = (DEVICE_CONTEXT *)(UINTN) Xhc->DCBAA[SlotId];\r
- EPType = (UINT8) OutputContext->EP[Dci-1].EPType;\r
+ OutputContext = (VOID *)(UINTN)Xhc->DCBAA[SlotId];\r
+ if (Xhc->HcCParams.Data.Csz == 0) {\r
+ EPType = (UINT8) ((DEVICE_CONTEXT *)OutputContext)->EP[Dci-1].EPType;\r
+ } else {\r
+ EPType = (UINT8) ((DEVICE_CONTEXT_64 *)OutputContext)->EP[Dci-1].EPType;\r
+ }\r
\r
//\r
// Construct the TRB\r
Urb->TrbStart = EPRing->RingEnqueue;\r
switch (EPType) {\r
case ED_CONTROL_BIDIR:\r
- Urb->EvtRing = &Xhc->CtrlTrEventRing;\r
+ Urb->EvtRing = &Xhc->EventRing;\r
XhcSyncEventRing (Xhc, Urb->EvtRing);\r
Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
//\r
TrbStart->TrbCtrSetup.wIndex = Urb->Request->Index;\r
TrbStart->TrbCtrSetup.wLength = Urb->Request->Length;\r
TrbStart->TrbCtrSetup.Lenth = 8;\r
- TrbStart->TrbCtrSetup.IntTarget = Urb->EvtRing->EventInterrupter;\r
+ TrbStart->TrbCtrSetup.IntTarget = 0;\r
TrbStart->TrbCtrSetup.IOC = 1;\r
TrbStart->TrbCtrSetup.IDT = 1;\r
TrbStart->TrbCtrSetup.Type = TRB_TYPE_SETUP_STAGE;\r
TrbStart->TrbCtrData.TRBPtrHi = XHC_HIGH_32BIT(Urb->Data);\r
TrbStart->TrbCtrData.Lenth = (UINT32) Urb->DataLen;\r
TrbStart->TrbCtrData.TDSize = 0;\r
- TrbStart->TrbCtrData.IntTarget = Urb->EvtRing->EventInterrupter;\r
+ TrbStart->TrbCtrData.IntTarget = 0;\r
TrbStart->TrbCtrData.ISP = 1;\r
TrbStart->TrbCtrData.IOC = 1;\r
TrbStart->TrbCtrData.IDT = 0;\r
//\r
XhcSyncTrsRing (Xhc, EPRing);\r
TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;\r
- TrbStart->TrbCtrStatus.IntTarget = Urb->EvtRing->EventInterrupter;\r
+ TrbStart->TrbCtrStatus.IntTarget = 0;\r
TrbStart->TrbCtrStatus.IOC = 1;\r
TrbStart->TrbCtrStatus.CH = 0;\r
TrbStart->TrbCtrStatus.Type = TRB_TYPE_STATUS_STAGE;\r
\r
case ED_BULK_OUT:\r
case ED_BULK_IN:\r
- Urb->EvtRing = &Xhc->BulkTrEventRing;\r
+ Urb->EvtRing = &Xhc->EventRing;\r
XhcSyncEventRing (Xhc, Urb->EvtRing);\r
Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
\r
TrbStart->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT((UINT8 *) Urb->Data + TotalLen);\r
TrbStart->TrbNormal.Lenth = (UINT32) Len;\r
TrbStart->TrbNormal.TDSize = 0;\r
- TrbStart->TrbNormal.IntTarget = Urb->EvtRing->EventInterrupter;\r
+ TrbStart->TrbNormal.IntTarget = 0;\r
TrbStart->TrbNormal.ISP = 1;\r
TrbStart->TrbNormal.IOC = 1;\r
TrbStart->TrbNormal.Type = TRB_TYPE_NORMAL;\r
\r
case ED_INTERRUPT_OUT:\r
case ED_INTERRUPT_IN:\r
- if (Urb->Ep.Type == XHC_INT_TRANSFER_ASYNC) {\r
- Urb->EvtRing = &Xhc->AsynIntTrEventRing;\r
- } else if(Urb->Ep.Type == XHC_INT_TRANSFER_SYNC){\r
- Urb->EvtRing = &Xhc->IntTrEventRing;\r
- } else {\r
- DEBUG ((EFI_D_ERROR, "EP Interrupt type error!\n"));\r
- ASSERT(FALSE);\r
- }\r
+ Urb->EvtRing = &Xhc->EventRing;\r
XhcSyncEventRing (Xhc, Urb->EvtRing);\r
Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
\r
TrbStart->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT((UINT8 *) Urb->Data + TotalLen);\r
TrbStart->TrbNormal.Lenth = (UINT32) Len;\r
TrbStart->TrbNormal.TDSize = 0;\r
- TrbStart->TrbNormal.IntTarget = Urb->EvtRing->EventInterrupter;\r
+ TrbStart->TrbNormal.IntTarget = 0;\r
TrbStart->TrbNormal.ISP = 1;\r
TrbStart->TrbNormal.IOC = 1;\r
TrbStart->TrbNormal.Type = TRB_TYPE_NORMAL;\r
// a 64-bit address pointing to where the Device Context Base Address Array is located.\r
//\r
Xhc->DCBAA = (UINT64 *)(UINTN)Dcbaa;\r
- XhcWriteOpReg64 (Xhc, XHC_DCBAAP_OFFSET, (UINT64)(UINTN)Xhc->DCBAA);\r
+ //\r
+ // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
+ // So divide it to two 32-bytes width register access.\r
+ //\r
+ XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET, XHC_LOW_32BIT(Xhc->DCBAA));\r
+ XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET + 4, XHC_HIGH_32BIT (Xhc->DCBAA));\r
DEBUG ((EFI_D_INFO, "XhcInitSched:DCBAA=0x%x\n", (UINT64)(UINTN)Xhc->DCBAA));\r
\r
//\r
CmdRing = (UINT64)(UINTN)Xhc->CmdRing.RingSeg0;\r
ASSERT ((CmdRing & 0x3F) == 0);\r
CmdRing |= XHC_CRCR_RCS;\r
- XhcWriteOpReg64 (Xhc, XHC_CRCR_OFFSET, CmdRing);\r
+ //\r
+ // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
+ // So divide it to two 32-bytes width register access.\r
+ //\r
+ XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET, XHC_LOW_32BIT(CmdRing));\r
+ XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET + 4, XHC_HIGH_32BIT (CmdRing));\r
\r
DEBUG ((EFI_D_INFO, "XhcInitSched:XHC_CRCR=0x%x\n", Xhc->CmdRing.RingSeg0));\r
\r
//\r
// Allocate EventRing for Cmd, Ctrl, Bulk, Interrupt, AsynInterrupt transfer\r
//\r
- CreateEventRing (Xhc, CMD_INTER, &Xhc->CmdEventRing);\r
- CreateEventRing (Xhc, CTRL_INTER, &Xhc->CtrlTrEventRing);\r
- CreateEventRing (Xhc, BULK_INTER, &Xhc->BulkTrEventRing);\r
- CreateEventRing (Xhc, INT_INTER, &Xhc->IntTrEventRing);\r
- CreateEventRing (Xhc, INT_INTER_ASYNC, &Xhc->AsynIntTrEventRing);\r
+ CreateEventRing (Xhc, &Xhc->EventRing);\r
+ DEBUG ((EFI_D_INFO, "XhcInitSched:XHC_EVENTRING=0x%x\n", Xhc->EventRing.EventRingSeg0));\r
}\r
\r
/**\r
UINT8 Dci;\r
UINT8 SlotId;\r
\r
- Status = EFI_SUCCESS;\r
- SlotId = XhcDevAddrToSlotId(Xhc, Urb->Ep.DevAddr);\r
- Dci = XhcEndpointToDci(Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));\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, "Recovery Halted Slot = %x,Dci = %x\n", SlotId, Dci));\r
\r
//\r
Create XHCI event ring.\r
\r
@param Xhc The XHCI Instance.\r
- @param EventInterrupter The interrupter of event.\r
@param EventRing The created event ring.\r
\r
**/\r
VOID\r
CreateEventRing (\r
IN USB_XHCI_INSTANCE *Xhc,\r
- IN UINT8 EventInterrupter,\r
OUT EVENT_RING *EventRing\r
)\r
{\r
ZeroMem (Buf, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);\r
\r
EventRing->EventRingSeg0 = Buf;\r
- EventRing->EventInterrupter = EventInterrupter;\r
EventRing->TrbNumber = EVENT_RING_TRB_NUMBER;\r
EventRing->EventRingDequeue = (TRB_TEMPLATE *) EventRing->EventRingSeg0;\r
EventRing->EventRingEnqueue = (TRB_TEMPLATE *) EventRing->EventRingSeg0;\r
//\r
XhcWriteRuntimeReg (\r
Xhc,\r
- XHC_ERSTSZ_OFFSET + (32 * EventRing->EventInterrupter),\r
+ XHC_ERSTSZ_OFFSET,\r
ERST_NUMBER\r
);\r
//\r
// Program the Interrupter Event Ring Dequeue Pointer (ERDP) register (5.5.2.3.3)\r
//\r
- XhcWriteRuntimeReg64 (\r
+ // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
+ // So divide it to two 32-bytes width register access.\r
+ //\r
+ XhcWriteRuntimeReg (\r
+ Xhc,\r
+ XHC_ERDP_OFFSET,\r
+ XHC_LOW_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)\r
+ );\r
+ XhcWriteRuntimeReg (\r
Xhc,\r
- XHC_ERDP_OFFSET + (32 * EventRing->EventInterrupter),\r
- (UINT64)(UINTN)EventRing->EventRingDequeue\r
+ XHC_ERDP_OFFSET + 4,\r
+ XHC_HIGH_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)\r
);\r
//\r
// Program the Interrupter Event Ring Segment Table Base Address (ERSTBA) register(5.5.2.3.2)\r
//\r
- XhcWriteRuntimeReg64 (\r
+ // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
+ // So divide it to two 32-bytes width register access.\r
+ //\r
+ XhcWriteRuntimeReg (\r
+ Xhc,\r
+ XHC_ERSTBA_OFFSET,\r
+ XHC_LOW_32BIT((UINT64)(UINTN)ERSTBase)\r
+ );\r
+ XhcWriteRuntimeReg (\r
Xhc,\r
- XHC_ERSTBA_OFFSET + (32 * EventRing->EventInterrupter),\r
- (UINT64)(UINTN)ERSTBase\r
+ XHC_ERSTBA_OFFSET + 4,\r
+ XHC_HIGH_32BIT((UINT64)(UINTN)ERSTBase)\r
);\r
//\r
// Need set IMAN IE bit to enble the ring interrupt\r
//\r
- XhcSetRuntimeRegBit (Xhc, XHC_IMAN_OFFSET + (32 * EventRing->EventInterrupter), XHC_IMAN_IE);\r
+ XhcSetRuntimeRegBit (Xhc, XHC_IMAN_OFFSET, XHC_IMAN_IE);\r
}\r
\r
/**\r
Xhc->CmdRing.RingSeg0 = NULL;\r
}\r
\r
- XhcFreeEventRing (Xhc,&Xhc->CmdEventRing);\r
- XhcFreeEventRing (Xhc,&Xhc->CtrlTrEventRing);\r
- XhcFreeEventRing (Xhc,&Xhc->BulkTrEventRing);\r
- XhcFreeEventRing (Xhc,&Xhc->AsynIntTrEventRing);\r
- XhcFreeEventRing (Xhc,&Xhc->IntTrEventRing);\r
+ XhcFreeEventRing (Xhc,&Xhc->EventRing);\r
}\r
\r
/**\r
goto EXIT;\r
}\r
\r
- TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | (UINT64) EvtTrb->TRBPtrHi << 32);\r
+ //\r
+ // Only handle COMMAND_COMPLETETION_EVENT and TRANSFER_EVENT.\r
+ //\r
+ if ((EvtTrb->Type != TRB_TYPE_COMMAND_COMPLT_EVENT) && (EvtTrb->Type != TRB_TYPE_TRANS_EVENT)) {\r
+ continue;\r
+ }\r
\r
- switch (EvtTrb->Completecode) {\r
- case TRB_COMPLETION_STALL_ERROR:\r
- Urb->Result |= EFI_USB_ERR_STALL;\r
- Status = EFI_DEVICE_ERROR;\r
- DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: STALL_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
- goto EXIT;\r
- break;\r
+ TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | (UINT64) EvtTrb->TRBPtrHi << 32);\r
+ if (IsTransferRingTrb (Urb->Ring, TRBPtr)) {\r
+ switch (EvtTrb->Completecode) {\r
+ case TRB_COMPLETION_STALL_ERROR:\r
+ Urb->Result |= EFI_USB_ERR_STALL;\r
+ Status = EFI_DEVICE_ERROR;\r
+ DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: STALL_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
+ goto EXIT;\r
+ break;\r
\r
- case TRB_COMPLETION_BABBLE_ERROR:\r
- Urb->Result |= EFI_USB_ERR_BABBLE;\r
- Status = EFI_DEVICE_ERROR;\r
- DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: BABBLE_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
- goto EXIT;\r
- break;\r
+ case TRB_COMPLETION_BABBLE_ERROR:\r
+ Urb->Result |= EFI_USB_ERR_BABBLE;\r
+ Status = EFI_DEVICE_ERROR;\r
+ DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: BABBLE_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
+ goto EXIT;\r
+ break;\r
\r
- case TRB_COMPLETION_DATA_BUFFER_ERROR:\r
- Urb->Result |= EFI_USB_ERR_BUFFER;\r
- Status = EFI_DEVICE_ERROR;\r
- DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: ERR_BUFFER! Completecode = %x\n",EvtTrb->Completecode));\r
- goto EXIT;\r
- break;\r
+ case TRB_COMPLETION_DATA_BUFFER_ERROR:\r
+ Urb->Result |= EFI_USB_ERR_BUFFER;\r
+ Status = EFI_DEVICE_ERROR;\r
+ DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: ERR_BUFFER! Completecode = %x\n",EvtTrb->Completecode));\r
+ goto EXIT;\r
+ break;\r
\r
- case TRB_COMPLETION_USB_TRANSACTION_ERROR:\r
- Urb->Result |= EFI_USB_ERR_TIMEOUT;\r
- Status = EFI_DEVICE_ERROR;\r
- DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: TRANSACTION_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
- goto EXIT;\r
- break;\r
+ case TRB_COMPLETION_USB_TRANSACTION_ERROR:\r
+ Urb->Result |= EFI_USB_ERR_TIMEOUT;\r
+ Status = EFI_DEVICE_ERROR;\r
+ DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: TRANSACTION_ERROR! Completecode = %x\n",EvtTrb->Completecode));\r
+ goto EXIT;\r
+ break;\r
\r
- case TRB_COMPLETION_SHORT_PACKET:\r
- case TRB_COMPLETION_SUCCESS:\r
- if (IsTransferRingTrb (Urb->Ring, TRBPtr)) {\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
}\r
+\r
TRBType = (UINT8) (TRBPtr->Type);\r
if ((TRBType == TRB_TYPE_DATA_STAGE) ||\r
(TRBType == TRB_TYPE_NORMAL) ||\r
(TRBType == TRB_TYPE_ISOCH)) {\r
Urb->Completed += (Urb->DataLen - EvtTrb->Lenth);\r
}\r
- }\r
- Status = EFI_SUCCESS;\r
- break;\r
\r
- default:\r
- DEBUG ((EFI_D_ERROR, "Transfer Default Error Occur! Completecode = 0x%x!\n",EvtTrb->Completecode));\r
- Urb->Result |= EFI_USB_ERR_TIMEOUT;\r
- Status = EFI_DEVICE_ERROR;\r
- goto EXIT;\r
- break;\r
- }\r
+ Status = EFI_SUCCESS;\r
+ break;\r
\r
- //\r
- // Only check first and end Trb event address\r
- //\r
- if (TRBPtr == Urb->TrbStart) {\r
- StartDone = TRUE;\r
- }\r
+ default:\r
+ DEBUG ((EFI_D_ERROR, "Transfer Default Error Occur! Completecode = 0x%x!\n",EvtTrb->Completecode));\r
+ Urb->Result |= EFI_USB_ERR_TIMEOUT;\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto EXIT;\r
+ break;\r
+ }\r
\r
- if (TRBPtr == Urb->TrbEnd) {\r
- EndDone = TRUE;\r
- }\r
+ //\r
+ // Only check first and end Trb event address\r
+ //\r
+ if (TRBPtr == Urb->TrbStart) {\r
+ StartDone = TRUE;\r
+ }\r
\r
- if (StartDone && EndDone) {\r
- break;\r
+ if (TRBPtr == Urb->TrbEnd) {\r
+ EndDone = TRUE;\r
+ }\r
+\r
+ if (StartDone && EndDone) {\r
+ break;\r
+ }\r
}\r
}\r
\r
SlotId = 0;\r
Dci = 0;\r
} else {\r
- SlotId = XhcDevAddrToSlotId(Xhc, Urb->Ep.DevAddr);\r
- Dci = XhcEndpointToDci(Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));\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
\r
Status = EFI_SUCCESS;\r
the device and endpoint.\r
\r
@param Xhc The XHCI Instance.\r
- @param DevAddr The address of the target device.\r
+ @param BusAddr The logical device address assigned by UsbBus driver.\r
@param EpNum The endpoint of the target.\r
\r
@retval EFI_SUCCESS An asynchronous transfer is removed.\r
EFI_STATUS\r
XhciDelAsyncIntTransfer (\r
IN USB_XHCI_INSTANCE *Xhc,\r
- IN UINT8 DevAddr,\r
+ IN UINT8 BusAddr,\r
IN UINT8 EpNum\r
)\r
{\r
Direction = ((EpNum & 0x80) != 0) ? EfiUsbDataIn : EfiUsbDataOut;\r
EpNum &= 0x0F;\r
\r
- Urb = NULL;\r
+ Urb = NULL;\r
\r
EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) {\r
Urb = EFI_LIST_CONTAINER (Entry, URB, UrbList);\r
- if ((Urb->Ep.DevAddr == DevAddr) &&\r
+ if ((Urb->Ep.BusAddr == BusAddr) &&\r
(Urb->Ep.EpAddr == EpNum) &&\r
(Urb->Ep.Direction == Direction)) {\r
RemoveEntryList (&Urb->UrbList);\r
\r
if (Urb->Result == EFI_USB_NOERROR) {\r
Status = XhcCreateTransferTrb (Xhc, Urb);\r
- ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
Status = RingIntTransferDoorBell (Xhc, Urb);\r
- ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
}\r
}\r
\r
//\r
// Make sure that the device is available before every check.\r
//\r
- SlotId = XhcDevAddrToSlotId(Xhc, Urb->Ep.DevAddr);\r
+ SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);\r
if (SlotId == 0) {\r
continue;\r
}\r
//\r
SlotId = XhcRouteStringToSlotId (Xhc, RouteChart);\r
if (SlotId == 0) {\r
- Status = XhcInitializeDeviceSlot (Xhc, ParentRouteChart, Port, RouteChart, Speed);\r
+ if (Xhc->HcCParams.Data.Csz == 0) {\r
+ Status = XhcInitializeDeviceSlot (Xhc, ParentRouteChart, Port, RouteChart, Speed);\r
+ } else {\r
+ Status = XhcInitializeDeviceSlot64 (Xhc, ParentRouteChart, Port, RouteChart, Speed);\r
+ }\r
ASSERT_EFI_ERROR (Status);\r
}\r
} else if ((PortState->PortStatus & USB_PORT_STAT_CONNECTION) == 0) {\r
//\r
SlotId = XhcRouteStringToSlotId (Xhc, RouteChart);\r
if (SlotId != 0) {\r
- Status = XhcDisableSlotCmd (Xhc, SlotId);\r
+ if (Xhc->HcCParams.Data.Csz == 0) {\r
+ Status = XhcDisableSlotCmd (Xhc, SlotId);\r
+ } else {\r
+ Status = XhcDisableSlotCmd64 (Xhc, SlotId);\r
+ }\r
ASSERT_EFI_ERROR (Status);\r
}\r
}\r
}\r
}\r
\r
-/**\r
- Find out the slot id according to device address assigned by XHCI's Address_Device cmd.\r
-\r
- @param Xhc The XHCI Instance.\r
- @param DevAddr The device address of the target device.\r
-\r
- @return The slot id used by the device.\r
-\r
-**/\r
-UINT8\r
-XhcDevAddrToSlotId (\r
- IN USB_XHCI_INSTANCE *Xhc,\r
- IN UINT8 DevAddr\r
- )\r
-{\r
- UINT8 Index;\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].XhciDevAddr == DevAddr)) {\r
- break;\r
- }\r
- }\r
-\r
- if (Index == 255) {\r
- return 0;\r
- }\r
-\r
- return Xhc->UsbDevContext[Index + 1].SlotId;\r
-}\r
-\r
/**\r
Find out the actual device address according to the requested device address from UsbBus.\r
\r
UINTN Index;\r
TRB_TEMPLATE *EvtTrb1;\r
TRB_TEMPLATE *EvtTrb2;\r
- TRB_TEMPLATE *XhcDequeue;\r
+ UINT64 XhcDequeue;\r
+ UINT32 High;\r
+ UINT32 Low;\r
\r
ASSERT (EvtRing != NULL);\r
\r
//\r
// Apply the EventRingDequeue to Xhc\r
//\r
- XhcDequeue = (TRB_TEMPLATE *)(UINTN) XhcReadRuntimeReg64 (\r
- Xhc,\r
- XHC_ERDP_OFFSET + (32 * EvtRing->EventInterrupter)\r
- );\r
-\r
- if (((UINT64)(UINTN)XhcDequeue & (~0x0F)) != ((UINT64)(UINTN)EvtRing->EventRingDequeue & (~0x0F))) {\r
- XhcWriteRuntimeReg64 (\r
- Xhc,\r
- XHC_ERDP_OFFSET + (32 * EvtRing->EventInterrupter),\r
- (UINT64)(UINTN)EvtRing->EventRingDequeue | BIT3\r
- );\r
+ // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
+ // So divide it to two 32-bytes width register access.\r
+ //\r
+ Low = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET);\r
+ High = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4);\r
+ XhcDequeue = (UINT64)(LShiftU64((UINT64)High, 32) | Low);\r
+\r
+ if ((XhcDequeue & (~0x0F)) != ((UINT64)(UINTN)EvtRing->EventRingDequeue & (~0x0F))) {\r
+ //\r
+ // Some 3rd party XHCI external cards don't support single 64-bytes width register access,\r
+ // So divide it to two 32-bytes width register access.\r
+ //\r
+ XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET, Low | BIT3);\r
+ XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4, High);\r
}\r
\r
return EFI_SUCCESS;\r
UINT8 SlotId;\r
UINT8 Dci;\r
\r
- SlotId = XhcDevAddrToSlotId(Xhc, Urb->Ep.DevAddr);\r
- Dci = XhcEndpointToDci(Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));\r
+ SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);\r
+ Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));\r
XhcRingDoorBell (Xhc, SlotId, Dci);\r
return EFI_SUCCESS;\r
}\r
}\r
\r
/**\r
- Disable the specified device slot.\r
+ Assign and initialize the device slot for a new device.\r
\r
- @param Xhc The XHCI Instance.\r
- @param SlotId The slot id to be disabled.\r
+ @param Xhc The XHCI Instance.\r
+ @param ParentRouteChart The route string pointed to the parent device.\r
+ @param ParentPort The port at which the device is located.\r
+ @param RouteChart The route string pointed to the device.\r
+ @param DeviceSpeed The device speed.\r
\r
- @retval EFI_SUCCESS Successfully disable the device slot.\r
+ @retval EFI_SUCCESS Successfully assign a slot to the device and assign an address to it.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-XhcDisableSlotCmd (\r
- IN USB_XHCI_INSTANCE *Xhc,\r
- IN UINT8 SlotId\r
+XhcInitializeDeviceSlot64 (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN USB_DEV_ROUTE ParentRouteChart,\r
+ IN UINT16 ParentPort,\r
+ IN USB_DEV_ROUTE RouteChart,\r
+ IN UINT8 DeviceSpeed\r
)\r
{\r
- EFI_STATUS Status;\r
- TRB_TEMPLATE *EvtTrb;\r
- CMD_TRB_DISABLE_SLOT CmdTrbDisSlot;\r
- UINT8 Index;\r
- VOID *RingSeg;\r
+ EFI_STATUS Status;\r
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;\r
+ INPUT_CONTEXT_64 *InputContext;\r
+ DEVICE_CONTEXT_64 *OutputContext;\r
+ TRANSFER_RING *EndpointTransferRing;\r
+ CMD_TRB_ADDRESS_DEVICE CmdTrbAddr;\r
+ UINT8 DeviceAddress;\r
+ CMD_TRB_ENABLE_SLOT CmdTrb;\r
+ UINT8 SlotId;\r
+ UINT8 ParentSlotId;\r
+ DEVICE_CONTEXT_64 *ParentDeviceContext;\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
+ ZeroMem (&CmdTrb, sizeof (CMD_TRB_ENABLE_SLOT));\r
+ CmdTrb.CycleBit = 1;\r
+ CmdTrb.Type = TRB_TYPE_EN_SLOT;\r
\r
- Status = XhcDisableSlotCmd (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);\r
+ Status = XhcCmdTransfer (\r
+ Xhc,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrb,\r
+ XHC_GENERIC_TIMEOUT,\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ ASSERT (EvtTrb->SlotId <= Xhc->MaxSlotsEn);\r
+ DEBUG ((EFI_D_INFO, "Enable Slot Successfully, The Slot ID = 0x%x\n", EvtTrb->SlotId));\r
+ SlotId = (UINT8)EvtTrb->SlotId;\r
+ ASSERT (SlotId != 0);\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
+ ZeroMem (&Xhc->UsbDevContext[SlotId], sizeof (USB_DEV_CONTEXT));\r
+ Xhc->UsbDevContext[SlotId].Enabled = TRUE;\r
+ Xhc->UsbDevContext[SlotId].SlotId = SlotId;\r
+ Xhc->UsbDevContext[SlotId].RouteString.Dword = RouteChart.Dword;\r
+ Xhc->UsbDevContext[SlotId].ParentRouteString.Dword = ParentRouteChart.Dword;\r
\r
//\r
- // Construct the disable slot command\r
+ // 4.3.3 Device Slot Initialization\r
+ // 1) Allocate an Input Context data structure (6.2.5) and initialize all fields to '0'.\r
//\r
- DEBUG ((EFI_D_INFO, "Disable device slot %d!\n", SlotId));\r
+ InputContext = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (INPUT_CONTEXT_64)));\r
+ ASSERT (InputContext != NULL);\r
+ ASSERT (((UINTN) InputContext & 0x3F) == 0);\r
+ ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64));\r
+\r
+ Xhc->UsbDevContext[SlotId].InputContext = (VOID *) InputContext;\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
+ // 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
- Xhc->DCBAA[SlotId] = 0;\r
+ InputContext->InputControlContext.Dword2 |= (BIT0 | BIT1);\r
\r
//\r
- // Free the slot related data structure\r
+ // 3) Initialize the Input Slot Context 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
+ 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
- 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
+ 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
- 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
+ // 4) Allocate and initialize the Transfer Ring for the Default Control Endpoint.\r
//\r
- Xhc->UsbDevContext[SlotId].Enabled = FALSE;\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 succeefully\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
+ //\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_64)));\r
+ }\r
+\r
+ if (Xhc->UsbDevContext[SlotId].OutputContext != NULL) {\r
+ FreePages (Xhc->UsbDevContext[SlotId].OutputContext, EFI_SIZE_TO_PAGES (sizeof (DEVICE_CONTEXT_64)));\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
+/**\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
+\r
+ USB_INTERFACE_DESCRIPTOR *IfDesc;\r
+ USB_ENDPOINT_DESCRIPTOR *EpDesc;\r
+ UINT8 Index;\r
+ UINTN NumEp;\r
+ UINTN EpIndex;\r
+ UINT8 EpAddr;\r
+ UINT8 Direction;\r
+ UINT8 Dci;\r
+ UINT8 MaxDci;\r
+ UINT32 PhyAddr;\r
+ UINT8 Interval;\r
+\r
+ TRANSFER_RING *EndpointTransferRing;\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) {\r
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+ }\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
+ // Hard code the interval to MAX first, need calculate through the bInterval field of Endpoint descriptor.\r
+ //\r
+ InputContext->EP[Dci-1].Interval = 6;\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 = XHC_LOW_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0);\r
+ PhyAddr &= ~(0x0F);\r
+ PhyAddr |= ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;\r
+ InputContext->EP[Dci-1].PtrLo = PhyAddr;\r
+ InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0);\r
+\r
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\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
+ CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (InputContext);\r
+ CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (InputContext);\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
+ ASSERT_EFI_ERROR(Status);\r
+\r
return Status;\r
}\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-XhcSetConfigCmd (\r
+XhcSetConfigCmd64 (\r
IN USB_XHCI_INSTANCE *Xhc,\r
IN UINT8 SlotId,\r
IN UINT8 DeviceSpeed,\r
\r
TRANSFER_RING *EndpointTransferRing;\r
CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;\r
- INPUT_CONTEXT *InputContext;\r
- DEVICE_CONTEXT *OutputContext;\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));\r
- CopyMem (&InputContext->Slot, &OutputContext->Slot, sizeof (SLOT_CONTEXT));\r
+ ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64));\r
+ CopyMem (&InputContext->Slot, &OutputContext->Slot, sizeof (SLOT_CONTEXT_64));\r
\r
ASSERT (ConfigDesc != NULL);\r
\r
return Status;\r
}\r
\r
+\r
/**\r
Evaluate the endpoint 0 context through XHCI's Evaluate_Context cmd.\r
\r
return Status;\r
}\r
\r
+/**\r
+ Evaluate the endpoint 0 context through XHCI's Evaluate_Context cmd.\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param SlotId The slot id to be evaluated.\r
+ @param MaxPacketSize The max packet size supported by the device control transfer.\r
+\r
+ @retval EFI_SUCCESS Successfully evaluate the device endpoint 0.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcEvaluateContext64 (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 SlotId,\r
+ IN UINT32 MaxPacketSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CMD_TRB_EVALUATE_CONTEXT CmdTrbEvalu;\r
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;\r
+ INPUT_CONTEXT_64 *InputContext;\r
+\r
+ ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);\r
+\r
+ //\r
+ // 4.6.7 Evaluate Context\r
+ //\r
+ InputContext = Xhc->UsbDevContext[SlotId].InputContext;\r
+ ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64));\r
+\r
+ InputContext->InputControlContext.Dword2 |= BIT1;\r
+ InputContext->EP[0].MaxPacketSize = MaxPacketSize;\r
+\r
+ ZeroMem (&CmdTrbEvalu, sizeof (CmdTrbEvalu));\r
+ CmdTrbEvalu.PtrLo = XHC_LOW_32BIT (InputContext);\r
+ CmdTrbEvalu.PtrHi = XHC_HIGH_32BIT (InputContext);\r
+ CmdTrbEvalu.CycleBit = 1;\r
+ CmdTrbEvalu.Type = TRB_TYPE_EVALU_CONTXT;\r
+ CmdTrbEvalu.SlotId = Xhc->UsbDevContext[SlotId].SlotId;\r
+ DEBUG ((EFI_D_INFO, "Evaluate context\n"));\r
+ Status = XhcCmdTransfer (\r
+ Xhc,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbEvalu,\r
+ XHC_GENERIC_TIMEOUT,\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+ );\r
+ ASSERT (!EFI_ERROR(Status));\r
+\r
+ return Status;\r
+}\r
+\r
+\r
/**\r
Evaluate the slot context for hub device through XHCI's Configure_Endpoint cmd.\r
\r
return Status;\r
}\r
\r
+/**\r
+ Evaluate the slot context for hub device through XHCI's Configure_Endpoint cmd.\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param SlotId The slot id to be configured.\r
+ @param PortNum The total number of downstream port supported by the hub.\r
+ @param TTT The TT think time of the hub device.\r
+ @param MTT The multi-TT of the hub device.\r
+\r
+ @retval EFI_SUCCESS Successfully configure the hub device's slot context.\r
+\r
+**/\r
+EFI_STATUS\r
+XhcConfigHubContext64 (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 SlotId,\r
+ IN UINT8 PortNum,\r
+ IN UINT8 TTT,\r
+ IN UINT8 MTT\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;\r
+ INPUT_CONTEXT_64 *InputContext;\r
+ DEVICE_CONTEXT_64 *OutputContext;\r
+ CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;\r
+\r
+ ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);\r
+ InputContext = Xhc->UsbDevContext[SlotId].InputContext;\r
+ OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;\r
+\r
+ //\r
+ // 4.6.7 Evaluate Context\r
+ //\r
+ ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64));\r
+\r
+ InputContext->InputControlContext.Dword2 |= BIT0;\r
+\r
+ //\r
+ // Copy the slot context from OutputContext to Input context\r
+ //\r
+ CopyMem(&(InputContext->Slot), &(OutputContext->Slot), sizeof (SLOT_CONTEXT_64));\r
+ InputContext->Slot.Hub = 1;\r
+ InputContext->Slot.PortNum = PortNum;\r
+ InputContext->Slot.TTT = TTT;\r
+ InputContext->Slot.MTT = MTT;\r
+\r
+ ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));\r
+ CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (InputContext);\r
+ CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (InputContext);\r
+ CmdTrbCfgEP.CycleBit = 1;\r
+ CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT;\r
+ CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId;\r
+ DEBUG ((EFI_D_INFO, "Configure Hub Slot Context\n"));\r
+ Status = XhcCmdTransfer (\r
+ Xhc,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP,\r
+ XHC_GENERIC_TIMEOUT,\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+ );\r
+ ASSERT (!EFI_ERROR(Status));\r
+\r
+ return Status;\r
+}\r
+\r
+\r