X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FBus%2FUsb%2FUsbBusDxe%2FUsbHub.c;h=2dfc5751d55d032b3d45959ee8834f00bde4bb25;hp=21270b80808030b308c65177ed83a48c20a11591;hb=92870c983c6d99d31f449d8dcd729090255dda49;hpb=da910a42c0421a9895898537026276acf0935099 diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c index 21270b8080..2dfc5751d5 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c @@ -22,19 +22,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // bits determine whether hub will report the port in changed // bit maps. // -#define USB_HUB_MAP_SIZE 5 - -USB_CHANGE_FEATURE_MAP mHubFeatureMap[USB_HUB_MAP_SIZE] = { +USB_CHANGE_FEATURE_MAP mHubFeatureMap[] = { {USB_PORT_STAT_C_CONNECTION, EfiUsbPortConnectChange}, {USB_PORT_STAT_C_ENABLE, EfiUsbPortEnableChange}, {USB_PORT_STAT_C_SUSPEND, EfiUsbPortSuspendChange}, {USB_PORT_STAT_C_OVERCURRENT, EfiUsbPortOverCurrentChange}, - {USB_PORT_STAT_C_RESET, EfiUsbPortResetChange}, + {USB_PORT_STAT_C_RESET, EfiUsbPortResetChange} }; -#define USB_ROOT_HUB_MAP_SIZE 5 - -USB_CHANGE_FEATURE_MAP mRootHubFeatureMap[USB_ROOT_HUB_MAP_SIZE] = { +USB_CHANGE_FEATURE_MAP mRootHubFeatureMap[] = { {USB_PORT_STAT_C_CONNECTION, EfiUsbPortConnectChange}, {USB_PORT_STAT_C_ENABLE, EfiUsbPortEnableChange}, {USB_PORT_STAT_C_SUSPEND, EfiUsbPortSuspendChange}, @@ -47,7 +43,38 @@ USB_CHANGE_FEATURE_MAP mRootHubFeatureMap[USB_ROOT_HUB_MAP_SIZE] = { // is related to an interface, these requests are sent // to the control endpoint of the device. // +/** + USB hub control transfer to set the hub depth. + + @param HubDev The device of the hub. + @param Depth The depth to set. + + @retval EFI_SUCCESS Depth of the hub is set. + @retval Others Failed to set the depth. + +**/ +EFI_STATUS +UsbHubCtrlSetHubDepth ( + IN USB_DEVICE *HubDev, + IN UINT16 Depth + ) +{ + EFI_STATUS Status; + Status = UsbCtrlRequest ( + HubDev, + EfiUsbNoData, + USB_REQ_TYPE_CLASS, + USB_HUB_TARGET_HUB, + USB_HUB_REQ_SET_DEPTH, + Depth, + 0, + NULL, + 0 + ); + + return Status; +} /** USB hub control transfer to clear the hub feature. @@ -173,6 +200,41 @@ UsbHubCtrlClearTTBuffer ( return Status; } +/** + Usb hub control transfer to get the super speed hub descriptor. + + @param HubDev The hub device. + @param Buf The buffer to hold the descriptor. + @param Len The length to retrieve. + + @retval EFI_SUCCESS The hub descriptor is retrieved. + @retval Others Failed to retrieve the hub descriptor. + +**/ +EFI_STATUS +UsbHubCtrlGetSuperSpeedHubDesc ( + IN USB_DEVICE *HubDev, + OUT VOID *Buf + ) +{ + EFI_STATUS Status; + + Status = EFI_INVALID_PARAMETER; + + Status = UsbCtrlRequest ( + HubDev, + EfiUsbDataIn, + USB_REQ_TYPE_CLASS, + USB_HUB_TARGET_HUB, + USB_HUB_REQ_GET_DESC, + (UINT16) (USB_DESC_TYPE_HUB_SUPER_SPEED << 8), + 0, + Buf, + 32 + ); + + return Status; +} /** Usb hub control transfer to get the hub descriptor. @@ -414,19 +476,27 @@ UsbHubReadDesc ( { EFI_STATUS Status; - // - // First get the hub descriptor length - // - Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, 2); + if (HubDev->Speed == EFI_USB_SPEED_SUPER) { + // + // Get the super speed hub descriptor + // + Status = UsbHubCtrlGetSuperSpeedHubDesc (HubDev, HubDesc); + } else { - if (EFI_ERROR (Status)) { - return Status; - } + // + // First get the hub descriptor length + // + Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, 2); - // - // Get the whole hub descriptor - // - Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, HubDesc->Length); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the whole hub descriptor + // + Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, HubDesc->Length); + } return Status; } @@ -629,6 +699,7 @@ UsbHubInit ( EFI_STATUS Status; UINT8 Index; UINT8 NumEndpoints; + UINT16 Depth; // // Locate the interrupt endpoint for port change map @@ -666,6 +737,37 @@ UsbHubInit ( DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d has %d ports\n", HubDev->Address,HubIf->NumOfPort)); + // + // 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; + + if (HubIf->Device->Speed == EFI_USB_SPEED_SUPER) { + Depth = (UINT16)(HubIf->Device->Tier - 1); + DEBUG ((EFI_D_INFO, "UsbHubInit: Set Hub Depth as 0x%x\n", Depth)); + UsbHubCtrlSetHubDepth (HubIf->Device, Depth); + + for (Index = 0; Index < HubDesc.NumPorts; Index++) { + UsbHubCtrlSetPortFeature (HubIf->Device, Index, USB_HUB_PORT_REMOTE_WAKE_MASK); + } + } else { + // + // 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); + } + // // Create an event to enumerate the hub's port. On // @@ -712,27 +814,6 @@ UsbHubInit ( 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; } @@ -764,6 +845,12 @@ UsbHubGetPortStatus ( Status = UsbHubCtrlGetPortStatus (HubIf->Device, Port, PortState); + // + // Mark the USB_PORT_STAT_SUPER_SPEED bit if SuperSpeed + // + if (HubIf->Device->Speed == EFI_USB_SPEED_SUPER) { + PortState->PortStatus |= USB_PORT_STAT_SUPER_SPEED; + } return Status; } @@ -799,7 +886,7 @@ UsbHubClearPortChange ( // 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++) { + for (Index = 0; Index < sizeof (mHubFeatureMap) / sizeof (mHubFeatureMap[0]); Index++) { Map = &mHubFeatureMap[Index]; if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) { @@ -1091,7 +1178,7 @@ UsbRootHubClearPortChange ( // It may lead to extra port state report. USB bus should // be able to handle this. // - for (Index = 0; Index < USB_ROOT_HUB_MAP_SIZE; Index++) { + for (Index = 0; Index < sizeof (mRootHubFeatureMap) / sizeof (mRootHubFeatureMap[0]); Index++) { Map = &mRootHubFeatureMap[Index]; if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {