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 + -
显示快捷键?