MdeModulePkg XhciPei/UsbBusPei: Add XHCI recovery support.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Feng Tian <feng.tian@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15611 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
662
MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c
Normal file
662
MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c
Normal file
@ -0,0 +1,662 @@
|
|||||||
|
/** @file
|
||||||
|
PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid
|
||||||
|
which is used to enable recovery function from USB Drivers.
|
||||||
|
|
||||||
|
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions
|
||||||
|
of the BSD License which accompanies this distribution. The
|
||||||
|
full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "XhcPeim.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocate a block of memory to be used by the buffer pool.
|
||||||
|
|
||||||
|
@param Pages How many pages to allocate.
|
||||||
|
|
||||||
|
@return Pointer to the allocated memory block or NULL if failed.
|
||||||
|
|
||||||
|
**/
|
||||||
|
USBHC_MEM_BLOCK *
|
||||||
|
UsbHcAllocMemBlock (
|
||||||
|
IN UINTN Pages
|
||||||
|
)
|
||||||
|
{
|
||||||
|
USBHC_MEM_BLOCK *Block;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN PageNumber;
|
||||||
|
EFI_PHYSICAL_ADDRESS TempPtr;
|
||||||
|
|
||||||
|
PageNumber = EFI_SIZE_TO_PAGES (sizeof (USBHC_MEM_BLOCK));
|
||||||
|
Status = PeiServicesAllocatePages (
|
||||||
|
EfiBootServicesData,
|
||||||
|
PageNumber,
|
||||||
|
&TempPtr
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ZeroMem ((VOID *) (UINTN) TempPtr, EFI_PAGES_TO_SIZE (PageNumber));
|
||||||
|
|
||||||
|
//
|
||||||
|
// each bit in the bit array represents USBHC_MEM_UNIT
|
||||||
|
// bytes of memory in the memory block.
|
||||||
|
//
|
||||||
|
ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE);
|
||||||
|
|
||||||
|
Block = (USBHC_MEM_BLOCK *) (UINTN) TempPtr;
|
||||||
|
Block->BufLen = EFI_PAGES_TO_SIZE (Pages);
|
||||||
|
Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8);
|
||||||
|
|
||||||
|
PageNumber = EFI_SIZE_TO_PAGES (Block->BitsLen);
|
||||||
|
Status = PeiServicesAllocatePages (
|
||||||
|
EfiBootServicesData,
|
||||||
|
PageNumber,
|
||||||
|
&TempPtr
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ZeroMem ((VOID *) (UINTN) TempPtr, EFI_PAGES_TO_SIZE (PageNumber));
|
||||||
|
|
||||||
|
Block->Bits = (UINT8 *) (UINTN) TempPtr;
|
||||||
|
|
||||||
|
Status = PeiServicesAllocatePages (
|
||||||
|
EfiBootServicesData,
|
||||||
|
Pages,
|
||||||
|
&TempPtr
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ZeroMem ((VOID *) (UINTN) TempPtr, EFI_PAGES_TO_SIZE (Pages));
|
||||||
|
|
||||||
|
Block->BufHost = (UINT8 *) (UINTN) TempPtr;;
|
||||||
|
Block->Buf = (UINT8 *) (UINTN) TempPtr;
|
||||||
|
Block->Next = NULL;
|
||||||
|
|
||||||
|
return Block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Free the memory block from the memory pool.
|
||||||
|
|
||||||
|
@param Pool The memory pool to free the block from.
|
||||||
|
@param Block The memory block to free.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
UsbHcFreeMemBlock (
|
||||||
|
IN USBHC_MEM_POOL *Pool,
|
||||||
|
IN USBHC_MEM_BLOCK *Block
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASSERT ((Pool != NULL) && (Block != NULL));
|
||||||
|
//
|
||||||
|
// No free memory in PEI.
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Alloc some memory from the block.
|
||||||
|
|
||||||
|
@param Block The memory block to allocate memory from.
|
||||||
|
@param Units Number of memory units to allocate.
|
||||||
|
|
||||||
|
@return The pointer to the allocated memory.
|
||||||
|
If couldn't allocate the needed memory, the return value is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID *
|
||||||
|
UsbHcAllocMemFromBlock (
|
||||||
|
IN USBHC_MEM_BLOCK *Block,
|
||||||
|
IN UINTN Units
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Byte;
|
||||||
|
UINT8 Bit;
|
||||||
|
UINTN StartByte;
|
||||||
|
UINT8 StartBit;
|
||||||
|
UINTN Available;
|
||||||
|
UINTN Count;
|
||||||
|
|
||||||
|
ASSERT ((Block != 0) && (Units != 0));
|
||||||
|
|
||||||
|
StartByte = 0;
|
||||||
|
StartBit = 0;
|
||||||
|
Available = 0;
|
||||||
|
|
||||||
|
for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {
|
||||||
|
//
|
||||||
|
// If current bit is zero, the corresponding memory unit is
|
||||||
|
// available, otherwise we need to restart our searching.
|
||||||
|
// Available counts the consective number of zero bit.
|
||||||
|
//
|
||||||
|
if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {
|
||||||
|
Available++;
|
||||||
|
|
||||||
|
if (Available >= Units) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NEXT_BIT (Byte, Bit);
|
||||||
|
} else {
|
||||||
|
NEXT_BIT (Byte, Bit);
|
||||||
|
|
||||||
|
Available = 0;
|
||||||
|
StartByte = Byte;
|
||||||
|
StartBit = Bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Available < Units) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mark the memory as allocated
|
||||||
|
//
|
||||||
|
Byte = StartByte;
|
||||||
|
Bit = StartBit;
|
||||||
|
|
||||||
|
for (Count = 0; Count < Units; Count++) {
|
||||||
|
ASSERT (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
|
||||||
|
|
||||||
|
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | (UINT8) USB_HC_BIT (Bit));
|
||||||
|
NEXT_BIT (Byte, Bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Block->BufHost + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Calculate the corresponding pci bus address according to the Mem parameter.
|
||||||
|
|
||||||
|
@param Pool The memory pool of the host controller.
|
||||||
|
@param Mem The pointer to host memory.
|
||||||
|
@param Size The size of the memory region.
|
||||||
|
|
||||||
|
@return The pci memory address
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_PHYSICAL_ADDRESS
|
||||||
|
UsbHcGetPciAddrForHostAddr (
|
||||||
|
IN USBHC_MEM_POOL *Pool,
|
||||||
|
IN VOID *Mem,
|
||||||
|
IN UINTN Size
|
||||||
|
)
|
||||||
|
{
|
||||||
|
USBHC_MEM_BLOCK *Head;
|
||||||
|
USBHC_MEM_BLOCK *Block;
|
||||||
|
UINTN AllocSize;
|
||||||
|
EFI_PHYSICAL_ADDRESS PhyAddr;
|
||||||
|
UINTN Offset;
|
||||||
|
|
||||||
|
Head = Pool->Head;
|
||||||
|
AllocSize = USBHC_MEM_ROUND (Size);
|
||||||
|
|
||||||
|
if (Mem == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Block = Head; Block != NULL; Block = Block->Next) {
|
||||||
|
//
|
||||||
|
// scan the memory block list for the memory block that
|
||||||
|
// completely contains the allocated memory.
|
||||||
|
//
|
||||||
|
if ((Block->BufHost <= (UINT8 *) Mem) && (((UINT8 *) Mem + AllocSize) <= (Block->BufHost + Block->BufLen))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT ((Block != NULL));
|
||||||
|
//
|
||||||
|
// calculate the pci memory address for host memory address.
|
||||||
|
//
|
||||||
|
Offset = (UINT8 *) Mem - Block->BufHost;
|
||||||
|
PhyAddr = (EFI_PHYSICAL_ADDRESS) (UINTN) (Block->Buf + Offset);
|
||||||
|
return PhyAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Calculate the corresponding host address according to the pci address.
|
||||||
|
|
||||||
|
@param Pool The memory pool of the host controller.
|
||||||
|
@param Mem The pointer to pci memory.
|
||||||
|
@param Size The size of the memory region.
|
||||||
|
|
||||||
|
@return The host memory address
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_PHYSICAL_ADDRESS
|
||||||
|
UsbHcGetHostAddrForPciAddr (
|
||||||
|
IN USBHC_MEM_POOL *Pool,
|
||||||
|
IN VOID *Mem,
|
||||||
|
IN UINTN Size
|
||||||
|
)
|
||||||
|
{
|
||||||
|
USBHC_MEM_BLOCK *Head;
|
||||||
|
USBHC_MEM_BLOCK *Block;
|
||||||
|
UINTN AllocSize;
|
||||||
|
EFI_PHYSICAL_ADDRESS HostAddr;
|
||||||
|
UINTN Offset;
|
||||||
|
|
||||||
|
Head = Pool->Head;
|
||||||
|
AllocSize = USBHC_MEM_ROUND (Size);
|
||||||
|
|
||||||
|
if (Mem == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Block = Head; Block != NULL; Block = Block->Next) {
|
||||||
|
//
|
||||||
|
// scan the memory block list for the memory block that
|
||||||
|
// completely contains the allocated memory.
|
||||||
|
//
|
||||||
|
if ((Block->Buf <= (UINT8 *) Mem) && (((UINT8 *) Mem + AllocSize) <= (Block->Buf + Block->BufLen))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT ((Block != NULL));
|
||||||
|
//
|
||||||
|
// calculate the host memory address for pci memory address.
|
||||||
|
//
|
||||||
|
Offset = (UINT8 *) Mem - Block->Buf;
|
||||||
|
HostAddr = (EFI_PHYSICAL_ADDRESS) (UINTN) (Block->BufHost + Offset);
|
||||||
|
return HostAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Insert the memory block to the pool's list of the blocks.
|
||||||
|
|
||||||
|
@param Head The head of the memory pool's block list.
|
||||||
|
@param Block The memory block to insert.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
UsbHcInsertMemBlockToPool (
|
||||||
|
IN USBHC_MEM_BLOCK *Head,
|
||||||
|
IN USBHC_MEM_BLOCK *Block
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASSERT ((Head != NULL) && (Block != NULL));
|
||||||
|
Block->Next = Head->Next;
|
||||||
|
Head->Next = Block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Is the memory block empty?
|
||||||
|
|
||||||
|
@param Block The memory block to check.
|
||||||
|
|
||||||
|
@retval TRUE The memory block is empty.
|
||||||
|
@retval FALSE The memory block isn't empty.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
UsbHcIsMemBlockEmpty (
|
||||||
|
IN USBHC_MEM_BLOCK *Block
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
for (Index = 0; Index < Block->BitsLen; Index++) {
|
||||||
|
if (Block->Bits[Index] != 0) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Unlink the memory block from the pool's list.
|
||||||
|
|
||||||
|
@param Head The block list head of the memory's pool.
|
||||||
|
@param BlockToUnlink The memory block to unlink.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
UsbHcUnlinkMemBlock (
|
||||||
|
IN USBHC_MEM_BLOCK *Head,
|
||||||
|
IN USBHC_MEM_BLOCK *BlockToUnlink
|
||||||
|
)
|
||||||
|
{
|
||||||
|
USBHC_MEM_BLOCK *Block;
|
||||||
|
|
||||||
|
ASSERT ((Head != NULL) && (BlockToUnlink != NULL));
|
||||||
|
|
||||||
|
for (Block = Head; Block != NULL; Block = Block->Next) {
|
||||||
|
if (Block->Next == BlockToUnlink) {
|
||||||
|
Block->Next = BlockToUnlink->Next;
|
||||||
|
BlockToUnlink->Next = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize the memory management pool for the host controller.
|
||||||
|
|
||||||
|
@return Pointer to the allocated memory pool or NULL if failed.
|
||||||
|
|
||||||
|
**/
|
||||||
|
USBHC_MEM_POOL *
|
||||||
|
UsbHcInitMemPool (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
USBHC_MEM_POOL *Pool;
|
||||||
|
UINTN PageNumber;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_PHYSICAL_ADDRESS TempPtr;
|
||||||
|
|
||||||
|
PageNumber = EFI_SIZE_TO_PAGES (sizeof (USBHC_MEM_POOL));
|
||||||
|
Status = PeiServicesAllocatePages (
|
||||||
|
EfiBootServicesData,
|
||||||
|
PageNumber,
|
||||||
|
&TempPtr
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ZeroMem ((VOID *) (UINTN) TempPtr, EFI_PAGES_TO_SIZE (PageNumber));
|
||||||
|
|
||||||
|
Pool = (USBHC_MEM_POOL *) ((UINTN) TempPtr);
|
||||||
|
Pool->Head = UsbHcAllocMemBlock (USBHC_MEM_DEFAULT_PAGES);
|
||||||
|
|
||||||
|
if (Pool->Head == NULL) {
|
||||||
|
//
|
||||||
|
// No free memory in PEI.
|
||||||
|
//
|
||||||
|
Pool = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Release the memory management pool.
|
||||||
|
|
||||||
|
@param Pool The USB memory pool to free.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
UsbHcFreeMemPool (
|
||||||
|
IN USBHC_MEM_POOL *Pool
|
||||||
|
)
|
||||||
|
{
|
||||||
|
USBHC_MEM_BLOCK *Block;
|
||||||
|
|
||||||
|
ASSERT (Pool->Head != NULL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Unlink all the memory blocks from the pool, then free them.
|
||||||
|
// UsbHcUnlinkMemBlock can't be used to unlink and free the
|
||||||
|
// first block.
|
||||||
|
//
|
||||||
|
for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {
|
||||||
|
//UsbHcUnlinkMemBlock (Pool->Head, Block);
|
||||||
|
UsbHcFreeMemBlock (Pool, Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
UsbHcFreeMemBlock (Pool, Pool->Head);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocate some memory from the host controller's memory pool
|
||||||
|
which can be used to communicate with host controller.
|
||||||
|
|
||||||
|
@param Pool The host controller's memory pool.
|
||||||
|
@param Size Size of the memory to allocate.
|
||||||
|
|
||||||
|
@return The allocated memory or NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID *
|
||||||
|
UsbHcAllocateMem (
|
||||||
|
IN USBHC_MEM_POOL *Pool,
|
||||||
|
IN UINTN Size
|
||||||
|
)
|
||||||
|
{
|
||||||
|
USBHC_MEM_BLOCK *Head;
|
||||||
|
USBHC_MEM_BLOCK *Block;
|
||||||
|
USBHC_MEM_BLOCK *NewBlock;
|
||||||
|
VOID *Mem;
|
||||||
|
UINTN AllocSize;
|
||||||
|
UINTN Pages;
|
||||||
|
|
||||||
|
Mem = NULL;
|
||||||
|
AllocSize = USBHC_MEM_ROUND (Size);
|
||||||
|
Head = Pool->Head;
|
||||||
|
ASSERT (Head != NULL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// First check whether current memory blocks can satisfy the allocation.
|
||||||
|
//
|
||||||
|
for (Block = Head; Block != NULL; Block = Block->Next) {
|
||||||
|
Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);
|
||||||
|
|
||||||
|
if (Mem != NULL) {
|
||||||
|
ZeroMem (Mem, Size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Mem != NULL) {
|
||||||
|
return Mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create a new memory block if there is not enough memory
|
||||||
|
// in the pool. If the allocation size is larger than the
|
||||||
|
// default page number, just allocate a large enough memory
|
||||||
|
// block. Otherwise allocate default pages.
|
||||||
|
//
|
||||||
|
if (AllocSize > EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES)) {
|
||||||
|
Pages = EFI_SIZE_TO_PAGES (AllocSize);
|
||||||
|
} else {
|
||||||
|
Pages = USBHC_MEM_DEFAULT_PAGES;
|
||||||
|
}
|
||||||
|
NewBlock = UsbHcAllocMemBlock (Pages);
|
||||||
|
|
||||||
|
if (NewBlock == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add the new memory block to the pool, then allocate memory from it
|
||||||
|
//
|
||||||
|
UsbHcInsertMemBlockToPool (Head, NewBlock);
|
||||||
|
Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);
|
||||||
|
|
||||||
|
if (Mem != NULL) {
|
||||||
|
ZeroMem (Mem, Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Free the allocated memory back to the memory pool.
|
||||||
|
|
||||||
|
@param Pool The memory pool of the host controller.
|
||||||
|
@param Mem The memory to free.
|
||||||
|
@param Size The size of the memory to free.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
UsbHcFreeMem (
|
||||||
|
IN USBHC_MEM_POOL *Pool,
|
||||||
|
IN VOID *Mem,
|
||||||
|
IN UINTN Size
|
||||||
|
)
|
||||||
|
{
|
||||||
|
USBHC_MEM_BLOCK *Head;
|
||||||
|
USBHC_MEM_BLOCK *Block;
|
||||||
|
UINT8 *ToFree;
|
||||||
|
UINTN AllocSize;
|
||||||
|
UINTN Byte;
|
||||||
|
UINTN Bit;
|
||||||
|
UINTN Count;
|
||||||
|
|
||||||
|
Head = Pool->Head;
|
||||||
|
AllocSize = USBHC_MEM_ROUND (Size);
|
||||||
|
ToFree = (UINT8 *) Mem;
|
||||||
|
|
||||||
|
for (Block = Head; Block != NULL; Block = Block->Next) {
|
||||||
|
//
|
||||||
|
// scan the memory block list for the memory block that
|
||||||
|
// completely contains the memory to free.
|
||||||
|
//
|
||||||
|
if ((Block->BufHost <= ToFree) && ((ToFree + AllocSize) <= (Block->BufHost + Block->BufLen))) {
|
||||||
|
//
|
||||||
|
// compute the start byte and bit in the bit array
|
||||||
|
//
|
||||||
|
Byte = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) / 8;
|
||||||
|
Bit = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) % 8;
|
||||||
|
|
||||||
|
//
|
||||||
|
// reset associated bits in bit arry
|
||||||
|
//
|
||||||
|
for (Count = 0; Count < (AllocSize / USBHC_MEM_UNIT); Count++) {
|
||||||
|
ASSERT (USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
|
||||||
|
|
||||||
|
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ USB_HC_BIT (Bit));
|
||||||
|
NEXT_BIT (Byte, Bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If Block == NULL, it means that the current memory isn't
|
||||||
|
// in the host controller's pool. This is critical because
|
||||||
|
// the caller has passed in a wrong memory pointer
|
||||||
|
//
|
||||||
|
ASSERT (Block != NULL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Release the current memory block if it is empty and not the head
|
||||||
|
//
|
||||||
|
if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) {
|
||||||
|
//UsbHcUnlinkMemBlock (Head, Block);
|
||||||
|
UsbHcFreeMemBlock (Pool, Block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocates pages at a specified alignment.
|
||||||
|
|
||||||
|
If Alignment is not a power of two and Alignment is not zero, then ASSERT().
|
||||||
|
|
||||||
|
@param Pages The number of pages to allocate.
|
||||||
|
@param Alignment The requested alignment of the allocation. Must be a power of two.
|
||||||
|
@param HostAddress The system memory address to map to the PCI controller.
|
||||||
|
@param DeviceAddress The resulting map address for the bus master PCI controller to
|
||||||
|
use to access the hosts HostAddress.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Success to allocate aligned pages.
|
||||||
|
@retval EFI_INVALID_PARAMETER Pages or Alignment is not valid.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Do not have enough resources to allocate memory.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbHcAllocateAlignedPages (
|
||||||
|
IN UINTN Pages,
|
||||||
|
IN UINTN Alignment,
|
||||||
|
OUT VOID **HostAddress,
|
||||||
|
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_PHYSICAL_ADDRESS Memory;
|
||||||
|
UINTN AlignedMemory;
|
||||||
|
UINTN AlignmentMask;
|
||||||
|
UINTN RealPages;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Alignment must be a power of two or zero.
|
||||||
|
//
|
||||||
|
ASSERT ((Alignment & (Alignment - 1)) == 0);
|
||||||
|
|
||||||
|
if ((Alignment & (Alignment - 1)) != 0) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Pages == 0) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Alignment > EFI_PAGE_SIZE) {
|
||||||
|
//
|
||||||
|
// Caculate the total number of pages since alignment is larger than page size.
|
||||||
|
//
|
||||||
|
AlignmentMask = Alignment - 1;
|
||||||
|
RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);
|
||||||
|
//
|
||||||
|
// Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
|
||||||
|
//
|
||||||
|
ASSERT (RealPages > Pages);
|
||||||
|
|
||||||
|
Status = PeiServicesAllocatePages (
|
||||||
|
EfiBootServicesData,
|
||||||
|
Pages,
|
||||||
|
&Memory
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Do not over-allocate pages in this case.
|
||||||
|
//
|
||||||
|
Status = PeiServicesAllocatePages (
|
||||||
|
EfiBootServicesData,
|
||||||
|
Pages,
|
||||||
|
&Memory
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
AlignedMemory = (UINTN) Memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
*HostAddress = (VOID *) AlignedMemory;
|
||||||
|
*DeviceAddress = (EFI_PHYSICAL_ADDRESS) AlignedMemory;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Frees memory that was allocated with UsbHcAllocateAlignedPages().
|
||||||
|
|
||||||
|
@param HostAddress The system memory address to map to the PCI controller.
|
||||||
|
@param Pages The number of pages to free.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
UsbHcFreeAlignedPages (
|
||||||
|
IN VOID *HostAddress,
|
||||||
|
IN UINTN Pages
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASSERT (Pages != 0);
|
||||||
|
//
|
||||||
|
// No free memory in PEI.
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
142
MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.h
Normal file
142
MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.h
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/** @file
|
||||||
|
Private Header file for Usb Host Controller PEIM
|
||||||
|
|
||||||
|
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions
|
||||||
|
of the BSD License which accompanies this distribution. The
|
||||||
|
full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef _EFI_PEI_XHCI_MEM_H_
|
||||||
|
#define _EFI_PEI_XHCI_MEM_H_
|
||||||
|
|
||||||
|
#include <Uefi.h>
|
||||||
|
|
||||||
|
#define USBHC_MEM_DEFAULT_PAGES 16
|
||||||
|
|
||||||
|
typedef struct _USBHC_MEM_BLOCK USBHC_MEM_BLOCK;
|
||||||
|
|
||||||
|
struct _USBHC_MEM_BLOCK {
|
||||||
|
UINT8 *Bits; // Bit array to record which unit is allocated
|
||||||
|
UINTN BitsLen;
|
||||||
|
UINT8 *Buf;
|
||||||
|
UINT8 *BufHost;
|
||||||
|
UINTN BufLen; // Memory size in bytes
|
||||||
|
USBHC_MEM_BLOCK *Next;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Memory allocation unit, must be 2^n, n>4
|
||||||
|
//
|
||||||
|
#define USBHC_MEM_UNIT 64
|
||||||
|
|
||||||
|
#define USBHC_MEM_UNIT_MASK (USBHC_MEM_UNIT - 1)
|
||||||
|
#define USBHC_MEM_ROUND(Len) (((Len) + USBHC_MEM_UNIT_MASK) & (~USBHC_MEM_UNIT_MASK))
|
||||||
|
|
||||||
|
#define USB_HC_BIT(a) ((UINTN)(1 << (a)))
|
||||||
|
|
||||||
|
#define USB_HC_BIT_IS_SET(Data, Bit) \
|
||||||
|
((BOOLEAN)(((Data) & USB_HC_BIT(Bit)) == USB_HC_BIT(Bit)))
|
||||||
|
|
||||||
|
//
|
||||||
|
// Advance the byte and bit to the next bit, adjust byte accordingly.
|
||||||
|
//
|
||||||
|
#define NEXT_BIT(Byte, Bit) \
|
||||||
|
do { \
|
||||||
|
(Bit)++; \
|
||||||
|
if ((Bit) > 7) { \
|
||||||
|
(Byte)++; \
|
||||||
|
(Bit) = 0; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
//
|
||||||
|
// USBHC_MEM_POOL is used to manage the memory used by USB
|
||||||
|
// host controller. XHCI requires the control memory and transfer
|
||||||
|
// data to be on the same 4G memory.
|
||||||
|
//
|
||||||
|
typedef struct _USBHC_MEM_POOL {
|
||||||
|
BOOLEAN Check4G;
|
||||||
|
UINT32 Which4G;
|
||||||
|
USBHC_MEM_BLOCK *Head;
|
||||||
|
} USBHC_MEM_POOL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Calculate the corresponding pci bus address according to the Mem parameter.
|
||||||
|
|
||||||
|
@param Pool The memory pool of the host controller.
|
||||||
|
@param Mem The pointer to host memory.
|
||||||
|
@param Size The size of the memory region.
|
||||||
|
|
||||||
|
@return The pci memory address
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_PHYSICAL_ADDRESS
|
||||||
|
UsbHcGetPciAddrForHostAddr (
|
||||||
|
IN USBHC_MEM_POOL *Pool,
|
||||||
|
IN VOID *Mem,
|
||||||
|
IN UINTN Size
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Calculate the corresponding host address according to the pci address.
|
||||||
|
|
||||||
|
@param Pool The memory pool of the host controller.
|
||||||
|
@param Mem The pointer to pci memory.
|
||||||
|
@param Size The size of the memory region.
|
||||||
|
|
||||||
|
@return The host memory address
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_PHYSICAL_ADDRESS
|
||||||
|
UsbHcGetHostAddrForPciAddr (
|
||||||
|
IN USBHC_MEM_POOL *Pool,
|
||||||
|
IN VOID *Mem,
|
||||||
|
IN UINTN Size
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocates pages at a specified alignment.
|
||||||
|
|
||||||
|
If Alignment is not a power of two and Alignment is not zero, then ASSERT().
|
||||||
|
|
||||||
|
@param Pages The number of pages to allocate.
|
||||||
|
@param Alignment The requested alignment of the allocation. Must be a power of two.
|
||||||
|
@param HostAddress The system memory address to map to the PCI controller.
|
||||||
|
@param DeviceAddress The resulting map address for the bus master PCI controller to
|
||||||
|
use to access the hosts HostAddress.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Success to allocate aligned pages.
|
||||||
|
@retval EFI_INVALID_PARAMETER Pages or Alignment is not valid.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Do not have enough resources to allocate memory.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UsbHcAllocateAlignedPages (
|
||||||
|
IN UINTN Pages,
|
||||||
|
IN UINTN Alignment,
|
||||||
|
OUT VOID **HostAddress,
|
||||||
|
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Frees memory that was allocated with UsbHcAllocateAlignedPages().
|
||||||
|
|
||||||
|
@param HostAddress The system memory address to map to the PCI controller.
|
||||||
|
@param Pages The number of pages to free.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
UsbHcFreeAlignedPages (
|
||||||
|
IN VOID *HostAddress,
|
||||||
|
IN UINTN Pages
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
1513
MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
Normal file
1513
MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
Normal file
File diff suppressed because it is too large
Load Diff
240
MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.h
Normal file
240
MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.h
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
/** @file
|
||||||
|
Private Header file for Usb Host Controller PEIM
|
||||||
|
|
||||||
|
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions
|
||||||
|
of the BSD License which accompanies this distribution. The
|
||||||
|
full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef _RECOVERY_XHC_H_
|
||||||
|
#define _RECOVERY_XHC_H_
|
||||||
|
|
||||||
|
#include <PiPei.h>
|
||||||
|
|
||||||
|
#include <Ppi/UsbController.h>
|
||||||
|
#include <Ppi/Usb2HostController.h>
|
||||||
|
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/PeimEntryPoint.h>
|
||||||
|
#include <Library/PeiServicesLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/TimerLib.h>
|
||||||
|
#include <Library/IoLib.h>
|
||||||
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
|
||||||
|
typedef struct _PEI_XHC_DEV PEI_XHC_DEV;
|
||||||
|
typedef struct _USB_DEV_CONTEXT USB_DEV_CONTEXT;
|
||||||
|
|
||||||
|
#include "UsbHcMem.h"
|
||||||
|
#include "XhciReg.h"
|
||||||
|
#include "XhciSched.h"
|
||||||
|
|
||||||
|
#define CMD_RING_TRB_NUMBER 0x100
|
||||||
|
#define TR_RING_TRB_NUMBER 0x100
|
||||||
|
#define ERST_NUMBER 0x01
|
||||||
|
#define EVENT_RING_TRB_NUMBER 0x200
|
||||||
|
|
||||||
|
#define XHC_1_MICROSECOND 1
|
||||||
|
#define XHC_1_MILLISECOND (1000 * XHC_1_MICROSECOND)
|
||||||
|
#define XHC_1_SECOND (1000 * XHC_1_MILLISECOND)
|
||||||
|
|
||||||
|
//
|
||||||
|
// XHC reset timeout experience values.
|
||||||
|
// The unit is microsecond, setting it as 1s.
|
||||||
|
//
|
||||||
|
#define XHC_RESET_TIMEOUT (1 * XHC_1_SECOND)
|
||||||
|
//
|
||||||
|
// XHC delay experience value for polling operation.
|
||||||
|
// The unit is microsecond, set it as 1ms.
|
||||||
|
//
|
||||||
|
#define XHC_POLL_DELAY (1 * XHC_1_MILLISECOND)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Wait for root port state stable.
|
||||||
|
//
|
||||||
|
#define XHC_ROOT_PORT_STATE_STABLE (200 * XHC_1_MILLISECOND)
|
||||||
|
|
||||||
|
#define XHC_GENERIC_TIMEOUT (10 * XHC_1_MILLISECOND)
|
||||||
|
|
||||||
|
#define XHC_LOW_32BIT(Addr64) ((UINT32)(((UINTN)(Addr64)) & 0XFFFFFFFF))
|
||||||
|
#define XHC_HIGH_32BIT(Addr64) ((UINT32)(RShiftU64((UINTN)(Addr64), 32) & 0XFFFFFFFF))
|
||||||
|
#define XHC_BIT_IS_SET(Data, Bit) ((BOOLEAN)(((Data) & (Bit)) == (Bit)))
|
||||||
|
|
||||||
|
#define XHC_REG_BIT_IS_SET(XHC, Offset, Bit) \
|
||||||
|
(XHC_BIT_IS_SET(XhcPeiReadOpReg ((XHC), (Offset)), (Bit)))
|
||||||
|
|
||||||
|
#define USB_DESC_TYPE_HUB 0x29
|
||||||
|
#define USB_DESC_TYPE_HUB_SUPER_SPEED 0x2a
|
||||||
|
|
||||||
|
//
|
||||||
|
// The RequestType in EFI_USB_DEVICE_REQUEST is composed of
|
||||||
|
// three fields: One bit direction, 2 bit type, and 5 bit
|
||||||
|
// target.
|
||||||
|
//
|
||||||
|
#define USB_REQUEST_TYPE(Dir, Type, Target) \
|
||||||
|
((UINT8)((((Dir) == EfiUsbDataIn ? 0x01 : 0) << 7) | (Type) | (Target)))
|
||||||
|
|
||||||
|
struct _USB_DEV_CONTEXT {
|
||||||
|
//
|
||||||
|
// Whether this entry in UsbDevContext array is used or not.
|
||||||
|
//
|
||||||
|
BOOLEAN Enabled;
|
||||||
|
//
|
||||||
|
// The slot id assigned to the new device through XHCI's Enable_Slot cmd.
|
||||||
|
//
|
||||||
|
UINT8 SlotId;
|
||||||
|
//
|
||||||
|
// The route string presented an attached usb device.
|
||||||
|
//
|
||||||
|
USB_DEV_ROUTE RouteString;
|
||||||
|
//
|
||||||
|
// The route string of parent device if it exists. Otherwise it's zero.
|
||||||
|
//
|
||||||
|
USB_DEV_ROUTE ParentRouteString;
|
||||||
|
//
|
||||||
|
// The actual device address assigned by XHCI through Address_Device command.
|
||||||
|
//
|
||||||
|
UINT8 XhciDevAddr;
|
||||||
|
//
|
||||||
|
// The requested device address from UsbBus driver through Set_Address standard usb request.
|
||||||
|
// As XHCI spec replaces this request with Address_Device command, we have to record the
|
||||||
|
// requested device address and establish a mapping relationship with the actual device address.
|
||||||
|
// Then UsbBus driver just need to be aware of the requested device address to access usb device
|
||||||
|
// through EFI_USB2_HC_PROTOCOL. Xhci driver would be responsible for translating it to actual
|
||||||
|
// device address and access the actual device.
|
||||||
|
//
|
||||||
|
UINT8 BusDevAddr;
|
||||||
|
//
|
||||||
|
// The pointer to the input device context.
|
||||||
|
//
|
||||||
|
VOID *InputContext;
|
||||||
|
//
|
||||||
|
// The pointer to the output device context.
|
||||||
|
//
|
||||||
|
VOID *OutputContext;
|
||||||
|
//
|
||||||
|
// The transfer queue for every endpoint.
|
||||||
|
//
|
||||||
|
VOID *EndpointTransferRing[31];
|
||||||
|
//
|
||||||
|
// The device descriptor which is stored to support XHCI's Evaluate_Context cmd.
|
||||||
|
//
|
||||||
|
EFI_USB_DEVICE_DESCRIPTOR DevDesc;
|
||||||
|
//
|
||||||
|
// As a usb device may include multiple configuration descriptors, we dynamically allocate an array
|
||||||
|
// to store them.
|
||||||
|
// Note that every configuration descriptor stored here includes those lower level descriptors,
|
||||||
|
// such as Interface descriptor, Endpoint descriptor, and so on.
|
||||||
|
// These information is used to support XHCI's Config_Endpoint cmd.
|
||||||
|
//
|
||||||
|
EFI_USB_CONFIG_DESCRIPTOR **ConfDesc;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define USB_XHC_DEV_SIGNATURE SIGNATURE_32 ('x', 'h', 'c', 'i')
|
||||||
|
|
||||||
|
struct _PEI_XHC_DEV {
|
||||||
|
UINTN Signature;
|
||||||
|
PEI_USB2_HOST_CONTROLLER_PPI Usb2HostControllerPpi;
|
||||||
|
EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
|
||||||
|
UINT32 UsbHostControllerBaseAddress;
|
||||||
|
USBHC_MEM_POOL *MemPool;
|
||||||
|
|
||||||
|
//
|
||||||
|
// XHCI configuration data
|
||||||
|
//
|
||||||
|
UINT8 CapLength; ///< Capability Register Length
|
||||||
|
XHC_HCSPARAMS1 HcSParams1; ///< Structural Parameters 1
|
||||||
|
XHC_HCSPARAMS2 HcSParams2; ///< Structural Parameters 2
|
||||||
|
XHC_HCCPARAMS HcCParams; ///< Capability Parameters
|
||||||
|
UINT32 DBOff; ///< Doorbell Offset
|
||||||
|
UINT32 RTSOff; ///< Runtime Register Space Offset
|
||||||
|
UINT32 PageSize;
|
||||||
|
UINT32 MaxScratchpadBufs;
|
||||||
|
UINT64 *ScratchBuf;
|
||||||
|
UINT64 *ScratchEntry;
|
||||||
|
UINT64 *DCBAA;
|
||||||
|
UINT32 MaxSlotsEn;
|
||||||
|
//
|
||||||
|
// Cmd Transfer Ring
|
||||||
|
//
|
||||||
|
TRANSFER_RING CmdRing;
|
||||||
|
//
|
||||||
|
// EventRing
|
||||||
|
//
|
||||||
|
EVENT_RING EventRing;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Store device contexts managed by XHCI device
|
||||||
|
// The array supports up to 255 devices, entry 0 is reserved and should not be used.
|
||||||
|
//
|
||||||
|
USB_DEV_CONTEXT UsbDevContext[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PEI_RECOVERY_USB_XHC_DEV_FROM_THIS(a) CR (a, PEI_XHC_DEV, Usb2HostControllerPpi, USB_XHC_DEV_SIGNATURE)
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize the memory management pool for the host controller.
|
||||||
|
|
||||||
|
@return Pointer to the allocated memory pool or NULL if failed.
|
||||||
|
|
||||||
|
**/
|
||||||
|
USBHC_MEM_POOL *
|
||||||
|
UsbHcInitMemPool (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Release the memory management pool.
|
||||||
|
|
||||||
|
@param Pool The USB memory pool to free.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
UsbHcFreeMemPool (
|
||||||
|
IN USBHC_MEM_POOL *Pool
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocate some memory from the host controller's memory pool
|
||||||
|
which can be used to communicate with host controller.
|
||||||
|
|
||||||
|
@param Pool The host controller's memory pool.
|
||||||
|
@param Size Size of the memory to allocate.
|
||||||
|
|
||||||
|
@return The allocated memory or NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID *
|
||||||
|
UsbHcAllocateMem (
|
||||||
|
IN USBHC_MEM_POOL *Pool,
|
||||||
|
IN UINTN Size
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Free the allocated memory back to the memory pool.
|
||||||
|
|
||||||
|
@param Pool The memory pool of the host controller.
|
||||||
|
@param Mem The memory to free.
|
||||||
|
@param Size The size of the memory to free.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
UsbHcFreeMem (
|
||||||
|
IN USBHC_MEM_POOL *Pool,
|
||||||
|
IN VOID *Mem,
|
||||||
|
IN UINTN Size
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
#endif
|
59
MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf
Normal file
59
MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
## @file
|
||||||
|
# Component description file for XhcPeim PEIM to produce gPeiUsb2HostControllerPpiGuid
|
||||||
|
# based on gPeiUsbControllerPpiGuid which is used to enable recovery function from USB Drivers.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||||
|
#
|
||||||
|
# This program and the accompanying materials
|
||||||
|
# are licensed and made available under the terms and conditions
|
||||||
|
# of the BSD License which accompanies this distribution. The
|
||||||
|
# full text of the license may be found at
|
||||||
|
# http://opensource.org/licenses/bsd-license.php
|
||||||
|
#
|
||||||
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 0x00010005
|
||||||
|
BASE_NAME = XhciPei
|
||||||
|
FILE_GUID = 65E5746E-9C14-467d-B5B3-932A66D59F79
|
||||||
|
MODULE_TYPE = PEIM
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
ENTRY_POINT = XhcPeimEntry
|
||||||
|
|
||||||
|
#
|
||||||
|
# The following information is for reference only and not required by the build tools.
|
||||||
|
#
|
||||||
|
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||||
|
#
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
XhcPeim.c
|
||||||
|
XhcPeim.h
|
||||||
|
XhciSched.c
|
||||||
|
UsbHcMem.c
|
||||||
|
XhciReg.h
|
||||||
|
XhciSched.h
|
||||||
|
UsbHcMem.h
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
IoLib
|
||||||
|
TimerLib
|
||||||
|
BaseMemoryLib
|
||||||
|
PeimEntryPoint
|
||||||
|
PeiServicesLib
|
||||||
|
MemoryAllocationLib
|
||||||
|
|
||||||
|
[Ppis]
|
||||||
|
gPeiUsb2HostControllerPpiGuid ## PRODUCES
|
||||||
|
gPeiUsbControllerPpiGuid ## CONSUMES
|
||||||
|
|
||||||
|
[Depex]
|
||||||
|
gEfiPeiMemoryDiscoveredPpiGuid AND gPeiUsbControllerPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid
|
||||||
|
|
471
MdeModulePkg/Bus/Pci/XhciPei/XhciReg.h
Normal file
471
MdeModulePkg/Bus/Pci/XhciPei/XhciReg.h
Normal file
@ -0,0 +1,471 @@
|
|||||||
|
/** @file
|
||||||
|
Private Header file for Usb Host Controller PEIM
|
||||||
|
|
||||||
|
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions
|
||||||
|
of the BSD License which accompanies this distribution. The
|
||||||
|
full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef _EFI_PEI_XHCI_REG_H_
|
||||||
|
#define _EFI_PEI_XHCI_REG_H_
|
||||||
|
|
||||||
|
//
|
||||||
|
// Capability registers offset
|
||||||
|
//
|
||||||
|
#define XHC_CAPLENGTH_OFFSET 0x00 // Capability register length offset
|
||||||
|
#define XHC_HCIVERSION_OFFSET 0x02 // Interface Version Number 02-03h
|
||||||
|
#define XHC_HCSPARAMS1_OFFSET 0x04 // Structural Parameters 1
|
||||||
|
#define XHC_HCSPARAMS2_OFFSET 0x08 // Structural Parameters 2
|
||||||
|
#define XHC_HCSPARAMS3_OFFSET 0x0c // Structural Parameters 3
|
||||||
|
#define XHC_HCCPARAMS_OFFSET 0x10 // Capability Parameters
|
||||||
|
#define XHC_DBOFF_OFFSET 0x14 // Doorbell Offset
|
||||||
|
#define XHC_RTSOFF_OFFSET 0x18 // Runtime Register Space Offset
|
||||||
|
|
||||||
|
//
|
||||||
|
// Operational registers offset
|
||||||
|
//
|
||||||
|
#define XHC_USBCMD_OFFSET 0x0000 // USB Command Register Offset
|
||||||
|
#define XHC_USBSTS_OFFSET 0x0004 // USB Status Register Offset
|
||||||
|
#define XHC_PAGESIZE_OFFSET 0x0008 // USB Page Size Register Offset
|
||||||
|
#define XHC_DNCTRL_OFFSET 0x0014 // Device Notification Control Register Offset
|
||||||
|
#define XHC_CRCR_OFFSET 0x0018 // Command Ring Control Register Offset
|
||||||
|
#define XHC_DCBAAP_OFFSET 0x0030 // Device Context Base Address Array Pointer Register Offset
|
||||||
|
#define XHC_CONFIG_OFFSET 0x0038 // Configure Register Offset
|
||||||
|
#define XHC_PORTSC_OFFSET 0x0400 // Port Status and Control Register Offset
|
||||||
|
|
||||||
|
//
|
||||||
|
// Runtime registers offset
|
||||||
|
//
|
||||||
|
#define XHC_MFINDEX_OFFSET 0x00 // Microframe Index Register Offset
|
||||||
|
#define XHC_IMAN_OFFSET 0x20 // Interrupter X Management Register Offset
|
||||||
|
#define XHC_IMOD_OFFSET 0x24 // Interrupter X Moderation Register Offset
|
||||||
|
#define XHC_ERSTSZ_OFFSET 0x28 // Event Ring Segment Table Size Register Offset
|
||||||
|
#define XHC_ERSTBA_OFFSET 0x30 // Event Ring Segment Table Base Address Register Offset
|
||||||
|
#define XHC_ERDP_OFFSET 0x38 // Event Ring Dequeue Pointer Register Offset
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register Bit Definition
|
||||||
|
//
|
||||||
|
#define XHC_USBCMD_RUN BIT0 // Run/Stop
|
||||||
|
#define XHC_USBCMD_RESET BIT1 // Host Controller Reset
|
||||||
|
#define XHC_USBCMD_INTE BIT2 // Interrupter Enable
|
||||||
|
#define XHC_USBCMD_HSEE BIT3 // Host System Error Enable
|
||||||
|
|
||||||
|
#define XHC_USBSTS_HALT BIT0 // Host Controller Halted
|
||||||
|
#define XHC_USBSTS_HSE BIT2 // Host System Error
|
||||||
|
#define XHC_USBSTS_EINT BIT3 // Event Interrupt
|
||||||
|
#define XHC_USBSTS_PCD BIT4 // Port Change Detect
|
||||||
|
#define XHC_USBSTS_SSS BIT8 // Save State Status
|
||||||
|
#define XHC_USBSTS_RSS BIT9 // Restore State Status
|
||||||
|
#define XHC_USBSTS_SRE BIT10 // Save/Restore Error
|
||||||
|
#define XHC_USBSTS_CNR BIT11 // Host Controller Not Ready
|
||||||
|
#define XHC_USBSTS_HCE BIT12 // Host Controller Error
|
||||||
|
|
||||||
|
#define XHC_PAGESIZE_MASK 0xFFFF // Page Size
|
||||||
|
|
||||||
|
#define XHC_CRCR_RCS BIT0 // Ring Cycle State
|
||||||
|
#define XHC_CRCR_CS BIT1 // Command Stop
|
||||||
|
#define XHC_CRCR_CA BIT2 // Command Abort
|
||||||
|
#define XHC_CRCR_CRR BIT3 // Command Ring Running
|
||||||
|
|
||||||
|
#define XHC_CONFIG_MASK 0xFF // Max Device Slots Enabled
|
||||||
|
|
||||||
|
#define XHC_PORTSC_CCS BIT0 // Current Connect Status
|
||||||
|
#define XHC_PORTSC_PED BIT1 // Port Enabled/Disabled
|
||||||
|
#define XHC_PORTSC_OCA BIT3 // Over-current Active
|
||||||
|
#define XHC_PORTSC_RESET BIT4 // Port Reset
|
||||||
|
#define XHC_PORTSC_PLS (BIT5|BIT6|BIT7|BIT8) // Port Link State
|
||||||
|
#define XHC_PORTSC_PP BIT9 // Port Power
|
||||||
|
#define XHC_PORTSC_PS (BIT10|BIT11|BIT12) // Port Speed
|
||||||
|
#define XHC_PORTSC_LWS BIT16 // Port Link State Write Strobe
|
||||||
|
#define XHC_PORTSC_CSC BIT17 // Connect Status Change
|
||||||
|
#define XHC_PORTSC_PEC BIT18 // Port Enabled/Disabled Change
|
||||||
|
#define XHC_PORTSC_WRC BIT19 // Warm Port Reset Change
|
||||||
|
#define XHC_PORTSC_OCC BIT20 // Over-Current Change
|
||||||
|
#define XHC_PORTSC_PRC BIT21 // Port Reset Change
|
||||||
|
#define XHC_PORTSC_PLC BIT22 // Port Link State Change
|
||||||
|
#define XHC_PORTSC_CEC BIT23 // Port Config Error Change
|
||||||
|
#define XHC_PORTSC_CAS BIT24 // Cold Attach Status
|
||||||
|
|
||||||
|
#define XHC_HUB_PORTSC_CCS BIT0 // Hub's Current Connect Status
|
||||||
|
#define XHC_HUB_PORTSC_PED BIT1 // Hub's Port Enabled/Disabled
|
||||||
|
#define XHC_HUB_PORTSC_OCA BIT3 // Hub's Over-current Active
|
||||||
|
#define XHC_HUB_PORTSC_RESET BIT4 // Hub's Port Reset
|
||||||
|
#define XHC_HUB_PORTSC_PP BIT9 // Hub's Port Power
|
||||||
|
#define XHC_HUB_PORTSC_CSC BIT16 // Hub's Connect Status Change
|
||||||
|
#define XHC_HUB_PORTSC_PEC BIT17 // Hub's Port Enabled/Disabled Change
|
||||||
|
#define XHC_HUB_PORTSC_OCC BIT19 // Hub's Over-Current Change
|
||||||
|
#define XHC_HUB_PORTSC_PRC BIT20 // Hub's Port Reset Change
|
||||||
|
#define XHC_HUB_PORTSC_BHRC BIT21 // Hub's Port Warm Reset Change
|
||||||
|
|
||||||
|
#define XHC_IMAN_IP BIT0 // Interrupt Pending
|
||||||
|
#define XHC_IMAN_IE BIT1 // Interrupt Enable
|
||||||
|
|
||||||
|
#define XHC_IMODI_MASK 0x0000FFFF // Interrupt Moderation Interval
|
||||||
|
#define XHC_IMODC_MASK 0xFFFF0000 // Interrupt Moderation Counter
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack (1)
|
||||||
|
typedef struct {
|
||||||
|
UINT8 MaxSlots; // Number of Device Slots
|
||||||
|
UINT16 MaxIntrs:11; // Number of Interrupters
|
||||||
|
UINT16 Rsvd:5;
|
||||||
|
UINT8 MaxPorts; // Number of Ports
|
||||||
|
} HCSPARAMS1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Structural Parameters 1 Register Bitmap Definition
|
||||||
|
//
|
||||||
|
typedef union {
|
||||||
|
UINT32 Dword;
|
||||||
|
HCSPARAMS1 Data;
|
||||||
|
} XHC_HCSPARAMS1;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Ist:4; // Isochronous Scheduling Threshold
|
||||||
|
UINT32 Erst:4; // Event Ring Segment Table Max
|
||||||
|
UINT32 Rsvd:13;
|
||||||
|
UINT32 ScratchBufHi:5; // Max Scratchpad Buffers Hi
|
||||||
|
UINT32 Spr:1; // Scratchpad Restore
|
||||||
|
UINT32 ScratchBufLo:5; // Max Scratchpad Buffers Lo
|
||||||
|
} HCSPARAMS2;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Structural Parameters 2 Register Bitmap Definition
|
||||||
|
//
|
||||||
|
typedef union {
|
||||||
|
UINT32 Dword;
|
||||||
|
HCSPARAMS2 Data;
|
||||||
|
} XHC_HCSPARAMS2;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT16 Ac64:1; // 64-bit Addressing Capability
|
||||||
|
UINT16 Bnc:1; // BW Negotiation Capability
|
||||||
|
UINT16 Csz:1; // Context Size
|
||||||
|
UINT16 Ppc:1; // Port Power Control
|
||||||
|
UINT16 Pind:1; // Port Indicators
|
||||||
|
UINT16 Lhrc:1; // Light HC Reset Capability
|
||||||
|
UINT16 Ltc:1; // Latency Tolerance Messaging Capability
|
||||||
|
UINT16 Nss:1; // No Secondary SID Support
|
||||||
|
UINT16 Pae:1; // Parse All Event Data
|
||||||
|
UINT16 Rsvd:3;
|
||||||
|
UINT16 MaxPsaSize:4; // Maximum Primary Stream Array Size
|
||||||
|
UINT16 ExtCapReg; // xHCI Extended Capabilities Pointer
|
||||||
|
} HCCPARAMS;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Capability Parameters Register Bitmap Definition
|
||||||
|
//
|
||||||
|
typedef union {
|
||||||
|
UINT32 Dword;
|
||||||
|
HCCPARAMS Data;
|
||||||
|
} XHC_HCCPARAMS;
|
||||||
|
|
||||||
|
#pragma pack ()
|
||||||
|
|
||||||
|
//
|
||||||
|
// XHCi Data and Ctrl Structures
|
||||||
|
//
|
||||||
|
#pragma pack(1)
|
||||||
|
typedef struct {
|
||||||
|
UINT8 Pi;
|
||||||
|
UINT8 SubClassCode;
|
||||||
|
UINT8 BaseCode;
|
||||||
|
} USB_CLASSC;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT8 Length;
|
||||||
|
UINT8 DescType;
|
||||||
|
UINT8 NumPorts;
|
||||||
|
UINT16 HubCharacter;
|
||||||
|
UINT8 PwrOn2PwrGood;
|
||||||
|
UINT8 HubContrCurrent;
|
||||||
|
UINT8 Filler[16];
|
||||||
|
} EFI_USB_HUB_DESCRIPTOR;
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
//
|
||||||
|
// Hub Class Feature Selector for Clear Port Feature Request
|
||||||
|
// It's the extension of hub class feature selector of USB 2.0 in USB 3.0 Spec.
|
||||||
|
// For more details, Please refer to USB 3.0 Spec Table 10-7.
|
||||||
|
//
|
||||||
|
typedef enum {
|
||||||
|
Usb3PortBHPortReset = 28,
|
||||||
|
Usb3PortBHPortResetChange = 29
|
||||||
|
} XHC_PORT_FEATURE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Structure to map the hardware port states to the
|
||||||
|
// UEFI's port states.
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
UINT32 HwState;
|
||||||
|
UINT16 UefiState;
|
||||||
|
} USB_PORT_STATE_MAP;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Structure to map the hardware port states to feature selector for clear port feature request.
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
UINT32 HwState;
|
||||||
|
UINT16 Selector;
|
||||||
|
} USB_CLEAR_PORT_MAP;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read XHCI Operation register.
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
@param Offset The operation register offset.
|
||||||
|
|
||||||
|
@retval the register content read.
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINT32
|
||||||
|
XhcPeiReadOpReg (
|
||||||
|
IN PEI_XHC_DEV *Xhc,
|
||||||
|
IN UINT32 Offset
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write the data to the XHCI operation register.
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
@param Offset The operation register offset.
|
||||||
|
@param Data The data to write.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
XhcPeiWriteOpReg (
|
||||||
|
IN PEI_XHC_DEV *Xhc,
|
||||||
|
IN UINT32 Offset,
|
||||||
|
IN UINT32 Data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set one bit of the operational register while keeping other bits.
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
@param Offset The offset of the operational register.
|
||||||
|
@param Bit The bit mask of the register to set.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
XhcPeiSetOpRegBit (
|
||||||
|
IN PEI_XHC_DEV *Xhc,
|
||||||
|
IN UINT32 Offset,
|
||||||
|
IN UINT32 Bit
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Clear one bit of the operational register while keeping other bits.
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
@param Offset The offset of the operational register.
|
||||||
|
@param Bit The bit mask of the register to clear.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
XhcPeiClearOpRegBit (
|
||||||
|
IN PEI_XHC_DEV *Xhc,
|
||||||
|
IN UINT32 Offset,
|
||||||
|
IN UINT32 Bit
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Wait the operation register's bit as specified by Bit
|
||||||
|
to be set (or clear).
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
@param Offset The offset of the operational register.
|
||||||
|
@param Bit The bit of the register to wait for.
|
||||||
|
@param WaitToSet Wait the bit to set or clear.
|
||||||
|
@param Timeout The time to wait before abort (in microsecond, us).
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The bit successfully changed by host controller.
|
||||||
|
@retval EFI_TIMEOUT The time out occurred.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
XhcPeiWaitOpRegBit (
|
||||||
|
IN PEI_XHC_DEV *Xhc,
|
||||||
|
IN UINT32 Offset,
|
||||||
|
IN UINT32 Bit,
|
||||||
|
IN BOOLEAN WaitToSet,
|
||||||
|
IN UINT32 Timeout
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read XHCI door bell register.
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
@param Offset The offset of the door bell register.
|
||||||
|
|
||||||
|
@return The register content read
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINT32
|
||||||
|
XhcPeiReadDoorBellReg (
|
||||||
|
IN PEI_XHC_DEV *Xhc,
|
||||||
|
IN UINT32 Offset
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write the data to the XHCI door bell register.
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
@param Offset The offset of the door bell register.
|
||||||
|
@param Data The data to write.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
XhcPeiWriteDoorBellReg (
|
||||||
|
IN PEI_XHC_DEV *Xhc,
|
||||||
|
IN UINT32 Offset,
|
||||||
|
IN UINT32 Data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read XHCI runtime register.
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
@param Offset The offset of the runtime register.
|
||||||
|
|
||||||
|
@return The register content read
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINT32
|
||||||
|
XhcPeiReadRuntimeReg (
|
||||||
|
IN PEI_XHC_DEV *Xhc,
|
||||||
|
IN UINT32 Offset
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write the data to the XHCI runtime register.
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
@param Offset The offset of the runtime register.
|
||||||
|
@param Data The data to write.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
XhcPeiWriteRuntimeReg (
|
||||||
|
IN PEI_XHC_DEV *Xhc,
|
||||||
|
IN UINT32 Offset,
|
||||||
|
IN UINT32 Data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set one bit of the runtime register while keeping other bits.
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
@param Offset The offset of the runtime register.
|
||||||
|
@param Bit The bit mask of the register to set.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
XhcPeiSetRuntimeRegBit (
|
||||||
|
IN PEI_XHC_DEV *Xhc,
|
||||||
|
IN UINT32 Offset,
|
||||||
|
IN UINT32 Bit
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Clear one bit of the runtime register while keeping other bits.
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
@param Offset The offset of the runtime register.
|
||||||
|
@param Bit The bit mask of the register to set.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
XhcPeiClearRuntimeRegBit (
|
||||||
|
IN PEI_XHC_DEV *Xhc,
|
||||||
|
IN UINT32 Offset,
|
||||||
|
IN UINT32 Bit
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check whether Xhc is halted.
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
|
||||||
|
@retval TRUE The controller is halted.
|
||||||
|
@retval FALSE The controller isn't halted.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
XhcPeiIsHalt (
|
||||||
|
IN PEI_XHC_DEV *Xhc
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check whether system error occurred.
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
|
||||||
|
@retval TRUE System error happened.
|
||||||
|
@retval FALSE No system error.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
XhcPeiIsSysError (
|
||||||
|
IN PEI_XHC_DEV *Xhc
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reset the host controller.
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
@param Timeout Time to wait before abort (in millisecond, ms).
|
||||||
|
|
||||||
|
@retval EFI_TIMEOUT The transfer failed due to time out.
|
||||||
|
@retval Others Failed to reset the host.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
XhcPeiResetHC (
|
||||||
|
IN PEI_XHC_DEV *Xhc,
|
||||||
|
IN UINT32 Timeout
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Halt the host controller.
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
@param Timeout Time to wait before abort.
|
||||||
|
|
||||||
|
@retval EFI_TIMEOUT Failed to halt the controller before Timeout.
|
||||||
|
@retval EFI_SUCCESS The XHCI is halt.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
XhcPeiHaltHC (
|
||||||
|
IN PEI_XHC_DEV *Xhc,
|
||||||
|
IN UINT32 Timeout
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set the XHCI to run.
|
||||||
|
|
||||||
|
@param Xhc The XHCI device.
|
||||||
|
@param Timeout Time to wait before abort.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The XHCI is running.
|
||||||
|
@retval Others Failed to set the XHCI to run.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
XhcPeiRunHC (
|
||||||
|
IN PEI_XHC_DEV *Xhc,
|
||||||
|
IN UINT32 Timeout
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
2761
MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
Normal file
2761
MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
Normal file
File diff suppressed because it is too large
Load Diff
1228
MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h
Normal file
1228
MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
|||||||
/** @file
|
/** @file
|
||||||
Usb Hub Request Support In PEI Phase
|
Usb Hub Request Support In PEI Phase
|
||||||
|
|
||||||
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions
|
are licensed and made available under the terms and conditions
|
||||||
@ -319,6 +319,139 @@ PeiGetHubDescriptor (
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get a given SuperSpeed hub descriptor.
|
||||||
|
|
||||||
|
@param PeiServices General-purpose services that are available to every PEIM.
|
||||||
|
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
|
||||||
|
@param HubDescriptor Caller allocated buffer to store the hub descriptor if
|
||||||
|
successfully returned.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Hub descriptor is obtained successfully.
|
||||||
|
@retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
|
||||||
|
@retval Others Other failure occurs.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
PeiGetSuperSpeedHubDesc (
|
||||||
|
IN EFI_PEI_SERVICES **PeiServices,
|
||||||
|
IN PEI_USB_IO_PPI *UsbIoPpi,
|
||||||
|
OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_USB_DEVICE_REQUEST DevReq;
|
||||||
|
ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Fill Device request packet
|
||||||
|
//
|
||||||
|
DevReq.RequestType = USB_RT_HUB | 0x80;
|
||||||
|
DevReq.Request = USB_HUB_GET_DESCRIPTOR;
|
||||||
|
DevReq.Value = USB_DT_SUPERSPEED_HUB << 8;
|
||||||
|
DevReq.Length = 12;
|
||||||
|
|
||||||
|
return UsbIoPpi->UsbControlTransfer (
|
||||||
|
PeiServices,
|
||||||
|
UsbIoPpi,
|
||||||
|
&DevReq,
|
||||||
|
EfiUsbDataIn,
|
||||||
|
PcdGet32 (PcdUsbTransferTimeoutValue),
|
||||||
|
HubDescriptor,
|
||||||
|
12
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read the whole usb hub descriptor. It is necessary
|
||||||
|
to do it in two steps because hub descriptor is of
|
||||||
|
variable length.
|
||||||
|
|
||||||
|
@param PeiServices General-purpose services that are available to every PEIM.
|
||||||
|
@param PeiUsbDevice Indicates the hub controller device.
|
||||||
|
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
|
||||||
|
@param HubDescriptor Caller allocated buffer to store the hub descriptor if
|
||||||
|
successfully returned.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Hub descriptor is obtained successfully.
|
||||||
|
@retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
|
||||||
|
@retval Others Other failure occurs.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
PeiUsbHubReadDesc (
|
||||||
|
IN EFI_PEI_SERVICES **PeiServices,
|
||||||
|
IN PEI_USB_DEVICE *PeiUsbDevice,
|
||||||
|
IN PEI_USB_IO_PPI *UsbIoPpi,
|
||||||
|
OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_SUPER) {
|
||||||
|
//
|
||||||
|
// Get the super speed hub descriptor
|
||||||
|
//
|
||||||
|
Status = PeiGetSuperSpeedHubDesc (PeiServices, UsbIoPpi, HubDescriptor);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
//
|
||||||
|
// First get the hub descriptor length
|
||||||
|
//
|
||||||
|
Status = PeiGetHubDescriptor (PeiServices, UsbIoPpi, 2, HubDescriptor);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the whole hub descriptor
|
||||||
|
//
|
||||||
|
Status = PeiGetHubDescriptor (PeiServices, UsbIoPpi, HubDescriptor->Length, HubDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
USB hub control transfer to set the hub depth.
|
||||||
|
|
||||||
|
@param PeiServices General-purpose services that are available to every PEIM.
|
||||||
|
@param PeiUsbDevice Indicates the hub controller device.
|
||||||
|
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Depth of the hub is set.
|
||||||
|
@retval Others Failed to set the depth.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
PeiUsbHubCtrlSetHubDepth (
|
||||||
|
IN EFI_PEI_SERVICES **PeiServices,
|
||||||
|
IN PEI_USB_DEVICE *PeiUsbDevice,
|
||||||
|
IN PEI_USB_IO_PPI *UsbIoPpi
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_USB_DEVICE_REQUEST DevReq;
|
||||||
|
ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Fill Device request packet
|
||||||
|
//
|
||||||
|
DevReq.RequestType = USB_RT_HUB;
|
||||||
|
DevReq.Request = USB_HUB_REQ_SET_DEPTH;
|
||||||
|
DevReq.Value = PeiUsbDevice->Tier;
|
||||||
|
DevReq.Length = 0;
|
||||||
|
|
||||||
|
return UsbIoPpi->UsbControlTransfer (
|
||||||
|
PeiServices,
|
||||||
|
UsbIoPpi,
|
||||||
|
&DevReq,
|
||||||
|
EfiUsbNoData,
|
||||||
|
PcdGet32 (PcdUsbTransferTimeoutValue),
|
||||||
|
NULL,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Configure a given hub.
|
Configure a given hub.
|
||||||
|
|
||||||
@ -339,32 +472,18 @@ PeiDoHubConfig (
|
|||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
EFI_USB_HUB_STATUS HubStatus;
|
EFI_USB_HUB_STATUS HubStatus;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
UINT32 PortStatus;
|
|
||||||
PEI_USB_IO_PPI *UsbIoPpi;
|
PEI_USB_IO_PPI *UsbIoPpi;
|
||||||
|
|
||||||
ZeroMem (&HubDescriptor, sizeof (HubDescriptor));
|
ZeroMem (&HubDescriptor, sizeof (HubDescriptor));
|
||||||
UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
|
UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
|
||||||
|
|
||||||
//
|
//
|
||||||
// First get the hub descriptor length
|
// Get the hub descriptor
|
||||||
//
|
//
|
||||||
Status = PeiGetHubDescriptor (
|
Status = PeiUsbHubReadDesc (
|
||||||
PeiServices,
|
PeiServices,
|
||||||
|
PeiUsbDevice,
|
||||||
UsbIoPpi,
|
UsbIoPpi,
|
||||||
2,
|
|
||||||
&HubDescriptor
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
return EFI_DEVICE_ERROR;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// First get the whole descriptor, then
|
|
||||||
// get the number of hub ports
|
|
||||||
//
|
|
||||||
Status = PeiGetHubDescriptor (
|
|
||||||
PeiServices,
|
|
||||||
UsbIoPpi,
|
|
||||||
HubDescriptor.Length,
|
|
||||||
&HubDescriptor
|
&HubDescriptor
|
||||||
);
|
);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
@ -373,74 +492,66 @@ PeiDoHubConfig (
|
|||||||
|
|
||||||
PeiUsbDevice->DownStreamPortNo = HubDescriptor.NbrPorts;
|
PeiUsbDevice->DownStreamPortNo = HubDescriptor.NbrPorts;
|
||||||
|
|
||||||
Status = PeiHubGetHubStatus (
|
if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_SUPER) {
|
||||||
PeiServices,
|
DEBUG ((EFI_D_INFO, "PeiDoHubConfig: Set Hub Depth as 0x%x\n", PeiUsbDevice->Tier));
|
||||||
UsbIoPpi,
|
PeiUsbHubCtrlSetHubDepth (
|
||||||
(UINT32 *) &HubStatus
|
PeiServices,
|
||||||
);
|
PeiUsbDevice,
|
||||||
|
UsbIoPpi
|
||||||
if (EFI_ERROR (Status)) {
|
);
|
||||||
return EFI_DEVICE_ERROR;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Get all hub ports status
|
|
||||||
//
|
|
||||||
for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
|
|
||||||
|
|
||||||
Status = PeiHubGetPortStatus (
|
|
||||||
PeiServices,
|
|
||||||
UsbIoPpi,
|
|
||||||
(UINT8) (Index + 1),
|
|
||||||
&PortStatus
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Power all the hub ports
|
|
||||||
//
|
|
||||||
for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
|
|
||||||
Status = PeiHubSetPortFeature (
|
|
||||||
PeiServices,
|
|
||||||
UsbIoPpi,
|
|
||||||
(UINT8) (Index + 1),
|
|
||||||
EfiUsbPortPower
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Clear Hub Status Change
|
|
||||||
//
|
|
||||||
Status = PeiHubGetHubStatus (
|
|
||||||
PeiServices,
|
|
||||||
UsbIoPpi,
|
|
||||||
(UINT32 *) &HubStatus
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
return EFI_DEVICE_ERROR;
|
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
// Hub power supply change happens
|
// Power all the hub ports
|
||||||
//
|
//
|
||||||
if ((HubStatus.HubChangeStatus & HUB_CHANGE_LOCAL_POWER) != 0) {
|
for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
|
||||||
PeiHubClearHubFeature (
|
Status = PeiHubSetPortFeature (
|
||||||
PeiServices,
|
PeiServices,
|
||||||
UsbIoPpi,
|
UsbIoPpi,
|
||||||
C_HUB_LOCAL_POWER
|
(UINT8) (Index + 1),
|
||||||
);
|
EfiUsbPortPower
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG (( EFI_D_ERROR, "PeiDoHubConfig: PeiHubSetPortFeature EfiUsbPortPower failed %x\n", Index));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG (( EFI_D_INFO, "PeiDoHubConfig: HubDescriptor.PwrOn2PwrGood: 0x%x\n", HubDescriptor.PwrOn2PwrGood));
|
||||||
|
if (HubDescriptor.PwrOn2PwrGood > 0) {
|
||||||
|
MicroSecondDelay (HubDescriptor.PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Hub change overcurrent happens
|
// Clear Hub Status Change
|
||||||
//
|
//
|
||||||
if ((HubStatus.HubChangeStatus & HUB_CHANGE_OVERCURRENT) != 0) {
|
Status = PeiHubGetHubStatus (
|
||||||
PeiHubClearHubFeature (
|
PeiServices,
|
||||||
PeiServices,
|
UsbIoPpi,
|
||||||
UsbIoPpi,
|
(UINT32 *) &HubStatus
|
||||||
C_HUB_OVER_CURRENT
|
);
|
||||||
);
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Hub power supply change happens
|
||||||
|
//
|
||||||
|
if ((HubStatus.HubChangeStatus & HUB_CHANGE_LOCAL_POWER) != 0) {
|
||||||
|
PeiHubClearHubFeature (
|
||||||
|
PeiServices,
|
||||||
|
UsbIoPpi,
|
||||||
|
C_HUB_LOCAL_POWER
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Hub change overcurrent happens
|
||||||
|
//
|
||||||
|
if ((HubStatus.HubChangeStatus & HUB_CHANGE_OVERCURRENT) != 0) {
|
||||||
|
PeiHubClearHubFeature (
|
||||||
|
PeiServices,
|
||||||
|
UsbIoPpi,
|
||||||
|
C_HUB_OVER_CURRENT
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,10 +573,10 @@ PeiResetHubPort (
|
|||||||
IN UINT8 PortNum
|
IN UINT8 PortNum
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT8 Try;
|
EFI_STATUS Status;
|
||||||
|
UINTN Index;
|
||||||
EFI_USB_PORT_STATUS HubPortStatus;
|
EFI_USB_PORT_STATUS HubPortStatus;
|
||||||
|
|
||||||
|
|
||||||
MicroSecondDelay (100 * 1000);
|
MicroSecondDelay (100 * 1000);
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -478,27 +589,49 @@ PeiResetHubPort (
|
|||||||
EfiUsbPortReset
|
EfiUsbPortReset
|
||||||
);
|
);
|
||||||
|
|
||||||
Try = 10;
|
//
|
||||||
do {
|
// Drive the reset signal for worst 20ms. Check USB 2.0 Spec
|
||||||
PeiHubGetPortStatus (
|
// section 7.1.7.5 for timing requirements.
|
||||||
PeiServices,
|
//
|
||||||
UsbIoPpi,
|
MicroSecondDelay (USB_SET_PORT_RESET_STALL);
|
||||||
PortNum,
|
|
||||||
(UINT32 *) &HubPortStatus
|
|
||||||
);
|
|
||||||
|
|
||||||
MicroSecondDelay (2 * 1000);
|
|
||||||
Try -= 1;
|
|
||||||
} while ((HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0 && Try > 0);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// clear reset root port
|
// Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done.
|
||||||
|
//
|
||||||
|
ZeroMem (&HubPortStatus, sizeof (EFI_USB_PORT_STATUS));
|
||||||
|
|
||||||
|
for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
|
||||||
|
Status = PeiHubGetPortStatus (
|
||||||
|
PeiServices,
|
||||||
|
UsbIoPpi,
|
||||||
|
PortNum,
|
||||||
|
(UINT32 *) &HubPortStatus
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (USB_BIT_IS_SET (HubPortStatus.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "PeiResetHubPort: reset not finished in time on port %d\n", PortNum));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// clear reset change root port
|
||||||
//
|
//
|
||||||
PeiHubClearPortFeature (
|
PeiHubClearPortFeature (
|
||||||
PeiServices,
|
PeiServices,
|
||||||
UsbIoPpi,
|
UsbIoPpi,
|
||||||
PortNum,
|
PortNum,
|
||||||
EfiUsbPortReset
|
EfiUsbPortResetChange
|
||||||
);
|
);
|
||||||
|
|
||||||
MicroSecondDelay (1 * 1000);
|
MicroSecondDelay (1 * 1000);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/** @file
|
/** @file
|
||||||
Constants definitions for Usb Hub Peim
|
Constants definitions for Usb Hub Peim
|
||||||
|
|
||||||
Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions
|
are licensed and made available under the terms and conditions
|
||||||
@ -80,6 +80,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
|
#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
|
||||||
#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
|
#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
|
||||||
|
|
||||||
|
#define USB_HUB_REQ_SET_DEPTH 12
|
||||||
|
|
||||||
#define MAXBYTES 8
|
#define MAXBYTES 8
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
//
|
//
|
||||||
|
@ -221,26 +221,24 @@ IsPortConnect (
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Judge if the port is connected with a low-speed usb device or not.
|
Get device speed according to port status.
|
||||||
|
|
||||||
@param PortStatus The usb port status gotten.
|
@param PortStatus The usb port status gotten.
|
||||||
|
|
||||||
@retval TRUE A low-speed usb device is connected with the port.
|
@return Device speed value.
|
||||||
@retval FALSE No low-speed usb device is connected with the port.
|
|
||||||
|
|
||||||
**/
|
**/
|
||||||
UINTN
|
UINTN
|
||||||
IsPortLowSpeedDeviceAttached (
|
PeiUsbGetDeviceSpeed (
|
||||||
IN UINT16 PortStatus
|
IN UINT16 PortStatus
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
//
|
|
||||||
// return the bit 9 value of PortStatus
|
|
||||||
//
|
|
||||||
if ((PortStatus & USB_PORT_STAT_LOW_SPEED) != 0) {
|
if ((PortStatus & USB_PORT_STAT_LOW_SPEED) != 0) {
|
||||||
return EFI_USB_SPEED_LOW;
|
return EFI_USB_SPEED_LOW;
|
||||||
} else if ((PortStatus & USB_PORT_STAT_HIGH_SPEED) != 0){
|
} else if ((PortStatus & USB_PORT_STAT_HIGH_SPEED) != 0){
|
||||||
return EFI_USB_SPEED_HIGH;
|
return EFI_USB_SPEED_HIGH;
|
||||||
|
} else if ((PortStatus & USB_PORT_STAT_SUPER_SPEED) != 0) {
|
||||||
|
return EFI_USB_SPEED_SUPER;
|
||||||
} else {
|
} else {
|
||||||
return EFI_USB_SPEED_FULL;
|
return EFI_USB_SPEED_FULL;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#define USB_DT_INTERFACE 0x04
|
#define USB_DT_INTERFACE 0x04
|
||||||
#define USB_DT_ENDPOINT 0x05
|
#define USB_DT_ENDPOINT 0x05
|
||||||
#define USB_DT_HUB 0x29
|
#define USB_DT_HUB 0x29
|
||||||
|
#define USB_DT_SUPERSPEED_HUB 0x2A
|
||||||
#define USB_DT_HID 0x21
|
#define USB_DT_HID 0x21
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -202,17 +203,16 @@ IsPortConnect (
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Judge if the port is connected with a low-speed usb device or not.
|
Get device speed according to port status.
|
||||||
|
|
||||||
@param PortStatus The usb port status gotten.
|
@param PortStatus The usb port status gotten.
|
||||||
|
|
||||||
@retval TRUE A low-speed usb device is connected with the port.
|
@return Device speed value.
|
||||||
@retval FALSE No low-speed usb device is connected with the port.
|
|
||||||
|
|
||||||
**/
|
**/
|
||||||
UINTN
|
UINTN
|
||||||
IsPortLowSpeedDeviceAttached (
|
PeiUsbGetDeviceSpeed (
|
||||||
IN UINT16 PortStatus
|
IN UINT16 PortStatus
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,7 +105,7 @@ PeiUsbControlTransfer (
|
|||||||
PeiUsbDev->UsbHcPpi,
|
PeiUsbDev->UsbHcPpi,
|
||||||
PeiUsbDev->DeviceAddress,
|
PeiUsbDev->DeviceAddress,
|
||||||
PeiUsbDev->DeviceSpeed,
|
PeiUsbDev->DeviceSpeed,
|
||||||
PeiUsbDev->MaxPacketSize0,
|
(UINT8) PeiUsbDev->MaxPacketSize0,
|
||||||
Request,
|
Request,
|
||||||
Direction,
|
Direction,
|
||||||
Data,
|
Data,
|
||||||
@ -126,6 +126,7 @@ PeiUsbControlTransfer (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "PeiUsbControlTransfer: %r\n", Status));
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,6 +239,7 @@ PeiUsbBulkTransfer (
|
|||||||
PeiUsbDev->DataToggle = (UINT16) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
|
PeiUsbDev->DataToggle = (UINT16) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "PeiUsbBulkTransfer: %r\n", Status));
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,6 +228,8 @@ PeiHubEnumeration (
|
|||||||
|
|
||||||
UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
|
UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "PeiHubEnumeration: DownStreamPortNo: %x\n", PeiUsbDevice->DownStreamPortNo));
|
||||||
|
|
||||||
for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
|
for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
|
||||||
|
|
||||||
Status = PeiHubGetPortStatus (
|
Status = PeiHubGetPortStatus (
|
||||||
@ -241,25 +243,14 @@ PeiHubEnumeration (
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsPortConnectChange (PortStatus.PortChangeStatus)) {
|
DEBUG ((EFI_D_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));
|
||||||
PeiHubClearPortFeature (
|
//
|
||||||
PeiServices,
|
// Only handle connection/enable/overcurrent/reset change.
|
||||||
UsbIoPpi,
|
//
|
||||||
(UINT8) (Index + 1),
|
if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
|
||||||
EfiUsbPortConnectChange
|
continue;
|
||||||
);
|
} else {
|
||||||
|
|
||||||
MicroSecondDelay (100 * 1000);
|
|
||||||
|
|
||||||
if (IsPortConnect (PortStatus.PortStatus)) {
|
if (IsPortConnect (PortStatus.PortStatus)) {
|
||||||
|
|
||||||
PeiHubGetPortStatus (
|
|
||||||
PeiServices,
|
|
||||||
UsbIoPpi,
|
|
||||||
(UINT8) (Index + 1),
|
|
||||||
(UINT32 *) &PortStatus
|
|
||||||
);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Begin to deal with the new device
|
// Begin to deal with the new device
|
||||||
//
|
//
|
||||||
@ -294,19 +285,44 @@ PeiHubEnumeration (
|
|||||||
NewPeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;
|
NewPeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;
|
||||||
NewPeiUsbDevice->UsbHcPpi = PeiUsbDevice->UsbHcPpi;
|
NewPeiUsbDevice->UsbHcPpi = PeiUsbDevice->UsbHcPpi;
|
||||||
NewPeiUsbDevice->Usb2HcPpi = PeiUsbDevice->Usb2HcPpi;
|
NewPeiUsbDevice->Usb2HcPpi = PeiUsbDevice->Usb2HcPpi;
|
||||||
|
NewPeiUsbDevice->Tier = (UINT8) (PeiUsbDevice->Tier + 1);
|
||||||
NewPeiUsbDevice->IsHub = 0x0;
|
NewPeiUsbDevice->IsHub = 0x0;
|
||||||
NewPeiUsbDevice->DownStreamPortNo = 0x0;
|
NewPeiUsbDevice->DownStreamPortNo = 0x0;
|
||||||
|
|
||||||
PeiResetHubPort (PeiServices, UsbIoPpi, (UINT8)(Index + 1));
|
if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||
|
||||||
|
((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0)) {
|
||||||
|
//
|
||||||
|
// If the port already has reset change flag and is connected and enabled, skip the port reset logic.
|
||||||
|
//
|
||||||
|
PeiResetHubPort (PeiServices, UsbIoPpi, (UINT8)(Index + 1));
|
||||||
|
|
||||||
|
PeiHubGetPortStatus (
|
||||||
|
PeiServices,
|
||||||
|
UsbIoPpi,
|
||||||
|
(UINT8) (Index + 1),
|
||||||
|
(UINT32 *) &PortStatus
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
PeiHubClearPortFeature (
|
||||||
|
PeiServices,
|
||||||
|
UsbIoPpi,
|
||||||
|
(UINT8) (Index + 1),
|
||||||
|
EfiUsbPortResetChange
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
PeiHubGetPortStatus (
|
NewPeiUsbDevice->DeviceSpeed = (UINT8) PeiUsbGetDeviceSpeed (PortStatus.PortStatus);
|
||||||
PeiServices,
|
DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
|
||||||
UsbIoPpi,
|
|
||||||
(UINT8) (Index + 1),
|
|
||||||
(UINT32 *) &PortStatus
|
|
||||||
);
|
|
||||||
|
|
||||||
NewPeiUsbDevice->DeviceSpeed = (UINT8)IsPortLowSpeedDeviceAttached (PortStatus.PortStatus);
|
if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)){
|
||||||
|
NewPeiUsbDevice->MaxPacketSize0 = 512;
|
||||||
|
} else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
|
||||||
|
NewPeiUsbDevice->MaxPacketSize0 = 64;
|
||||||
|
} else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
|
||||||
|
NewPeiUsbDevice->MaxPacketSize0 = 8;
|
||||||
|
} else {
|
||||||
|
NewPeiUsbDevice->MaxPacketSize0 = 8;
|
||||||
|
}
|
||||||
|
|
||||||
if(NewPeiUsbDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {
|
if(NewPeiUsbDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {
|
||||||
if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_HIGH) {
|
if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_HIGH) {
|
||||||
@ -330,6 +346,7 @@ PeiHubEnumeration (
|
|||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
DEBUG ((EFI_D_INFO, "PeiHubEnumeration: PeiConfigureUsbDevice Success\n"));
|
||||||
|
|
||||||
Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);
|
Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);
|
||||||
|
|
||||||
@ -435,6 +452,8 @@ PeiUsbEnumeration (
|
|||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "PeiUsbEnumeration: NumOfRootPort: %x\n", NumOfRootPort));
|
||||||
|
|
||||||
for (Index = 0; Index < NumOfRootPort; Index++) {
|
for (Index = 0; Index < NumOfRootPort; Index++) {
|
||||||
//
|
//
|
||||||
// First get root port status to detect changes happen
|
// First get root port status to detect changes happen
|
||||||
@ -454,48 +473,14 @@ PeiUsbEnumeration (
|
|||||||
&PortStatus
|
&PortStatus
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
DEBUG ((EFI_D_INFO, "USB Status --- ConnectChange[%04x] Status[%04x]\n", PortStatus.PortChangeStatus, PortStatus.PortStatus));
|
DEBUG ((EFI_D_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));
|
||||||
if (IsPortConnectChange (PortStatus.PortChangeStatus)) {
|
//
|
||||||
//
|
// Only handle connection/enable/overcurrent/reset change.
|
||||||
// Changes happen, first clear this change status
|
//
|
||||||
//
|
if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
|
||||||
if (Usb2HcPpi != NULL) {
|
continue;
|
||||||
Usb2HcPpi->ClearRootHubPortFeature (
|
} else {
|
||||||
PeiServices,
|
|
||||||
Usb2HcPpi,
|
|
||||||
(UINT8) Index,
|
|
||||||
EfiUsbPortConnectChange
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
UsbHcPpi->ClearRootHubPortFeature (
|
|
||||||
PeiServices,
|
|
||||||
UsbHcPpi,
|
|
||||||
(UINT8) Index,
|
|
||||||
EfiUsbPortConnectChange
|
|
||||||
);
|
|
||||||
}
|
|
||||||
MicroSecondDelay (100 * 1000);
|
|
||||||
|
|
||||||
if (IsPortConnect (PortStatus.PortStatus)) {
|
if (IsPortConnect (PortStatus.PortStatus)) {
|
||||||
if (Usb2HcPpi != NULL) {
|
|
||||||
Usb2HcPpi->GetRootHubPortStatus (
|
|
||||||
PeiServices,
|
|
||||||
Usb2HcPpi,
|
|
||||||
(UINT8) Index,
|
|
||||||
&PortStatus
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
UsbHcPpi->GetRootHubPortStatus (
|
|
||||||
PeiServices,
|
|
||||||
UsbHcPpi,
|
|
||||||
(UINT8) Index,
|
|
||||||
&PortStatus
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Connect change happen
|
|
||||||
//
|
|
||||||
MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
|
MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
|
||||||
Status = PeiServicesAllocatePages (
|
Status = PeiServicesAllocatePages (
|
||||||
EfiBootServicesCode,
|
EfiBootServicesCode,
|
||||||
@ -530,33 +515,65 @@ PeiUsbEnumeration (
|
|||||||
PeiUsbDevice->IsHub = 0x0;
|
PeiUsbDevice->IsHub = 0x0;
|
||||||
PeiUsbDevice->DownStreamPortNo = 0x0;
|
PeiUsbDevice->DownStreamPortNo = 0x0;
|
||||||
|
|
||||||
ResetRootPort (
|
if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||
|
||||||
PeiServices,
|
((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0)) {
|
||||||
PeiUsbDevice->UsbHcPpi,
|
//
|
||||||
PeiUsbDevice->Usb2HcPpi,
|
// If the port already has reset change flag and is connected and enabled, skip the port reset logic.
|
||||||
Index,
|
//
|
||||||
0
|
ResetRootPort (
|
||||||
);
|
PeiServices,
|
||||||
|
PeiUsbDevice->UsbHcPpi,
|
||||||
|
PeiUsbDevice->Usb2HcPpi,
|
||||||
|
Index,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
if (Usb2HcPpi != NULL) {
|
if (Usb2HcPpi != NULL) {
|
||||||
Usb2HcPpi->GetRootHubPortStatus (
|
Usb2HcPpi->GetRootHubPortStatus (
|
||||||
PeiServices,
|
PeiServices,
|
||||||
Usb2HcPpi,
|
Usb2HcPpi,
|
||||||
(UINT8) Index,
|
(UINT8) Index,
|
||||||
&PortStatus
|
&PortStatus
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
UsbHcPpi->GetRootHubPortStatus (
|
||||||
|
PeiServices,
|
||||||
|
UsbHcPpi,
|
||||||
|
(UINT8) Index,
|
||||||
|
&PortStatus
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
UsbHcPpi->GetRootHubPortStatus (
|
if (Usb2HcPpi != NULL) {
|
||||||
PeiServices,
|
Usb2HcPpi->ClearRootHubPortFeature (
|
||||||
UsbHcPpi,
|
PeiServices,
|
||||||
(UINT8) Index,
|
Usb2HcPpi,
|
||||||
&PortStatus
|
(UINT8) Index,
|
||||||
);
|
EfiUsbPortResetChange
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
UsbHcPpi->ClearRootHubPortFeature (
|
||||||
|
PeiServices,
|
||||||
|
UsbHcPpi,
|
||||||
|
(UINT8) Index,
|
||||||
|
EfiUsbPortResetChange
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PeiUsbDevice->DeviceSpeed = (UINT8)IsPortLowSpeedDeviceAttached (PortStatus.PortStatus);
|
PeiUsbDevice->DeviceSpeed = (UINT8) PeiUsbGetDeviceSpeed (PortStatus.PortStatus);
|
||||||
DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
|
DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
|
||||||
|
|
||||||
|
if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)){
|
||||||
|
PeiUsbDevice->MaxPacketSize0 = 512;
|
||||||
|
} else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
|
||||||
|
PeiUsbDevice->MaxPacketSize0 = 64;
|
||||||
|
} else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
|
||||||
|
PeiUsbDevice->MaxPacketSize0 = 8;
|
||||||
|
} else {
|
||||||
|
PeiUsbDevice->MaxPacketSize0 = 8;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Configure that Usb Device
|
// Configure that Usb Device
|
||||||
//
|
//
|
||||||
@ -570,7 +587,7 @@ PeiUsbEnumeration (
|
|||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
DEBUG ((EFI_D_INFO, "PeiConfigureUsbDevice Success\n"));
|
DEBUG ((EFI_D_INFO, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n"));
|
||||||
|
|
||||||
Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
|
Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
|
||||||
|
|
||||||
@ -665,9 +682,6 @@ PeiConfigureUsbDevice (
|
|||||||
//
|
//
|
||||||
|
|
||||||
for (Retry = 0; Retry < 3; Retry ++) {
|
for (Retry = 0; Retry < 3; Retry ++) {
|
||||||
|
|
||||||
PeiUsbDevice->MaxPacketSize0 = 8;
|
|
||||||
|
|
||||||
Status = PeiUsbGetDescriptor (
|
Status = PeiUsbGetDescriptor (
|
||||||
PeiServices,
|
PeiServices,
|
||||||
UsbIoPpi,
|
UsbIoPpi,
|
||||||
@ -678,17 +692,21 @@ PeiConfigureUsbDevice (
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!EFI_ERROR (Status)) {
|
if (!EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_INFO, "PeiUsbGet Device Descriptor the %d time Sucess\n", Retry));
|
DEBUG ((EFI_D_INFO, "PeiUsbGet Device Descriptor the %d time Success\n", Retry));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Retry == 3) {
|
if (Retry == 3) {
|
||||||
DEBUG ((EFI_D_ERROR, "PeiUsbGet Device Descriptor fail\n", Retry));
|
DEBUG ((EFI_D_ERROR, "PeiUsbGet Device Descriptor fail: %x %r\n", Retry, Status));
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
PeiUsbDevice->MaxPacketSize0 = DeviceDescriptor.MaxPacketSize0;
|
if ((DeviceDescriptor.BcdUSB == 0x0300) && (DeviceDescriptor.MaxPacketSize0 == 9)) {
|
||||||
|
PeiUsbDevice->MaxPacketSize0 = 1 << 9;
|
||||||
|
} else {
|
||||||
|
PeiUsbDevice->MaxPacketSize0 = DeviceDescriptor.MaxPacketSize0;
|
||||||
|
}
|
||||||
|
|
||||||
(*DeviceAddress) ++;
|
(*DeviceAddress) ++;
|
||||||
|
|
||||||
@ -699,7 +717,7 @@ PeiConfigureUsbDevice (
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_ERROR, "PeiUsbSetDeviceAddress Failed\n"));
|
DEBUG ((EFI_D_ERROR, "PeiUsbSetDeviceAddress Failed: %r\n", Status));
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -995,6 +1013,8 @@ ResetRootPort (
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
|
UINTN Index;
|
||||||
|
EFI_USB_PORT_STATUS PortStatus;
|
||||||
|
|
||||||
|
|
||||||
if (Usb2HcPpi != NULL) {
|
if (Usb2HcPpi != NULL) {
|
||||||
@ -1015,8 +1035,12 @@ ResetRootPort (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MicroSecondDelay (200 * 1000);
|
//
|
||||||
|
// Drive the reset signal for at least 50ms. Check USB 2.0 Spec
|
||||||
|
// section 7.1.7.5 for timing requirements.
|
||||||
|
//
|
||||||
|
MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);
|
||||||
|
|
||||||
//
|
//
|
||||||
// clear reset root port
|
// clear reset root port
|
||||||
//
|
//
|
||||||
@ -1031,9 +1055,45 @@ ResetRootPort (
|
|||||||
DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
|
DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MicroSecondDelay (1 * 1000);
|
MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// USB host controller won't clear the RESET bit until
|
||||||
|
// reset is actually finished.
|
||||||
|
//
|
||||||
|
ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));
|
||||||
|
|
||||||
|
for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
|
||||||
|
Status = Usb2HcPpi->GetRootHubPortStatus (
|
||||||
|
PeiServices,
|
||||||
|
Usb2HcPpi,
|
||||||
|
PortNum,
|
||||||
|
&PortStatus
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Usb2HcPpi->ClearRootHubPortFeature (
|
||||||
|
PeiServices,
|
||||||
|
Usb2HcPpi,
|
||||||
|
PortNum,
|
||||||
|
EfiUsbPortResetChange
|
||||||
|
);
|
||||||
|
|
||||||
Usb2HcPpi->ClearRootHubPortFeature (
|
Usb2HcPpi->ClearRootHubPortFeature (
|
||||||
PeiServices,
|
PeiServices,
|
||||||
Usb2HcPpi,
|
Usb2HcPpi,
|
||||||
@ -1077,7 +1137,11 @@ ResetRootPort (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MicroSecondDelay (200 * 1000);
|
//
|
||||||
|
// Drive the reset signal for at least 50ms. Check USB 2.0 Spec
|
||||||
|
// section 7.1.7.5 for timing requirements.
|
||||||
|
//
|
||||||
|
MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);
|
||||||
|
|
||||||
//
|
//
|
||||||
// clear reset root port
|
// clear reset root port
|
||||||
@ -1094,8 +1158,44 @@ ResetRootPort (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MicroSecondDelay (1 * 1000);
|
MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// USB host controller won't clear the RESET bit until
|
||||||
|
// reset is actually finished.
|
||||||
|
//
|
||||||
|
ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));
|
||||||
|
|
||||||
|
for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
|
||||||
|
Status = UsbHcPpi->GetRootHubPortStatus (
|
||||||
|
PeiServices,
|
||||||
|
UsbHcPpi,
|
||||||
|
PortNum,
|
||||||
|
&PortStatus
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UsbHcPpi->ClearRootHubPortFeature (
|
||||||
|
PeiServices,
|
||||||
|
UsbHcPpi,
|
||||||
|
PortNum,
|
||||||
|
EfiUsbPortResetChange
|
||||||
|
);
|
||||||
|
|
||||||
UsbHcPpi->ClearRootHubPortFeature (
|
UsbHcPpi->ClearRootHubPortFeature (
|
||||||
PeiServices,
|
PeiServices,
|
||||||
UsbHcPpi,
|
UsbHcPpi,
|
||||||
|
@ -33,25 +33,20 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
|
|
||||||
#include <IndustryStandard/Usb.h>
|
#include <IndustryStandard/Usb.h>
|
||||||
|
|
||||||
#define MAX_ROOT_PORT 2
|
|
||||||
#define MAX_INTERFACE 8
|
#define MAX_INTERFACE 8
|
||||||
#define MAX_ENDPOINT 16
|
#define MAX_ENDPOINT 16
|
||||||
|
|
||||||
#define USB_SLOW_SPEED_DEVICE 0x01
|
|
||||||
#define USB_FULL_SPEED_DEVICE 0x02
|
|
||||||
|
|
||||||
#define PEI_USB_DEVICE_SIGNATURE SIGNATURE_32 ('U', 's', 'b', 'D')
|
#define PEI_USB_DEVICE_SIGNATURE SIGNATURE_32 ('U', 's', 'b', 'D')
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINTN Signature;
|
UINTN Signature;
|
||||||
PEI_USB_IO_PPI UsbIoPpi;
|
PEI_USB_IO_PPI UsbIoPpi;
|
||||||
EFI_PEI_PPI_DESCRIPTOR UsbIoPpiList;
|
EFI_PEI_PPI_DESCRIPTOR UsbIoPpiList;
|
||||||
|
UINT16 MaxPacketSize0;
|
||||||
|
UINT16 DataToggle;
|
||||||
UINT8 DeviceAddress;
|
UINT8 DeviceAddress;
|
||||||
UINT8 MaxPacketSize0;
|
|
||||||
UINT8 DeviceSpeed;
|
UINT8 DeviceSpeed;
|
||||||
UINT8 IsHub;
|
UINT8 IsHub;
|
||||||
UINT16 DataToggle;
|
|
||||||
UINT8 DownStreamPortNo;
|
UINT8 DownStreamPortNo;
|
||||||
UINT8 Reserved; // Padding for IPF
|
|
||||||
UINTN AllocateAddress;
|
UINTN AllocateAddress;
|
||||||
PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;
|
PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;
|
||||||
PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi;
|
PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi;
|
||||||
@ -61,11 +56,48 @@ typedef struct {
|
|||||||
EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescList[MAX_INTERFACE];
|
EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescList[MAX_INTERFACE];
|
||||||
EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDesc[MAX_ENDPOINT];
|
EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDesc[MAX_ENDPOINT];
|
||||||
EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescList[MAX_INTERFACE][MAX_ENDPOINT];
|
EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescList[MAX_INTERFACE][MAX_ENDPOINT];
|
||||||
EFI_USB2_HC_TRANSACTION_TRANSLATOR Translator;
|
EFI_USB2_HC_TRANSACTION_TRANSLATOR Translator;
|
||||||
|
UINT8 Tier;
|
||||||
} PEI_USB_DEVICE;
|
} PEI_USB_DEVICE;
|
||||||
|
|
||||||
#define PEI_USB_DEVICE_FROM_THIS(a) CR (a, PEI_USB_DEVICE, UsbIoPpi, PEI_USB_DEVICE_SIGNATURE)
|
#define PEI_USB_DEVICE_FROM_THIS(a) CR (a, PEI_USB_DEVICE, UsbIoPpi, PEI_USB_DEVICE_SIGNATURE)
|
||||||
|
|
||||||
|
#define USB_BIT_IS_SET(Data, Bit) ((BOOLEAN)(((Data) & (Bit)) == (Bit)))
|
||||||
|
|
||||||
|
#define USB_BUS_1_MILLISECOND 1000
|
||||||
|
|
||||||
|
//
|
||||||
|
// Wait for port reset, refers to specification
|
||||||
|
// [USB20-7.1.7.5, it says 10ms for hub and 50ms for
|
||||||
|
// root hub]
|
||||||
|
//
|
||||||
|
// According to USB2.0, Chapter 11.5.1.5 Resetting,
|
||||||
|
// the worst case for TDRST is 20ms
|
||||||
|
//
|
||||||
|
#define USB_SET_PORT_RESET_STALL (20 * USB_BUS_1_MILLISECOND)
|
||||||
|
#define USB_SET_ROOT_PORT_RESET_STALL (50 * USB_BUS_1_MILLISECOND)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Wait for clear roothub port reset, set by experience
|
||||||
|
//
|
||||||
|
#define USB_CLR_ROOT_PORT_RESET_STALL (20 * USB_BUS_1_MILLISECOND)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Wait for port statue reg change, set by experience
|
||||||
|
//
|
||||||
|
#define USB_WAIT_PORT_STS_CHANGE_STALL (100)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Host software return timeout if port status doesn't change
|
||||||
|
// after 500ms(LOOP * STALL = 5000 * 0.1ms), set by experience
|
||||||
|
//
|
||||||
|
#define USB_WAIT_PORT_STS_CHANGE_LOOP 5000
|
||||||
|
|
||||||
|
//
|
||||||
|
// Wait for hub port power-on, refers to specification
|
||||||
|
// [USB20-11.23.2]
|
||||||
|
//
|
||||||
|
#define USB_SET_PORT_POWER_STALL (2 * USB_BUS_1_MILLISECOND)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Submits control transfer to a target USB device.
|
Submits control transfer to a target USB device.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
Define APIs to retrieve USB Host Controller Info such as controller type and
|
Define APIs to retrieve USB Host Controller Info such as controller type and
|
||||||
I/O Port Base Address.
|
I/O Port Base Address.
|
||||||
|
|
||||||
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions
|
are licensed and made available under the terms and conditions
|
||||||
@ -49,6 +49,12 @@ typedef struct _PEI_USB_CONTROLLER_PPI PEI_USB_CONTROLLER_PPI;
|
|||||||
///
|
///
|
||||||
#define PEI_EHCI_CONTROLLER 0x03
|
#define PEI_EHCI_CONTROLLER 0x03
|
||||||
|
|
||||||
|
///
|
||||||
|
/// This bit is used in the ControllerType return parameter of GetUsbController()
|
||||||
|
/// to identify the USB Host Controller type as XHCI
|
||||||
|
///
|
||||||
|
#define PEI_XHCI_CONTROLLER 0x04
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Retrieve USB Host Controller Info such as controller type and I/O Base Address.
|
Retrieve USB Host Controller Info such as controller type and I/O Base Address.
|
||||||
|
|
||||||
|
@ -202,6 +202,7 @@
|
|||||||
MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
|
MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
|
||||||
MdeModulePkg/Bus/Pci/UhciPei/UhciPei.inf
|
MdeModulePkg/Bus/Pci/UhciPei/UhciPei.inf
|
||||||
MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
|
MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
|
||||||
|
MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf
|
||||||
MdeModulePkg/Bus/Pci/IdeBusPei/IdeBusPei.inf
|
MdeModulePkg/Bus/Pci/IdeBusPei/IdeBusPei.inf
|
||||||
MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
|
MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
|
||||||
MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
|
MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
|
||||||
|
Reference in New Issue
Block a user