usbbus.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,516 行 · 第 1/5 页
C
2,516 行
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (OpenStatus)) {
UsbBusDev->Hc2ProtocolSupported = FALSE;
OpenStatus = gBS->OpenProtocol (
Controller,
&gEfiUsbHcProtocolGuid,
(VOID **) &(UsbBusDev->UsbHCInterface),
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (OpenStatus)) {
//
// Report Status Code here since we will reset the host controller
//
ReportStatusCodeWithDevicePath (
EFI_ERROR_CODE | EFI_ERROR_MINOR,
EFI_IO_BUS_USB | EFI_IOB_EC_CONTROLLER_ERROR,
0,
&gUSBBusDriverGuid,
UsbBusDev->DevicePath
);
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
This->DriverBindingHandle,
Controller
);
gBS->FreePool (UsbBusDev);
return OpenStatus;
}
DEBUG ((gUSBDebugLevel, "UsbHcProtocol Opened.\n"));
} else {
DEBUG ((gUSBDebugLevel, "Usb2HcProtocol Opened.\n"));
UsbBusDev->Hc2ProtocolSupported = TRUE;
}
//
// Attach EFI_USB_BUS_PROTOCOL to controller handle,
// for locate UsbBusDev later
//
Status = gBS->InstallProtocolInterface (
&Controller,
&mUsbBusProtocolGuid,
EFI_NATIVE_INTERFACE,
&UsbBusDev->BusIdentify
);
if (EFI_ERROR (Status)) {
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
This->DriverBindingHandle,
Controller
);
if (UsbBusDev->Hc2ProtocolSupported) {
gBS->CloseProtocol (
Controller,
&gEfiUsb2HcProtocolGuid,
This->DriverBindingHandle,
Controller
);
} else {
gBS->CloseProtocol (
Controller,
&gEfiUsbHcProtocolGuid,
This->DriverBindingHandle,
Controller
);
}
gBS->FreePool (UsbBusDev);
return Status;
}
//
// Add root hub to the tree
//
RootHub = NULL;
RootHub = EfiLibAllocateZeroPool (sizeof (USB_IO_DEVICE));
if (RootHub == NULL) {
gBS->UninstallProtocolInterface (
Controller,
&mUsbBusProtocolGuid,
&UsbBusDev->BusIdentify
);
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
This->DriverBindingHandle,
Controller
);
if (UsbBusDev->Hc2ProtocolSupported) {
gBS->CloseProtocol (
Controller,
&gEfiUsb2HcProtocolGuid,
This->DriverBindingHandle,
Controller
);
} else {
gBS->CloseProtocol (
Controller,
&gEfiUsbHcProtocolGuid,
This->DriverBindingHandle,
Controller
);
}
gBS->FreePool (UsbBusDev);
return EFI_OUT_OF_RESOURCES;
}
RootHub->BusController = UsbBusDev;
RootHub->DeviceAddress = UsbAllocateAddress (UsbBusDev->AddressPool);
UsbBusDev->Root = RootHub;
//
// Allocate Root Hub Controller
//
RootHubController = CreateUsbIoControllerDevice ();
if (RootHubController == NULL) {
gBS->UninstallProtocolInterface (
Controller,
&mUsbBusProtocolGuid,
&UsbBusDev->BusIdentify
);
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
This->DriverBindingHandle,
Controller
);
if (UsbBusDev->Hc2ProtocolSupported) {
gBS->CloseProtocol (
Controller,
&gEfiUsb2HcProtocolGuid,
This->DriverBindingHandle,
Controller
);
} else {
gBS->CloseProtocol (
Controller,
&gEfiUsbHcProtocolGuid,
This->DriverBindingHandle,
Controller
);
}
gBS->FreePool (UsbBusDev);
gBS->FreePool (RootHub);
return EFI_OUT_OF_RESOURCES;
}
UsbVirtualHcGetCapability (
UsbBusDev,
&MaxSpeed,
&PortNumber,
&Is64BitCapable
);
RootHubController->DownstreamPorts = PortNumber;
RootHubController->UsbDevice = RootHub;
RootHubController->IsUsbHub = TRUE;
RootHubController->DevicePath = UsbBusDev->DevicePath;
RootHubController->HostController = Controller;
RootHub->NumOfControllers = 1;
RootHub->UsbController[0] = RootHubController;
RootHub->DeviceSpeed = MaxSpeed;
//
// Report Status Code here since we will reset the host controller
//
ReportStatusCodeWithDevicePath (
EFI_PROGRESS_CODE,
EFI_IO_BUS_USB | EFI_IOB_PC_RESET,
0,
&gUSBBusDriverGuid,
UsbBusDev->DevicePath
);
//
// Reset USB Host Controller
//
UsbVirtualHcReset (
UsbBusDev,
EFI_USB_HC_RESET_GLOBAL
);
//
// Report Status Code while we are going to bring up the Host Controller
// and start bus enumeration
//
ReportStatusCodeWithDevicePath (
EFI_PROGRESS_CODE,
EFI_IO_BUS_USB | EFI_IOB_PC_ENABLE,
0,
&gUSBBusDriverGuid,
UsbBusDev->DevicePath
);
//
// Start USB Host Controller
//
UsbVirtualHcSetState (
UsbBusDev,
EfiUsbHcStateOperational
);
//
// Create a timer to query root ports periodically
//
Status = gBS->CreateEvent (
EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
EFI_TPL_CALLBACK,
RootHubEnumeration,
RootHubController,
&RootHubController->HubNotify
);
if (EFI_ERROR (Status)) {
gBS->UninstallProtocolInterface (
Controller,
&mUsbBusProtocolGuid,
&UsbBusDev->BusIdentify
);
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
This->DriverBindingHandle,
Controller
);
if (UsbBusDev->Hc2ProtocolSupported) {
gBS->CloseProtocol (
Controller,
&gEfiUsb2HcProtocolGuid,
This->DriverBindingHandle,
Controller
);
} else {
gBS->CloseProtocol (
Controller,
&gEfiUsbHcProtocolGuid,
This->DriverBindingHandle,
Controller
);
}
gBS->FreePool (RootHubController);
gBS->FreePool (RootHub);
gBS->FreePool (UsbBusDev);
return EFI_OUT_OF_RESOURCES;
}
//
// Before depending on the timer to check root ports periodically,
// here we should check them immediately for the first time, or
// there will be an interval between bus start and devices start.
//
gBS->SignalEvent (RootHubController->HubNotify);
Status = gBS->SetTimer (
RootHubController->HubNotify,
TimerPeriodic,
BUSPOLLING_PERIOD
);
if (EFI_ERROR (Status)) {
gBS->UninstallProtocolInterface (
Controller,
&mUsbBusProtocolGuid,
&UsbBusDev->BusIdentify
);
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
This->DriverBindingHandle,
Controller
);
if (UsbBusDev->Hc2ProtocolSupported) {
gBS->CloseProtocol (
Controller,
&gEfiUsb2HcProtocolGuid,
This->DriverBindingHandle,
Controller
);
} else {
gBS->CloseProtocol (
Controller,
&gEfiUsbHcProtocolGuid,
This->DriverBindingHandle,
Controller
);
}
gBS->CloseEvent (RootHubController->HubNotify);
gBS->FreePool (RootHubController);
gBS->FreePool (RootHub);
gBS->FreePool (UsbBusDev);
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
//
// Stop the bus controller
//
EFI_STATUS
EFIAPI
UsbBusControllerDriverStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
/*++
Routine Description:
Stop this driver on ControllerHandle. Support stoping any child handles
created by this driver.
Arguments:
This - Protocol instance pointer.
Controller - Handle of device to stop driver on
NumberOfChildren - Number of Children in the ChildHandleBuffer
ChildHandleBuffer - List of handles for the children we need to stop.
Returns:
EFI_SUCCESS
EFI_DEVICE_ERROR
others
--*/
{
EFI_STATUS Status;
USB_IO_DEVICE *Root;
USB_IO_CONTROLLER_DEVICE *RootHubController;
USB_BUS_CONTROLLER_DEVICE *UsbBusController;
EFI_USB_BUS_PROTOCOL *UsbIdentifier;
UINT8 Index2;
USB_IO_CONTROLLER_DEVICE *UsbController;
USB_IO_DEVICE *UsbIoDevice;
USB_IO_CONTROLLER_DEVICE *HubController;
UINTN Index;
EFI_USB_IO_PROTOCOL *UsbIo;
if (NumberOfChildren > 0) {
for (Index = 0; Index < NumberOfChildren; Index++) {
Status = gBS->OpenProtocol (
ChildHandleBuffer[Index],
&gEfiUsbIoProtocolGuid,
(VOID **) &UsbIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
//
// We are here since the handle passed in does not support
// UsbIo protocol. There are several reasons that will cause
// this.
// For combo device such as keyboard, it may have 2 devices
// in one, namely, keyboard and mouse. If we deconfigure one
// of them, the other will be freed at the same time. This will
// cause the status error. But this is the correct behavior.
// For hub device, if we deconfigure hub first, the other chile
// device will be disconnected also, this will also provide us
// a status error. Now we will only report EFI_SUCCESS since Uhc
// driver will be disconnected at the second time.(pls see
// CoreDisconnectController for details)
//
continue;
}
UsbController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (UsbIo);
UsbIoDevice = UsbController->UsbDevice;
HubController = UsbController->Parent;
UsbDeviceDeConfiguration (UsbIoDevice);
for (Index2 = 0; Index2 < HubController->DownstreamPorts; Index2++) {
if (HubController->Children[Index2] == UsbIoDevice) {
HubController->Children[Index2] = NULL;
}
}
}
return EFI_SUCCESS;
}
//
// Get the USB_BUS_CONTROLLER_DEVICE
//
Status = gBS->OpenProtocol (
Controller,
&mUsbBusProtocolGuid,
(VOID **) &UsbIdentifier,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
UsbBusController = USB_BUS_CONTROLLER_DEVICE_FROM_THIS (UsbIdentifier);
//
// Stop USB Host Controller
//
// Report Status Code here since we will reset the host controller
//
ReportUsbStatusCode (
UsbBusController,
EFI_PROGRESS_CODE,
EFI_IO_BUS_USB | EFI_IOB_PC_RESET
);
UsbVirtualHcSetState (
UsbBusController,
EfiUsbHcStateHalt
);
//
// Deconfiguration all its devices
//
Root = UsbBusController->Root;
RootHubController = Root->UsbController[0];
gBS->CloseEvent (RootHubController->HubNotify);
for (Index2 = 0; Index2 < RootHubController->DownstreamPorts; Index2++) {
if (RootHubController->Children[Index2]) {
UsbDeviceDeConfiguration (RootHubController->Children[Index2]);
RootHubController->Children[Index2] = NULL;
}
}
gBS->FreePool (RootHubController);
gBS->FreePool (Root);
//
// Uninstall USB Bus Protocol
//
gBS->UninstallProtocolInterface (
Controller,
&mUsbBusProtocolGuid,
&UsbBusController->BusIdentify
);
//
// Close USB_HC_PROTOCOL & DEVICE_PATH_PROTOCOL
// Opened by this Controller
//
if (UsbBusController->Hc2ProtocolSupported) {
gBS->CloseProtocol (
Controller,
&gEfiUsb2HcProtocolGuid,
This->DriverBindingHandle,
Controller
);
} else {
gBS->CloseProtocol (
Controller,
&gEfiUsbHcProtocolGuid,
This->DriverBindingHandle,
Controller
);
}
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
This->DriverBindingHandle,
Controller
);
gBS->FreePool (UsbBusController);
return EFI_SUCCESS;
}
//
// USB Device Configuration
//
STATIC
EFI_STATUS
UsbDeviceConfiguration (
IN USB_IO_CONTROLLER_DEVICE *ParentHubController,
IN EFI_HANDLE HostController,
IN UINT8 ParentPort,
IN USB_IO_DEVICE *UsbIoDevice
)
/*++
Routine Description:
Configurate a new device attached to the usb bus
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?