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