/**\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