mirror of https://github.com/acidanthera/audk.git
508 lines
12 KiB
C
508 lines
12 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 2006, Intel Corporation
|
||
|
All rights reserved. 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.
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
Hub.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Usb Hub Request
|
||
|
|
||
|
Revision History
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "usbbus.h"
|
||
|
|
||
|
EFI_STATUS
|
||
|
HubGetPortStatus (
|
||
|
IN EFI_USB_IO_PROTOCOL *UsbIo,
|
||
|
IN UINT8 Port,
|
||
|
OUT UINT32 *PortStatus
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Get a given hub port status
|
||
|
|
||
|
Arguments:
|
||
|
UsbIo - EFI_USB_IO_PROTOCOL instance
|
||
|
Port - Usb hub port number (starting from 1).
|
||
|
PortStatus - Current Hub port status and change status.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_DEVICE
|
||
|
EFI_TIME_OUT
|
||
|
EFI_INVALID_PARAMETER
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
EFI_USB_DEVICE_REQUEST DevReq;
|
||
|
EFI_STATUS EfiStatus;
|
||
|
UINT32 UsbStatus;
|
||
|
UINT32 Timeout;
|
||
|
|
||
|
ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
|
||
|
|
||
|
//
|
||
|
// Fill Device request packet
|
||
|
//
|
||
|
DevReq.RequestType = HUB_GET_PORT_STATUS_REQ_TYPE;
|
||
|
DevReq.Request = HUB_GET_PORT_STATUS;
|
||
|
DevReq.Value = 0;
|
||
|
DevReq.Index = Port;
|
||
|
DevReq.Length = sizeof (UINT32);
|
||
|
|
||
|
Timeout = 3000;
|
||
|
|
||
|
EfiStatus = UsbIo->UsbControlTransfer (
|
||
|
UsbIo,
|
||
|
&DevReq,
|
||
|
EfiUsbDataIn,
|
||
|
Timeout,
|
||
|
PortStatus,
|
||
|
sizeof (UINT32),
|
||
|
&UsbStatus
|
||
|
);
|
||
|
|
||
|
return EfiStatus;
|
||
|
}
|
||
|
|
||
|
EFI_STATUS
|
||
|
HubSetPortFeature (
|
||
|
IN EFI_USB_IO_PROTOCOL *UsbIo,
|
||
|
IN UINT8 Port,
|
||
|
IN UINT8 Value
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Set specified feature to a give hub port
|
||
|
|
||
|
Arguments:
|
||
|
UsbIo - EFI_USB_IO_PROTOCOL instance
|
||
|
Port - Usb hub port number (starting from 1).
|
||
|
Value - New feature value.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_DEVICE
|
||
|
EFI_TIME_OUT
|
||
|
EFI_INVALID_PARAMETER
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
EFI_USB_DEVICE_REQUEST DevReq;
|
||
|
EFI_STATUS EfiStatus;
|
||
|
UINT32 UsbStatus;
|
||
|
UINT32 Timeout;
|
||
|
|
||
|
ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
|
||
|
|
||
|
//
|
||
|
// Fill Device request packet
|
||
|
//
|
||
|
DevReq.RequestType = HUB_SET_PORT_FEATURE_REQ_TYPE;
|
||
|
DevReq.Request = HUB_SET_PORT_FEATURE;
|
||
|
DevReq.Value = Value;
|
||
|
DevReq.Index = Port;
|
||
|
DevReq.Length = 0;
|
||
|
|
||
|
Timeout = 3000;
|
||
|
EfiStatus = UsbIo->UsbControlTransfer (
|
||
|
UsbIo,
|
||
|
&DevReq,
|
||
|
EfiUsbNoData,
|
||
|
Timeout,
|
||
|
NULL,
|
||
|
0,
|
||
|
&UsbStatus
|
||
|
);
|
||
|
|
||
|
return EfiStatus;
|
||
|
}
|
||
|
|
||
|
EFI_STATUS
|
||
|
HubClearPortFeature (
|
||
|
IN EFI_USB_IO_PROTOCOL *UsbIo,
|
||
|
IN UINT8 Port,
|
||
|
IN UINT8 Value
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Clear a specified feature of a given hub port
|
||
|
|
||
|
Arguments:
|
||
|
UsbIo - EFI_USB_IO_PROTOCOL instance
|
||
|
Port - Usb hub port number (starting from 1).
|
||
|
Value - Feature value that will be cleared from
|
||
|
that hub port.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_DEVICE
|
||
|
EFI_TIME_OUT
|
||
|
EFI_INVALID_PARAMETER
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
EFI_USB_DEVICE_REQUEST DevReq;
|
||
|
EFI_STATUS EfiStatus;
|
||
|
UINT32 UsbStatus;
|
||
|
UINT32 Timeout;
|
||
|
|
||
|
ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
|
||
|
|
||
|
//
|
||
|
// Fill Device request packet
|
||
|
//
|
||
|
DevReq.RequestType = HUB_CLEAR_FEATURE_PORT_REQ_TYPE;
|
||
|
DevReq.Request = HUB_CLEAR_FEATURE_PORT;
|
||
|
DevReq.Value = Value;
|
||
|
DevReq.Index = Port;
|
||
|
DevReq.Length = 0;
|
||
|
|
||
|
Timeout = 3000;
|
||
|
EfiStatus = UsbIo->UsbControlTransfer (
|
||
|
UsbIo,
|
||
|
&DevReq,
|
||
|
EfiUsbNoData,
|
||
|
Timeout,
|
||
|
NULL,
|
||
|
0,
|
||
|
&UsbStatus
|
||
|
);
|
||
|
|
||
|
return EfiStatus;
|
||
|
}
|
||
|
|
||
|
EFI_STATUS
|
||
|
HubGetHubStatus (
|
||
|
IN EFI_USB_IO_PROTOCOL *UsbIo,
|
||
|
OUT UINT32 *HubStatus
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Get Hub Status
|
||
|
|
||
|
Arguments:
|
||
|
UsbIo - EFI_USB_IO_PROTOCOL instance
|
||
|
HubStatus - Current Hub status and change status.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_DEVICE
|
||
|
EFI_TIME_OUT
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
EFI_USB_DEVICE_REQUEST DevReq;
|
||
|
EFI_STATUS EfiStatus;
|
||
|
UINT32 UsbStatus;
|
||
|
UINT32 Timeout;
|
||
|
|
||
|
ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
|
||
|
|
||
|
//
|
||
|
// Fill Device request packet
|
||
|
//
|
||
|
DevReq.RequestType = HUB_GET_HUB_STATUS_REQ_TYPE;
|
||
|
DevReq.Request = HUB_GET_HUB_STATUS;
|
||
|
DevReq.Value = 0;
|
||
|
DevReq.Index = 0;
|
||
|
DevReq.Length = sizeof (UINT32);
|
||
|
|
||
|
Timeout = 3000;
|
||
|
EfiStatus = UsbIo->UsbControlTransfer (
|
||
|
UsbIo,
|
||
|
&DevReq,
|
||
|
EfiUsbDataIn,
|
||
|
Timeout,
|
||
|
HubStatus,
|
||
|
sizeof (UINT32),
|
||
|
&UsbStatus
|
||
|
);
|
||
|
|
||
|
return EfiStatus;
|
||
|
}
|
||
|
|
||
|
EFI_STATUS
|
||
|
HubSetHubFeature (
|
||
|
IN EFI_USB_IO_PROTOCOL *UsbIo,
|
||
|
IN UINT8 Value
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Set a specified feature to the hub
|
||
|
|
||
|
Arguments:
|
||
|
UsbIo - EFI_USB_IO_PROTOCOL instance
|
||
|
Value - Feature value that will be set to the hub.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_DEVICE
|
||
|
EFI_TIME_OUT
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
EFI_USB_DEVICE_REQUEST DevReq;
|
||
|
EFI_STATUS EfiStatus;
|
||
|
UINT32 UsbStatus;
|
||
|
UINT32 Timeout;
|
||
|
|
||
|
ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
|
||
|
|
||
|
//
|
||
|
// Fill Device request packet
|
||
|
//
|
||
|
DevReq.RequestType = HUB_SET_HUB_FEATURE_REQ_TYPE;
|
||
|
DevReq.Request = HUB_SET_HUB_FEATURE;
|
||
|
DevReq.Value = Value;
|
||
|
DevReq.Index = 0;
|
||
|
DevReq.Length = 0;
|
||
|
|
||
|
Timeout = 3000;
|
||
|
EfiStatus = UsbIo->UsbControlTransfer (
|
||
|
UsbIo,
|
||
|
&DevReq,
|
||
|
EfiUsbNoData,
|
||
|
Timeout,
|
||
|
NULL,
|
||
|
0,
|
||
|
&UsbStatus
|
||
|
);
|
||
|
|
||
|
return EfiStatus;
|
||
|
}
|
||
|
|
||
|
EFI_STATUS
|
||
|
HubClearHubFeature (
|
||
|
IN EFI_USB_IO_PROTOCOL *UsbIo,
|
||
|
IN UINT8 Value
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Set a specified feature to the hub
|
||
|
|
||
|
Arguments:
|
||
|
UsbIo - EFI_USB_IO_PROTOCOL instance
|
||
|
Value - Feature value that will be cleared from the hub.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_DEVICE
|
||
|
EFI_TIME_OUT
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
EFI_USB_DEVICE_REQUEST DevReq;
|
||
|
EFI_STATUS EfiStatus;
|
||
|
UINT32 UsbStatus;
|
||
|
UINT32 Timeout;
|
||
|
|
||
|
ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
|
||
|
|
||
|
//
|
||
|
// Fill Device request packet
|
||
|
//
|
||
|
DevReq.RequestType = HUB_CLEAR_FEATURE_REQ_TYPE;
|
||
|
DevReq.Request = HUB_CLEAR_FEATURE;
|
||
|
DevReq.Value = Value;
|
||
|
DevReq.Index = 0;
|
||
|
DevReq.Length = 0;
|
||
|
|
||
|
Timeout = 3000;
|
||
|
EfiStatus = UsbIo->UsbControlTransfer (
|
||
|
UsbIo,
|
||
|
&DevReq,
|
||
|
EfiUsbNoData,
|
||
|
Timeout,
|
||
|
NULL,
|
||
|
0,
|
||
|
&UsbStatus
|
||
|
);
|
||
|
|
||
|
return EfiStatus;
|
||
|
|
||
|
}
|
||
|
|
||
|
EFI_STATUS
|
||
|
GetHubDescriptor (
|
||
|
IN EFI_USB_IO_PROTOCOL *UsbIo,
|
||
|
IN UINTN DescriptorSize,
|
||
|
OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Get the hub descriptor
|
||
|
|
||
|
Arguments:
|
||
|
UsbIo - EFI_USB_IO_PROTOCOL instance
|
||
|
DescriptorSize - The length of Hub Descriptor buffer.
|
||
|
HubDescriptor - Caller allocated buffer to store the hub descriptor
|
||
|
if successfully returned.
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_DEVICE
|
||
|
EFI_TIME_OUT
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
EFI_USB_DEVICE_REQUEST DevReq;
|
||
|
EFI_STATUS EfiStatus;
|
||
|
UINT32 UsbStatus;
|
||
|
UINT32 Timeout;
|
||
|
|
||
|
ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
|
||
|
|
||
|
//
|
||
|
// Fill Device request packet
|
||
|
//
|
||
|
DevReq.RequestType = USB_RT_HUB | 0x80;
|
||
|
DevReq.Request = HUB_GET_DESCRIPTOR;
|
||
|
DevReq.Value = USB_DT_HUB << 8;
|
||
|
DevReq.Index = 0;
|
||
|
DevReq.Length = (UINT16) DescriptorSize;
|
||
|
|
||
|
Timeout = 3000;
|
||
|
EfiStatus = UsbIo->UsbControlTransfer (
|
||
|
UsbIo,
|
||
|
&DevReq,
|
||
|
EfiUsbDataIn,
|
||
|
Timeout,
|
||
|
HubDescriptor,
|
||
|
(UINT16) DescriptorSize,
|
||
|
&UsbStatus
|
||
|
);
|
||
|
|
||
|
return EfiStatus;
|
||
|
|
||
|
}
|
||
|
|
||
|
EFI_STATUS
|
||
|
DoHubConfig (
|
||
|
IN USB_IO_CONTROLLER_DEVICE *HubController
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Configure the hub
|
||
|
|
||
|
Arguments:
|
||
|
HubController - Indicating the hub controller device that
|
||
|
will be configured
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
EFI_DEVICE_ERROR
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
EFI_USB_IO_PROTOCOL *UsbIo;
|
||
|
EFI_USB_HUB_DESCRIPTOR HubDescriptor;
|
||
|
EFI_STATUS Status;
|
||
|
EFI_USB_HUB_STATUS HubStatus;
|
||
|
UINTN Index;
|
||
|
UINT32 PortStatus;
|
||
|
|
||
|
UsbIo = &HubController->UsbIo;
|
||
|
|
||
|
ZeroMem (&HubDescriptor, sizeof (HubDescriptor));
|
||
|
|
||
|
//
|
||
|
// First get the hub descriptor length
|
||
|
//
|
||
|
Status = GetHubDescriptor (UsbIo, 2, &HubDescriptor);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return EFI_DEVICE_ERROR;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// First get the whole descriptor, then
|
||
|
// get the number of hub ports
|
||
|
//
|
||
|
Status = GetHubDescriptor (
|
||
|
UsbIo,
|
||
|
HubDescriptor.Length,
|
||
|
&HubDescriptor
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
DEBUG ((gUSBErrorLevel, "Get hub descriptor fail\n"));
|
||
|
return EFI_DEVICE_ERROR;
|
||
|
}
|
||
|
|
||
|
HubController->DownstreamPorts = HubDescriptor.NbrPorts;
|
||
|
|
||
|
Status = HubGetHubStatus (UsbIo, (UINT32 *) &HubStatus);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
DEBUG ((gUSBErrorLevel, "Get hub status fail when configure\n"));
|
||
|
return EFI_DEVICE_ERROR;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get all hub ports status
|
||
|
//
|
||
|
for (Index = 0; Index < HubController->DownstreamPorts; Index++) {
|
||
|
|
||
|
Status = HubGetPortStatus (UsbIo, (UINT8) (Index + 1), &PortStatus);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Power all the hub ports
|
||
|
//
|
||
|
for (Index = 0; Index < HubController->DownstreamPorts; Index++) {
|
||
|
Status = HubSetPortFeature (
|
||
|
UsbIo,
|
||
|
(UINT8) (Index + 1),
|
||
|
EfiUsbPortPower
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Clear Hub Status Change
|
||
|
//
|
||
|
Status = HubGetHubStatus (UsbIo, (UINT32 *) &HubStatus);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
DEBUG ((gUSBErrorLevel, "Get hub status fail\n"));
|
||
|
return EFI_DEVICE_ERROR;
|
||
|
} else {
|
||
|
//
|
||
|
// Hub power supply change happens
|
||
|
//
|
||
|
if (HubStatus.HubChange & HUB_CHANGE_LOCAL_POWER) {
|
||
|
HubClearHubFeature (UsbIo, C_HUB_LOCAL_POWER);
|
||
|
}
|
||
|
//
|
||
|
// Hub change overcurrent happens
|
||
|
//
|
||
|
if (HubStatus.HubChange & HUB_CHANGE_OVERCURRENT) {
|
||
|
HubClearHubFeature (UsbIo, C_HUB_OVER_CURRENT);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
|
||
|
}
|