📄 uhci.c
字号:
if (EFI_ERROR(Status)) {
return Status;
}
switch (State) {
case EfiUsbHcStateHalt:
if (CurrentState == EfiUsbHcStateHalt) {
return EFI_SUCCESS;
}
Command = ReadUHCCommandReg(HcDev->PciIo,CommandRegAddr);
Command &= ~USBCMD_RS ;
WriteUHCCommandReg(HcDev->PciIo,CommandRegAddr,Command);
StatusRegAddr = (UINT32)(USBSTS);
//
// ensure the HC is in halt status after send the stop command
//
if(WaitForUHCHalt(HcDev->PciIo,StatusRegAddr,STALL_1_SECOND) == EFI_TIMEOUT) {
return EFI_DEVICE_ERROR ;
}
break;
case EfiUsbHcStateOperational:
if (IsHostSysErr(HcDev->PciIo,StatusRegAddr)
|| IsHCProcessErr(HcDev->PciIo,StatusRegAddr)) {
return EFI_DEVICE_ERROR;
}
switch (CurrentState) {
case EfiUsbHcStateOperational:
return EFI_SUCCESS;
case EfiUsbHcStateHalt:
//
// Set Run/Stop bit to 1.
//
Command = ReadUHCCommandReg(HcDev->PciIo,CommandRegAddr);
Command |= USBCMD_RS ;
WriteUHCCommandReg(HcDev->PciIo,CommandRegAddr,Command) ;
break;
case EfiUsbHcStateSuspend:
Command = ReadUHCCommandReg(HcDev->PciIo,CommandRegAddr);
//
// FGR(Force Global Resume) bit is 0
//
if((Command | (~USBCMD_FGR)) != 0xFF) {
//
// Write FGR bit to 1
//
Command |= USBCMD_FGR;
WriteUHCCommandReg(HcDev->PciIo,CommandRegAddr,Command);
}
//
// wait 20ms to let resume complete
// (20ms is specified by UHCI spec)
//
gBS->Stall(20000);
//
// Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0
//
Command &= ~USBCMD_FGR;
Command &= ~USBCMD_EGSM;
WriteUHCCommandReg(HcDev->PciIo,CommandRegAddr, Command);
break;
}
break;
case EfiUsbHcStateSuspend:
if (CurrentState == EfiUsbHcStateSuspend) {
return EFI_SUCCESS;
}
Status = UHCISetState (This,EfiUsbHcStateHalt);
if (EFI_ERROR(Status)) {
return Status;
}
//
// Set Enter Global Suspend Mode bit to 1.
//
Command = ReadUHCCommandReg(HcDev->PciIo,CommandRegAddr);
Command |= USBCMD_EGSM ;
WriteUHCCommandReg(HcDev->PciIo,CommandRegAddr,Command);
break;
default:
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
EFI_STATUS
UHCIGetRootHubPortNumber (
IN EFI_USB_HC_PROTOCOL *This,
OUT UINT8 *PortNumber
)
/*++
Routine Description:
Retrieves the number of root hub ports.
Arguments:
This A pointer to the EFI_USB_HC_PROTOCOL instance.
PortNumber A pointer to the number of the root hub ports.
Returns:
EFI_SUCCESS
The port number was retrieved successfully.
EFI_INVALID_PARAMETER
PortNumber is NULL.
EFI_DEVICE_ERROR
An error was encountered while attempting to
retrieve the port number.
--*/
{
USB_HC_DEV *HcDev;
UINT32 PSAddr;
UINT16 RHPortControl;
UINT32 Index;
HcDev = USB_HC_DEV_FROM_THIS(This);
if (PortNumber == NULL) {
return EFI_INVALID_PARAMETER;
}
*PortNumber = 0;
for (Index = 0 ; Index < 2; Index ++) {
PSAddr = (UINT32)(USBPORTSC1 + Index * 2);
RHPortControl = ReadRootPortReg (HcDev->PciIo, PSAddr);
//
// Port Register content is valid
//
if (RHPortControl != 0xff) {
(*PortNumber) ++;
}
}
return EFI_SUCCESS;
}
EFI_STATUS
UHCIGetRootHubPortStatus (
IN EFI_USB_HC_PROTOCOL *This,
IN UINT8 PortNumber,
OUT EFI_USB_PORT_STATUS *PortStatus
)
/*++
Routine Description:
Retrieves the current status of a USB root hub port.
Arguments:
This A pointer to the EFI_USB_HC_PROTOCOL.
PortNumber Specifies the root hub port from which the status
is to be retrieved. This value is zero-based. For example,
if a root hub has two ports, then the first port is numbered 0,
and the second port is numbered 1.
PortStatus A pointer to the current port status bits and
port status change bits.
Returns:
EFI_SUCCESS
The status of the USB root hub port specified by PortNumber
was returned in PortStatus.
EFI_INVALID_PARAMETER
PortNumber is invalid.
--*/
{
USB_HC_DEV *HcDev;
UINT32 PSAddr;
UINT16 RHPortStatus; // root hub port status
UINT8 TotalPortNumber;
if (PortStatus == NULL) {
return EFI_INVALID_PARAMETER;
}
UHCIGetRootHubPortNumber(This,&TotalPortNumber);
if(PortNumber >= TotalPortNumber) {
return EFI_INVALID_PARAMETER;
}
HcDev = USB_HC_DEV_FROM_THIS(This) ;
PSAddr = (UINT32)(USBPORTSC1 + PortNumber * 2);
PortStatus -> PortStatus = 0 ;
PortStatus -> PortChangeStatus = 0 ;
RHPortStatus = ReadRootPortReg(HcDev->PciIo,PSAddr) ;
//
// Fill Port Status bits
//
//
// Current Connect Status
//
if(RHPortStatus & USBPORTSC_CCS) {
PortStatus -> PortStatus |= USB_PORT_STAT_CONNECTION ;
}
//
// Port Enabled/Disabled
//
if(RHPortStatus & USBPORTSC_PED) {
PortStatus -> PortStatus |= USB_PORT_STAT_ENABLE ;
}
//
// Port Suspend
//
if(RHPortStatus & USBPORTSC_SUSP) {
PortStatus -> PortStatus |= USB_PORT_STAT_SUSPEND ;
}
//
// Port Reset
//
if(RHPortStatus & USBPORTSC_PR) {
PortStatus -> PortStatus |= USB_PORT_STAT_RESET ;
}
//
// Low Speed Device Attached
//
if(RHPortStatus & USBPORTSC_LSDA) {
PortStatus -> PortStatus |= USB_PORT_STAT_LOW_SPEED ;
}
//
// Fill Port Status Change bits
//
//
// Connect Status Change
//
if(RHPortStatus & USBPORTSC_CSC) {
PortStatus -> PortChangeStatus |= USB_PORT_STAT_C_CONNECTION ;
}
//
// Port Enabled/Disabled Change
//
if(RHPortStatus & USBPORTSC_PEDC) {
PortStatus -> PortChangeStatus |= USB_PORT_STAT_C_ENABLE ;
}
return EFI_SUCCESS ;
}
EFI_STATUS
UHCISetRootHubPortFeature (
IN EFI_USB_HC_PROTOCOL *This,
IN UINT8 PortNumber,
IN EFI_USB_PORT_FEATURE PortFeature
)
/*++
Routine Description:
Sets a feature for the specified root hub port.
Arguments:
This A pointer to the EFI_USB_HC_PROTOCOL.
PortNumber Specifies the root hub port whose feature
is requested to be set.
PortFeature Indicates the feature selector associated
with the feature set request.
Returns:
EFI_SUCCESS
The feature specified by PortFeature was set for the
USB root hub port specified by PortNumber.
EFI_INVALID_PARAMETER
PortNumber is invalid or PortFeature is invalid.
--*/
{
USB_HC_DEV *HcDev;
UINT32 PSAddr;
UINT32 CommandRegAddr;
UINT16 RHPortControl; // root hub port status
UINT8 TotalPortNumber;
UHCIGetRootHubPortNumber(This,&TotalPortNumber);
if(PortNumber >= TotalPortNumber) {
return EFI_INVALID_PARAMETER;
}
HcDev = USB_HC_DEV_FROM_THIS(This) ;
PSAddr = (UINT32)(USBPORTSC1 + PortNumber * 2) ;
CommandRegAddr = (UINT32)(USBCMD) ;
RHPortControl = ReadRootPortReg(HcDev->PciIo,PSAddr) ;
switch(PortFeature) {
case EfiUsbPortSuspend:
if(!(ReadUHCCommandReg(HcDev->PciIo,CommandRegAddr) & USBCMD_EGSM)) {
//
// if global suspend is not active, can set port suspend
//
RHPortControl &= 0xfff5;
RHPortControl |= USBPORTSC_SUSP;
}
break ;
case EfiUsbPortReset:
RHPortControl &= 0xfff5;
RHPortControl |= USBPORTSC_PR; // Set the reset bit
break ;
case EfiUsbPortPower:
break ;
case EfiUsbPortEnable:
RHPortControl &= 0xfff5;
RHPortControl |= USBPORTSC_PED;
break;
default:
return EFI_INVALID_PARAMETER;
}
WriteRootPortReg(HcDev->PciIo,PSAddr,RHPortControl) ;
return EFI_SUCCESS ;
}
EFI_STATUS
UHCIClearRootHubPortFeature (
IN EFI_USB_HC_PROTOCOL *This,
IN UINT8 PortNumber,
IN EFI_USB_PORT_FEATURE PortFeature
)
/*++
Routine Description:
Clears a feature for the specified root hub port.
Arguments:
This A pointer to the EFI_USB_HC_PROTOCOL instance.
PortNumber Specifies the root hub port whose feature
is requested to be cleared.
PortFeature Indicates the feature selector associated with the
feature clear request.
Returns:
EFI_SUCCESS
The feature specified by PortFeature was cleared for the
USB root hub port specified by PortNumber.
EFI_INVALID_PARAMETER
PortNumber is invalid or PortFeature is invalid.
--*/
{
USB_HC_DEV *HcDev;
UINT32 PSAddr;
UINT16 RHPortControl;
UINT8 TotalPortNumber;
UHCIGetRootHubPortNumber(This,&TotalPortNumber);
if(PortNumber >= TotalPortNumber) {
return EFI_INVALID_PARAMETER;
}
HcDev = USB_HC_DEV_FROM_THIS(This);
PSAddr = (UINT32)(USBPORTSC1 + PortNumber * 2) ;
RHPortControl = ReadRootPortReg(HcDev->PciIo,PSAddr) ;
switch (PortFeature) {
//
// clear PORT_ENABLE feature means disable port.
//
case EfiUsbPortEnable:
RHPortControl &= 0xfff5;
RHPortControl &= ~USBPORTSC_PED ;
break;
//
// clear PORT_SUSPEND feature means resume the port.
// (cause a resume on the specified port if in suspend mode)
//
case EfiUsbPortSuspend:
RHPortControl &= 0xfff5;
RHPortControl &= ~USBPORTSC_SUSP ;
break;
//
// no operation
//
case EfiUsbPortPower:
break;
//
// clear PORT_RESET means clear the reset signal.
//
case EfiUsbPortReset:
RHPortControl &= 0xfff5;
RHPortControl &= ~USBPORTSC_PR ;
break ;
//
// clear connect status change
//
case EfiUsbPortConnectChange:
RHPortControl &= 0xfff5;
RHPortControl |= USBPORTSC_CSC ;
break;
//
// clear enable/disable status change
//
case EfiUsbPortEnableChange:
RHPortControl &= 0xfff5;
RHPortControl |= USBPORTSC_PEDC ;
break;
//
// root hub does not support this request
//
case EfiUsbPortSuspendChange:
break;
//
// root hub does not support this request
//
case EfiUsbPortOverCurrentChange:
break;
//
// root hub does not support this request
//
case EfiUsbPortResetChange:
break;
default:
return EFI_INVALID_PARAMETER ;
}
WriteRootPortReg(HcDev->PciIo,PSAddr,RHPortControl) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -