⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbbus.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 4 页
字号:
    // Check if it is a hub, if so, de configuration all its
    // downstream ports
    //
    UsbController = UsbIoDevice->UsbController[index];

    //
    // Check the controller pointer
    //
    if (UsbController == NULL) {
      continue;
    }

    if (UsbController->IsUsbHub) {       

       DEBUG ((EFI_D_USB, "Hub Deconfig, First Deconfig its downstream ports\n"));

       //
       // First Remove interrupt transfer request for the status
       // change port
       //
       UsbIo = &UsbController->UsbIo;
       UsbIo->UsbAsyncInterruptTransfer(
                UsbIo,
                UsbController->HubEndpointAddress,
                FALSE,
                0,
                0,
                NULL,
                NULL
              );
       
       if (NULL != UsbController->HubNotify) {
         gBS->CloseEvent (UsbController->HubNotify);
       }

       for (i = 0; i < UsbController->DownstreamPorts; i++) {
         if (UsbController->Children[i]) {
           ChildDevice = UsbController->Children[i];
           UsbDeviceDeConfiguration(ChildDevice);
           UsbController->Children[i] = NULL;
         }
       }
    }

    //
    // If the controller is managed by a device driver, we need to
    // disconnect them
    //
    if (UsbController->IsManagedByDriver) {
       gBS->DisconnectController(
              UsbController->Handle,
              NULL,
              NULL
            );
    }
    
    //
    // remove child handle reference to the USB_HC_PROTOCOL
    //
    gBS->CloseProtocol(
          UsbController->HostController,
          &gEfiUsbHcProtocolGuid,
          gUsbBusDriverBinding.DriverBindingHandle,
          UsbController->Handle
         );

    //
    // Uninstall EFI_USB_IO_PROTOCOL & DEVICE_PATH_PROTOCOL
    // installed on this handle
    //
    gBS->UninstallMultipleProtocolInterfaces(
           UsbController->Handle,
           &gEfiDevicePathProtocolGuid,
           UsbController->DevicePath,
           &gEfiUsbIoProtocolGuid,
           &UsbController->UsbIo,
           NULL
         );    

    gBS->FreePool(UsbController);
    UsbIoDevice->UsbController[index] = NULL;
  }

  //
  // Free address for later use
  //
  UsbFreeAddress(
    UsbIoDevice->DeviceAddress,
    UsbIoDevice->BusController->AddressPool
  );

  //
  // Free all resouces allocated for all its configurations
  //
  UsbDestroyAllConfiguration(UsbIoDevice);

  if (UsbIoDevice) {
    gBS->FreePool(UsbIoDevice);
    UsbIoDevice = NULL;
  }

  return EFI_SUCCESS;
}

//
// After interrupt complete, this function will be called,
// This function need to be well-defined later
//
STATIC EFI_STATUS
OnHubInterruptComplete (
  IN  VOID          *Data,
  IN  UINTN         DataLength,
  IN  VOID          *Context,
  IN  UINT32        Result
  )
/*++

  Routine Description:
    Whenever hub interrupt occurs, this routine will be called to check
    which event happens.

  Parameter:
    Data          -   Hub interrupt transfer data.
    DataLength    -   The length of the Data.
    Context       -   Hub Controller Device.
    Result        -   Hub interrupt transfer status.

  Return Value:
    EFI_SUCCESS
    EFI_DEVICE_ERROR

--*/
{
  USB_IO_CONTROLLER_DEVICE    *HubController;
  UINT8                       i;
  UINT8                       *ptr;
  EFI_USB_IO_PROTOCOL         *UsbIo;
  UINT32                      UsbResult;
  
  HubController = (USB_IO_CONTROLLER_DEVICE *)Context;
  UsbIo = &HubController->UsbIo;
  
  //
  // If something error in this interrupt transfer,
  //
  if (Result != EFI_USB_NOERROR) {
    if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
      UsbClearEndpointHalt(
        UsbIo,
        HubController->HubEndpointAddress,
        &UsbResult
      );      
    }
    
    //
    // Delete & Submit this interrupt again
    //
    UsbIo->UsbAsyncInterruptTransfer(
             UsbIo,
             HubController->HubEndpointAddress,
             FALSE,
             0,
             0,
             NULL,
             NULL
           );
           
    UsbIo->UsbAsyncInterruptTransfer(
             UsbIo,
             HubController->HubEndpointAddress,
             TRUE,
             100,
             1,  //Hub ports < 7
             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 (i = 0; i < DataLength * 8; i++) {
    ptr = (UINT8 *)Data + i /8;
    if ((*ptr) & (1 << (i % 8))) {
      HubController->StatusChangePort = i;
      break;
    }
  }

  //
  //Signal hub notify event
  //
  gBS->SignalEvent (HubController->HubNotify);

  return EFI_SUCCESS;
}

//
// USB Root Hub Enumerator
//
STATIC
VOID
UsbEnumeration (
  IN EFI_EVENT    Event,
  IN VOID         *Context
  )
/*++

  Routine Description:
    This is USB enumerator

  Arguments:
    Event:   Indicating which event is signaled
    Context: actually it is a USB_IO_DEVICE

  Returns:
    EFI_SUCCESS
    Others

--*/
{
  USB_IO_CONTROLLER_DEVICE            *HubController;
  EFI_USB_PORT_STATUS                 HubPortStatus;
  EFI_STATUS                          Status;
  UINT8                               i;
  EFI_USB_HC_PROTOCOL                 *UsbHCInterface;
  USB_IO_DEVICE                       *UsbIoDev;
  EFI_HANDLE                          HostController;
  USB_IO_DEVICE                       *OldUsbIoDevice;
  USB_IO_DEVICE                       *NewDevice;
  USB_IO_CONTROLLER_DEVICE            *NewController;
  UINT8                               j;
  UINT8                               n;
  EFI_USB_IO_PROTOCOL                 *UsbIo;
  UINT8                               StatusChangePort;
  
  HubController = (USB_IO_CONTROLLER_DEVICE *)Context;
  HostController = HubController->HostController;
  
  if (HubController->UsbDevice->DeviceAddress == 1) {
    //
    // Root hub has the address 1
    //
    UsbIoDev = HubController->UsbDevice;
    UsbHCInterface = UsbIoDev->BusController->UsbHCInterface;

    for (i = 0; i < HubController->DownstreamPorts; i++) {
      UsbHCInterface->GetRootHubPortStatus (
                        UsbHCInterface,
                        i,
                        (EFI_USB_PORT_STATUS *)&HubPortStatus
                       );

      if (!IsPortConnectChange(HubPortStatus.PortChangeStatus)) {
        continue;
      }

      //
      //Clear root hub status change status
      //
      ClearRootPortConnectionChangeStatus(
        i,
        UsbHCInterface
      );

      UsbHCInterface->GetRootHubPortStatus (
                        UsbHCInterface,
                        i,
                        (EFI_USB_PORT_STATUS *)&HubPortStatus
                       );

      if (IsPortConnect(HubPortStatus.PortStatus)) {
        
        //
        // There is something connected to this port
        //
        DEBUG ((EFI_D_USB, "Something attached from Root Hub\n"));
        
        //
        // if there is something physically detached, but still logically 
        // attached...
        //
        OldUsbIoDevice = HubController->Children[i];

        if (NULL != OldUsbIoDevice) {
          UsbDeviceDeConfiguration(OldUsbIoDevice);
          HubController->Children[i] = NULL;
        }
        
        //
        // Reset the port.
        //
        ResetRootPort(
          i,
          UsbHCInterface
        );

        UsbHCInterface->GetRootHubPortStatus (
                          UsbHCInterface,
                          i,
                          (EFI_USB_PORT_STATUS *)&HubPortStatus
                         );
                         
        NewDevice = NULL;
        Status = gBS->AllocatePool(
                        EfiBootServicesData,
                        sizeof(USB_IO_DEVICE),
                        (VOID **)&NewDevice
                      );

        if (EFI_ERROR(Status)) {
           return;
        }

        EfiZeroMem(NewDevice, sizeof(USB_IO_DEVICE));

        //
        // Initialize some fields by copying data from
        // its parents
        //
        NewDevice->IsSlowDevice = \
             IsPortLowSpeedDeviceAttached (HubPortStatus.PortStatus);

        NewDevice->DeviceDescriptor.MaxPacketSize0 = 8;

        NewDevice->BusController = UsbIoDev->BusController;

        //
        // Configure that device
        //
        Status = UsbDeviceConfiguration(
                   HubController,
                   HostController,
                   i,
                   NewDevice
                  );
        if (EFI_ERROR (Status)) {
          gBS->FreePool (NewDevice);
          return;
        }

        //
        // Add this device to the usb bus tree
        //
        HubController->Children[i] = NewDevice;

        for (j = 0; j < NewDevice->NumOfControllers; j++) {
          //
          // If this device is hub, add to the hub index
          //
          NewController = NewDevice->UsbController[j];

          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,
                   UsbEnumeration,
                   NewController,
                   &NewController->HubNotify
                 );

             //
             // Add request to do query hub status
             // change endpoint
             //
             UsbIo = &NewController->UsbIo;
             UsbIo->UsbAsyncInterruptTransfer(
                       UsbIo,
                       NewController->HubEndpointAddress,
                       TRUE,
                       100,
                       1,  //Hub ports < 7
                       OnHubInterruptComplete,
                       NewController
                    );

          }
        }
      } else {
        //
        // Something disconnected from USB root hub
        //
        
        DEBUG ((EFI_D_USB, "Something deteached from Root Hub\n"));
        
        OldUsbIoDevice = HubController->Children[i];

        UsbDeviceDeConfiguration(OldUsbIoDevice);

        HubController->Children[i] = NULL;

        UsbHCInterface->ClearRootHubPortFeature(
                          UsbHCInterface,
                          i,
                          EfiUsbPortEnableChange
                        );

        UsbHCInterface->GetRootHubPortStatus (
                          UsbHCInterface,
                          i,
                          (EFI_USB_PORT_STATUS *)&HubPortStatus
                         );
                        
      }
    }
    return;
  } else {
    //
    // 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 ((EFI_D_USB, "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 ((EFI_D_USB, "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 ((EFI_D_USB, "Port Overcurrent Change\n"));
      HubClearPortFeature(
        UsbIo,
        StatusChangePort,
        EfiUsbPortOverCurrentChange
      );

      HubGetPortStatus(
        UsbIo,
        StatusChangePort,
        (UINT32 *)&HubPortStatus
      );
    }

    if (IsPortConnectChange(HubPortStatus.PortChangeStatus)) {
      //
      // First clear port connection change
      //
      DEBUG ((EFI_D_USB, "Port Connection Change\n"));
      HubClearPortFeature(
        UsbIo,
        StatusChangePort,
        EfiUsbPortConnectChange
      );

      HubGetPortStatus(
        UsbIo,
        StatusChangePort,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -