📄 uhchlp.c
字号:
/*++
Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
UhcHlp.c
Abstract:
Revision History
--*/
#include "Efi.h"
#include "EfiDriverLib.h"
#include "uhci.h"
//
// UHCI IO Space Address Register Register locates at
// offset 20 ~ 23h of PCI Configuration Space (UHCI spec, Revision 1.1),
// so, its BAR Index is 4.
//
#define USB_BAR_INDEX 4
UINT8
USBReadPortB (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 PortOffset
)
{
UINT8 Data;
//
// Perform 8bit Read in PCI IO Space
//
PciIo->Io.Read (PciIo,
EfiPciIoWidthUint8,
USB_BAR_INDEX,
(UINT64)PortOffset,
1,
&Data
);
return Data;
}
UINT16
USBReadPortW (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 PortOffset
)
{
UINT16 Data;
//
// Perform 16bit Read in PCI IO Space
//
PciIo->Io.Read (PciIo,
EfiPciIoWidthUint16,
USB_BAR_INDEX,
(UINT64)PortOffset,
1,
&Data
);
return Data;
}
UINT32
USBReadPortDW (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 PortOffset
)
{
UINT32 Data;
//
// Perform 32bit Read in PCI IO Space
//
PciIo->Io.Read (PciIo,
EfiPciIoWidthUint32,
USB_BAR_INDEX,
(UINT64)PortOffset,
1,
&Data
);
return Data;
}
VOID
USBWritePortB (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 PortOffset,
IN UINT8 Data
)
{
//
// Perform 8bit Write in PCI IO Space
//
PciIo->Io.Write (PciIo,
EfiPciIoWidthUint8,
USB_BAR_INDEX,
(UINT64)PortOffset,
1,
&Data
);
}
VOID
USBWritePortW (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 PortOffset,
IN UINT16 Data
)
{
//
// Perform 16bit Write in PCI IO Space
//
PciIo->Io.Write (PciIo,
EfiPciIoWidthUint16,
USB_BAR_INDEX,
(UINT64)PortOffset,
1,
&Data
);
}
VOID
USBWritePortDW (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 PortOffset,
IN UINT32 Data
)
{
//
// Perform 32bit Write in PCI IO Space
//
PciIo->Io.Write (PciIo,
EfiPciIoWidthUint32,
USB_BAR_INDEX,
(UINT64)PortOffset,
1,
&Data
);
}
//
// USB register-base helper functions
//
VOID
WriteUHCCommandReg(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 CmdAddrOffset,
IN UINT16 UsbCmd
)
{
//
// Write to UHC's Command Register
//
USBWritePortW (PciIo,CmdAddrOffset, UsbCmd);
return;
}
UINT16
ReadUHCCommandReg(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 CmdAddrOffset
)
{
//
// Read from UHC's Command Register
//
return USBReadPortW (PciIo,CmdAddrOffset);
}
VOID
WriteUHCStatusReg(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusAddrOffset,
IN UINT16 UsbSts
)
{
//
// Write to UHC's Status Register
//
USBWritePortW (PciIo,StatusAddrOffset, UsbSts);
return;
}
UINT16
ReadUHCStatusReg(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusAddrOffset
)
{
//
// Read from UHC's Status Register
//
return USBReadPortW (PciIo,StatusAddrOffset);
}
VOID
ClearStatusReg(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusAddrOffset
)
{
UINT16 UsbSts;
//
// Clear the content of UHC's Status Register
//
UsbSts = 0x003F;
WriteUHCStatusReg (PciIo,StatusAddrOffset,UsbSts);
}
VOID
WriteUHCIntReg(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 InterruptAddrOffset,
IN UINT16 UsbInt
)
{
//
// Write to UHC's Interrupt Enable Register
//
USBWritePortW (PciIo,InterruptAddrOffset, UsbInt);
return;
}
UINT16
ReadUHCIntReg(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 InterruptAddrOffset
)
{
//
// Read from UHC's Interrupt Enable Register
//
return USBReadPortW (PciIo,InterruptAddrOffset);
}
VOID
WriteUHCFrameNumberReg(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 FrameNumAddrOffset,
IN UINT16 UsbFrameNum
)
{
//
// Write to UHC's Frame Number Register
//
USBWritePortW (PciIo,FrameNumAddrOffset, UsbFrameNum);
return;
}
UINT16
ReadUHCFrameNumberReg(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 FrameNumAddrOffset
)
{
//
// Read from UHC's Frame Number Register
//
return USBReadPortW (PciIo,FrameNumAddrOffset);
}
VOID
WriteUHCFrameListBaseReg(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 FlBaseAddrOffset,
IN UINT32 UsbFrameListBaseAddr
)
{
//
// Write to UHC's Frame List Base Register
//
USBWritePortDW (PciIo,FlBaseAddrOffset, UsbFrameListBaseAddr);
return;
}
UINT32
ReadUHCFrameListBaseReg(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 FlBaseAddrOffset
)
{
UINT32 UsbFrameListBaseAddr;
//
// Read from UHC's Frame List Register, and return the valid value.
//
UsbFrameListBaseAddr = USBReadPortDW (PciIo,FlBaseAddrOffset);
UsbFrameListBaseAddr = UsbFrameListBaseAddr & 0xFFFFF000 ;
return UsbFrameListBaseAddr;
}
UINT16
ReadRootPortReg(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 PortAddrOffset
)
{
//
// Read from UHC's Root Port Register
//
return USBReadPortW (PciIo,PortAddrOffset);
}
VOID
WriteRootPortReg(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 PortAddrOffset,
IN UINT16 ControlBits
)
{
//
// Write to UHC's Root Port Register
//
USBWritePortW (PciIo,PortAddrOffset,ControlBits);
return ;
}
EFI_STATUS
WaitForUHCHalt(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusRegAddr,
IN UINTN Timeout
)
{
UINTN Delay;
UINT16 Status ;
//
// Timeout is in us unit
//
Delay = (Timeout / 50) + 1;
do {
Status = ReadUHCStatusReg(PciIo,StatusRegAddr) ;
if ( (Status & USBSTS_HCH) == USBSTS_HCH) {
break;
}
gBS->Stall(50); // Stall for 50 us
} while (Delay--);
if (Delay == 0) {
return EFI_TIMEOUT;
}
return EFI_SUCCESS;
}
BOOLEAN
DetectUHCInterrupt(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusRegAddr
)
{
UINT16 Status ;
//
// Scan whether there is any interrupt flag set in Status Register.
//
Status = ReadUHCStatusReg (PciIo,StatusRegAddr) ;
if (Status & 0x003B) { // bit0~bit1,bit3~bit5
return TRUE;
} else {
return FALSE;
}
}
BOOLEAN
IsUSBInterrupt(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusRegAddr
)
{
UINT16 Status ;
//
// Detect whether the interrupt is caused by IOC or Short Packet Detected.
// see "UHCI Design Guid".
//
Status = ReadUHCStatusReg (PciIo,StatusRegAddr) ;
if (Status & USBSTS_USBINT) {
return TRUE;
} else {
return FALSE;
}
}
BOOLEAN
IsUSBErrInterrupt(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusRegAddr
)
{
UINT16 Status ;
//
// Detect whether the interrupt is caused by any error condition.
// see "UHCI Design Guid".
//
Status = ReadUHCStatusReg (PciIo,StatusRegAddr) ;
if (Status & USBSTS_ERROR) {
return TRUE;
} else {
return FALSE;
}
}
BOOLEAN
IsHostSysErr(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusRegAddr
)
{
UINT16 Status ;
//
// Detect whether the interrupt is caused by serious error.
// see "UHCI Design Guid".
//
Status = ReadUHCStatusReg (PciIo,StatusRegAddr) ;
if (Status & USBSTS_HSE) {
return TRUE;
} else {
return FALSE;
}
}
BOOLEAN
IsHCProcessErr(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusRegAddr
)
{
UINT16 Status ;
//
// Detect whether the interrupt is caused by fatal error.
// see "UHCI Design Guid".
//
Status = ReadUHCStatusReg (PciIo,StatusRegAddr) ;
if (Status & USBSTS_HCPE) {
return TRUE;
} else {
return FALSE;
}
}
BOOLEAN
IsHCHalted(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 StatusRegAddr
)
{
UINT16 Status ;
//
// Detect whether the the Host Controller is halted.
//
Status = ReadUHCStatusReg (PciIo,StatusRegAddr) ;
if (Status & USBSTS_HCH) {
return TRUE;
} else {
return FALSE;
}
}
VOID
SetFrameNumberReg(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 FrameNumAddrOffset,
IN UINT16 Index
)
{
//
// Modifies the USB frame number register.
// It is assumed that the HC schedule execution is stopped.
//
Index &= 0x03FF;
WriteUHCFrameNumberReg (PciIo,FrameNumAddrOffset,Index);
}
UINT16
GetCurrentFrameNumber(
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT32 FrameNumAddrOffset
)
{
//
// Gets value in the USB frame number register.
//
return (UINT16)(ReadUHCFrameNumberReg (PciIo,FrameNumAddrOffset) & 0x03FF);
}
VOID
SetFrameListBaseAddress(
EFI_PCI_IO_PROTOCOL *PciIo,
UINT32 FlBaseAddrReg,
UINT32 Addr
)
{
//
// Sets value in the USB Frame List Base Address register.
//
WriteUHCFrameListBaseReg(PciIo,FlBaseAddrReg,(UINT32)(Addr & 0xFFFFF000));
}
UINT32
GetFrameListBaseAddress(
EFI_PCI_IO_PROTOCOL *PciIo,
UINT32 FLBAddr
)
{
//
// Gets value from the USB Frame List Base Address register.
//
return ReadUHCFrameListBaseReg(PciIo,FLBAddr) & 0xFFFFF000;
}
VOID
EnableUhc (
IN EFI_PCI_IO_PROTOCOL *PciIo
)
{
UINT16 Command;
//
// Enable Bas master & IO access
//
Command = 0x05;
PciIo->Pci.Write (
PciIo,
EfiPciIoWidthUint16,
0x04, //command reg
1,
&Command
);
return;
}
VOID
EnableMaxPacketSize (
USB_HC_DEV *HcDev
)
{
UINT16 CommandContent;
CommandContent = ReadUHCCommandReg (
HcDev->PciIo,
(UINT32)(USBCMD)
);
if ((CommandContent & USBCMD_MAXP) != USBCMD_MAXP) {
CommandContent |= USBCMD_MAXP;
WriteUHCCommandReg (
HcDev->PciIo,
(UINT32)(USBCMD),
CommandContent
);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -