usbbus.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,516 行 · 第 1/5 页
C
2,516 行
UsbIo,
StatusChangePort,
EfiUsbPortReset
);
gBS->Stall (50 * 1000);
//
// Wait for port reset complete
//
Number = 10;
do {
HubGetPortStatus (
UsbIo,
StatusChangePort,
(UINT32 *) &HubPortStatus
);
gBS->Stall (10 * 1000);
Number -= 1;
} while ((HubPortStatus.PortStatus & USB_PORT_STAT_RESET) == 1 && Number > 0);
if (Number == 0) {
//
// Cannot reset port, return error
//
DEBUG ((gUSBErrorLevel, "Reset Port Failed\n"));
gBS->FreePool (NewDevice);
return ;
}
//
// Check high speed or full speed device
//
if (HubPortStatus.PortStatus & USB_PORT_STAT_LOW_SPEED) {
DEBUG ((gUSBDebugLevel, "Low Speed Device Attached to Hub\n"));
NewDevice->DeviceSpeed = EFI_USB_SPEED_LOW;
} else if (HubPortStatus.PortStatus & USB_PORT_STAT_HIGH_SPEED) {
DEBUG ((gUSBDebugLevel, "High Speed Device Attached to Hub\n"));
NewDevice->DeviceSpeed = EFI_USB_SPEED_HIGH;
} else {
DEBUG ((gUSBDebugLevel, "Full Speed Device Attached to Hub\n"));
NewDevice->DeviceSpeed = EFI_USB_SPEED_FULL;
}
//
// Configure that device
//
Status = UsbDeviceConfiguration (
HubController,
HostController,
(UINT8) (StatusChangePort - 1),
NewDevice
);
if (EFI_ERROR (Status)) {
gBS->FreePool (NewDevice);
return ;
}
//
// Add this device to the usb bus tree
// StatusChangePort is begin from 1,
//
HubController->Children[StatusChangePort - 1] = NewDevice;
for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {
//
// If this device is hub, add to the hub index
//
NewController = NewDevice->UsbController[Index2];
//
// Connect the controller to the driver image
//
Status = gBS->ConnectController (
NewController->Handle,
NULL,
NULL,
TRUE
);
//
// If connect success, we need to disconnect when
// stop the controller, otherwise we need not call
// gBS->DisconnectController ()
// This is used by those usb devices we don't plan
// to support. We can allocate
// controller handles for them, but we don't have
// device drivers to manage them.
//
NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status));
//
// If this device is hub, add to the hub index
//
if (IsHub (NewController)) {
NewController->IsUsbHub = TRUE;
//
// Configure Hub
//
Status = DoHubConfig (NewController);
if (EFI_ERROR (Status)) {
continue;
}
//
// Create an event to do hub enumeration
//
gBS->CreateEvent (
EFI_EVENT_NOTIFY_SIGNAL,
EFI_TPL_CALLBACK,
HubEnumeration,
NewController,
&NewController->HubNotify
);
//
// Add request to do query hub status
// change endpoint
//
UsbIo = &NewController->UsbIo;
UsbIo->UsbAsyncInterruptTransfer (
UsbIo,
NewController->HubEndpointAddress, // Hub endpoint address
TRUE,
100,
1, // Hub ports < 7
OnHubInterruptComplete,
NewController
);
}
}
} else {
//
// Something disconnected from USB hub
//
DEBUG ((gUSBDebugLevel, "Something Device Detached on Hub port\n"));
OldUsbIoDevice = HubController->Children[StatusChangePort - 1];
UsbDeviceDeConfiguration (OldUsbIoDevice);
HubController->Children[StatusChangePort - 1] = NULL;
}
return ;
}
return ;
}
STATIC
USB_IO_CONTROLLER_DEVICE *
CreateUsbIoControllerDevice (
VOID
)
/*++
Routine Description:
Allocate a structure for USB_IO_CONTROLLER_DEVICE
Arguments:
N/A
Returns:
A pointer to a USB_IO_CONTROLLER_DEVICE structure,
Or NULL.
--*/
{
USB_IO_CONTROLLER_DEVICE *UsbIoControllerDev;
//
// Allocate USB_IO_CONTROLLER_DEVICE structure
//
UsbIoControllerDev = NULL;
UsbIoControllerDev = EfiLibAllocateZeroPool (sizeof (USB_IO_CONTROLLER_DEVICE));
if (UsbIoControllerDev == NULL) {
return NULL;
}
UsbIoControllerDev->Signature = USB_IO_CONTROLLER_SIGNATURE;
return UsbIoControllerDev;
}
STATIC
EFI_STATUS
InitUsbIoController (
IN USB_IO_CONTROLLER_DEVICE *UsbIoController
)
/*++
Routine Description:
Init and install EFI_USB_IO_PROTOCOL onto that controller.
Arguments:
UsbIoController - The Controller to be operated.
Returns:
EFI_SUCCESS
EFI_OUT_OF_RESOURCES
--*/
{
USB_DEVICE_PATH UsbNode;
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
EFI_USB_HC_PROTOCOL *UsbHcProtocol;
EFI_USB2_HC_PROTOCOL *Usb2HcProtocol;
//
// Build the child device path for each new USB_IO device
//
EfiZeroMem (&UsbNode, sizeof (UsbNode));
UsbNode.Header.Type = MESSAGING_DEVICE_PATH;
UsbNode.Header.SubType = MSG_USB_DP;
SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode));
UsbNode.InterfaceNumber = UsbIoController->InterfaceNumber;
UsbNode.ParentPortNumber = UsbIoController->ParentPort;
ParentDevicePath = UsbIoController->Parent->DevicePath;
UsbIoController->DevicePath = EfiAppendDevicePathNode (ParentDevicePath, &UsbNode.Header);
if (UsbIoController->DevicePath == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = gBS->InstallMultipleProtocolInterfaces (
&UsbIoController->Handle,
&gEfiDevicePathProtocolGuid,
UsbIoController->DevicePath,
&gEfiUsbIoProtocolGuid,
&UsbIoController->UsbIo,
NULL
);
if (EFI_ERROR (Status)) {
return Status;
}
if (UsbIoController->UsbDevice->BusController->Hc2ProtocolSupported) {
Status = gBS->OpenProtocol (
UsbIoController->HostController,
&gEfiUsb2HcProtocolGuid,
&Usb2HcProtocol,
gUsbBusDriverBinding.DriverBindingHandle,
UsbIoController->Handle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
} else {
Status = gBS->OpenProtocol (
UsbIoController->HostController,
&gEfiUsbHcProtocolGuid,
&UsbHcProtocol,
gUsbBusDriverBinding.DriverBindingHandle,
UsbIoController->Handle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
}
return Status;
}
STATIC
EFI_STATUS
ParentPortReset (
IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
IN BOOLEAN ReConfigure,
IN UINT8 RetryTimes
)
/*++
Routine Description:
Reset parent hub port to which this device is connected.
Arguments:
UsbIoController - Indicating the Usb Controller Device.
ReConfigure - Do we need to reconfigure it.
RetryTimes - Retry Times when failed
Returns:
EFI_SUCCESS
EFI_DEVICE_ERROR
--*/
{
USB_IO_DEVICE *ParentIoDev;
USB_IO_DEVICE *UsbIoDev;
USB_IO_CONTROLLER_DEVICE *ParentController;
UINT8 HubPort;
UINT32 Status;
EFI_STATUS Result;
EFI_USB_IO_PROTOCOL *UsbIo;
UINT8 Address;
ParentController = UsbIoController->Parent;
ParentIoDev = ParentController->UsbDevice;
UsbIoDev = UsbIoController->UsbDevice;
HubPort = UsbIoController->ParentPort;
gBS->Stall (100 * 1000);
if (ParentIoDev->DeviceAddress == 1) {
DEBUG ((gUSBDebugLevel, "Reset from Root Hub 0x%x\n", HubPort));
ResetRootPort (ParentIoDev->BusController, HubPort, RetryTimes);
} else {
DEBUG ((gUSBDebugLevel, "Reset from Hub, Addr 0x%x\n", ParentIoDev->DeviceAddress));
ResetHubPort (ParentController, HubPort + 1);
}
//
// If we only need port reset, just return
//
if (!ReConfigure) {
return EFI_SUCCESS;
}
//
// Re-config that USB device
//
UsbIo = &UsbIoController->UsbIo;
//
// Assign a unique address to this device
//
Address = UsbIoDev->DeviceAddress;
UsbIoDev->DeviceAddress = 0;
Result = UsbSetDeviceAddress (UsbIo, Address, &Status);
UsbIoDev->DeviceAddress = Address;
if (EFI_ERROR (Result)) {
return EFI_DEVICE_ERROR;
}
//
// Set the device to the default configuration
//
Result = UsbSetDefaultConfiguration (UsbIoDev);
if (EFI_ERROR (Result)) {
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
UsbPortReset (
IN EFI_USB_IO_PROTOCOL *This
)
/*++
Routine Description:
Resets and reconfigures the USB controller. This function will
work for all USB devices except USB Hub Controllers.
Arguments:
This - Indicates the calling context.
Returns:
EFI_SUCCESS
EFI_INVALID_PARAMETER
EFI_DEVICE_ERROR
--*/
{
USB_IO_CONTROLLER_DEVICE *UsbIoController;
UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
if (IsHub (UsbIoController)) {
return EFI_INVALID_PARAMETER;
}
//
// Since at this time, this device has already been configured,
// it needs to be re-configured.
//
return ParentPortReset (UsbIoController, TRUE, 0);
}
EFI_STATUS
ResetRootPort (
IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,
IN UINT8 PortNum,
IN UINT8 RetryTimes
)
/*++
Routine Description:
Reset Root Hub port.
Arguments:
UsbBusDev - Bus controller of the device.
PortNum - The given port to be reset.
RetryTimes - RetryTimes when failed
Returns:
EFI_SUCCESS
EFI_DEVICE_ERROR
--*/
{
EFI_STATUS Status;
EFI_USB_PORT_STATUS PortStatus;
//
// reset root port
//
Status = UsbVirtualHcSetRootHubPortFeature (
UsbBusDev,
PortNum,
EfiUsbPortReset
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
gBS->Stall (50 * 1000);
//
// clear reset root port
//
Status = UsbVirtualHcClearRootHubPortFeature (
UsbBusDev,
PortNum,
EfiUsbPortReset
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
gBS->Stall (1000);
Status = UsbVirtualHcClearRootHubPortFeature (
UsbBusDev,
PortNum,
EfiUsbPortConnectChange
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
UsbVirtualHcGetRootHubPortStatus (
UsbBusDev,
PortNum,
&PortStatus
);
if (PortStatus.PortStatus & USB_PORT_STAT_OWNER) {
//
// Set port enable
//
Status = UsbVirtualHcSetRootHubPortFeature (
UsbBusDev,
PortNum,
EfiUsbPortEnable
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
Status = UsbVirtualHcClearRootHubPortFeature (
UsbBusDev,
PortNum,
EfiUsbPortEnableChange
);
}
gBS->Stall ((1 + RetryTimes) * 50 * 1000);
return EFI_SUCCESS;
}
EFI_STATUS
ResetHubPort (
IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
IN UINT8 PortIndex
)
/*++
Routine Description:
Reset Hub port.
Arguments:
UsbIoController - The USB_IO_CONTROLLER_DEVICE instance.
PortIndex - The given port to be reset.
Returns:
EFI_SUCCESS
EFI_DEVICE_ERROR
--*/
{
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_USB_PORT_STATUS HubPortStatus;
UINT8 Number;
ASSERT (UsbIoController->IsUsbHub == TRUE);
UsbIo = &UsbIoController->UsbIo;
HubSetPor
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?