/** Interface function to reset the port. @param HubIf The hub interface. @param Port The port to reset. @retval EFI_SUCCESS The hub port is reset. @retval EFI_TIMEOUT Failed to reset the port in time. @retval Others Failed to reset the port. **/ EFI_STATUS UsbHubResetPort ( IN USB_INTERFACE *HubIf, IN UINT8 Port ) { EFI_USB_PORT_STATUS PortState; UINTN Index; EFI_STATUS Status; Status = UsbHubGetPortStatus (HubIf, Port, &PortState); if (EFI_ERROR (Status)) { return Status; } else if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) { DEBUG (( EFI_D_INFO, "UsbHubResetPort: skip reset on hub %p port %d\n", HubIf, Port)); return EFI_SUCCESS; } Status = UsbHubSetPortFeature (HubIf, Port, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_RESET); if (EFI_ERROR (Status)) { return Status; } // // Drive the reset signal for worst 20ms. Check USB 2.0 Spec // section 7.1.7.5 for timing requirements. // gBS->Stall (USB_SET_PORT_RESET_STALL); // // Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done. // ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS)); for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) { Status = UsbHubGetPortStatus (HubIf, Port, &PortState); if (EFI_ERROR (Status)) { return Status; } if (!EFI_ERROR (Status) && USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) { gBS->Stall (USB_SET_PORT_RECOVERY_STALL); return EFI_SUCCESS; } gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL); } return EFI_TIMEOUT; }
/** Clear the port change status. @param HubIf The hub interface. @param Port The hub port. **/ VOID UsbHubClearPortChange ( IN USB_INTERFACE *HubIf, IN UINT8 Port ) { EFI_USB_PORT_STATUS PortState; USB_CHANGE_FEATURE_MAP *Map; UINTN Index; EFI_STATUS Status; Status = UsbHubGetPortStatus (HubIf, Port, &PortState); if (EFI_ERROR (Status)) { return; } // // OK, get the usb port status, now ACK the change bits. // Don't return error when failed to clear the change bits. // It may lead to extra port state report. USB bus should // be able to handle this. // for (Index = 0; Index < USB_HUB_MAP_SIZE; Index++) { Map = &mHubFeatureMap[Index]; if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) { UsbHubCtrlClearPortFeature (HubIf->Device, Port, (UINT16) Map->Feature); } } }
/** Interface function to reset the port. @param HubIf The hub interface. @param Port The port to reset. @retval EFI_SUCCESS The hub port is reset. @retval EFI_TIMEOUT Failed to reset the port in time. @retval Others Failed to reset the port. **/ EFI_STATUS UsbHubResetPort ( IN USB_INTERFACE *HubIf, IN UINT8 Port ) { EFI_USB_PORT_STATUS PortState; UINTN Index; EFI_STATUS Status; Status = UsbHubSetPortFeature (HubIf, Port, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_RESET); if (EFI_ERROR (Status)) { return Status; } // // Drive the reset signal for at least 10ms. Check USB 2.0 Spec // section 7.1.7.5 for timing requirements. // gBS->Stall (USB_SET_PORT_RESET_STALL); // // USB hub will clear RESET bit if reset is actually finished. // ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS)); for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) { Status = UsbHubGetPortStatus (HubIf, Port, &PortState); if (!EFI_ERROR (Status) && !USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_RESET)) { return EFI_SUCCESS; } gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL); } return EFI_TIMEOUT; }