VOID EFIAPI UsbHubEnumeration ( IN EFI_EVENT Event, IN VOID *Context ) /*++ Routine Description: Enumerate all the changed hub ports Arguments: Event - The event that is triggered Context - The context to the event Returns: None --*/ { USB_INTERFACE *HubIf; UINT8 Byte; UINT8 Bit; UINT8 Index; ASSERT (Context); HubIf = (USB_INTERFACE *) Context; if (HubIf->ChangeMap == NULL) { return ; } // // HUB starts its port index with 1. // Byte = 0; Bit = 1; for (Index = 0; Index < HubIf->NumOfPort; Index++) { if (USB_BIT_IS_SET (HubIf->ChangeMap[Byte], USB_BIT (Bit))) { UsbEnumeratePort (HubIf, Index); } USB_NEXT_BIT (Byte, Bit); } UsbHubAckHubStatus (HubIf->Device); gBS->FreePool (HubIf->ChangeMap); HubIf->ChangeMap = NULL; return ; }
/** Enumerate all the changed hub ports. @param Event The event that is triggered. @param Context The context to the event. **/ VOID EFIAPI UsbHubEnumeration ( IN EFI_EVENT Event, IN VOID *Context ) { USB_INTERFACE *HubIf; UINT8 Byte; UINT8 Bit; UINT8 Index; USB_DEVICE *Child; // ASSERT (Context != NULL); if (!Context) { return; } HubIf = (USB_INTERFACE *) Context; for (Index = 0; Index < HubIf->NumOfPort; Index++) { Child = UsbFindChild (HubIf, Index); if ((Child != NULL) && (Child->DisconnectFail == TRUE)) { // DEBUG (( EFI_D_INFO, "UsbEnumeratePort: The device disconnect fails at port %d from hub %p, try again\n", Index, HubIf)); DBG("UsbEnumeratePort: The device disconnect fails at port %d from hub %p, try again\n", Index, HubIf); UsbRemoveDevice (Child); } } if (HubIf->ChangeMap == NULL) { return ; } // // HUB starts its port index with 1. // Byte = 0; Bit = 1; DBG("Enumerate %d ports\n", HubIf->NumOfPort); for (Index = 0; Index < HubIf->NumOfPort; Index++) { if (USB_BIT_IS_SET (HubIf->ChangeMap[Byte], USB_BIT (Bit))) { UsbEnumeratePort (HubIf, Index); DBG("Port %d enumerated\n", Index); } USB_NEXT_BIT (Byte, Bit); } UsbHubAckHubStatus (HubIf->Device); gBS->FreePool (HubIf->ChangeMap); HubIf->ChangeMap = NULL; return ; }
/** Enumerate all the changed hub ports. @param Event The event that is triggered. @param Context The context to the event. **/ VOID EFIAPI UsbHubEnumeration ( IN EFI_EVENT Event, IN VOID *Context ) { USB_INTERFACE *HubIf; UINT8 Byte; UINT8 Bit; UINT8 Index; ASSERT (Context != NULL); HubIf = (USB_INTERFACE *) Context; if (HubIf->ChangeMap == NULL) { return ; } // // HUB starts its port index with 1. // Byte = 0; Bit = 1; for (Index = 0; Index < HubIf->NumOfPort; Index++) { if (USB_BIT_IS_SET (HubIf->ChangeMap[Byte], USB_BIT (Bit))) { UsbEnumeratePort (HubIf, Index); } USB_NEXT_BIT (Byte, Bit); } UsbHubAckHubStatus (HubIf->Device); gBS->FreePool (HubIf->ChangeMap); HubIf->ChangeMap = NULL; return ; }
/** Initialize the device for a non-root hub. @param HubIf The USB hub interface. @retval EFI_SUCCESS The hub is initialized. @retval EFI_DEVICE_ERROR Failed to initialize the hub. **/ EFI_STATUS UsbHubInit ( IN USB_INTERFACE *HubIf ) { EFI_USB_HUB_DESCRIPTOR HubDesc; USB_ENDPOINT_DESC *EpDesc; USB_INTERFACE_SETTING *Setting; EFI_USB_IO_PROTOCOL *UsbIo; USB_DEVICE *HubDev; EFI_STATUS Status; UINT8 Index; UINT8 NumEndpoints; // // Locate the interrupt endpoint for port change map // HubIf->IsHub = FALSE; Setting = HubIf->IfSetting; HubDev = HubIf->Device; EpDesc = NULL; NumEndpoints = Setting->Desc.NumEndpoints; for (Index = 0; Index < NumEndpoints; Index++) { ASSERT ((Setting->Endpoints != NULL) && (Setting->Endpoints[Index] != NULL)); EpDesc = Setting->Endpoints[Index]; if (USB_BIT_IS_SET (EpDesc->Desc.EndpointAddress, USB_ENDPOINT_DIR_IN) && (USB_ENDPOINT_TYPE (&EpDesc->Desc) == USB_ENDPOINT_INTERRUPT)) { break; } } if (Index == NumEndpoints) { DEBUG (( EFI_D_ERROR, "UsbHubInit: no interrupt endpoint found for hub %d\n", HubDev->Address)); return EFI_DEVICE_ERROR; } Status = UsbHubReadDesc (HubDev, &HubDesc); if (EFI_ERROR (Status)) { DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to read HUB descriptor %r\n", Status)); return Status; } HubIf->NumOfPort = HubDesc.NumPorts; DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d has %d ports\n", HubDev->Address,HubIf->NumOfPort)); // // Create an event to enumerate the hub's port. On // Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_CALLBACK, UsbHubEnumeration, HubIf, &HubIf->HubNotify ); if (EFI_ERROR (Status)) { DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to create signal for hub %d - %r\n", HubDev->Address, Status)); return Status; } // // Create AsyncInterrupt to query hub port change endpoint // periodically. If the hub ports are changed, hub will return // changed port map from the interrupt endpoint. The port map // must be able to hold (HubIf->NumOfPort + 1) bits (one bit for // host change status). // UsbIo = &HubIf->UsbIo; Status = UsbIo->UsbAsyncInterruptTransfer ( UsbIo, EpDesc->Desc.EndpointAddress, TRUE, USB_HUB_POLL_INTERVAL, HubIf->NumOfPort / 8 + 1, UsbOnHubInterrupt, HubIf ); if (EFI_ERROR (Status)) { DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to queue interrupt transfer for hub %d - %r\n", HubDev->Address, Status)); gBS->CloseEvent (HubIf->HubNotify); HubIf->HubNotify = NULL; return Status; } // // OK, set IsHub to TRUE. Now usb bus can handle this device // as a working HUB. If failed eariler, bus driver will not // recognize it as a hub. Other parts of the bus should be able // to work. // HubIf->IsHub = TRUE; HubIf->HubApi = &mUsbHubApi; HubIf->HubEp = EpDesc; // // Feed power to all the hub ports. It should be ok // for both gang/individual powered hubs. // for (Index = 0; Index < HubDesc.NumPorts; Index++) { UsbHubCtrlSetPortFeature (HubIf->Device, Index, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER); } gBS->Stall (HubDesc.PwrOn2PwrGood * USB_SET_PORT_POWER_STALL); UsbHubAckHubStatus (HubIf->Device); DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d initialized\n", HubDev->Address)); return Status; }