\r
XHCI transfer scheduling routines.\r
\r
-Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
\r
#include "Xhci.h"\r
\r
-/**\r
- Allocates a buffer of a certain pool type at a specified alignment.\r
-\r
- Allocates the number bytes specified by AllocationSize of a certain pool type with an alignment\r
- specified by Alignment. The allocated buffer is returned. If AllocationSize is 0, then a valid\r
- buffer of 0 size is returned. If there is not enough memory at the specified alignment remaining\r
- to satisfy the request, then NULL is returned.\r
- If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
-\r
- @param PoolType The type of pool to allocate.\r
- @param AllocationSize The number of bytes to allocate.\r
- @param Alignment The requested alignment of the allocation. Must be a power of two.\r
- If Alignment is zero, then byte alignment is used.\r
-\r
- @return A pointer to the allocated buffer or NULL if allocation fails.\r
-\r
-**/\r
-VOID *\r
-InternalAllocateAlignedPool (\r
- IN EFI_MEMORY_TYPE PoolType,\r
- IN UINTN AllocationSize,\r
- IN UINTN Alignment\r
- )\r
-{\r
- VOID *RawAddress;\r
- UINTN AlignedAddress;\r
- UINTN AlignmentMask;\r
- UINTN OverAllocationSize;\r
- UINTN RealAllocationSize;\r
- VOID **FreePointer;\r
-\r
- //\r
- // Alignment must be a power of two or zero.\r
- //\r
- ASSERT ((Alignment & (Alignment - 1)) == 0);\r
-\r
- if (Alignment == 0) {\r
- AlignmentMask = Alignment;\r
- } else {\r
- AlignmentMask = Alignment - 1;\r
- }\r
- //\r
- // Calculate the extra memory size, over-allocate memory pool and get the aligned memory address.\r
- //\r
- OverAllocationSize = sizeof (RawAddress) + AlignmentMask;\r
- RealAllocationSize = AllocationSize + OverAllocationSize;\r
- //\r
- // Make sure that AllocationSize plus OverAllocationSize does not overflow.\r
- //\r
- ASSERT (RealAllocationSize > AllocationSize);\r
-\r
- RawAddress = NULL;\r
- gBS->AllocatePool (PoolType, RealAllocationSize, &RawAddress);\r
- if (RawAddress == NULL) {\r
- return NULL;\r
- }\r
- AlignedAddress = ((UINTN) RawAddress + OverAllocationSize) & ~AlignmentMask;\r
- //\r
- // Save the original memory address just before the aligned address.\r
- //\r
- FreePointer = (VOID **)(AlignedAddress - sizeof (RawAddress));\r
- *FreePointer = RawAddress;\r
-\r
- return (VOID *) AlignedAddress;\r
-}\r
-\r
-/**\r
- Allocates and zeros a buffer of a certain pool type at a specified alignment.\r
-\r
- Allocates the number bytes specified by AllocationSize of a certain pool type with an alignment\r
- specified by Alignment, clears the buffer with zeros, and returns a pointer to the allocated\r
- buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is not\r
- enough memory at the specified alignment remaining to satisfy the request, then NULL is returned.\r
- If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
-\r
- @param PoolType The type of pool to allocate.\r
- @param AllocationSize The number of bytes to allocate.\r
- @param Alignment The requested alignment of the allocation. Must be a power of two.\r
- If Alignment is zero, then byte alignment is used.\r
-\r
- @return A pointer to the allocated buffer or NULL if allocation fails.\r
-\r
-**/\r
-VOID *\r
-InternalAllocateAlignedZeroPool (\r
- IN EFI_MEMORY_TYPE PoolType,\r
- IN UINTN AllocationSize,\r
- IN UINTN Alignment\r
- )\r
-{\r
- VOID *Memory;\r
- Memory = InternalAllocateAlignedPool (PoolType, AllocationSize, Alignment);\r
- if (Memory != NULL) {\r
- ZeroMem (Memory, AllocationSize);\r
- }\r
- return Memory;\r
-}\r
-\r
-/**\r
- Allocates and zeros a buffer of type EfiBootServicesData at a specified alignment.\r
-\r
- Allocates the number bytes specified by AllocationSize of type EfiBootServicesData with an\r
- alignment specified by Alignment, clears the buffer with zeros, and returns a pointer to the\r
- allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
- is not enough memory at the specified alignment remaining to satisfy the request, then NULL is\r
- returned.\r
- If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
-\r
- @param AllocationSize The number of bytes to allocate.\r
- @param Alignment The requested alignment of the allocation. Must be a power of two.\r
- If Alignment is zero, then byte alignment is used.\r
-\r
- @return A pointer to the allocated buffer or NULL if allocation fails.\r
-\r
-**/\r
-VOID *\r
-EFIAPI\r
-AllocateAlignedZeroPool (\r
- IN UINTN AllocationSize,\r
- IN UINTN Alignment\r
- )\r
-{\r
- return InternalAllocateAlignedZeroPool (EfiBootServicesData, AllocationSize, Alignment);\r
-}\r
-\r
-/**\r
- Frees a buffer that was previously allocated with one of the aligned pool allocation functions\r
- in the Memory Allocation Library.\r
-\r
- Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the\r
- aligned pool allocation services of the Memory Allocation Library.\r
- If Buffer was not allocated with an aligned pool allocation function in the Memory Allocation\r
- Library, then ASSERT().\r
-\r
- @param Buffer Pointer to the buffer to free.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-FreeAlignedPool (\r
- IN VOID *Buffer\r
- )\r
-{\r
- VOID *RawAddress;\r
- VOID **FreePointer;\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Get the pre-saved original address in the over-allocate pool.\r
- //\r
- FreePointer = (VOID **)((UINTN) Buffer - sizeof (RawAddress));\r
- RawAddress = *FreePointer;\r
-\r
- Status = gBS->FreePool (RawAddress);\r
- ASSERT_EFI_ERROR (Status);\r
-}\r
-\r
/**\r
Create a command transfer TRB to support XHCI command interfaces.\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
@param CmdTrb The cmd TRB to be executed.\r
\r
@return Created URB or NULL.\r
**/\r
URB*\r
XhcCreateCmdTrb (\r
- IN USB_XHCI_DEV *Xhc,\r
- IN TRB *CmdTrb\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN TRB_TEMPLATE *CmdTrb\r
)\r
{\r
URB *Urb;\r
XhcSyncTrsRing (Xhc, Urb->Ring);\r
Urb->TrbNum = 1;\r
Urb->TrbStart = Urb->Ring->RingEnqueue;\r
- CopyMem (Urb->TrbStart, CmdTrb, sizeof (TRB));\r
+ CopyMem (Urb->TrbStart, CmdTrb, sizeof (TRB_TEMPLATE));\r
Urb->TrbStart->CycleBit = Urb->Ring->RingPCS & BIT0;\r
Urb->TrbEnd = Urb->TrbStart;\r
\r
- Urb->EvtRing = &Xhc->CmdEventRing;\r
- XhcSyncEventRing (Xhc, Urb->EvtRing);\r
- Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
-\r
return Urb;\r
}\r
\r
/**\r
Execute a XHCI cmd TRB pointed by CmdTrb.\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
@param CmdTrb The cmd TRB to be executed.\r
- @param TimeOut Indicates the maximum time, in millisecond, which the\r
+ @param Timeout Indicates the maximum time, in millisecond, which the\r
transfer is allowed to complete.\r
@param EvtTrb The event TRB corresponding to the cmd TRB.\r
\r
EFI_STATUS\r
EFIAPI\r
XhcCmdTransfer (\r
- IN USB_XHCI_DEV *Xhc,\r
- IN TRB *CmdTrb,\r
- IN UINTN TimeOut,\r
- OUT TRB **EvtTrb\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN TRB_TEMPLATE *CmdTrb,\r
+ IN UINTN Timeout,\r
+ OUT TRB_TEMPLATE **EvtTrb\r
)\r
{\r
EFI_STATUS Status;\r
goto ON_EXIT;\r
}\r
\r
- ASSERT (Urb->EvtRing == &Xhc->CmdEventRing);\r
-\r
- Status = XhcExecTransfer (Xhc, TRUE, Urb, TimeOut);\r
- *EvtTrb = Urb->EvtTrbStart;\r
+ Status = XhcExecTransfer (Xhc, TRUE, Urb, Timeout);\r
+ *EvtTrb = Urb->EvtTrb;\r
\r
if (Urb->Result == EFI_USB_NOERROR) {\r
Status = EFI_SUCCESS;\r
}\r
\r
- FreePool (Urb);\r
+ XhcFreeUrb (Xhc, Urb);\r
\r
ON_EXIT:\r
return Status;\r
/**\r
Create a new URB for a new transaction.\r
\r
- @param Xhc The XHCI device\r
- @param DevAddr The device address\r
+ @param Xhc The XHCI Instance\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
**/\r
URB*\r
XhcCreateUrb (\r
- IN USB_XHCI_DEV *Xhc,\r
- IN UINT8 DevAddr,\r
+ IN USB_XHCI_INSTANCE *Xhc,\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
Urb->Context = Context;\r
\r
Status = XhcCreateTransferTrb (Xhc, Urb);\r
+ ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcCreateUrb: XhcCreateTransferTrb Failed, Status = %r\n", Status));\r
+ FreePool (Urb);\r
+ Urb = NULL;\r
+ }\r
\r
return Urb;\r
}\r
\r
+/**\r
+ Free an allocated URB.\r
+\r
+ @param Xhc The XHCI device.\r
+ @param Urb The URB to free.\r
+\r
+**/\r
+VOID\r
+XhcFreeUrb (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN URB *Urb\r
+ )\r
+{\r
+ if ((Xhc == NULL) || (Urb == NULL)) {\r
+ return;\r
+ }\r
+ \r
+ if (Urb->DataMap != NULL) {\r
+ Xhc->PciIo->Unmap (Xhc->PciIo, Urb->DataMap);\r
+ }\r
+\r
+ FreePool (Urb);\r
+}\r
+\r
/**\r
Create a transfer TRB.\r
\r
- @param Xhc The XHCI device\r
+ @param Xhc The XHCI Instance\r
@param Urb The urb used to construct the transfer TRB.\r
\r
@return Created TRB or NULL\r
**/\r
EFI_STATUS\r
XhcCreateTransferTrb (\r
- IN USB_XHCI_DEV *Xhc,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
IN URB *Urb\r
)\r
{\r
- DEVICE_CONTEXT *OutputDevContxt;\r
+ VOID *OutputContext;\r
TRANSFER_RING *EPRing;\r
UINT8 EPType;\r
UINT8 SlotId;\r
UINTN TotalLen;\r
UINTN Len;\r
UINTN TrbNum;\r
+ EFI_PCI_IO_PROTOCOL_OPERATION MapOp;\r
+ EFI_PHYSICAL_ADDRESS PhyAddr;\r
+ VOID *Map;\r
+ EFI_STATUS Status;\r
+\r
+ SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);\r
+ if (SlotId == 0) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Urb->Finished = FALSE;\r
+ Urb->StartDone = FALSE;\r
+ Urb->EndDone = FALSE;\r
+ Urb->Completed = 0;\r
+ Urb->Result = EFI_USB_NOERROR;\r
\r
- SlotId = XhcDevAddrToSlotId(Urb->Ep.DevAddr);\r
Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));\r
- EPRing = (TRANSFER_RING *)(UINTN) UsbDevContext[SlotId].EndpointTransferRing[Dci-1];\r
+ ASSERT (Dci < 32);\r
+ EPRing = (TRANSFER_RING *)(UINTN) Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1];\r
Urb->Ring = EPRing;\r
- OutputDevContxt = (DEVICE_CONTEXT *)(UINTN) Xhc->DCBAA[SlotId];\r
- EPType = (UINT8) OutputDevContxt->EP[Dci-1].EPType;\r
+ OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;\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
+ if (Urb->Data != NULL) {\r
+ if (((UINT8) (Urb->Ep.Direction)) == EfiUsbDataIn) {\r
+ MapOp = EfiPciIoOperationBusMasterWrite;\r
+ } else {\r
+ MapOp = EfiPciIoOperationBusMasterRead;\r
+ }\r
+ \r
+ Len = Urb->DataLen;\r
+ Status = Xhc->PciIo->Map (Xhc->PciIo, MapOp, Urb->Data, &Len, &PhyAddr, &Map);\r
+ \r
+ if (EFI_ERROR (Status) || (Len != Urb->DataLen)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcCreateTransferTrb: Fail to map Urb->Data.\n"));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ Urb->DataPhy = (VOID *) ((UINTN) PhyAddr);\r
+ Urb->DataMap = Map;\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
- XhcSyncEventRing (Xhc, Urb->EvtRing);\r
- Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
//\r
// For control transfer, create SETUP_STAGE_TRB first.\r
//\r
- TrbStart = EPRing->RingEnqueue;\r
- ((TRANSFER_TRB_CONTROL_SETUP *) TrbStart)->bmRequestType = Urb->Request->RequestType;\r
- ((TRANSFER_TRB_CONTROL_SETUP *) TrbStart)->bRequest = Urb->Request->Request;\r
- ((TRANSFER_TRB_CONTROL_SETUP *) TrbStart)->wValue = Urb->Request->Value;\r
- ((TRANSFER_TRB_CONTROL_SETUP *) TrbStart)->wIndex = Urb->Request->Index;\r
- ((TRANSFER_TRB_CONTROL_SETUP *) TrbStart)->wLength = Urb->Request->Length;\r
- ((TRANSFER_TRB_CONTROL_SETUP *) TrbStart)->Lenth = 8;\r
- ((TRANSFER_TRB_CONTROL_SETUP *) TrbStart)->IntTarget = Urb->EvtRing->EventInterrupter;\r
- ((TRANSFER_TRB_CONTROL_SETUP *) TrbStart)->IOC = 1;\r
- ((TRANSFER_TRB_CONTROL_SETUP *) TrbStart)->IDT = 1;\r
- ((TRANSFER_TRB_CONTROL_SETUP *) TrbStart)->Type = TRB_TYPE_SETUP_STAGE;\r
+ TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;\r
+ TrbStart->TrbCtrSetup.bmRequestType = Urb->Request->RequestType;\r
+ TrbStart->TrbCtrSetup.bRequest = Urb->Request->Request;\r
+ TrbStart->TrbCtrSetup.wValue = Urb->Request->Value;\r
+ TrbStart->TrbCtrSetup.wIndex = Urb->Request->Index;\r
+ TrbStart->TrbCtrSetup.wLength = Urb->Request->Length;\r
+ TrbStart->TrbCtrSetup.Lenth = 8;\r
+ TrbStart->TrbCtrSetup.IntTarget = 0;\r
+ TrbStart->TrbCtrSetup.IOC = 1;\r
+ TrbStart->TrbCtrSetup.IDT = 1;\r
+ TrbStart->TrbCtrSetup.Type = TRB_TYPE_SETUP_STAGE;\r
if (Urb->Ep.Direction == EfiUsbDataIn) {\r
- ((TRANSFER_TRB_CONTROL_SETUP *) TrbStart)->TRT = 3;\r
+ TrbStart->TrbCtrSetup.TRT = 3;\r
} else if (Urb->Ep.Direction == EfiUsbDataOut) {\r
- ((TRANSFER_TRB_CONTROL_SETUP *) TrbStart)->TRT = 2;\r
+ TrbStart->TrbCtrSetup.TRT = 2;\r
} else {\r
- ((TRANSFER_TRB_CONTROL_SETUP *) TrbStart)->TRT = 0;\r
+ TrbStart->TrbCtrSetup.TRT = 0;\r
}\r
//\r
// Update the cycle bit\r
//\r
- ((TRANSFER_TRB_CONTROL_SETUP *) TrbStart)->CycleBit = EPRing->RingPCS & BIT0;\r
+ TrbStart->TrbCtrSetup.CycleBit = EPRing->RingPCS & BIT0;\r
Urb->TrbNum++;\r
\r
//\r
//\r
if (Urb->DataLen > 0) {\r
XhcSyncTrsRing (Xhc, EPRing);\r
- TrbStart = EPRing->RingEnqueue;\r
- ((TRANSFER_TRB_CONTROL_DATA *) TrbStart)->TRBPtrLo = XHC_LOW_32BIT(Urb->Data);\r
- ((TRANSFER_TRB_CONTROL_DATA *) TrbStart)->TRBPtrHi = XHC_HIGH_32BIT(Urb->Data);\r
- ((TRANSFER_TRB_CONTROL_DATA *) TrbStart)->Lenth = (UINT32) Urb->DataLen;\r
- ((TRANSFER_TRB_CONTROL_DATA *) TrbStart)->TDSize = 0;\r
- ((TRANSFER_TRB_CONTROL_DATA *) TrbStart)->IntTarget = Urb->EvtRing->EventInterrupter;\r
- ((TRANSFER_TRB_CONTROL_DATA *) TrbStart)->ISP = 1;\r
- ((TRANSFER_TRB_CONTROL_DATA *) TrbStart)->IOC = 1;\r
- ((TRANSFER_TRB_CONTROL_DATA *) TrbStart)->IDT = 0;\r
- ((TRANSFER_TRB_CONTROL_DATA *) TrbStart)->CH = 0;\r
- ((TRANSFER_TRB_CONTROL_DATA *) TrbStart)->Type = TRB_TYPE_DATA_STAGE;\r
+ TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;\r
+ TrbStart->TrbCtrData.TRBPtrLo = XHC_LOW_32BIT(Urb->DataPhy);\r
+ TrbStart->TrbCtrData.TRBPtrHi = XHC_HIGH_32BIT(Urb->DataPhy);\r
+ TrbStart->TrbCtrData.Lenth = (UINT32) Urb->DataLen;\r
+ TrbStart->TrbCtrData.TDSize = 0;\r
+ TrbStart->TrbCtrData.IntTarget = 0;\r
+ TrbStart->TrbCtrData.ISP = 1;\r
+ TrbStart->TrbCtrData.IOC = 1;\r
+ TrbStart->TrbCtrData.IDT = 0;\r
+ TrbStart->TrbCtrData.CH = 0;\r
+ TrbStart->TrbCtrData.Type = TRB_TYPE_DATA_STAGE;\r
if (Urb->Ep.Direction == EfiUsbDataIn) {\r
- ((TRANSFER_TRB_CONTROL_DATA *) TrbStart)->DIR = 1;\r
+ TrbStart->TrbCtrData.DIR = 1;\r
} else if (Urb->Ep.Direction == EfiUsbDataOut) {\r
- ((TRANSFER_TRB_CONTROL_DATA *) TrbStart)->DIR = 0;\r
+ TrbStart->TrbCtrData.DIR = 0;\r
} else {\r
- ((TRANSFER_TRB_CONTROL_DATA *) TrbStart)->DIR = 0;\r
+ TrbStart->TrbCtrData.DIR = 0;\r
}\r
//\r
// Update the cycle bit\r
//\r
- ((TRANSFER_TRB_CONTROL_DATA *) TrbStart)->CycleBit = EPRing->RingPCS & BIT0;\r
+ TrbStart->TrbCtrData.CycleBit = EPRing->RingPCS & BIT0;\r
Urb->TrbNum++;\r
}\r
//\r
// Get the pointer to next TRB for status stage use\r
//\r
XhcSyncTrsRing (Xhc, EPRing);\r
- TrbStart = EPRing->RingEnqueue;\r
- ((TRANSFER_TRB_CONTROL_STATUS *) TrbStart)->IntTarget = Urb->EvtRing->EventInterrupter;\r
- ((TRANSFER_TRB_CONTROL_STATUS *) TrbStart)->IOC = 1;\r
- ((TRANSFER_TRB_CONTROL_STATUS *) TrbStart)->CH = 0;\r
- ((TRANSFER_TRB_CONTROL_STATUS *) TrbStart)->Type = TRB_TYPE_STATUS_STAGE;\r
+ TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;\r
+ TrbStart->TrbCtrStatus.IntTarget = 0;\r
+ TrbStart->TrbCtrStatus.IOC = 1;\r
+ TrbStart->TrbCtrStatus.CH = 0;\r
+ TrbStart->TrbCtrStatus.Type = TRB_TYPE_STATUS_STAGE;\r
if (Urb->Ep.Direction == EfiUsbDataIn) {\r
- ((TRANSFER_TRB_CONTROL_STATUS *) TrbStart)->DIR = 0;\r
+ TrbStart->TrbCtrStatus.DIR = 0;\r
} else if (Urb->Ep.Direction == EfiUsbDataOut) {\r
- ((TRANSFER_TRB_CONTROL_STATUS *) TrbStart)->DIR = 1;\r
+ TrbStart->TrbCtrStatus.DIR = 1;\r
} else {\r
- ((TRANSFER_TRB_CONTROL_STATUS *) TrbStart)->DIR = 0;\r
+ TrbStart->TrbCtrStatus.DIR = 0;\r
}\r
//\r
// Update the cycle bit\r
//\r
- ((TRANSFER_TRB_CONTROL_STATUS *) TrbStart)->CycleBit = EPRing->RingPCS & BIT0;\r
+ TrbStart->TrbCtrStatus.CycleBit = EPRing->RingPCS & BIT0;\r
//\r
// Update the enqueue pointer\r
//\r
XhcSyncTrsRing (Xhc, EPRing);\r
Urb->TrbNum++;\r
- Urb->TrbEnd = TrbStart;\r
+ Urb->TrbEnd = (TRB_TEMPLATE *)(UINTN)TrbStart;\r
\r
break;\r
\r
case ED_BULK_OUT:\r
case ED_BULK_IN:\r
- Urb->EvtRing = &Xhc->BulkTrEventRing;\r
- XhcSyncEventRing (Xhc, Urb->EvtRing);\r
- Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
-\r
TotalLen = 0;\r
Len = 0;\r
TrbNum = 0;\r
- TrbStart = EPRing->RingEnqueue;\r
+ TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;\r
while (TotalLen < Urb->DataLen) {\r
if ((TotalLen + 0x10000) >= Urb->DataLen) {\r
Len = Urb->DataLen - TotalLen;\r
} else {\r
Len = 0x10000;\r
}\r
- TrbStart = EPRing->RingEnqueue;\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->TRBPtrLo = XHC_LOW_32BIT((UINT8 *) Urb->Data + TotalLen);\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->TRBPtrHi = XHC_HIGH_32BIT((UINT8 *) Urb->Data + TotalLen);\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->Lenth = (UINT32) Len;\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->TDSize = 0;\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->IntTarget = Urb->EvtRing->EventInterrupter;\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->ISP = 1;\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->IOC = 1;\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->Type = TRB_TYPE_NORMAL;\r
+ TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;\r
+ TrbStart->TrbNormal.TRBPtrLo = XHC_LOW_32BIT((UINT8 *) Urb->DataPhy + TotalLen);\r
+ TrbStart->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT((UINT8 *) Urb->DataPhy + TotalLen);\r
+ TrbStart->TrbNormal.Lenth = (UINT32) Len;\r
+ TrbStart->TrbNormal.TDSize = 0;\r
+ TrbStart->TrbNormal.IntTarget = 0;\r
+ TrbStart->TrbNormal.ISP = 1;\r
+ TrbStart->TrbNormal.IOC = 1;\r
+ TrbStart->TrbNormal.Type = TRB_TYPE_NORMAL;\r
//\r
// Update the cycle bit\r
//\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->CycleBit = EPRing->RingPCS & BIT0;\r
+ TrbStart->TrbNormal.CycleBit = EPRing->RingPCS & BIT0;\r
\r
XhcSyncTrsRing (Xhc, EPRing);\r
TrbNum++;\r
}\r
\r
Urb->TrbNum = TrbNum;\r
- Urb->TrbEnd = TrbStart;\r
+ Urb->TrbEnd = (TRB_TEMPLATE *)(UINTN)TrbStart;\r
break;\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
- XhcSyncEventRing (Xhc, Urb->EvtRing);\r
- Urb->EvtTrbStart = Urb->EvtRing->EventRingEnqueue;\r
-\r
TotalLen = 0;\r
Len = 0;\r
TrbNum = 0;\r
- TrbStart = EPRing->RingEnqueue;\r
+ TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;\r
while (TotalLen < Urb->DataLen) {\r
if ((TotalLen + 0x10000) >= Urb->DataLen) {\r
Len = Urb->DataLen - TotalLen;\r
} else {\r
Len = 0x10000;\r
}\r
- TrbStart = EPRing->RingEnqueue;\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->TRBPtrLo = XHC_LOW_32BIT((UINT8 *) Urb->Data + TotalLen);\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->TRBPtrHi = XHC_HIGH_32BIT((UINT8 *) Urb->Data + TotalLen);\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->Lenth = (UINT32) Len;\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->TDSize = 0;\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->IntTarget = Urb->EvtRing->EventInterrupter;\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->ISP = 1;\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->IOC = 1;\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->Type = TRB_TYPE_NORMAL;\r
+ TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;\r
+ TrbStart->TrbNormal.TRBPtrLo = XHC_LOW_32BIT((UINT8 *) Urb->DataPhy + TotalLen);\r
+ TrbStart->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT((UINT8 *) Urb->DataPhy + TotalLen);\r
+ TrbStart->TrbNormal.Lenth = (UINT32) Len;\r
+ TrbStart->TrbNormal.TDSize = 0;\r
+ TrbStart->TrbNormal.IntTarget = 0;\r
+ TrbStart->TrbNormal.ISP = 1;\r
+ TrbStart->TrbNormal.IOC = 1;\r
+ TrbStart->TrbNormal.Type = TRB_TYPE_NORMAL;\r
//\r
// Update the cycle bit\r
//\r
- ((TRANSFER_TRB_NORMAL *) TrbStart)->CycleBit = EPRing->RingPCS & BIT0;\r
+ TrbStart->TrbNormal.CycleBit = EPRing->RingPCS & BIT0;\r
\r
XhcSyncTrsRing (Xhc, EPRing);\r
TrbNum++;\r
}\r
\r
Urb->TrbNum = TrbNum;\r
- Urb->TrbEnd = TrbStart;\r
+ Urb->TrbEnd = (TRB_TEMPLATE *)(UINTN)TrbStart;\r
break;\r
\r
default:\r
/**\r
Initialize the XHCI host controller for schedule.\r
\r
- @param Xhc The XHCI device to be initialized.\r
+ @param Xhc The XHCI Instance to be initialized.\r
\r
**/\r
VOID\r
XhcInitSched (\r
- IN USB_XHCI_DEV *Xhc\r
+ IN USB_XHCI_INSTANCE *Xhc\r
)\r
{\r
VOID *Dcbaa;\r
+ EFI_PHYSICAL_ADDRESS DcbaaPhy;\r
UINT64 CmdRing;\r
+ EFI_PHYSICAL_ADDRESS CmdRingPhy; \r
UINTN Entries;\r
UINT32 MaxScratchpadBufs;\r
UINT64 *ScratchBuf;\r
- UINT64 *ScratchEntryBuf;\r
+ EFI_PHYSICAL_ADDRESS ScratchPhy;\r
+ UINT64 *ScratchEntry;\r
+ EFI_PHYSICAL_ADDRESS ScratchEntryPhy;\r
UINT32 Index;\r
+ UINTN *ScratchEntryMap;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Initialize memory management.\r
+ //\r
+ Xhc->MemPool = UsbHcInitMemPool (Xhc->PciIo);\r
+ ASSERT (Xhc->MemPool != NULL);\r
\r
//\r
// Program the Max Device Slots Enabled (MaxSlotsEn) field in the CONFIG register (5.4.7)\r
// Software shall set Device Context Base Address Array entries for unallocated Device Slots to '0'.\r
//\r
Entries = (Xhc->MaxSlotsEn + 1) * sizeof(UINT64);\r
- Dcbaa = AllocateAlignedZeroPool(Entries, 64);\r
+ Dcbaa = UsbHcAllocateMem (Xhc->MemPool, Entries);\r
ASSERT (Dcbaa != NULL);\r
+ ZeroMem (Dcbaa, Entries);\r
\r
//\r
// A Scratchpad Buffer is a PAGESIZE block of system memory located on a PAGESIZE boundary.\r
Xhc->MaxScratchpadBufs = MaxScratchpadBufs;\r
ASSERT (MaxScratchpadBufs <= 1023);\r
if (MaxScratchpadBufs != 0) {\r
- ScratchBuf = AllocateAlignedZeroPool(MaxScratchpadBufs * sizeof (UINT64), Xhc->PageSize);\r
- ASSERT (ScratchBuf != NULL);\r
+ //\r
+ // Allocate the buffer to record the Mapping for each scratch buffer in order to Unmap them\r
+ //\r
+ ScratchEntryMap = AllocateZeroPool (sizeof (UINTN) * MaxScratchpadBufs);\r
+ ASSERT (ScratchEntryMap != NULL);\r
+ Xhc->ScratchEntryMap = ScratchEntryMap;\r
+ \r
+ //\r
+ // Allocate the buffer to record the host address for each entry\r
+ //\r
+ ScratchEntry = AllocateZeroPool (sizeof (UINT64) * MaxScratchpadBufs);\r
+ ASSERT (ScratchEntry != NULL);\r
+ Xhc->ScratchEntry = ScratchEntry;\r
+\r
+ ScratchPhy = 0;\r
+ Status = UsbHcAllocateAlignedPages (\r
+ Xhc->PciIo,\r
+ EFI_SIZE_TO_PAGES (MaxScratchpadBufs * sizeof (UINT64)),\r
+ Xhc->PageSize,\r
+ (VOID **) &ScratchBuf, \r
+ &ScratchPhy,\r
+ &Xhc->ScratchMap\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ ZeroMem (ScratchBuf, MaxScratchpadBufs * sizeof (UINT64));\r
Xhc->ScratchBuf = ScratchBuf;\r
\r
+ //\r
+ // Allocate each scratch buffer\r
+ //\r
for (Index = 0; Index < MaxScratchpadBufs; Index++) {\r
- ScratchEntryBuf = AllocateAlignedZeroPool(Xhc->PageSize, Xhc->PageSize);\r
- *ScratchBuf++ = (UINT64)(UINTN)ScratchEntryBuf;\r
+ ScratchEntryPhy = 0;\r
+ Status = UsbHcAllocateAlignedPages (\r
+ Xhc->PciIo,\r
+ EFI_SIZE_TO_PAGES (Xhc->PageSize),\r
+ Xhc->PageSize,\r
+ (VOID **) &ScratchEntry[Index],\r
+ &ScratchEntryPhy,\r
+ (VOID **) &ScratchEntryMap[Index]\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ ZeroMem ((VOID *)(UINTN)ScratchEntry[Index], Xhc->PageSize);\r
+ //\r
+ // Fill with the PCI device address\r
+ //\r
+ *ScratchBuf++ = ScratchEntryPhy;\r
}\r
-\r
//\r
// The Scratchpad Buffer Array contains pointers to the Scratchpad Buffers. Entry 0 of the\r
// Device Context Base Address Array points to the Scratchpad Buffer Array.\r
//\r
- *(UINT64 *)Dcbaa = (UINT64)(UINTN)Xhc->ScratchBuf;\r
+ *(UINT64 *)Dcbaa = (UINT64)(UINTN) ScratchPhy;\r
}\r
\r
//\r
// Program the Device Context Base Address Array Pointer (DCBAAP) register (5.4.6) with\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
+ Xhc->DCBAA = (UINT64 *)(UINTN)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
+ DcbaaPhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Dcbaa, Entries);\r
+ XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET, XHC_LOW_32BIT(DcbaaPhy));\r
+ XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET + 4, XHC_HIGH_32BIT (DcbaaPhy));\r
+\r
DEBUG ((EFI_D_INFO, "XhcInitSched:DCBAA=0x%x\n", (UINT64)(UINTN)Xhc->DCBAA));\r
\r
//\r
// So we set RCS as inverted PCS init value to let Command Ring empty\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
+ CmdRingPhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, (VOID *)(UINTN) CmdRing, sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER);\r
+ ASSERT ((CmdRingPhy & 0x3F) == 0);\r
+ CmdRingPhy |= XHC_CRCR_RCS;\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(CmdRingPhy));\r
+ XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET + 4, XHC_HIGH_32BIT (CmdRingPhy));\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
reenabled. The next write to the Doorbell of the Endpoint will transition the Endpoint Context from the\r
Stopped to the Running state.\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
@param Urb The urb which makes the endpoint halted.\r
\r
@retval EFI_SUCCESS The recovery is successful.\r
EFI_STATUS\r
EFIAPI\r
XhcRecoverHaltedEndpoint (\r
- IN USB_XHCI_DEV *Xhc,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
IN URB *Urb\r
)\r
{\r
- EFI_STATUS Status;\r
- EVT_TRB_COMMAND *EvtTrb;\r
- CMD_TRB_RESET_ED CmdTrbResetED;\r
- CMD_SET_TR_DEQ CmdSetTRDeq;\r
- UINT8 Dci;\r
- UINT8 SlotId;\r
-\r
- Status = EFI_SUCCESS;\r
- SlotId = XhcDevAddrToSlotId(Urb->Ep.DevAddr);\r
- Dci = XhcEndpointToDci(Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction));\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
+ 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
CmdTrbResetED.SlotId = SlotId;\r
Status = XhcCmdTransfer (\r
Xhc,\r
- (TRB *) (UINTN) &CmdTrbResetED,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbResetED,\r
XHC_GENERIC_TIMEOUT,\r
- (TRB **) (UINTN) &EvtTrb\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
);\r
- ASSERT (!EFI_ERROR(Status));\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcRecoverHaltedEndpoint: Reset Endpoint Failed, Status = %r\n", Status));\r
+ goto Done;\r
+ }\r
\r
//\r
// 2)Set dequeue pointer\r
//\r
ZeroMem (&CmdSetTRDeq, sizeof (CmdSetTRDeq));\r
- CmdSetTRDeq.PtrLo = XHC_LOW_32BIT (Urb->Ring->RingEnqueue) | Urb->Ring->RingPCS;\r
- CmdSetTRDeq.PtrHi = XHC_HIGH_32BIT (Urb->Ring->RingEnqueue);\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 *) (UINTN) &CmdSetTRDeq,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdSetTRDeq,\r
XHC_GENERIC_TIMEOUT,\r
- (TRB **) (UINTN) &EvtTrb\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
);\r
- ASSERT (!EFI_ERROR(Status));\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcRecoverHaltedEndpoint: Set 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
Create XHCI event ring.\r
\r
- @param Xhc The XHCI device.\r
- @param EventInterrupter The interrupter of event.\r
+ @param Xhc The XHCI Instance.\r
@param EventRing The created event ring.\r
\r
**/\r
VOID\r
CreateEventRing (\r
- IN USB_XHCI_DEV *Xhc,\r
- IN UINT8 EventInterrupter,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
OUT EVENT_RING *EventRing\r
)\r
{\r
VOID *Buf;\r
EVENT_RING_SEG_TABLE_ENTRY *ERSTBase;\r
+ UINTN Size;\r
+ EFI_PHYSICAL_ADDRESS ERSTPhy;\r
+ EFI_PHYSICAL_ADDRESS DequeuePhy;\r
\r
ASSERT (EventRing != NULL);\r
\r
- Buf = AllocateAlignedZeroPool(sizeof (TRB) * EVENT_RING_TRB_NUMBER, 64);\r
+ Size = sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER;\r
+ Buf = UsbHcAllocateMem (Xhc->MemPool, Size);\r
ASSERT (Buf != NULL);\r
ASSERT (((UINTN) Buf & 0x3F) == 0);\r
+ ZeroMem (Buf, Size);\r
\r
EventRing->EventRingSeg0 = Buf;\r
- EventRing->EventInterrupter = EventInterrupter;\r
EventRing->TrbNumber = EVENT_RING_TRB_NUMBER;\r
- EventRing->EventRingDequeue = (TRB *) EventRing->EventRingSeg0;\r
- EventRing->EventRingEnqueue = (TRB *) EventRing->EventRingSeg0;\r
+ EventRing->EventRingDequeue = (TRB_TEMPLATE *) EventRing->EventRingSeg0;\r
+ EventRing->EventRingEnqueue = (TRB_TEMPLATE *) EventRing->EventRingSeg0;\r
+ \r
+ DequeuePhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Buf, Size);\r
+ \r
//\r
// Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it to '1'\r
// and toggling it every time the Event Ring Dequeue Pointer wraps back to the beginning of the Event Ring.\r
//\r
EventRing->EventRingCCS = 1;\r
\r
- Buf = AllocateAlignedZeroPool(sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER, 64);\r
+ Size = sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER;\r
+ Buf = UsbHcAllocateMem (Xhc->MemPool, Size);\r
ASSERT (Buf != NULL);\r
ASSERT (((UINTN) Buf & 0x3F) == 0);\r
+ ZeroMem (Buf, Size);\r
\r
ERSTBase = (EVENT_RING_SEG_TABLE_ENTRY *) Buf;\r
EventRing->ERSTBase = ERSTBase;\r
- ERSTBase->PtrLo = XHC_LOW_32BIT (EventRing->EventRingSeg0);\r
- ERSTBase->PtrHi = XHC_HIGH_32BIT (EventRing->EventRingSeg0);\r
+ ERSTBase->PtrLo = XHC_LOW_32BIT (DequeuePhy);\r
+ ERSTBase->PtrHi = XHC_HIGH_32BIT (DequeuePhy);\r
ERSTBase->RingTrbSize = EVENT_RING_TRB_NUMBER;\r
\r
+ ERSTPhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, ERSTBase, Size);\r
+\r
//\r
// Program the Interrupter Event Ring Segment Table Size (ERSTSZ) register (5.5.2.3.1)\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)DequeuePhy)\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)DequeuePhy)\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 + (32 * EventRing->EventInterrupter),\r
- (UINT64)(UINTN)ERSTBase\r
+ XHC_ERSTBA_OFFSET,\r
+ XHC_LOW_32BIT((UINT64)(UINTN)ERSTPhy)\r
+ );\r
+ XhcWriteRuntimeReg (\r
+ Xhc,\r
+ XHC_ERSTBA_OFFSET + 4,\r
+ XHC_HIGH_32BIT((UINT64)(UINTN)ERSTPhy)\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
Create XHCI transfer ring.\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
@param TrbNum The number of TRB in the ring.\r
@param TransferRing The created transfer ring.\r
\r
**/\r
VOID\r
CreateTransferRing (\r
- IN USB_XHCI_DEV *Xhc,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
IN UINTN TrbNum,\r
OUT TRANSFER_RING *TransferRing\r
)\r
{\r
VOID *Buf;\r
- LNK_TRB *EndTrb;\r
+ LINK_TRB *EndTrb;\r
+ EFI_PHYSICAL_ADDRESS PhyAddr;\r
\r
- Buf = AllocateAlignedZeroPool(sizeof (TRB) * TrbNum, 64);\r
+ Buf = UsbHcAllocateMem (Xhc->MemPool, sizeof (TRB_TEMPLATE) * TrbNum);\r
ASSERT (Buf != NULL);\r
ASSERT (((UINTN) Buf & 0x3F) == 0);\r
+ ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum);\r
\r
TransferRing->RingSeg0 = Buf;\r
TransferRing->TrbNumber = TrbNum;\r
- TransferRing->RingEnqueue = (TRB *) TransferRing->RingSeg0;\r
- TransferRing->RingDequeue = (TRB *) TransferRing->RingSeg0;\r
+ TransferRing->RingEnqueue = (TRB_TEMPLATE *) TransferRing->RingSeg0;\r
+ TransferRing->RingDequeue = (TRB_TEMPLATE *) TransferRing->RingSeg0;\r
TransferRing->RingPCS = 1;\r
//\r
// 4.9.2 Transfer Ring Management\r
// To form a ring (or circular queue) a Link TRB may be inserted at the end of a ring to\r
// point to the first TRB in the ring.\r
//\r
- EndTrb = (LNK_TRB*) ((UINTN)Buf + sizeof (TRB) * (TrbNum - 1));\r
+ EndTrb = (LINK_TRB *) ((UINTN)Buf + sizeof (TRB_TEMPLATE) * (TrbNum - 1));\r
EndTrb->Type = TRB_TYPE_LINK;\r
- EndTrb->PtrLo = XHC_LOW_32BIT (Buf);\r
- EndTrb->PtrHi = XHC_HIGH_32BIT (Buf);\r
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Buf, sizeof (TRB_TEMPLATE) * TrbNum);\r
+ EndTrb->PtrLo = XHC_LOW_32BIT (PhyAddr);\r
+ EndTrb->PtrHi = XHC_HIGH_32BIT (PhyAddr);\r
//\r
// Toggle Cycle (TC). When set to '1', the xHC shall toggle its interpretation of the Cycle bit.\r
//\r
/**\r
Free XHCI event ring.\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
@param EventRing The event ring to be freed.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
XhcFreeEventRing (\r
- IN USB_XHCI_DEV *Xhc,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
IN EVENT_RING *EventRing\r
)\r
{\r
- UINT8 Index;\r
- EVENT_RING_SEG_TABLE_ENTRY *TablePtr;\r
- VOID *RingBuf;\r
- EVENT_RING_SEG_TABLE_ENTRY *EventRingPtr;\r
- UINTN InterrupterTarget;\r
-\r
if(EventRing->EventRingSeg0 == NULL) {\r
return EFI_SUCCESS;\r
}\r
\r
- InterrupterTarget = EventRing->EventInterrupter;\r
//\r
- // Get the Event Ring Segment Table base address\r
+ // Free EventRing Segment 0\r
//\r
- TablePtr = (EVENT_RING_SEG_TABLE_ENTRY *)(EventRing->ERSTBase);\r
+ UsbHcFreeMem (Xhc->MemPool, EventRing->EventRingSeg0, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);\r
\r
//\r
- // Get all the TRBs Ring and release\r
+ // Free ESRT table\r
//\r
- for (Index = 0; Index < ERST_NUMBER; Index++) {\r
- EventRingPtr = TablePtr + Index;\r
- RingBuf = (VOID *)(UINTN)(EventRingPtr->PtrLo | ((UINT64)EventRingPtr->PtrHi << 32));\r
-\r
- if(RingBuf != NULL) {\r
- FreeAlignedPool (RingBuf);\r
- ZeroMem (EventRingPtr, sizeof (EVENT_RING_SEG_TABLE_ENTRY));\r
- }\r
- }\r
-\r
- FreeAlignedPool (TablePtr);\r
+ UsbHcFreeMem (Xhc->MemPool, EventRing->ERSTBase, sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);\r
return EFI_SUCCESS;\r
}\r
\r
/**\r
Free the resouce allocated at initializing schedule.\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
\r
**/\r
VOID\r
XhcFreeSched (\r
- IN USB_XHCI_DEV *Xhc\r
+ IN USB_XHCI_INSTANCE *Xhc\r
)\r
{\r
- UINT32 Index;\r
-\r
+ UINT32 Index;\r
+ UINT64 *ScratchEntry;\r
+ \r
if (Xhc->ScratchBuf != NULL) {\r
+ ScratchEntry = Xhc->ScratchEntry;\r
for (Index = 0; Index < Xhc->MaxScratchpadBufs; Index++) {\r
- FreeAlignedPool ((VOID*)(UINTN)*Xhc->ScratchBuf++);\r
+ //\r
+ // Free Scratchpad Buffers\r
+ //\r
+ UsbHcFreeAlignedPages (Xhc->PciIo, (VOID*)(UINTN)ScratchEntry[Index], EFI_SIZE_TO_PAGES (Xhc->PageSize), (VOID *) Xhc->ScratchEntryMap[Index]);\r
}\r
+ //\r
+ // Free Scratchpad Buffer Array\r
+ //\r
+ UsbHcFreeAlignedPages (Xhc->PciIo, Xhc->ScratchBuf, EFI_SIZE_TO_PAGES (Xhc->MaxScratchpadBufs * sizeof (UINT64)), Xhc->ScratchMap);\r
+ FreePool (Xhc->ScratchEntryMap);\r
+ FreePool (Xhc->ScratchEntry);\r
+ }\r
+\r
+ if (Xhc->CmdRing.RingSeg0 != NULL) {\r
+ UsbHcFreeMem (Xhc->MemPool, Xhc->CmdRing.RingSeg0, sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER);\r
+ Xhc->CmdRing.RingSeg0 = NULL;\r
}\r
+ \r
+ XhcFreeEventRing (Xhc,&Xhc->EventRing);\r
\r
if (Xhc->DCBAA != NULL) {\r
- FreeAlignedPool (Xhc->DCBAA);\r
+ UsbHcFreeMem (Xhc->MemPool, Xhc->DCBAA, (Xhc->MaxSlotsEn + 1) * sizeof(UINT64));\r
Xhc->DCBAA = NULL;\r
}\r
+ \r
+ //\r
+ // Free memory pool at last\r
+ //\r
+ if (Xhc->MemPool != NULL) {\r
+ UsbHcFreeMemPool (Xhc->MemPool);\r
+ Xhc->MemPool = NULL;\r
+ }\r
+}\r
\r
- if (Xhc->CmdRing.RingSeg0 != NULL){\r
- FreeAlignedPool (Xhc->CmdRing.RingSeg0);\r
- Xhc->CmdRing.RingSeg0 = NULL;\r
+/**\r
+ Check if the Trb is a transaction of the URBs in XHCI's asynchronous transfer list.\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param Trb The TRB to be checked.\r
+ @param Urb The pointer to the matched Urb.\r
+\r
+ @retval TRUE The Trb is matched with a transaction of the URBs in the async list.\r
+ @retval FALSE The Trb is not matched with any URBs in the async list.\r
+\r
+**/\r
+BOOLEAN\r
+IsAsyncIntTrb (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN TRB_TEMPLATE *Trb,\r
+ OUT URB **Urb\r
+ )\r
+{\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *Next;\r
+ TRB_TEMPLATE *CheckedTrb;\r
+ URB *CheckedUrb;\r
+ UINTN Index;\r
+\r
+ EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) {\r
+ CheckedUrb = EFI_LIST_CONTAINER (Entry, URB, UrbList);\r
+ CheckedTrb = CheckedUrb->TrbStart;\r
+ for (Index = 0; Index < CheckedUrb->TrbNum; Index++) {\r
+ if (Trb == CheckedTrb) {\r
+ *Urb = CheckedUrb;\r
+ return TRUE;\r
+ }\r
+ CheckedTrb++;\r
+ if ((UINTN)CheckedTrb >= ((UINTN) CheckedUrb->Ring->RingSeg0 + sizeof (TRB_TEMPLATE) * CheckedUrb->Ring->TrbNumber)) {\r
+ CheckedTrb = (TRB_TEMPLATE*) CheckedUrb->Ring->RingSeg0;\r
+ }\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
+\r
+ return FALSE;\r
}\r
\r
/**\r
- Check if it is ring TRB.\r
+ Check if the Trb is a transaction of the URB.\r
\r
- @param Ring The transfer ring\r
- @param Trb The TRB to check if it's in the transfer ring\r
+ @param Trb The TRB to be checked\r
+ @param Urb The transfer ring to be checked.\r
\r
- @retval TRUE It is in the ring\r
- @retval FALSE It is not in the ring\r
+ @retval TRUE It is a transaction of the URB.\r
+ @retval FALSE It is not any transaction of the URB.\r
\r
**/\r
BOOLEAN\r
IsTransferRingTrb (\r
- IN TRANSFER_RING *Ring,\r
- IN TRB *Trb\r
+ IN TRB_TEMPLATE *Trb,\r
+ IN URB *Urb\r
)\r
{\r
- BOOLEAN Flag;\r
- TRB *Trb1;\r
+ TRB_TEMPLATE *CheckedTrb;\r
UINTN Index;\r
\r
- Trb1 = Ring->RingSeg0;\r
- Flag = FALSE;\r
+ CheckedTrb = Urb->Ring->RingSeg0;\r
\r
- ASSERT (Ring->TrbNumber == CMD_RING_TRB_NUMBER || Ring->TrbNumber == TR_RING_TRB_NUMBER);\r
+ ASSERT (Urb->Ring->TrbNumber == CMD_RING_TRB_NUMBER || Urb->Ring->TrbNumber == TR_RING_TRB_NUMBER);\r
\r
- for (Index = 0; Index < Ring->TrbNumber; Index++) {\r
- if (Trb == Trb1) {\r
- Flag = TRUE;\r
- break;\r
+ for (Index = 0; Index < Urb->Ring->TrbNumber; Index++) {\r
+ if (Trb == CheckedTrb) {\r
+ return TRUE;\r
}\r
- Trb1++;\r
+ CheckedTrb++;\r
}\r
\r
- return Flag;\r
+ return FALSE;\r
}\r
\r
/**\r
Check the URB's execution result and update the URB's\r
result accordingly.\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
@param Urb The URB to check result.\r
\r
@return Whether the result of URB transfer is finialized.\r
**/\r
EFI_STATUS\r
XhcCheckUrbResult (\r
- IN USB_XHCI_DEV *Xhc,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
IN URB *Urb\r
)\r
{\r
- BOOLEAN StartDone;\r
- BOOLEAN EndDone;\r
EVT_TRB_TRANSFER *EvtTrb;\r
- TRB *TRBPtr;\r
+ TRB_TEMPLATE *TRBPtr;\r
UINTN Index;\r
UINT8 TRBType;\r
EFI_STATUS Status;\r
+ URB *AsyncUrb;\r
+ URB *CheckedUrb;\r
+ UINT64 XhcDequeue;\r
+ UINT32 High;\r
+ UINT32 Low;\r
+ EFI_PHYSICAL_ADDRESS PhyAddr;\r
\r
ASSERT ((Xhc != NULL) && (Urb != NULL));\r
\r
- Urb->Completed = 0;\r
- Urb->Result = EFI_USB_NOERROR;\r
- Status = EFI_SUCCESS;\r
- EvtTrb = NULL;\r
+ Status = EFI_SUCCESS;\r
+ AsyncUrb = NULL;\r
+\r
+ if (Urb->Finished) {\r
+ goto EXIT;\r
+ }\r
+\r
+ EvtTrb = NULL;\r
\r
if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {\r
Urb->Result |= EFI_USB_ERR_SYSTEM;\r
}\r
\r
//\r
- // Restore the EventRingDequeue and poll the transfer event ring from beginning\r
+ // Traverse the event ring to find out all new events from the previous check.\r
//\r
- StartDone = FALSE;\r
- EndDone = FALSE;\r
- Urb->EvtRing->EventRingDequeue = Urb->EvtTrbStart;\r
- for (Index = 0; Index < Urb->EvtRing->TrbNumber; Index++) {\r
- XhcSyncEventRing (Xhc, Urb->EvtRing);\r
- Status = XhcCheckNewEvent (Xhc, Urb->EvtRing, ((TRB **)&EvtTrb));\r
+ XhcSyncEventRing (Xhc, &Xhc->EventRing);\r
+ for (Index = 0; Index < Xhc->EventRing.TrbNumber; Index++) {\r
+ Status = XhcCheckNewEvent (Xhc, &Xhc->EventRing, ((TRB_TEMPLATE **)&EvtTrb));\r
if (Status == EFI_NOT_READY) {\r
- Urb->Result |= EFI_USB_ERR_TIMEOUT;\r
+ //\r
+ // All new events are handled, return directly.\r
+ //\r
goto EXIT;\r
}\r
\r
- TRBPtr = (TRB *)(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
+ //\r
+ // Need convert pci device address to host address\r
+ //\r
+ PhyAddr = (EFI_PHYSICAL_ADDRESS)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32));\r
+ TRBPtr = (TRB_TEMPLATE *)(UINTN) UsbHcGetHostAddrForPciAddr (Xhc->MemPool, (VOID *)(UINTN) PhyAddr, sizeof (TRB_TEMPLATE));\r
\r
- switch (EvtTrb->Completcode) {\r
+ //\r
+ // Update the status of Urb according to the finished event regardless of whether\r
+ // the urb is current checked one or in the XHCI's async transfer list.\r
+ // This way is used to avoid that those completed async transfer events don't get\r
+ // handled in time and are flushed by newer coming events.\r
+ //\r
+ if (IsTransferRingTrb (TRBPtr, Urb)) {\r
+ CheckedUrb = Urb;\r
+ } else if (IsAsyncIntTrb (Xhc, TRBPtr, &AsyncUrb)) { \r
+ CheckedUrb = AsyncUrb;\r
+ } else {\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! Completcode = %x\n",EvtTrb->Completcode));\r
+ CheckedUrb->Result |= EFI_USB_ERR_STALL;\r
+ CheckedUrb->Finished = TRUE;\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! Completcode = %x\n",EvtTrb->Completcode));\r
+ CheckedUrb->Result |= EFI_USB_ERR_BABBLE;\r
+ CheckedUrb->Finished = TRUE;\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! Completcode = %x\n",EvtTrb->Completcode));\r
+ CheckedUrb->Result |= EFI_USB_ERR_BUFFER;\r
+ CheckedUrb->Finished = TRUE;\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! Completcode = %x\n",EvtTrb->Completcode));\r
+ CheckedUrb->Result |= EFI_USB_ERR_TIMEOUT;\r
+ CheckedUrb->Finished = TRUE;\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
- if (EvtTrb->Completcode == TRB_COMPLETION_SHORT_PACKET) {\r
- DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: short packet happens!\n"));\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
+ 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
+ CheckedUrb->Completed += (CheckedUrb->DataLen - EvtTrb->Lenth);\r
}\r
- Status = EFI_SUCCESS;\r
+\r
break;\r
\r
default:\r
- DEBUG ((EFI_D_ERROR, "Transfer Default Error Occur! Completcode = 0x%x!\n",EvtTrb->Completcode));\r
- Urb->Result |= EFI_USB_ERR_TIMEOUT;\r
- Status = EFI_DEVICE_ERROR;\r
+ DEBUG ((EFI_D_ERROR, "Transfer Default Error Occur! Completecode = 0x%x!\n",EvtTrb->Completecode));\r
+ CheckedUrb->Result |= EFI_USB_ERR_TIMEOUT;\r
+ CheckedUrb->Finished = TRUE;\r
goto EXIT;\r
- break;\r
}\r
\r
//\r
// Only check first and end Trb event address\r
//\r
- if (TRBPtr == Urb->TrbStart) {\r
- StartDone = TRUE;\r
+ if (TRBPtr == CheckedUrb->TrbStart) {\r
+ CheckedUrb->StartDone = TRUE;\r
}\r
\r
- if (TRBPtr == Urb->TrbEnd) {\r
- EndDone = TRUE;\r
+ if (TRBPtr == CheckedUrb->TrbEnd) {\r
+ CheckedUrb->EndDone = TRUE;\r
}\r
\r
- if (StartDone && EndDone) {\r
- break;\r
+ if (CheckedUrb->StartDone && CheckedUrb->EndDone) {\r
+ CheckedUrb->Finished = TRUE;\r
+ CheckedUrb->EvtTrb = (TRB_TEMPLATE *)EvtTrb;\r
}\r
}\r
\r
EXIT:\r
+\r
+ //\r
+ // Advance event ring to last available entry\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
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->EventRing.EventRingDequeue, sizeof (TRB_TEMPLATE));\r
+\r
+ if ((XhcDequeue & (~0x0F)) != (PhyAddr & (~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, XHC_LOW_32BIT (PhyAddr) | BIT3);\r
+ XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4, XHC_HIGH_32BIT (PhyAddr));\r
+ }\r
+\r
return Status;\r
}\r
\r
/**\r
Execute the transfer by polling the URB. This is a synchronous operation.\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
@param CmdTransfer The executed URB is for cmd transfer or not.\r
@param Urb The URB to execute.\r
- @param TimeOut The time to wait before abort, in millisecond.\r
+ @param Timeout The time to wait before abort, in millisecond.\r
\r
@return EFI_DEVICE_ERROR The transfer failed due to transfer error.\r
@return EFI_TIMEOUT The transfer failed due to time out.\r
**/\r
EFI_STATUS\r
XhcExecTransfer (\r
- IN USB_XHCI_DEV *Xhc,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
IN BOOLEAN CmdTransfer,\r
IN URB *Urb,\r
- IN UINTN TimeOut\r
+ IN UINTN Timeout\r
)\r
{\r
EFI_STATUS Status;\r
SlotId = 0;\r
Dci = 0;\r
} else {\r
- SlotId = XhcDevAddrToSlotId(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
- Loop = (TimeOut * XHC_1_MILLISECOND / XHC_SYNC_POLL_INTERVAL) + 1;\r
- if (TimeOut == 0) {\r
+ Loop = Timeout * XHC_1_MILLISECOND;\r
+ if (Timeout == 0) {\r
Loop = 0xFFFFFFFF;\r
}\r
\r
\r
for (Index = 0; Index < Loop; Index++) {\r
Status = XhcCheckUrbResult (Xhc, Urb);\r
- if ((Status != EFI_NOT_READY)) {\r
+ if (Urb->Finished) {\r
break;\r
}\r
- gBS->Stall (XHC_SYNC_POLL_INTERVAL);\r
+ gBS->Stall (XHC_1_MICROSECOND);\r
+ }\r
+\r
+ if (Index == Loop) {\r
+ Urb->Result = EFI_USB_ERR_TIMEOUT;\r
}\r
\r
return Status;\r
Delete a single asynchronous interrupt transfer for\r
the device and endpoint.\r
\r
- @param Xhc The XHCI device.\r
- @param DevAddr The address of the target device.\r
+ @param Xhc The XHCI Instance.\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
**/\r
EFI_STATUS\r
XhciDelAsyncIntTransfer (\r
- IN USB_XHCI_DEV *Xhc,\r
- IN UINT8 DevAddr,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 BusAddr,\r
IN UINT8 EpNum\r
)\r
{\r
LIST_ENTRY *Next;\r
URB *Urb;\r
EFI_USB_DATA_DIRECTION Direction;\r
- BOOLEAN Found;\r
\r
Direction = ((EpNum & 0x80) != 0) ? EfiUsbDataIn : EfiUsbDataOut;\r
EpNum &= 0x0F;\r
\r
- Found = FALSE;\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
FreePool (Urb->Data);\r
- FreePool (Urb);\r
+ XhcFreeUrb (Xhc, Urb);\r
return EFI_SUCCESS;\r
}\r
}\r
/**\r
Remove all the asynchronous interrutp transfers.\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
\r
**/\r
VOID\r
XhciDelAllAsyncIntTransfers (\r
- IN USB_XHCI_DEV *Xhc\r
+ IN USB_XHCI_INSTANCE *Xhc\r
)\r
{\r
LIST_ENTRY *Entry;\r
Urb = EFI_LIST_CONTAINER (Entry, URB, UrbList);\r
RemoveEntryList (&Urb->UrbList);\r
FreePool (Urb->Data);\r
- FreePool (Urb);\r
+ XhcFreeUrb (Xhc, Urb);\r
}\r
}\r
\r
/**\r
Update the queue head for next round of asynchronous transfer\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
@param Urb The URB to update\r
\r
**/\r
VOID\r
XhcUpdateAsyncRequest (\r
- IN USB_XHCI_DEV* Xhc,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
IN URB *Urb\r
)\r
{\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
+ Flush data from PCI controller specific address to mapped system\r
+ memory address.\r
+\r
+ @param Xhc The XHCI device.\r
+ @param Urb The URB to unmap.\r
+\r
+ @retval EFI_SUCCESS Success to flush data to mapped system memory.\r
+ @retval EFI_DEVICE_ERROR Fail to flush data to mapped system memory.\r
+\r
+**/\r
+EFI_STATUS\r
+XhcFlushAsyncIntMap (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN URB *Urb\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS PhyAddr;\r
+ EFI_PCI_IO_PROTOCOL_OPERATION MapOp;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINTN Len;\r
+ VOID *Map;\r
+\r
+ PciIo = Xhc->PciIo;\r
+ Len = Urb->DataLen;\r
+\r
+ if (Urb->Ep.Direction == EfiUsbDataIn) {\r
+ MapOp = EfiPciIoOperationBusMasterWrite;\r
+ } else {\r
+ MapOp = EfiPciIoOperationBusMasterRead;\r
+ }\r
+\r
+ if (Urb->DataMap != NULL) {\r
+ Status = PciIo->Unmap (PciIo, Urb->DataMap);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ }\r
+\r
+ Urb->DataMap = NULL;\r
+\r
+ Status = PciIo->Map (PciIo, MapOp, Urb->Data, &Len, &PhyAddr, &Map);\r
+ if (EFI_ERROR (Status) || (Len != Urb->DataLen)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ Urb->DataPhy = (VOID *) ((UINTN) PhyAddr);\r
+ Urb->DataMap = Map;\r
+ return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+ return EFI_DEVICE_ERROR;\r
+}\r
\r
/**\r
Interrupt transfer periodic check handler.\r
\r
@param Event Interrupt event.\r
- @param Context Pointer to USB_XHCI_DEV.\r
+ @param Context Pointer to USB_XHCI_INSTANCE.\r
\r
**/\r
VOID\r
IN VOID *Context\r
)\r
{\r
- USB_XHCI_DEV *Xhc;\r
+ USB_XHCI_INSTANCE *Xhc;\r
LIST_ENTRY *Entry;\r
LIST_ENTRY *Next;\r
UINT8 *ProcBuf;\r
\r
OldTpl = gBS->RaiseTPL (XHC_TPL);\r
\r
- Xhc = (USB_XHCI_DEV*) Context;\r
+ Xhc = (USB_XHCI_INSTANCE*) Context;\r
\r
EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) {\r
Urb = EFI_LIST_CONTAINER (Entry, URB, UrbList);\r
//\r
// Make sure that the device is available before every check.\r
//\r
- SlotId = XhcDevAddrToSlotId(Urb->Ep.DevAddr);\r
+ SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);\r
if (SlotId == 0) {\r
continue;\r
}\r
// Check the result of URB execution. If it is still\r
// active, check the next one.\r
//\r
- Status = XhcCheckUrbResult (Xhc, Urb);\r
+ XhcCheckUrbResult (Xhc, Urb);\r
\r
- if (Status == EFI_NOT_READY) {\r
+ if (!Urb->Finished) {\r
continue;\r
}\r
\r
//\r
- // Allocate a buffer then copy the transferred data for user.\r
- // If failed to allocate the buffer, update the URB for next\r
- // round of transfer. Ignore the data of this round.\r
+ // Flush any PCI posted write transactions from a PCI host\r
+ // bridge to system memory.\r
//\r
- ProcBuf = NULL;\r
+ Status = XhcFlushAsyncIntMap (Xhc, Urb);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcMonitorAsyncRequests: Fail to Flush AsyncInt Mapped Memeory\n"));\r
+ }\r
+\r
+ //\r
+ // Allocate a buffer then copy the transferred data for user.\r
+ // If failed to allocate the buffer, update the URB for next\r
+ // round of transfer. Ignore the data of this round.\r
+ //\r
+ ProcBuf = NULL;\r
if (Urb->Result == EFI_USB_NOERROR) {\r
ASSERT (Urb->Completed <= Urb->DataLen);\r
\r
- ProcBuf = AllocatePool (Urb->Completed);\r
+ ProcBuf = AllocateZeroPool (Urb->Completed);\r
\r
if (ProcBuf == NULL) {\r
XhcUpdateAsyncRequest (Xhc, Urb);\r
CopyMem (ProcBuf, Urb->Data, Urb->Completed);\r
}\r
\r
- XhcUpdateAsyncRequest (Xhc, Urb);\r
-\r
//\r
// Leave error recovery to its related device driver. A\r
// common case of the error recovery is to re-submit the\r
if (ProcBuf != NULL) {\r
gBS->FreePool (ProcBuf);\r
}\r
+\r
+ XhcUpdateAsyncRequest (Xhc, Urb);\r
}\r
gBS->RestoreTPL (OldTpl);\r
}\r
/**\r
Monitor the port status change. Enable/Disable device slot if there is a device attached/detached.\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
@param ParentRouteChart The route string pointed to the parent device if it exists.\r
@param Port The port to be polled.\r
@param PortState The port state.\r
EFI_STATUS\r
EFIAPI\r
XhcPollPortStatusChange (\r
- IN USB_XHCI_DEV* Xhc,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
IN USB_DEV_ROUTE ParentRouteChart,\r
IN UINT8 Port,\r
IN EFI_USB_PORT_STATUS *PortState\r
\r
Status = EFI_SUCCESS;\r
\r
+ if ((PortState->PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
if (ParentRouteChart.Dword == 0) {\r
- RouteChart.Field.RouteString = 0;\r
- RouteChart.Field.RootPortNum = Port + 1;\r
- RouteChart.Field.TierNum = 1;\r
+ RouteChart.Route.RouteString = 0;\r
+ RouteChart.Route.RootPortNum = Port + 1;\r
+ RouteChart.Route.TierNum = 1;\r
} else {\r
if(Port < 14) {\r
- RouteChart.Field.RouteString = ParentRouteChart.Field.RouteString | (Port << (4 * (ParentRouteChart.Field.TierNum - 1)));\r
+ RouteChart.Route.RouteString = ParentRouteChart.Route.RouteString | (Port << (4 * (ParentRouteChart.Route.TierNum - 1)));\r
+ } else {\r
+ RouteChart.Route.RouteString = ParentRouteChart.Route.RouteString | (15 << (4 * (ParentRouteChart.Route.TierNum - 1)));\r
+ }\r
+ RouteChart.Route.RootPortNum = ParentRouteChart.Route.RootPortNum;\r
+ RouteChart.Route.TierNum = ParentRouteChart.Route.TierNum + 1;\r
+ }\r
+\r
+ SlotId = XhcRouteStringToSlotId (Xhc, RouteChart);\r
+ if (SlotId != 0) {\r
+ if (Xhc->HcCParams.Data.Csz == 0) {\r
+ Status = XhcDisableSlotCmd (Xhc, SlotId);\r
} else {\r
- RouteChart.Field.RouteString = ParentRouteChart.Field.RouteString | (15 << (4 * (ParentRouteChart.Field.TierNum - 1)));\r
+ Status = XhcDisableSlotCmd64 (Xhc, SlotId);\r
}\r
- RouteChart.Field.RootPortNum = ParentRouteChart.Field.RootPortNum;\r
- RouteChart.Field.TierNum = ParentRouteChart.Field.TierNum + 1;\r
}\r
\r
if (((PortState->PortStatus & USB_PORT_STAT_ENABLE) != 0) &&\r
//\r
// Execute Enable_Slot cmd for attached device, initialize device context and assign device address.\r
//\r
- SlotId = XhcRouteStringToSlotId (RouteChart);\r
- if (SlotId == 0) {\r
- Status = XhcInitializeDeviceSlot (Xhc, ParentRouteChart, Port, RouteChart, Speed);\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
- } else if ((PortState->PortStatus & USB_PORT_STAT_CONNECTION) == 0) {\r
- //\r
- // Device is detached. Disable the allocated device slot and release resource.\r
- //\r
- SlotId = XhcRouteStringToSlotId (RouteChart);\r
- if (SlotId != 0) {\r
- Status = XhcDisableSlotCmd (Xhc, SlotId);\r
- ASSERT_EFI_ERROR (Status);\r
+ SlotId = XhcRouteStringToSlotId (Xhc, RouteChart);\r
+ if ((SlotId == 0) && ((PortState->PortChangeStatus & USB_PORT_STAT_C_RESET) != 0)) {\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
}\r
- }\r
+ } \r
+\r
return 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 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 UINT8 DevAddr\r
- )\r
-{\r
- UINT8 Index;\r
-\r
- for (Index = 0; Index < 255; Index++) {\r
- if (UsbDevContext[Index + 1].Enabled &&\r
- (UsbDevContext[Index + 1].SlotId != 0) &&\r
- (UsbDevContext[Index + 1].XhciDevAddr == DevAddr)) {\r
- break;\r
- }\r
- }\r
-\r
- if (Index == 255) {\r
- return 0;\r
- }\r
-\r
- return UsbDevContext[Index + 1].SlotId;\r
-}\r
-\r
/**\r
Find out the actual device address according to the requested device address from UsbBus.\r
\r
- @param BusDevAddr The requested device address by UsbBus upper driver.\r
+ @param Xhc The XHCI Instance.\r
+ @param BusDevAddr The requested device address by UsbBus upper driver.\r
\r
@return The actual device address assigned to the device.\r
\r
UINT8\r
EFIAPI\r
XhcBusDevAddrToSlotId (\r
- IN UINT8 BusDevAddr\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 BusDevAddr\r
)\r
{\r
UINT8 Index;\r
\r
for (Index = 0; Index < 255; Index++) {\r
- if (UsbDevContext[Index + 1].Enabled &&\r
- (UsbDevContext[Index + 1].SlotId != 0) &&\r
- (UsbDevContext[Index + 1].BusDevAddr == BusDevAddr)) {\r
+ if (Xhc->UsbDevContext[Index + 1].Enabled &&\r
+ (Xhc->UsbDevContext[Index + 1].SlotId != 0) &&\r
+ (Xhc->UsbDevContext[Index + 1].BusDevAddr == BusDevAddr)) {\r
break;\r
}\r
}\r
return 0;\r
}\r
\r
- return UsbDevContext[Index + 1].SlotId;\r
+ return Xhc->UsbDevContext[Index + 1].SlotId;\r
}\r
\r
/**\r
Find out the slot id according to the device's route string.\r
\r
- @param RouteString The route string described the device location.\r
+ @param Xhc The XHCI Instance.\r
+ @param RouteString The route string described the device location.\r
\r
@return The slot id used by the device.\r
\r
UINT8\r
EFIAPI\r
XhcRouteStringToSlotId (\r
- IN USB_DEV_ROUTE RouteString\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN USB_DEV_ROUTE RouteString\r
)\r
{\r
UINT8 Index;\r
\r
for (Index = 0; Index < 255; Index++) {\r
- if (UsbDevContext[Index + 1].Enabled &&\r
- (UsbDevContext[Index + 1].SlotId != 0) &&\r
- (UsbDevContext[Index + 1].RouteString.Dword == RouteString.Dword)) {\r
+ if (Xhc->UsbDevContext[Index + 1].Enabled &&\r
+ (Xhc->UsbDevContext[Index + 1].SlotId != 0) &&\r
+ (Xhc->UsbDevContext[Index + 1].RouteString.Dword == RouteString.Dword)) {\r
break;\r
}\r
}\r
return 0;\r
}\r
\r
- return UsbDevContext[Index + 1].SlotId;\r
+ return Xhc->UsbDevContext[Index + 1].SlotId;\r
}\r
\r
/**\r
Synchronize the specified event ring to update the enqueue and dequeue pointer.\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
@param EvtRing The event ring to sync.\r
\r
@retval EFI_SUCCESS The event ring is synchronized successfully.\r
EFI_STATUS\r
EFIAPI\r
XhcSyncEventRing (\r
- IN USB_XHCI_DEV *Xhc,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
IN EVENT_RING *EvtRing\r
)\r
{\r
UINTN Index;\r
- TRB *EvtTrb1;\r
- TRB *EvtTrb2;\r
- TRB *XhcDequeue;\r
+ TRB_TEMPLATE *EvtTrb1;\r
\r
ASSERT (EvtRing != NULL);\r
\r
// Calculate the EventRingEnqueue and EventRingCCS.\r
// Note: only support single Segment\r
//\r
- EvtTrb1 = EvtRing->EventRingSeg0;\r
- EvtTrb2 = EvtRing->EventRingSeg0;\r
+ EvtTrb1 = EvtRing->EventRingDequeue;\r
\r
for (Index = 0; Index < EvtRing->TrbNumber; Index++) {\r
- if (EvtTrb1->CycleBit != EvtTrb2->CycleBit) {\r
+ if (EvtTrb1->CycleBit != EvtRing->EventRingCCS) {\r
break;\r
}\r
+\r
EvtTrb1++;\r
+\r
+ if ((UINTN)EvtTrb1 >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {\r
+ EvtTrb1 = EvtRing->EventRingSeg0;\r
+ EvtRing->EventRingCCS = (EvtRing->EventRingCCS) ? 0 : 1;\r
+ }\r
}\r
\r
if (Index < EvtRing->TrbNumber) {\r
EvtRing->EventRingEnqueue = EvtTrb1;\r
- EvtRing->EventRingCCS = (EvtTrb2->CycleBit) ? 1 : 0;\r
} else {\r
- EvtRing->EventRingEnqueue = EvtTrb2;\r
- EvtRing->EventRingCCS = (EvtTrb2->CycleBit) ? 0 : 1;\r
- }\r
-\r
- //\r
- // Apply the EventRingDequeue to Xhc\r
- //\r
- XhcDequeue = (TRB *)(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
+ ASSERT (FALSE);\r
}\r
\r
return EFI_SUCCESS;\r
/**\r
Synchronize the specified transfer ring to update the enqueue and dequeue pointer.\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
@param TrsRing The transfer ring to sync.\r
\r
@retval EFI_SUCCESS The transfer ring is synchronized successfully.\r
EFI_STATUS\r
EFIAPI\r
XhcSyncTrsRing (\r
- IN USB_XHCI_DEV *Xhc,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
IN TRANSFER_RING *TrsRing\r
)\r
{\r
UINTN Index;\r
- TRB *TrsTrb;\r
+ TRB_TEMPLATE *TrsTrb;\r
\r
ASSERT (TrsRing != NULL);\r
//\r
}\r
TrsTrb++;\r
if ((UINT8) TrsTrb->Type == TRB_TYPE_LINK) {\r
- ASSERT (((LNK_TRB*)TrsTrb)->TC != 0);\r
+ ASSERT (((LINK_TRB*)TrsTrb)->TC != 0);\r
//\r
// set cycle bit in Link TRB as normal\r
//\r
- ((LNK_TRB*)TrsTrb)->CycleBit = TrsRing->RingPCS & BIT0;\r
+ ((LINK_TRB*)TrsTrb)->CycleBit = TrsRing->RingPCS & BIT0;\r
//\r
// Toggle PCS maintained by software\r
//\r
TrsRing->RingPCS = (TrsRing->RingPCS & BIT0) ? 0 : 1;\r
- TrsTrb = (TRB*)(UINTN)((TrsTrb->Dword1 | ((UINT64)TrsTrb->Dword2 << 32)) & ~0x0F);\r
+ TrsTrb = (TRB_TEMPLATE *) TrsRing->RingSeg0; // Use host address\r
}\r
}\r
\r
//\r
// Clear the Trb context for enqueue, but reserve the PCS bit\r
//\r
- TrsTrb->Dword1 = 0;\r
- TrsTrb->Dword2 = 0;\r
- TrsTrb->Dword3 = 0;\r
- TrsTrb->RsvdZ1 = 0;\r
- TrsTrb->Type = 0;\r
- TrsTrb->RsvdZ2 = 0;\r
+ TrsTrb->Parameter1 = 0;\r
+ TrsTrb->Parameter2 = 0;\r
+ TrsTrb->Status = 0;\r
+ TrsTrb->RsvdZ1 = 0;\r
+ TrsTrb->Type = 0;\r
+ TrsTrb->Control = 0;\r
\r
return EFI_SUCCESS;\r
}\r
/**\r
Check if there is a new generated event.\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
@param EvtRing The event ring to check.\r
@param NewEvtTrb The new event TRB found.\r
\r
EFI_STATUS\r
EFIAPI\r
XhcCheckNewEvent (\r
- IN USB_XHCI_DEV *Xhc,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
IN EVENT_RING *EvtRing,\r
- OUT TRB **NewEvtTrb\r
+ OUT TRB_TEMPLATE **NewEvtTrb\r
)\r
{\r
- EFI_STATUS Status;\r
- TRB *EvtTrb;\r
-\r
ASSERT (EvtRing != NULL);\r
\r
- EvtTrb = EvtRing->EventRingDequeue;\r
*NewEvtTrb = EvtRing->EventRingDequeue;\r
\r
if (EvtRing->EventRingDequeue == EvtRing->EventRingEnqueue) {\r
return EFI_NOT_READY;\r
}\r
\r
- Status = EFI_SUCCESS;\r
-\r
- if (((EvtTrb->Dword3 >> 24) & 0xFF) != TRB_COMPLETION_SUCCESS) {\r
- Status = EFI_DEVICE_ERROR;\r
- }\r
-\r
EvtRing->EventRingDequeue++;\r
//\r
// If the dequeue pointer is beyond the ring, then roll-back it to the begining of the ring.\r
//\r
- if ((UINTN)EvtRing->EventRingDequeue >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB) * EvtRing->TrbNumber)) {\r
+ if ((UINTN)EvtRing->EventRingDequeue >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {\r
EvtRing->EventRingDequeue = EvtRing->EventRingSeg0;\r
}\r
\r
- return Status;\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
Ring the door bell to notify XHCI there is a transaction to be executed.\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
@param SlotId The slot id of the target device.\r
@param Dci The device context index of the target slot or endpoint.\r
\r
EFI_STATUS\r
EFIAPI\r
XhcRingDoorBell (\r
- IN USB_XHCI_DEV *Xhc,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
IN UINT8 SlotId,\r
IN UINT8 Dci\r
)\r
/**\r
Ring the door bell to notify XHCI there is a transaction to be executed through URB.\r
\r
- @param Xhc The XHCI device.\r
+ @param Xhc The XHCI Instance.\r
@param Urb The URB to be rung.\r
\r
@retval EFI_SUCCESS Successfully ring the door bell.\r
**/\r
EFI_STATUS\r
RingIntTransferDoorBell (\r
- IN USB_XHCI_DEV *Xhc,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
IN URB *Urb\r
)\r
{\r
UINT8 SlotId;\r
UINT8 Dci;\r
\r
- SlotId = XhcDevAddrToSlotId(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
Assign and initialize the device slot for a new device.\r
\r
- @param Xhc The XHCI device.\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
EFI_STATUS\r
EFIAPI\r
XhcInitializeDeviceSlot (\r
- IN USB_XHCI_DEV *Xhc,\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
- EVT_TRB_COMMAND *EvtTrb;\r
- INPUT_CONTEXT *InputContext;\r
- DEVICE_CONTEXT *OutputDevContxt;\r
- TRANSFER_RING *EndpointTransferRing;\r
- CMD_TRB_ADDR_DEV CmdTrbAddr;\r
- UINT8 DeviceAddress;\r
- CMD_TRB_EN_SLOT CmdTrb;\r
- UINT8 SlotId;\r
- UINT8 ParentSlotId;\r
- DEVICE_CONTEXT *ParentDeviceContext;\r
-\r
- ZeroMem (&CmdTrb, sizeof (CMD_TRB_EN_SLOT));\r
+ EFI_STATUS Status;\r
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;\r
+ INPUT_CONTEXT *InputContext;\r
+ DEVICE_CONTEXT *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 *ParentDeviceContext;\r
+ EFI_PHYSICAL_ADDRESS PhyAddr;\r
+\r
+ ZeroMem (&CmdTrb, sizeof (CMD_TRB_ENABLE_SLOT));\r
CmdTrb.CycleBit = 1;\r
CmdTrb.Type = TRB_TYPE_EN_SLOT;\r
\r
Status = XhcCmdTransfer (\r
Xhc,\r
- (TRB *) (UINTN) &CmdTrb,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrb,\r
XHC_GENERIC_TIMEOUT,\r
- (TRB **) (UINTN) &EvtTrb\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
);\r
- ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcInitializeDeviceSlot: Enable Slot Failed, Status = %r\n", Status));\r
+ return Status;\r
+ }\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
- ZeroMem (&UsbDevContext[SlotId], sizeof (USB_DEV_CONTEXT));\r
- UsbDevContext[SlotId].Enabled = TRUE;\r
- UsbDevContext[SlotId].SlotId = SlotId;\r
- UsbDevContext[SlotId].RouteString.Dword = RouteChart.Dword;\r
- UsbDevContext[SlotId].ParentRouteString.Dword = ParentRouteChart.Dword;\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
// 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
- InputContext = AllocateAlignedZeroPool(sizeof (INPUT_CONTEXT), 64);\r
+ InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT));\r
ASSERT (InputContext != NULL);\r
ASSERT (((UINTN) InputContext & 0x3F) == 0);\r
+ ZeroMem (InputContext, sizeof (INPUT_CONTEXT));\r
\r
- UsbDevContext[SlotId].InputContext = (VOID *) InputContext;\r
+ Xhc->UsbDevContext[SlotId].InputContext = (VOID *) InputContext;\r
\r
//\r
// 2) Initialize the Input Control Context (6.2.5.1) of the Input Context by setting the A0 and A1\r
//\r
// 3) Initialize the Input Slot Context data structure\r
//\r
- InputContext->Slot.RouteStr = RouteChart.Field.RouteString;\r
+ InputContext->Slot.RouteString = RouteChart.Route.RouteString;\r
InputContext->Slot.Speed = DeviceSpeed + 1;\r
InputContext->Slot.ContextEntries = 1;\r
- InputContext->Slot.RootHubPortNum = RouteChart.Field.RootPortNum;\r
+ InputContext->Slot.RootHubPortNum = RouteChart.Route.RootPortNum;\r
\r
- if (RouteChart.Field.RouteString) {\r
+ if (RouteChart.Route.RouteString) {\r
//\r
// The device is behind of hub device.\r
//\r
- ParentSlotId = XhcRouteStringToSlotId(ParentRouteChart);\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 *)UsbDevContext[ParentSlotId].OutputDevContxt;\r
+ ParentDeviceContext = (DEVICE_CONTEXT *)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
// 4) Allocate and initialize the Transfer Ring for the Default Control Endpoint.\r
//\r
- EndpointTransferRing = AllocateAlignedZeroPool(sizeof (TRANSFER_RING), 64);\r
- UsbDevContext[SlotId].EndpointTransferRing[0] = EndpointTransferRing;\r
- CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)UsbDevContext[SlotId].EndpointTransferRing[0]);\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
//\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)UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0) | BIT0;\r
- InputContext->EP[0].PtrHi = XHC_HIGH_32BIT (((TRANSFER_RING *)(UINTN)UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0);\r
+ PhyAddr = UsbHcGetPciAddrForHostAddr (\r
+ Xhc->MemPool,\r
+ ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0,\r
+ sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER\r
+ );\r
+ InputContext->EP[0].PtrLo = XHC_LOW_32BIT (PhyAddr) | BIT0;\r
+ InputContext->EP[0].PtrHi = XHC_HIGH_32BIT (PhyAddr);\r
\r
//\r
// 6) Allocate the Output Device Context data structure (6.2.1) and initialize it to '0'.\r
//\r
- OutputDevContxt = AllocateAlignedZeroPool(sizeof (DEVICE_CONTEXT), 64);\r
- ASSERT (OutputDevContxt != NULL);\r
- ASSERT (((UINTN) OutputDevContxt & 0x3F) == 0);\r
+ OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT));\r
+ ASSERT (OutputContext != NULL);\r
+ ASSERT (((UINTN) OutputContext & 0x3F) == 0);\r
+ ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT));\r
\r
- UsbDevContext[SlotId].OutputDevContxt = OutputDevContxt;\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) OutputDevContxt;\r
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, OutputContext, sizeof (DEVICE_CONTEXT));\r
+ //\r
+ // Fill DCBAA with PCI device address\r
+ //\r
+ Xhc->DCBAA[SlotId] = (UINT64) (UINTN) PhyAddr;\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 (UsbDevContext[SlotId].InputContext);\r
- CmdTrbAddr.PtrHi = XHC_HIGH_32BIT (UsbDevContext[SlotId].InputContext);\r
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT));\r
+ CmdTrbAddr.PtrLo = XHC_LOW_32BIT (PhyAddr);\r
+ CmdTrbAddr.PtrHi = XHC_HIGH_32BIT (PhyAddr);\r
CmdTrbAddr.CycleBit = 1;\r
CmdTrbAddr.Type = TRB_TYPE_ADDRESS_DEV;\r
- CmdTrbAddr.SlotId = UsbDevContext[SlotId].SlotId;\r
+ CmdTrbAddr.SlotId = Xhc->UsbDevContext[SlotId].SlotId;\r
Status = XhcCmdTransfer (\r
Xhc,\r
- (TRB *) (UINTN) &CmdTrbAddr,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbAddr,\r
XHC_GENERIC_TIMEOUT,\r
- (TRB **) (UINTN) &EvtTrb\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
);\r
- ASSERT (!EFI_ERROR(Status));\r
+ if (!EFI_ERROR (Status)) {\r
+ DeviceAddress = (UINT8) ((DEVICE_CONTEXT *) OutputContext)->Slot.DeviceAddress;\r
+ DEBUG ((EFI_D_INFO, " Address %d assigned successfully\n", DeviceAddress));\r
+ Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Assign and initialize the device slot for a new device.\r
+\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 assign a slot to the device and assign an address to it.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\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
+ 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
+ EFI_PHYSICAL_ADDRESS PhyAddr;\r
+\r
+ ZeroMem (&CmdTrb, sizeof (CMD_TRB_ENABLE_SLOT));\r
+ CmdTrb.CycleBit = 1;\r
+ CmdTrb.Type = TRB_TYPE_EN_SLOT;\r
+\r
+ Status = XhcCmdTransfer (\r
+ Xhc,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrb,\r
+ XHC_GENERIC_TIMEOUT,\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcInitializeDeviceSlot64: Enable Slot Failed, Status = %r\n", Status));\r
+ return Status;\r
+ }\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
+ 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
+ // 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
+ InputContext = UsbHcAllocateMem (Xhc->MemPool, 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
+ //\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
+ 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
+ PhyAddr = UsbHcGetPciAddrForHostAddr (\r
+ Xhc->MemPool,\r
+ ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0,\r
+ sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER\r
+ );\r
+ InputContext->EP[0].PtrLo = XHC_LOW_32BIT (PhyAddr) | BIT0;\r
+ InputContext->EP[0].PtrHi = XHC_HIGH_32BIT (PhyAddr);\r
\r
- DeviceAddress = (UINT8) ((DEVICE_CONTEXT *) OutputDevContxt)->Slot.DeviceAddress;\r
- DEBUG ((EFI_D_INFO, " Address %d assigned succeefully\n", DeviceAddress));\r
+ //\r
+ // 6) Allocate the Output Device Context data structure (6.2.1) and initialize it to '0'.\r
+ //\r
+ OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT_64));\r
+ ASSERT (OutputContext != NULL);\r
+ ASSERT (((UINTN) OutputContext & 0x3F) == 0);\r
+ ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT_64));\r
\r
- UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;\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
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, OutputContext, sizeof (DEVICE_CONTEXT_64));\r
+ //\r
+ // Fill DCBAA with PCI device address\r
+ //\r
+ Xhc->DCBAA[SlotId] = (UINT64) (UINTN) PhyAddr;\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
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT_64));\r
+ CmdTrbAddr.PtrLo = XHC_LOW_32BIT (PhyAddr);\r
+ CmdTrbAddr.PtrHi = XHC_HIGH_32BIT (PhyAddr);\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
+ if (!EFI_ERROR (Status)) {\r
+ DeviceAddress = (UINT8) ((DEVICE_CONTEXT_64 *) OutputContext)->Slot.DeviceAddress;\r
+ DEBUG ((EFI_D_INFO, " Address %d assigned successfully\n", DeviceAddress));\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 device.\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
EFI_STATUS\r
EFIAPI\r
XhcDisableSlotCmd (\r
- IN USB_XHCI_DEV *Xhc,\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
IN UINT8 SlotId\r
)\r
{\r
EFI_STATUS Status;\r
- TRB *EvtTrb;\r
- CMD_TRB_DIS_SLOT CmdTrbDisSlot;\r
+ TRB_TEMPLATE *EvtTrb;\r
+ CMD_TRB_DISABLE_SLOT CmdTrbDisSlot;\r
UINT8 Index;\r
VOID *RingSeg;\r
\r
// Entry 0 is reserved.\r
//\r
for (Index = 0; Index < 255; Index++) {\r
- if (!UsbDevContext[Index + 1].Enabled ||\r
- (UsbDevContext[Index + 1].SlotId == 0) ||\r
- (UsbDevContext[Index + 1].ParentRouteString.Dword != UsbDevContext[SlotId].RouteString.Dword)) {\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, UsbDevContext[Index + 1].SlotId);\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
- UsbDevContext[Index + 1].SlotId = 0;\r
+ Xhc->UsbDevContext[Index + 1].SlotId = 0;\r
}\r
}\r
\r
CmdTrbDisSlot.SlotId = SlotId;\r
Status = XhcCmdTransfer (\r
Xhc,\r
- (TRB *) (UINTN) &CmdTrbDisSlot,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbDisSlot,\r
XHC_GENERIC_TIMEOUT,\r
- (TRB **) (UINTN) &EvtTrb\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
);\r
- ASSERT_EFI_ERROR(Status);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcDisableSlotCmd: Disable Slot Command Failed, Status = %r\n", Status));\r
+ return Status;\r
+ }\r
//\r
// Free the slot's device context entry\r
//\r
// Free the slot related data structure\r
//\r
for (Index = 0; Index < 31; Index++) {\r
- if (UsbDevContext[SlotId].EndpointTransferRing[Index] != NULL) {\r
- RingSeg = ((TRANSFER_RING *)(UINTN)UsbDevContext[SlotId].EndpointTransferRing[Index])->RingSeg0;\r
+ if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] != NULL) {\r
+ RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index])->RingSeg0;\r
if (RingSeg != NULL) {\r
- FreeAlignedPool(RingSeg);\r
+ UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);\r
}\r
- FreeAlignedPool(UsbDevContext[SlotId].EndpointTransferRing[Index]);\r
+ FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index]);\r
+ Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] = NULL;\r
}\r
}\r
\r
- for (Index = 0; Index < UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {\r
- if (UsbDevContext[SlotId].ConfDesc[Index] != NULL) {\r
- FreePool (UsbDevContext[SlotId].ConfDesc[Index]);\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 (UsbDevContext[SlotId].InputContext != NULL) {\r
- FreeAlignedPool (UsbDevContext[SlotId].InputContext);\r
+ if (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting != NULL) {\r
+ FreePool (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting);\r
+ }\r
+\r
+ if (Xhc->UsbDevContext[SlotId].InputContext != NULL) {\r
+ UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT));\r
}\r
\r
- if (UsbDevContext[SlotId].OutputDevContxt != NULL) {\r
- FreeAlignedPool (UsbDevContext[SlotId].OutputDevContxt);\r
+ if (Xhc->UsbDevContext[SlotId].OutputContext != NULL) {\r
+ UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].OutputContext, 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
- UsbDevContext[SlotId].Enabled = FALSE;\r
+ Xhc->UsbDevContext[SlotId].Enabled = FALSE;\r
+ Xhc->UsbDevContext[SlotId].SlotId = 0;\r
\r
return Status;\r
}\r
\r
/**\r
- Configure all the device endpoints through XHCI's Configure_Endpoint cmd.\r
+ Disable the specified device slot.\r
\r
- @param Xhc The XHCI device.\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 Xhc The XHCI Instance.\r
+ @param SlotId The slot id to be disabled.\r
\r
- @retval EFI_SUCCESS Successfully configure all the device endpoints.\r
+ @retval EFI_SUCCESS Successfully disable the device slot.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-XhcSetConfigCmd (\r
- IN USB_XHCI_DEV *Xhc,\r
- IN UINT8 SlotId,\r
- IN UINT8 DeviceSpeed,\r
- IN USB_CONFIG_DESCRIPTOR *ConfigDesc\r
+XhcDisableSlotCmd64 (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 SlotId\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_CFG_ED CmdTrbCfgEP;\r
- INPUT_CONTEXT *InputContext;\r
- DEVICE_CONTEXT *OutputDevContxt;\r
- EVT_TRB_COMMAND *EvtTrb;\r
+ EFI_STATUS Status;\r
+ TRB_TEMPLATE *EvtTrb;\r
+ CMD_TRB_DISABLE_SLOT CmdTrbDisSlot;\r
+ UINT8 Index;\r
+ VOID *RingSeg;\r
+\r
//\r
- // 4.6.6 Configure Endpoint\r
+ // Disable the device slots occupied by these devices on its downstream ports.\r
+ // Entry 0 is reserved.\r
//\r
- InputContext = UsbDevContext[SlotId].InputContext;\r
- OutputDevContxt = UsbDevContext[SlotId].OutputDevContxt;\r
- ZeroMem (InputContext, sizeof (INPUT_CONTEXT));\r
- CopyMem (&InputContext->Slot, &OutputDevContxt->Slot, sizeof (SLOT_CONTEXT));\r
-\r
- ASSERT (ConfigDesc != NULL);\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
- MaxDci = 0;\r
+ Status = XhcDisableSlotCmd64 (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);\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
+ 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
- NumEp = IfDesc->NumEndpoints;\r
-\r
- EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);\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
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcDisableSlotCmd: Disable Slot Command Failed, Status = %r\n", Status));\r
+ return Status;\r
+ }\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
+ UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);\r
+ }\r
+ FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index]);\r
+ Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] = NULL;\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].ActiveAlternateSetting != NULL) {\r
+ FreePool (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting);\r
+ }\r
+\r
+ if (Xhc->UsbDevContext[SlotId].InputContext != NULL) {\r
+ UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT_64));\r
+ }\r
+\r
+ if (Xhc->UsbDevContext[SlotId].OutputContext != NULL) {\r
+ UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].OutputContext, 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
+ 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
+\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
+ 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
+ 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
+ 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
+\r
+ CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;\r
+ INPUT_CONTEXT *InputContext;\r
+ DEVICE_CONTEXT *OutputContext;\r
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ InputContext = Xhc->UsbDevContext[SlotId].InputContext;\r
+ OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;\r
+ //\r
+ // XHCI 4.6.6 Configure Endpoint\r
+ // When this command is used to "Set an Alternate Interface on a device", software shall set the Drop\r
+ // Context and Add Context flags as follows:\r
+ // 1) If an endpoint is not modified by the Alternate Interface setting, then software shall set the Drop\r
+ // Context and Add Context flags to '0'.\r
+ //\r
+ // Except the interface indicated by Reqeust->Index, no impact to other interfaces.\r
+ // So the default Drop Context and Add Context flags can be '0' to cover 1).\r
+ //\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
+ IfDescActive = NULL;\r
+ IfDescSet = NULL;\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->InterfaceNumber == (UINT8) Request->Index) {\r
+ if (IfDesc->AlternateSetting == Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[IfDesc->InterfaceNumber]) {\r
+ //\r
+ // Find out the active interface descriptor.\r
+ //\r
+ IfDescActive = IfDesc;\r
+ } else if (IfDesc->AlternateSetting == (UINT8) Request->Value) {\r
+ //\r
+ // Find out the interface descriptor to set.\r
+ //\r
+ IfDescSet = IfDesc;\r
+ }\r
+ }\r
+ }\r
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+ }\r
+\r
+ //\r
+ // XHCI 4.6.6 Configure Endpoint\r
+ // When this command is used to "Set an Alternate Interface on a device", software shall set the Drop\r
+ // Context and Add Context flags as follows:\r
+ // 2) If an endpoint previously disabled, is enabled by the Alternate Interface setting, then software shall set\r
+ // the Drop Context flag to '0' and Add Context flag to '1', and initialize the Input Endpoint Context.\r
+ // 3) If an endpoint previously enabled, is disabled by the Alternate Interface setting, then software shall set\r
+ // the Drop Context flag to '1' and Add Context flag to '0'.\r
+ // 4) If a parameter of an enabled endpoint is modified by an Alternate Interface setting, the Drop Context\r
+ // and Add Context flags shall be set to '1'.\r
+ //\r
+ // Below codes are to cover 2), 3) and 4).\r
+ //\r
+\r
+ if ((IfDescActive != NULL) && (IfDescSet != NULL)) {\r
+ NumEp = IfDescActive->NumEndpoints;\r
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *) (IfDescActive + 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
+ 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
+ // XHCI 4.3.6 - Setting Alternate Interfaces\r
+ // 1) Stop any Running Transfer Rings affected by the Alternate Interface setting.\r
+ //\r
+ Status = XhcStopEndpoint (Xhc, SlotId, Dci);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // XHCI 4.3.6 - Setting Alternate Interfaces\r
+ // 2) Free Transfer Rings of all endpoints that will be affected by the Alternate Interface setting.\r
+ //\r
+ if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] != NULL) {\r
+ RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1])->RingSeg0;\r
+ if (RingSeg != NULL) {\r
+ UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);\r
+ }\r
+ FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1]);\r
+ Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] = NULL;\r
+ }\r
\r
- InputContext->InputControlContext.Dword2 |= (BIT0 << Dci);\r
- InputContext->EP[Dci-1].MaxPacketSize = EpDesc->MaxPacketSize;\r
+ //\r
+ // Set the Drop Context flag to '1'.\r
+ //\r
+ InputContext->InputControlContext.Dword1 |= (BIT0 << Dci);\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
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\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
+ // XHCI 4.3.6 - Setting Alternate Interfaces\r
+ // 3) Clear all the Endpoint Context fields of each endpoint that will be disabled by the Alternate\r
+ // Interface setting, to '0'.\r
+ //\r
+ // The step 3) has been covered by the ZeroMem () to InputContext at the start of the function.\r
+ //\r
\r
- InputContext->EP[Dci-1].AverageTRBLength = 0x1000;\r
- if (UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {\r
- EndpointTransferRing = AllocateAlignedZeroPool(sizeof (TRANSFER_RING), 64);\r
- UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;\r
- CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)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
+ // XHCI 4.3.6 - Setting Alternate Interfaces\r
+ // 4) For each endpoint enabled by the Configure Endpoint Command:\r
+ // a. Allocate a Transfer Ring.\r
+ // b. Initialize the Transfer Ring Segment(s) by clearing all fields of all TRBs to '0'.\r
+ // c. Initialize the Endpoint Context data structure.\r
+ //\r
+ Dci = XhcInitializeEndpointContext (Xhc, SlotId, DeviceSpeed, InputContext, IfDescSet);\r
+ if (Dci > MaxDci) {\r
+ MaxDci = Dci;\r
+ }\r
+\r
+ InputContext->InputControlContext.Dword2 |= BIT0;\r
+ InputContext->Slot.ContextEntries = MaxDci;\r
+ //\r
+ // XHCI 4.3.6 - Setting Alternate Interfaces\r
+ // 5) Issue and successfully complete a Configure Endpoint Command.\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, "SetInterface: 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, "SetInterface: Config Endpoint Failed, Status = %r\n", Status));\r
+ } else {\r
+ //\r
+ // Update the active AlternateSetting.\r
+ //\r
+ Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[(UINT8) Request->Index] = (UINT8) Request->Value;\r
+ }\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
+XhcSetInterface64 (\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
+\r
+ CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;\r
+ INPUT_CONTEXT_64 *InputContext;\r
+ DEVICE_CONTEXT_64 *OutputContext;\r
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ InputContext = Xhc->UsbDevContext[SlotId].InputContext;\r
+ OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;\r
+ //\r
+ // XHCI 4.6.6 Configure Endpoint\r
+ // When this command is used to "Set an Alternate Interface on a device", software shall set the Drop\r
+ // Context and Add Context flags as follows:\r
+ // 1) If an endpoint is not modified by the Alternate Interface setting, then software shall set the Drop\r
+ // Context and Add Context flags to '0'.\r
+ //\r
+ // Except the interface indicated by Reqeust->Index, no impact to other interfaces.\r
+ // So the default Drop Context and Add Context flags can be '0' to cover 1).\r
+ //\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
+ IfDescActive = NULL;\r
+ IfDescSet = NULL;\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->InterfaceNumber == (UINT8) Request->Index) {\r
+ if (IfDesc->AlternateSetting == Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[IfDesc->InterfaceNumber]) {\r
+ //\r
+ // Find out the active interface descriptor.\r
+ //\r
+ IfDescActive = IfDesc;\r
+ } else if (IfDesc->AlternateSetting == (UINT8) Request->Value) {\r
//\r
- // Get the bInterval from descriptor and init the the interval field of endpoint context\r
+ // Find out the interface descriptor to set.\r
//\r
- if ((DeviceSpeed == EFI_USB_SPEED_FULL) || (DeviceSpeed == EFI_USB_SPEED_LOW)) {\r
- Interval = EpDesc->Interval;\r
- //\r
- // BUGBUG: Hard code the interval to MAX\r
- //\r
- InputContext->EP[Dci-1].Interval = 6;\r
- } else if (DeviceSpeed == EFI_USB_SPEED_SUPER) {\r
- Interval = EpDesc->Interval;\r
- InputContext->EP[Dci-1].Interval = 0x0F;\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 (UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) {\r
- EndpointTransferRing = AllocateAlignedZeroPool(sizeof (TRANSFER_RING), 64);\r
- UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing;\r
- CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)UsbDevContext[SlotId].EndpointTransferRing[Dci-1]);\r
- }\r
- break;\r
-\r
- case USB_ENDPOINT_CONTROL:\r
- default:\r
- ASSERT (0);\r
- break;\r
+ IfDescSet = IfDesc;\r
+ }\r
+ }\r
+ }\r
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+ }\r
+\r
+ //\r
+ // XHCI 4.6.6 Configure Endpoint\r
+ // When this command is used to "Set an Alternate Interface on a device", software shall set the Drop\r
+ // Context and Add Context flags as follows:\r
+ // 2) If an endpoint previously disabled, is enabled by the Alternate Interface setting, then software shall set\r
+ // the Drop Context flag to '0' and Add Context flag to '1', and initialize the Input Endpoint Context.\r
+ // 3) If an endpoint previously enabled, is disabled by the Alternate Interface setting, then software shall set\r
+ // the Drop Context flag to '1' and Add Context flag to '0'.\r
+ // 4) If a parameter of an enabled endpoint is modified by an Alternate Interface setting, the Drop Context\r
+ // and Add Context flags shall be set to '1'.\r
+ //\r
+ // Below codes are to cover 2), 3) and 4).\r
+ //\r
+\r
+ if ((IfDescActive != NULL) && (IfDescSet != NULL)) {\r
+ NumEp = IfDescActive->NumEndpoints;\r
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *) (IfDescActive + 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
+ // XHCI 4.3.6 - Setting Alternate Interfaces\r
+ // 1) Stop any Running Transfer Rings affected by the Alternate Interface setting.\r
+ //\r
+ Status = XhcStopEndpoint (Xhc, SlotId, Dci);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // XHCI 4.3.6 - Setting Alternate Interfaces\r
+ // 2) Free Transfer Rings of all endpoints that will be affected by the Alternate Interface setting.\r
+ //\r
+ if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] != NULL) {\r
+ RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1])->RingSeg0;\r
+ if (RingSeg != NULL) {\r
+ UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);\r
+ }\r
+ FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1]);\r
+ Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] = NULL;\r
}\r
\r
- PhyAddr = XHC_LOW_32BIT (((TRANSFER_RING *)(UINTN)UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0);\r
- PhyAddr &= ~(0x0F);\r
- PhyAddr |= ((TRANSFER_RING *)(UINTN)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)UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0);\r
+ //\r
+ // Set the Drop Context flag to '1'.\r
+ //\r
+ InputContext->InputControlContext.Dword1 |= (BIT0 << Dci);\r
\r
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);\r
}\r
- IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);\r
+\r
+ //\r
+ // XHCI 4.3.6 - Setting Alternate Interfaces\r
+ // 3) Clear all the Endpoint Context fields of each endpoint that will be disabled by the Alternate\r
+ // Interface setting, to '0'.\r
+ //\r
+ // The step 3) has been covered by the ZeroMem () to InputContext at the start of the function.\r
+ //\r
+\r
+ //\r
+ // XHCI 4.3.6 - Setting Alternate Interfaces\r
+ // 4) For each endpoint enabled by the Configure Endpoint Command:\r
+ // a. Allocate a Transfer Ring.\r
+ // b. Initialize the Transfer Ring Segment(s) by clearing all fields of all TRBs to '0'.\r
+ // c. Initialize the Endpoint Context data structure.\r
+ //\r
+ Dci = XhcInitializeEndpointContext64 (Xhc, SlotId, DeviceSpeed, InputContext, IfDescSet);\r
+ if (Dci > MaxDci) {\r
+ MaxDci = Dci;\r
+ }\r
+\r
+ InputContext->InputControlContext.Dword2 |= BIT0;\r
+ InputContext->Slot.ContextEntries = MaxDci;\r
+ //\r
+ // XHCI 4.3.6 - Setting Alternate Interfaces\r
+ // 5) Issue and successfully complete a Configure Endpoint Command.\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, "SetInterface64: 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, "SetInterface64: Config Endpoint Failed, Status = %r\n", Status));\r
+ } else {\r
+ //\r
+ // Update the active AlternateSetting.\r
+ //\r
+ Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[(UINT8) Request->Index] = (UINT8) Request->Value;\r
+ }\r
}\r
\r
- InputContext->InputControlContext.Dword2 |= BIT0;\r
- InputContext->Slot.ContextEntries = MaxDci;\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
+XhcEvaluateContext (\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 *InputContext;\r
+ EFI_PHYSICAL_ADDRESS PhyAddr;\r
+\r
+ ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);\r
+\r
//\r
- // configure endpoint\r
+ // 4.6.7 Evaluate Context\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 = UsbDevContext[SlotId].SlotId;\r
- DEBUG ((EFI_D_INFO, "Configure Endpoint\n"));\r
+ InputContext = Xhc->UsbDevContext[SlotId].InputContext;\r
+ ZeroMem (InputContext, sizeof (INPUT_CONTEXT));\r
+\r
+ InputContext->InputControlContext.Dword2 |= BIT1;\r
+ InputContext->EP[0].MaxPacketSize = MaxPacketSize;\r
+\r
+ ZeroMem (&CmdTrbEvalu, sizeof (CmdTrbEvalu));\r
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT));\r
+ CmdTrbEvalu.PtrLo = XHC_LOW_32BIT (PhyAddr);\r
+ CmdTrbEvalu.PtrHi = XHC_HIGH_32BIT (PhyAddr);\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 *) (UINTN) &CmdTrbCfgEP,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbEvalu,\r
XHC_GENERIC_TIMEOUT,\r
- (TRB **) (UINTN) &EvtTrb\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
);\r
- ASSERT_EFI_ERROR(Status);\r
-\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcEvaluateContext: Evaluate Context Failed, Status = %r\n", Status));\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 device.\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
**/\r
EFI_STATUS\r
EFIAPI\r
-XhcEvaluateContext (\r
- IN USB_XHCI_DEV *Xhc,\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_EVALU_CONTX CmdTrbEvalu;\r
- EVT_TRB_COMMAND *EvtTrb;\r
- INPUT_CONTEXT *InputContext;\r
+ EFI_STATUS Status;\r
+ CMD_TRB_EVALUATE_CONTEXT CmdTrbEvalu;\r
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;\r
+ INPUT_CONTEXT_64 *InputContext;\r
+ EFI_PHYSICAL_ADDRESS PhyAddr;\r
\r
- ASSERT (UsbDevContext[SlotId].SlotId != 0);\r
+ ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);\r
\r
//\r
// 4.6.7 Evaluate Context\r
//\r
- InputContext = UsbDevContext[SlotId].InputContext;\r
- ZeroMem (InputContext, sizeof (INPUT_CONTEXT));\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
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64));\r
+ CmdTrbEvalu.PtrLo = XHC_LOW_32BIT (PhyAddr);\r
+ CmdTrbEvalu.PtrHi = XHC_HIGH_32BIT (PhyAddr);\r
CmdTrbEvalu.CycleBit = 1;\r
CmdTrbEvalu.Type = TRB_TYPE_EVALU_CONTXT;\r
- CmdTrbEvalu.SlotId = UsbDevContext[SlotId].SlotId;\r
+ CmdTrbEvalu.SlotId = Xhc->UsbDevContext[SlotId].SlotId;\r
DEBUG ((EFI_D_INFO, "Evaluate context\n"));\r
Status = XhcCmdTransfer (\r
Xhc,\r
- (TRB *) (UINTN) &CmdTrbEvalu,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbEvalu,\r
XHC_GENERIC_TIMEOUT,\r
- (TRB **) (UINTN) &EvtTrb\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
);\r
- ASSERT (!EFI_ERROR(Status));\r
-\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcEvaluateContext64: Evaluate Context Failed, Status = %r\n", 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
- @param Xhc The XHCI device.\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
**/\r
EFI_STATUS\r
XhcConfigHubContext (\r
- IN USB_XHCI_DEV *Xhc,\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
+ EFI_STATUS Status;\r
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;\r
+ INPUT_CONTEXT *InputContext;\r
+ DEVICE_CONTEXT *OutputContext;\r
+ CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;\r
+ EFI_PHYSICAL_ADDRESS PhyAddr;\r
\r
- EVT_TRB_COMMAND *EvtTrb;\r
- INPUT_CONTEXT *InputContext;\r
- DEVICE_CONTEXT *OutputDevContxt;\r
- CMD_CFG_ED CmdTrbCfgEP;\r
-\r
- ASSERT (UsbDevContext[SlotId].SlotId != 0);\r
- InputContext = UsbDevContext[SlotId].InputContext;\r
- OutputDevContxt = UsbDevContext[SlotId].OutputDevContxt;\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
// Copy the slot context from OutputContext to Input context\r
//\r
- CopyMem(&(InputContext->Slot), &(OutputDevContxt->Slot), sizeof (SLOT_CONTEXT));\r
+ CopyMem(&(InputContext->Slot), &(OutputContext->Slot), sizeof (SLOT_CONTEXT));\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
+ 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 = UsbDevContext[SlotId].SlotId;\r
+ CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId;\r
DEBUG ((EFI_D_INFO, "Configure Hub Slot Context\n"));\r
Status = XhcCmdTransfer (\r
Xhc,\r
- (TRB *) (UINTN) &CmdTrbCfgEP,\r
+ (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP,\r
XHC_GENERIC_TIMEOUT,\r
- (TRB **) (UINTN) &EvtTrb\r
+ (TRB_TEMPLATE **) (UINTN) &EvtTrb\r
);\r
- ASSERT (!EFI_ERROR(Status));\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcConfigHubContext: Config Endpoint Failed, Status = %r\n", Status));\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
+ EVT_TRB_COMMAND_COMPLETION *EvtTrb;\r
+ INPUT_CONTEXT_64 *InputContext;\r
+ DEVICE_CONTEXT_64 *OutputContext;\r
+ CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;\r
+ EFI_PHYSICAL_ADDRESS PhyAddr;\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
+ 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 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
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcConfigHubContext64: Config Endpoint Failed, Status = %r\n", Status));\r
+ }\r
return Status;\r
}\r
\r
+\r