/**\r
Alloc some memory from the block.\r
\r
- @param Block The memory block to allocate memory from.\r
- @param Units Number of memory units to allocate.\r
+ @param Block The memory block to allocate memory from.\r
+ @param Units Number of memory units to allocate.\r
+ @param AllocationForRing The allocated memory is for Ring or not.\r
\r
@return The pointer to the allocated memory. If couldn't allocate the needed memory,\r
the return value is NULL.\r
VOID *\r
UsbHcAllocMemFromBlock (\r
IN USBHC_MEM_BLOCK *Block,\r
- IN UINTN Units\r
+ IN UINTN Units,\r
+ IN BOOLEAN AllocationForRing\r
)\r
{\r
UINTN Byte;\r
UINT8 StartBit;\r
UINTN Available;\r
UINTN Count;\r
+ UINTN MemUnitAddr;\r
+ UINTN AlignmentMask;\r
\r
ASSERT ((Block != 0) && (Units != 0));\r
\r
- StartByte = 0;\r
- StartBit = 0;\r
- Available = 0;\r
+ StartByte = 0;\r
+ StartBit = 0;\r
+ Available = 0;\r
+ AlignmentMask = ~((UINTN)USBHC_MEM_TRB_RINGS_BOUNDARY - 1);\r
\r
for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {\r
//\r
// Available counts the consective number of zero bit.\r
//\r
if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {\r
+ if (AllocationForRing && (Available != 0)) {\r
+ MemUnitAddr = (UINTN)Block->BufHost + (Byte * 8 + Bit) * USBHC_MEM_UNIT;\r
+ if ((MemUnitAddr & AlignmentMask) != ((MemUnitAddr - USBHC_MEM_UNIT) & AlignmentMask)) {\r
+ //\r
+ // If the TRB Ring memory cross 64K-byte boundary, then restart the\r
+ // search starting at current memory unit.\r
+ // Doing so is to meet the TRB Ring boundary requirement in XHCI spec.\r
+ //\r
+ Available = 0;\r
+ StartByte = Byte;\r
+ StartBit = Bit;\r
+ }\r
+ }\r
+\r
Available++;\r
\r
if (Available >= Units) {\r
Allocate some memory from the host controller's memory pool\r
which can be used to communicate with host controller.\r
\r
- @param Pool The host controller's memory pool.\r
- @param Size Size of the memory to allocate.\r
+ @param Pool The host controller's memory pool.\r
+ @param Size Size of the memory to allocate.\r
+ @param AllocationForRing The allocated memory is for Ring or not.\r
\r
@return The allocated memory or NULL.\r
\r
VOID *\r
UsbHcAllocateMem (\r
IN USBHC_MEM_POOL *Pool,\r
- IN UINTN Size\r
+ IN UINTN Size,\r
+ IN BOOLEAN AllocationForRing\r
)\r
{\r
USBHC_MEM_BLOCK *Head;\r
// First check whether current memory blocks can satisfy the allocation.\r
//\r
for (Block = Head; Block != NULL; Block = Block->Next) {\r
- Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);\r
+ Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT, AllocationForRing);\r
\r
if (Mem != NULL) {\r
ZeroMem (Mem, Size);\r
// Add the new memory block to the pool, then allocate memory from it\r
//\r
UsbHcInsertMemBlockToPool (Head, NewBlock);\r
- Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);\r
+ Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT, AllocationForRing);\r
\r
if (Mem != NULL) {\r
ZeroMem (Mem, Size);\r
\r
#define USBHC_MEM_ROUND(Len) (((Len) + USBHC_MEM_UNIT_MASK) & (~USBHC_MEM_UNIT_MASK))\r
\r
+#define USBHC_MEM_TRB_RINGS_BOUNDARY SIZE_64KB\r
+\r
//\r
// Advance the byte and bit to the next bit, adjust byte accordingly.\r
//\r
Allocate some memory from the host controller's memory pool\r
which can be used to communicate with host controller.\r
\r
- @param Pool The host controller's memory pool.\r
- @param Size Size of the memory to allocate.\r
+ @param Pool The host controller's memory pool.\r
+ @param Size Size of the memory to allocate.\r
+ @param AllocationForRing The allocated memory is for Ring or not.\r
\r
@return The allocated memory or NULL.\r
\r
VOID *\r
UsbHcAllocateMem (\r
IN USBHC_MEM_POOL *Pool,\r
- IN UINTN Size\r
+ IN UINTN Size,\r
+ IN BOOLEAN AllocationForRing\r
);\r
\r
/**\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 = UsbHcAllocateMem (Xhc->MemPool, Entries);\r
+ Dcbaa = UsbHcAllocateMem (Xhc->MemPool, Entries, FALSE);\r
ASSERT (Dcbaa != NULL);\r
ZeroMem (Dcbaa, Entries);\r
\r
ASSERT (EventRing != NULL);\r
\r
Size = sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER;\r
- Buf = UsbHcAllocateMem (Xhc->MemPool, Size);\r
+ Buf = UsbHcAllocateMem (Xhc->MemPool, Size, TRUE);\r
ASSERT (Buf != NULL);\r
ASSERT (((UINTN)Buf & 0x3F) == 0);\r
ZeroMem (Buf, Size);\r
EventRing->EventRingCCS = 1;\r
\r
Size = sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER;\r
- Buf = UsbHcAllocateMem (Xhc->MemPool, Size);\r
+ Buf = UsbHcAllocateMem (Xhc->MemPool, Size, FALSE);\r
ASSERT (Buf != NULL);\r
ASSERT (((UINTN)Buf & 0x3F) == 0);\r
ZeroMem (Buf, Size);\r
LINK_TRB *EndTrb;\r
EFI_PHYSICAL_ADDRESS PhyAddr;\r
\r
- Buf = UsbHcAllocateMem (Xhc->MemPool, sizeof (TRB_TEMPLATE) * TrbNum);\r
+ Buf = UsbHcAllocateMem (Xhc->MemPool, sizeof (TRB_TEMPLATE) * TrbNum, TRUE);\r
ASSERT (Buf != NULL);\r
ASSERT (((UINTN)Buf & 0x3F) == 0);\r
ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum);\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));\r
+ InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT), FALSE);\r
ASSERT (InputContext != NULL);\r
ASSERT (((UINTN)InputContext & 0x3F) == 0);\r
ZeroMem (InputContext, sizeof (INPUT_CONTEXT));\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));\r
+ OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT), FALSE);\r
ASSERT (OutputContext != NULL);\r
ASSERT (((UINTN)OutputContext & 0x3F) == 0);\r
ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT));\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
+ InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT_64), FALSE);\r
ASSERT (InputContext != NULL);\r
ASSERT (((UINTN)InputContext & 0x3F) == 0);\r
ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64));\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
+ OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT_64), FALSE);\r
ASSERT (OutputContext != NULL);\r
ASSERT (((UINTN)OutputContext & 0x3F) == 0);\r
ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT_64));\r