usbbus.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,516 行 · 第 1/5 页
C
2,516 行
// Delete & Submit this interrupt again
//
UsbIo->UsbAsyncInterruptTransfer (
UsbIo,
HubController->HubEndpointAddress,
FALSE,
0,
0,
NULL,
NULL
);
//
// try to detect if the hub itself was disconnected or not
//
Status = IsDeviceDisconnected (
HubController,
&Disconnected
);
if (!EFI_ERROR (Status) && Disconnected == TRUE) {
DEBUG ((gUSBErrorLevel, "Hub is disconnected\n"));
return EFI_DEVICE_ERROR;
}
//
// Hub ports < 7
//
UsbIo->UsbAsyncInterruptTransfer (
UsbIo,
HubController->HubEndpointAddress,
TRUE,
100,
1,
OnHubInterruptComplete,
HubController
);
return EFI_DEVICE_ERROR;
}
if (DataLength == 0 || Data == NULL) {
return EFI_SUCCESS;
}
//
// Scan which port has status change
// Bit 0 stands for hub itself, other bit stands for
// the corresponding port
//
for (Index = 0; Index < DataLength * 8; Index++) {
ptr = (UINT8 *) Data + Index / 8;
if ((*ptr) & (1 << (Index & 0x7))) {
HubController->StatusChangePort = Index;
break;
}
}
//
// Signal hub notify event
//
gBS->SignalEvent (HubController->HubNotify);
return EFI_SUCCESS;
}
//
// USB Root Hub Enumerator
//
STATIC
VOID
EFIAPI
RootHubEnumeration (
IN EFI_EVENT Event,
IN VOID *Context
)
/*++
Routine Description:
This is USB RootHub enumerator
Arguments:
Event - Indicating which event is signaled
Context - actually it is a USB_IO_DEVICE
Returns:
VOID
--*/
{
USB_IO_CONTROLLER_DEVICE *HubController;
EFI_USB_PORT_STATUS HubPortStatus;
EFI_STATUS Status;
UINT8 Index;
USB_IO_DEVICE *UsbIoDev;
USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
EFI_HANDLE HostController;
USB_IO_DEVICE *OldUsbIoDevice;
USB_IO_DEVICE *NewDevice;
USB_IO_CONTROLLER_DEVICE *NewController;
UINT8 Index2;
EFI_USB_IO_PROTOCOL *UsbIo;
HubController = (USB_IO_CONTROLLER_DEVICE *) Context;
HostController = HubController->HostController;
UsbBusDev = HubController->UsbDevice->BusController;
//
// Root hub has the address 1
//
UsbIoDev = HubController->UsbDevice;
for (Index = 0; Index < HubController->DownstreamPorts; Index++) {
UsbVirtualHcGetRootHubPortStatus (
UsbBusDev,
Index,
(EFI_USB_PORT_STATUS *) &HubPortStatus
);
if (!IsPortConnectChange (HubPortStatus.PortChangeStatus)) {
continue;
}
//
// Clear root hub status change status
//
UsbVirtualHcClearRootHubPortFeature (
UsbBusDev,
Index,
EfiUsbPortConnectChange
);
gBS->Stall (100 * 1000);
UsbVirtualHcGetRootHubPortStatus (
UsbBusDev,
Index,
(EFI_USB_PORT_STATUS *) &HubPortStatus
);
if (IsPortConnect (HubPortStatus.PortStatus)) {
//
// There is something connected to this port
//
DEBUG ((gUSBDebugLevel, "Something connected to Root Hub at Port0x%x\n", Index));
ReportUsbStatusCode (
UsbBusDev,
EFI_PROGRESS_CODE,
EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG
);
//
// if there is something physically detached, but still logically
// attached...
//
OldUsbIoDevice = HubController->Children[Index];
if (NULL != OldUsbIoDevice) {
UsbDeviceDeConfiguration (OldUsbIoDevice);
HubController->Children[Index] = NULL;
}
NewDevice = EfiLibAllocateZeroPool (sizeof (USB_IO_DEVICE));
if (NewDevice == NULL) {
return ;
}
//
// Initialize some fields by copying data from
// its parents
//
NewDevice->DeviceDescriptor.MaxPacketSize0 = 8;
NewDevice->BusController = UsbIoDev->BusController;
//
// Process of identify device speed
//
Status = IdentifyDeviceSpeed (
UsbBusDev,
NewDevice,
Index
);
if (EFI_ERROR (Status)) {
gBS->FreePool (NewDevice);
continue;
}
//
// Configure that device
//
Status = UsbDeviceConfiguration (
HubController,
HostController,
Index,
NewDevice
);
if (EFI_ERROR (Status)) {
gBS->FreePool (NewDevice);
return ;
}
//
// Add this device to the usb bus tree
//
HubController->Children[Index] = NewDevice;
for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {
//
// If this device is hub, add to the hub index
//
NewController = NewDevice->UsbController[Index2];
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 (IsHub (NewController)) {
NewController->IsUsbHub = TRUE;
//
// Configure Hub Controller
//
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
// Hub ports < 7
//
UsbIo = &NewController->UsbIo;
UsbIo->UsbAsyncInterruptTransfer (
UsbIo,
NewController->HubEndpointAddress,
TRUE,
100,
1,
OnHubInterruptComplete,
NewController
);
}
}
} else {
//
// Something disconnected from USB root hub
//
DEBUG ((gUSBDebugLevel, "Something disconnected from Root Hub at Port0x%x\n", Index));
OldUsbIoDevice = HubController->Children[Index];
UsbDeviceDeConfiguration (OldUsbIoDevice);
HubController->Children[Index] = NULL;
UsbVirtualHcClearRootHubPortFeature (
UsbBusDev,
Index,
EfiUsbPortEnableChange
);
}
}
return ;
}
//
// USB Root Hub Enumerator
//
STATIC
VOID
EFIAPI
HubEnumeration (
IN EFI_EVENT Event,
IN VOID *Context
)
/*++
Routine Description:
This is Usb Hub enumerator
Arguments:
Event - Indicating which event is signaled
Context - actually it is a USB_IO_DEVICE
Returns:
VOID
--*/
{
USB_IO_CONTROLLER_DEVICE *HubController;
EFI_USB_PORT_STATUS HubPortStatus;
EFI_STATUS Status;
USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
EFI_HANDLE HostController;
USB_IO_DEVICE *OldUsbIoDevice;
USB_IO_DEVICE *NewDevice;
USB_IO_CONTROLLER_DEVICE *NewController;
UINT8 Index2;
EFI_USB_IO_PROTOCOL *UsbIo;
UINT8 StatusChangePort;
UINT8 Number;
HubController = (USB_IO_CONTROLLER_DEVICE *) Context;
HostController = HubController->HostController;
UsbBusDev = HubController->UsbDevice->BusController;
//
// Event from Hub, Get the hub controller handle
//
//
// Get the status change endpoint
//
StatusChangePort = HubController->StatusChangePort;
//
// Clear HubController Status Change Bit
//
HubController->StatusChangePort = 0;
if (StatusChangePort == 0) {
//
// Hub changes, we don't handle here
//
return ;
}
//
// Check which event took place at that port
//
UsbIo = &HubController->UsbIo;
Status = HubGetPortStatus (
UsbIo,
StatusChangePort,
(UINT32 *) &HubPortStatus
);
if (EFI_ERROR (Status)) {
return ;
}
//
// Clear some change status
//
if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) {
//
// Clear Hub port enable change
//
DEBUG ((gUSBDebugLevel, "Port Enable Change\n"));
HubClearPortFeature (
UsbIo,
StatusChangePort,
EfiUsbPortEnableChange
);
HubGetPortStatus (
UsbIo,
StatusChangePort,
(UINT32 *) &HubPortStatus
);
}
if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) {
//
// Clear Hub reset change
//
DEBUG ((gUSBDebugLevel, "Port Reset Change\n"));
HubClearPortFeature (
UsbIo,
StatusChangePort,
EfiUsbPortResetChange
);
HubGetPortStatus (
UsbIo,
StatusChangePort,
(UINT32 *) &HubPortStatus
);
}
if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_OVERCURRENT) {
//
// Clear Hub overcurrent change
//
DEBUG ((gUSBDebugLevel, "Port Overcurrent Change\n"));
HubClearPortFeature (
UsbIo,
StatusChangePort,
EfiUsbPortOverCurrentChange
);
HubGetPortStatus (
UsbIo,
StatusChangePort,
(UINT32 *) &HubPortStatus
);
}
if (IsPortConnectChange (HubPortStatus.PortChangeStatus)) {
//
// First clear port connection change
//
DEBUG ((gUSBDebugLevel, "Port Connection Change\n"));
HubClearPortFeature (
UsbIo,
StatusChangePort,
EfiUsbPortConnectChange
);
HubGetPortStatus (
UsbIo,
StatusChangePort,
(UINT32 *) &HubPortStatus
);
if (IsPortConnect (HubPortStatus.PortStatus)) {
DEBUG ((gUSBDebugLevel, "New Device Connect on Hub port \n"));
ReportUsbStatusCode (
UsbBusDev,
EFI_PROGRESS_CODE,
EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG
);
//
// if there is something physically detached, but still logically
// attached...
//
OldUsbIoDevice = HubController->Children[StatusChangePort - 1];
if (NULL != OldUsbIoDevice) {
UsbDeviceDeConfiguration (OldUsbIoDevice);
HubController->Children[StatusChangePort - 1] = NULL;
}
NewDevice = EfiLibAllocateZeroPool (sizeof (USB_IO_DEVICE));
if (NewDevice == NULL) {
return ;
}
//
// Initialize some fields
//
NewDevice->DeviceDescriptor.MaxPacketSize0 = 8;
NewDevice->BusController = HubController->UsbDevice->BusController;
//
// There is something connected to this port,
// reset that port
//
// Disable the enable bit in port status
//
HubClearPortFeature (
UsbIo,
StatusChangePort,
EfiUsbPortEnable
);
gBS->Stall (50 * 1000);
//
// Wait for bit change
//
Number = 10;
do {
HubGetPortStatus (
UsbIo,
StatusChangePort,
(UINT32 *) &HubPortStatus
);
gBS->Stall (10 * 1000);
Number -= 1;
} while ((HubPortStatus.PortStatus & USB_PORT_STAT_ENABLE) == 1 && Number > 0);
if (Number == 0) {
//
// Cannot disable port, return error
//
DEBUG ((gUSBErrorLevel, "Disable Port Failed\n"));
gBS->FreePool (NewDevice);
return ;
}
HubSetPortFeature (
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?