uhchlp.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 3,348 行 · 第 1/5 页

C
3,348
字号
      );
  }

  return ;
}

EFI_STATUS
CreateFrameList (
  IN USB_HC_DEV     *HcDev,
  IN UINT32         FlBaseAddrReg
  )
/*++

Routine Description:

  CreateFrameList

Arguments:

  HcDev         - USB_HC_DEV
  FlBaseAddrReg - Frame List register

Returns:

  EFI_OUT_OF_RESOURCES - Can't allocate memory resources
  EFI_UNSUPPORTED      - Map memory fail
  EFI_SUCCESS          - Success

--*/
{
  EFI_STATUS            Status;
  VOID                  *CommonBuffer;
  EFI_PHYSICAL_ADDRESS  MappedAddress;
  VOID                  *Mapping;
  UINTN                 BufferSizeInPages;
  UINTN                 BufferSizeInBytes;

  //
  // The Frame List is a common buffer that will be
  // accessed by both the cpu and the usb bus master
  // at the same time.
  // The Frame List ocupies 4K bytes,
  // and must be aligned on 4-Kbyte boundaries.
  //
  BufferSizeInBytes = 4096;
  BufferSizeInPages = EFI_SIZE_TO_PAGES (BufferSizeInBytes);
  Status = HcDev->PciIo->AllocateBuffer (
                           HcDev->PciIo,
                           AllocateAnyPages,
                           EfiBootServicesData,
                           BufferSizeInPages,
                           &CommonBuffer,
                           0
                           );
  if (EFI_ERROR (Status)) {
    return EFI_OUT_OF_RESOURCES;
  }

  Status = HcDev->PciIo->Map (
                           HcDev->PciIo,
                           EfiPciIoOperationBusMasterCommonBuffer,
                           CommonBuffer,
                           &BufferSizeInBytes,
                           &MappedAddress,
                           &Mapping
                           );
  if (EFI_ERROR (Status) || (BufferSizeInBytes != 4096)) {
    HcDev->PciIo->FreeBuffer (HcDev->PciIo, BufferSizeInPages, CommonBuffer);
    return EFI_UNSUPPORTED;
  }

  HcDev->FrameListEntry   = (FRAMELIST_ENTRY *) ((UINTN) MappedAddress);

  HcDev->FrameListMapping = Mapping;

  InitFrameList (HcDev);

  //
  // Tell the Host Controller where the Frame List lies,
  // by set the Frame List Base Address Register.
  //
  SetFrameListBaseAddress (
    HcDev->PciIo,
    FlBaseAddrReg,
    (UINT32) ((UINTN) HcDev->FrameListEntry)
    );

  return EFI_SUCCESS;
}

EFI_STATUS
FreeFrameListEntry (
  IN USB_HC_DEV     *HcDev
  )
/*++

Routine Description:

  Free FrameList buffer

Arguments:

  HcDev - USB_HC_DEV

Returns:

  EFI_SUCCESS - success

--*/
{
  //
  // Unmap the common buffer for framelist entry,
  // and free the common buffer.
  // Uhci's frame list occupy 4k memory.
  //
  HcDev->PciIo->Unmap (HcDev->PciIo, HcDev->FrameListMapping);
  HcDev->PciIo->FreeBuffer (
                  HcDev->PciIo,
                  EFI_SIZE_TO_PAGES (4096),
                  (VOID *) (HcDev->FrameListEntry)
                  );
  return EFI_SUCCESS;
}

VOID
InitFrameList (
  IN USB_HC_DEV     *HcDev
  )
/*++

Routine Description:

  Initialize FrameList

Arguments:

  HcDev - USB_HC_DEV

Returns:
   VOID

--*/  
{
  FRAMELIST_ENTRY *FrameListPtr;
  UINTN           Index;

  //
  // Validate each Frame List Entry
  //
  FrameListPtr = HcDev->FrameListEntry;
  for (Index = 0; Index < 1024; Index++) {
    FrameListPtr->FrameListPtrTerminate = 1;
    FrameListPtr->FrameListPtr          = 0;
    FrameListPtr->FrameListPtrQSelect   = 0;
    FrameListPtr->FrameListRsvd         = 0;
    FrameListPtr++;
  }
}
//
// //////////////////////////////////////////////////////////////
//
// QH TD related Helper Functions
//
////////////////////////////////////////////////////////////////
//
// functions for QH
//
EFI_STATUS
AllocateQHStruct (
  IN  USB_HC_DEV     *HcDev,
  OUT QH_STRUCT      **ppQHStruct
  )
/*++

Routine Description:

  Allocate QH Struct

Arguments:

  HcDev       - USB_HC_DEV
  ppQHStruct  - QH_STRUCT content to return
Returns:

  EFI_SUCCESS

--*/
{
  *ppQHStruct = NULL;

  //
  // QH must align on 16 bytes alignment,
  // since the memory allocated by UhciAllocatePool ()
  // is aligned on 32 bytes, it is no need to adjust
  // the allocated memory returned.
  //
  return UhciAllocatePool (HcDev, (UINT8 **) ppQHStruct, sizeof (QH_STRUCT));
}


EFI_STATUS
CreateQH (
  IN  USB_HC_DEV     *HcDev,
  OUT QH_STRUCT      **pptrQH
  )
/*++

Routine Description:

  CreateQH

Arguments:

  HcDev       - USB_HC_DEV
  ppQHStruct  - QH_STRUCT content to return
Returns:

  EFI_SUCCESS          - Success
  EFI_OUT_OF_RESOURCES - Can't allocate memory
--*/
{
  EFI_STATUS  Status;

  //
  // allocate align memory for QH_STRUCT
  //
  Status = AllocateQHStruct (HcDev, pptrQH);
  if (EFI_ERROR (Status)) {
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // init each field of the QH_STRUCT
  //
  //
  // Make QH ready
  //
  SetQHHorizontalValidorInvalid (*pptrQH, FALSE);
  SetQHVerticalValidorInvalid   (*pptrQH, FALSE);

  return EFI_SUCCESS;
}

VOID
SetQHHorizontalLinkPtr (
  IN QH_STRUCT     *PtrQH,
  IN VOID          *ptrNext
  )
/*++

Routine Description:

  Set QH Horizontal Link Pointer

Arguments:

  PtrQH   - QH_STRUCT
  ptrNext - Data to write 

Returns:

  VOID

--*/
{
  //
  // Since the QH_STRUCT is aligned on 16-byte boundaries,
  // Only the highest 28bit of the address is valid
  // (take 32bit address as an example).
  //
  PtrQH->QH.QHHorizontalPtr = (UINT32) ((UINTN) ptrNext >> 4);
}

VOID *
GetQHHorizontalLinkPtr (
  IN QH_STRUCT     *PtrQH
  )
/*++

Routine Description:

  Get QH Horizontal Link Pointer

Arguments:

  PtrQH   - QH_STRUCT
  

Returns:

  Data to return 

--*/
{
  //
  // Restore the 28bit address to 32bit address
  // (take 32bit address as an example)
  //
  return (VOID *) ((UINTN) (PtrQH->QH.QHHorizontalPtr << 4));
}

VOID
SetQHHorizontalQHorTDSelect (
  IN QH_STRUCT     *PtrQH,
  IN BOOLEAN       bQH
  )
/*++

Routine Description:

  Set QH Horizontal QH or TD 

Arguments:

  PtrQH - QH_STRUCT
  bQH   - TRUE is QH FALSE is TD

Returns:
  VOID

--*/
{
  //
  // if QH is connected, the specified bit is set,
  // if TD is connected, the specified bit is cleared.
  //
  PtrQH->QH.QHHorizontalQSelect = bQH ? 1 : 0;
}


VOID
SetQHHorizontalValidorInvalid (
  IN QH_STRUCT     *PtrQH,
  IN BOOLEAN       bValid
  )
/*++

Routine Description:

  Set QH Horizontal Valid or Invalid

Arguments:

  PtrQH  - QH_STRUCT
  bValid - TRUE is Valid FALSE is Invalid

Returns:
  VOID

--*/
{
  //
  // Valid means the horizontal link pointer is valid,
  // else, it's invalid.
  //
  PtrQH->QH.QHHorizontalTerminate = bValid ? 0 : 1;
}

VOID
SetQHVerticalLinkPtr (
  IN QH_STRUCT     *PtrQH,
  IN VOID          *ptrNext
  )
/*++

Routine Description:

  Set QH Vertical Link Pointer
  
Arguments:

  PtrQH   - QH_STRUCT
  ptrNext - Data to write
Returns:

  VOID

--*/
{
  //
  // Since the QH_STRUCT is aligned on 16-byte boundaries,
  // Only the highest 28bit of the address is valid
  // (take 32bit address as an example).
  //
  PtrQH->QH.QHVerticalPtr = (UINT32) ((UINTN) ptrNext >> 4);
}

VOID *
GetQHVerticalLinkPtr (
  IN QH_STRUCT     *PtrQH
  )
/*++

Routine Description:

  Get QH Vertical Link Pointer
  
Arguments:

  PtrQH   - QH_STRUCT
 
Returns:

   Data to return

--*/
{
  //
  // Restore the 28bit address to 32bit address
  // (take 32bit address as an example)
  //
  return (VOID *) ((UINTN) (PtrQH->QH.QHVerticalPtr << 4));
}

VOID
SetQHVerticalQHorTDSelect (
  IN QH_STRUCT     *PtrQH,
  IN BOOLEAN       bQH
  )
/*++

Routine Description:

  Set QH Vertical QH or TD

Arguments:

  PtrQH - QH_STRUCT
  bQH   - TRUE is QH FALSE is TD

Returns:

  VOID

--*/
{
  //
  // Set the specified bit if the Vertical Link Pointer pointing to a QH,
  // Clear the specified bit if the Vertical Link Pointer pointing to a TD.
  //
  PtrQH->QH.QHVerticalQSelect = bQH ? 1 : 0;
}

BOOLEAN
IsQHHorizontalQHSelect (
  IN QH_STRUCT     *PtrQH
  )
/*++

Routine Description:

  Is QH Horizontal QH Select

Arguments:

  PtrQH - QH_STRUCT
 
Returns:

  TRUE  - QH
  FALSE - TD

--*/
{
  //
  // Retrieve the information about whether the Horizontal Link Pointer
  // pointing to a QH or TD.
  //
  return (BOOLEAN) (PtrQH->QH.QHHorizontalQSelect ? TRUE : FALSE);
}

VOID
SetQHVerticalValidorInvalid (
  IN QH_STRUCT     *PtrQH,
  IN BOOLEAN       IsValid
  )
/*++

Routine Description:

  Set QH Vertical Valid or Invalid

Arguments:

  PtrQH   - QH_STRUCT
  IsValid - TRUE is valid FALSE is invalid

Returns:

  VOID

--*/
{
  //
  // If TRUE, indicates the Vertical Link Pointer field is valid,
  // else, the field is invalid.
  //
  PtrQH->QH.QHVerticalTerminate = IsValid ? 0 : 1;
}


BOOLEAN
GetQHVerticalValidorInvalid (
  IN QH_STRUCT     *PtrQH
  )
/*++

Routine Description:

  Get QH Vertical Valid or Invalid

Arguments:

  PtrQH - QH_STRUCT

Returns:

  TRUE  - Valid
  FALSE - Invalid

--*/
{
  //
  // If TRUE, indicates the Vertical Link Pointer field is valid,
  // else, the field is invalid.
  //
  return (BOOLEAN) (!(PtrQH->QH.QHVerticalTerminate));
}

BOOLEAN
GetQHHorizontalValidorInvalid (
  IN QH_STRUCT     *PtrQH
  )
/*++

Routine Description:

  Get QH Horizontal Valid or Invalid

Arguments:

  PtrQH - QH_STRUCT

Returns:

  TRUE  - Valid
  FALSE - Invalid

--*/
{
  //
  // If TRUE, meaning the Horizontal Link Pointer field is valid,
  // else, the field is invalid.
  //
  return (BOOLEAN) (!(PtrQH->QH.QHHorizontalTerminate));
}
//
// functions for TD
//
EFI_STATUS
AllocateTDStruct (
  IN  USB_HC_DEV     *HcDev,
  OUT TD_STRUCT      **ppTDStruct
  )
/*++

Routine Description:

  Allocate TD Struct

Arguments:

  HcDev       - USB_HC_DEV
  ppTDStruct  - place to store TD_STRUCT pointer
Returns:

  EFI_SUCCESS

--*/
{
  *ppTDStruct = NULL;

  //
  // TD must align on 16 bytes alignment,
  // since the memory allocated by UhciAllocatePool ()
  // is aligned on 32 bytes, it is no need to adjust
  // the allocated memory returned.
  //
  return UhciAllocatePool (
          HcDev,
          (UINT8 **) ppTDStruct,
          sizeof (TD_STRUCT)
          );
}

EFI_STATUS
CreateTD (
  IN  USB_HC_DEV     *HcDev,
  OUT TD_STRUCT      **pptrTD
  )
/*++

Routine Description:

  Create TD

Arguments:

  HcDev   - USB_HC_DEV
  pptrTD  - TD_STRUCT pointer to store

Returns:

  EFI_OUT_OF_RESOURCES - Can't allocate resources
  EFI_SUCCESS          - Success

--*/
{
  EFI_STATUS  Status;
  //
  // create memory for TD_STRUCT, and align the memory.
  //
  Status = AllocateTDStruct (HcDev, pptrTD);
  if (EFI_ERROR (Status)) {
    return EFI_OUT_OF_RESOURCES;
  }

  //
  // Make TD ready.
  //
  SetTDLinkPtrValidorInvalid (*pptrTD, FALSE);


  return EFI_SUCCESS;
}

EFI_STATUS
GenSetupStageTD (
  IN  USB_HC_DEV     *HcDev,
  IN  UINT8          DevAddr,
  IN  UINT8          Endpoint,
  IN  BOOLEAN        bSlow,
  IN  UINT8          *pDevReq,
  IN  UINT8          RequestLen,
  OUT TD_STRUCT      **ppTD
  )
/*++

Routine Description:

  Generate Setup Stage TD

Arguments:

  HcDev       - USB_HC_DEV
  DevAddr     - Device address
  Endpoint    - Endpoint number 
  bSlow       - Full speed or low speed
  pDevReq     - Device request
  RequestLen  - Request length
  ppTD        - TD_STRUCT to return
Returns:

  EFI_OUT_OF_RESOURCES - Can't allocate memory
  EFI_SUCCESS          - Success

--*/
{
  EFI_STATUS  Status;
  TD_STRUCT   *pTDStruct;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?