From: yshang1 Date: Mon, 8 Oct 2007 06:14:13 +0000 (+0000) Subject: Fixed unexpected timeout in Usb MassStorage Driver. X-Git-Tag: edk2-stable201903~21987 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=41e8ff2781f3ca14f73ef5f39e781ccba8cb373d Fixed unexpected timeout in Usb MassStorage Driver. Fixed unexpected timeout in Uhci/Ehci driver. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4038 6f19259b-4bc3-4df7-8a09-765794883524 --- diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c index 13ce7fdfb1..07a690edce 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c +++ b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c @@ -126,14 +126,14 @@ EhcReset ( // Host Controller must be Halt when Reset it // if (!EhcIsHalt (Ehc)) { - Status = EhcHaltHC (Ehc, EHC_GENERIC_TIME); + Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto ON_EXIT; } } - + // // Clean up the asynchronous transfers, currently only // interrupt supports asynchronous operation. @@ -142,7 +142,7 @@ EhcReset ( EhcAckAllInterrupt (Ehc); EhcFreeSched (Ehc); - Status = EhcResetHC (Ehc, EHC_STALL_1_SECOND); + Status = EhcResetHC (Ehc, EHC_RESET_TIMEOUT); if (EFI_ERROR (Status)) { goto ON_EXIT; @@ -251,7 +251,7 @@ EhcSetState ( switch (State) { case EfiUsbHcStateHalt: - Status = EhcHaltHC (Ehc, EHC_GENERIC_TIME); + Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); break; case EfiUsbHcStateOperational: @@ -260,7 +260,17 @@ EhcSetState ( break; } - Status = EhcRunHC (Ehc, EHC_GENERIC_TIME); + // + // Software must not write a one to this field unless the host controller + // is in the Halted state. Doing so will yield undefined results. + // refers to Spec[EHCI1.0-2.3.1] + // + if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) { + Status = EFI_DEVICE_ERROR; + break; + } + + Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT); break; case EfiUsbHcStateSuspend: @@ -437,14 +447,14 @@ EhcSetRootHubPortFeature ( // Make sure Host Controller not halt before reset it // if (EhcIsHalt (Ehc)) { - Status = EhcRunHC (Ehc, EHC_GENERIC_TIME); + Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT); if (EFI_ERROR (Status)) { EHC_DEBUG (("EhcSetRootHubPortFeature :failed to start HC - %r\n", Status)); break; } } - + // // Set one to PortReset bit must also set zero to PortEnable bit // @@ -1539,7 +1549,7 @@ EhcDriverBindingStart ( // Robustnesss improvement such as for UoL // EhcClearLegacySupport (Ehc); - EhcResetHC (Ehc, EHC_STALL_1_SECOND); + EhcResetHC (Ehc, EHC_RESET_TIMEOUT); Status = EhcInitHC (Ehc); @@ -1551,12 +1561,12 @@ EhcDriverBindingStart ( // // Start the asynchronous interrupt monitor // - Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_TIME); + Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_INTERVAL); if (EFI_ERROR (Status)) { EHC_ERROR (("EhcDriverBindingStart: failed to start async interrupt monitor\n")); - EhcHaltHC (Ehc, EHC_GENERIC_TIME); + EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); goto UNINSTALL_USBHC; } @@ -1659,8 +1669,8 @@ EhcDriverBindingStop ( // Stop AsyncRequest Polling timer then stop the EHCI driver // and uninstall the EHCI protocl. // - gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_TIME); - EhcHaltHC (Ehc, EHC_GENERIC_TIME); + gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL); + EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); Status = gBS->UninstallProtocolInterface ( Controller, diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h index 7eb61be05a..816587db8d 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h +++ b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h @@ -49,18 +49,35 @@ typedef struct _USB2_HC_DEV USB2_HC_DEV; #include "EhciDebug.h" enum { - USB2_HC_DEV_SIGNATURE = EFI_SIGNATURE_32 ('e', 'h', 'c', 'i'), - EHC_STALL_1_MICROSECOND = 1, - EHC_STALL_1_MILLISECOND = 1000 * EHC_STALL_1_MICROSECOND, - EHC_STALL_1_SECOND = 1000 * EHC_STALL_1_MILLISECOND, - - EHC_SET_PORT_RESET_TIME = 50 * EHC_STALL_1_MILLISECOND, - EHC_CLEAR_PORT_RESET_TIME = EHC_STALL_1_MILLISECOND, - EHC_GENERIC_TIME = 10 * EHC_STALL_1_MILLISECOND, - EHC_SYNC_POLL_TIME = 20 * EHC_STALL_1_MICROSECOND, - EHC_ASYNC_POLL_TIME = 50 * 10000UL, // The unit of time is 100us - - EHC_TPL = TPL_NOTIFY + EHC_1_MICROSECOND = 1, + EHC_1_MILLISECOND = 1000 * EHC_1_MICROSECOND, + EHC_1_SECOND = 1000 * EHC_1_MILLISECOND, + + // + // EHCI register operation timeout, set by experience + // + EHC_RESET_TIMEOUT = 1 * EHC_1_SECOND, + EHC_GENERIC_TIMEOUT = 10 * EHC_1_MILLISECOND, + + // + // Wait for roothub port power stable, refers to Spec[EHCI1.0-2.3.9] + // + EHC_ROOT_PORT_RECOVERY_STALL = 20 * EHC_1_MILLISECOND, + + // + // Sync and Async transfer polling interval, set by experience, + // and the unit of Async is 100us, means 50ms as interval. + // + EHC_SYNC_POLL_INTERVAL = 20 * EHC_1_MICROSECOND, + EHC_ASYNC_POLL_INTERVAL = 50 * 10000U, + + // + // EHC raises TPL to TPL_NOTIFY to serialize all its operations + // to protect shared data structures. + // + EHC_TPL = TPL_NOTIFY, + + USB2_HC_DEV_SIGNATURE = EFI_SIGNATURE_32 ('e', 'h', 'c', 'i'), }; // diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c b/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c index 290cb3847a..45b6df5c83 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c +++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c @@ -214,12 +214,12 @@ EhcWaitOpRegBit ( { UINT32 Index; - for (Index = 0; Index < Timeout / EHC_SYNC_POLL_TIME + 1; Index++) { + for (Index = 0; Index < Timeout / EHC_SYNC_POLL_INTERVAL + 1; Index++) { if (EHC_REG_BIT_IS_SET (Ehc, Offset, Bit) == WaitToSet) { return EFI_SUCCESS; } - gBS->Stall (EHC_SYNC_POLL_TIME); + gBS->Stall (EHC_SYNC_POLL_INTERVAL); } return EFI_TIMEOUT; @@ -614,14 +614,19 @@ EhcInitHC ( // EhcSetOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC); - Status = EhcEnablePeriodSchd (Ehc, EHC_GENERIC_TIME); + // + // Wait roothub port power stable + // + gBS->Stall (EHC_ROOT_PORT_RECOVERY_STALL); + + Status = EhcEnablePeriodSchd (Ehc, EHC_GENERIC_TIMEOUT); if (EFI_ERROR (Status)) { EHC_ERROR (("EhcInitHC: failed to enable period schedule\n")); return Status; } - Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIME); + Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIMEOUT); if (EFI_ERROR (Status)) { EHC_ERROR (("EhcInitHC: failed to enable async schedule\n")); diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c b/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c index 4c2dc86f06..349b5c233a 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c +++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c @@ -342,7 +342,7 @@ EhcUnlinkQhFromAsync ( // // Set and wait the door bell to synchronize with the hardware // - Status = EhcSetAndWaitDoorBell (Ehc, EHC_GENERIC_TIME); + Status = EhcSetAndWaitDoorBell (Ehc, EHC_GENERIC_TIMEOUT); if (EFI_ERROR (Status)) { EHC_ERROR (("EhcUnlinkQhFromAsync: Failed to synchronize with doorbell\n")); @@ -659,7 +659,7 @@ EhcExecTransfer ( BOOLEAN Finished; Status = EFI_SUCCESS; - Loop = (TimeOut * EHC_STALL_1_MILLISECOND / EHC_SYNC_POLL_TIME) + 1; + Loop = (TimeOut * EHC_1_MILLISECOND / EHC_SYNC_POLL_INTERVAL) + 1; Finished = FALSE; for (Index = 0; Index < Loop; Index++) { @@ -669,7 +669,7 @@ EhcExecTransfer ( break; } - gBS->Stall (EHC_SYNC_POLL_TIME); + gBS->Stall (EHC_SYNC_POLL_INTERVAL); } if (!Finished) { diff --git a/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c b/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c index 1dee976504..00108b87e2 100644 --- a/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c +++ b/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c @@ -56,44 +56,33 @@ UhciReset ( // // Stop schedule and set the Global Reset bit in the command register // - UhciStopHc (Uhc, STALL_1_SECOND); + UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT); UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET); - // - // Wait 50ms for root port to let reset complete - // See UHCI spec page122 Reset signaling - // - gBS->Stall (ROOT_PORT_REST_TIME); + gBS->Stall (UHC_ROOT_PORT_RESET_STALL); // // Clear the Global Reset bit to zero. // UhciClearRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET); - // - // UHCI spec page120 reset recovery time - // - gBS->Stall (PORT_RESET_RECOVERY_TIME); + gBS->Stall (UHC_ROOT_PORT_RECOVERY_STALL); break; case EFI_USB_HC_RESET_HOST_CONTROLLER: // // Stop schedule and set Host Controller Reset bit to 1 // - UhciStopHc (Uhc, STALL_1_SECOND); + UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT); UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_HCRESET); - // - // this bit will be reset by Host Controller when reset is completed. - // wait 10ms to let reset complete - // - gBS->Stall (PORT_RESET_RECOVERY_TIME); + gBS->Stall (UHC_ROOT_PORT_RECOVERY_STALL); break; default: goto ON_INVAILD_PARAMETER; } - + // // Delete all old transactions on the USB bus, then // reinitialize the frame list @@ -103,13 +92,13 @@ UhciReset ( UhciInitFrameList (Uhc); gBS->RestoreTPL (OldTpl); - + return EFI_SUCCESS; ON_INVAILD_PARAMETER: - + gBS->RestoreTPL (OldTpl); - + return EFI_INVALID_PARAMETER; } @@ -202,7 +191,7 @@ UhciSetState ( switch (State) { case EfiUsbHcStateHalt: - Status = UhciStopHc (Uhc, STALL_1_SECOND); + Status = UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT); break; case EfiUsbHcStateOperational: @@ -224,11 +213,11 @@ UhciSetState ( UsbCmd |= USBCMD_FGR; UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd); } - + // // wait 20ms to let resume complete (20ms is specified by UHCI spec) // - gBS->Stall (FORCE_GLOBAL_RESUME_TIME); + gBS->Stall (UHC_FORCE_GLOBAL_RESUME_STALL); // // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0 @@ -248,7 +237,7 @@ UhciSetState ( Status = EFI_DEVICE_ERROR; goto ON_EXIT; } - + // // Set Enter Global Suspend Mode bit to 1. // @@ -2084,7 +2073,7 @@ UhciCleanDevUp ( // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller // Uhc = UHC_FROM_USB_HC_PROTO (This); - UhciStopHc (Uhc, STALL_1_SECOND); + UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT); gBS->UninstallProtocolInterface ( Controller, @@ -2188,7 +2177,7 @@ UhciDriverBindingStart ( Status = gBS->SetTimer ( Uhc->AsyncIntMonitor, TimerPeriodic, - INTERRUPT_POLLING_TIME + UHC_ASYNC_POLL_INTERVAL ); if (EFI_ERROR (Status)) { diff --git a/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.h b/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.h index 3f2540faf7..e7b4447def 100644 --- a/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.h +++ b/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.h @@ -51,25 +51,43 @@ typedef struct _USB_HC_DEV USB_HC_DEV; #include "UhciDebug.h" enum { + UHC_1_MICROSECOND = 1, + UHC_1_MILLISECOND = 1000 * UHC_1_MICROSECOND, + UHC_1_SECOND = 1000 * UHC_1_MILLISECOND, + + // + // UHCI register operation timeout, set by experience // - // Stall times + UHC_GENERIC_TIMEOUT = UHC_1_SECOND, + // - STALL_1_MS = 1000, - STALL_1_SECOND = 1000 *STALL_1_MS, + // Wait for force global resume(FGR) complete, refers to + // specification[UHCI11-2.1.1] + // + UHC_FORCE_GLOBAL_RESUME_STALL = 20 * UHC_1_MILLISECOND, - UHC_SYN_POLL = 50, - FORCE_GLOBAL_RESUME_TIME = 20 *STALL_1_MS, - ROOT_PORT_REST_TIME = 50 *STALL_1_MS, - PORT_RESET_RECOVERY_TIME = 10 *STALL_1_MS, - INTERRUPT_POLLING_TIME = 50 * 10000UL, + // + // Wait for roothub port reset and recovery, reset stall + // is set by experience, and recovery stall refers to + // specification[UHCI11-2.1.1] + // + UHC_ROOT_PORT_RESET_STALL = 50 * UHC_1_MILLISECOND, + UHC_ROOT_PORT_RECOVERY_STALL = 10 * UHC_1_MILLISECOND, + // + // Sync and Async transfer polling interval, set by experience, + // and the unit of Async is 100us. + // + UHC_SYNC_POLL_INTERVAL = 50 * UHC_1_MICROSECOND, + UHC_ASYNC_POLL_INTERVAL = 50 * 10000UL, + // // UHC raises TPL to TPL_NOTIFY to serialize all its operations // to protect shared data structures. // UHCI_TPL = TPL_NOTIFY, - USB_HC_DEV_SIGNATURE = EFI_SIGNATURE_32 ('u', 'h', 'c', 'i') + USB_HC_DEV_SIGNATURE = EFI_SIGNATURE_32 ('u', 'h', 'c', 'i'), }; #pragma pack(1) diff --git a/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c b/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c index e1b602e7e2..401d32eb34 100644 --- a/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c +++ b/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c @@ -575,8 +575,8 @@ UhciExecuteTransfer ( Finished = FALSE; Status = EFI_SUCCESS; - Delay = (TimeOut * STALL_1_MS / UHC_SYN_POLL) + 1; - + Delay = (TimeOut * UHC_1_MILLISECOND / UHC_SYNC_POLL_INTERVAL) + 1; + for (Index = 0; Index < Delay; Index++) { Finished = UhciCheckTdStatus (Uhc, Td, IsLow, QhResult); @@ -587,7 +587,7 @@ UhciExecuteTransfer ( break; } - gBS->Stall (UHC_SYN_POLL); + gBS->Stall (UHC_SYNC_POLL_INTERVAL); } if (!Finished) { diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c index 6d68d818d2..c9e1755fde 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c @@ -464,7 +464,7 @@ UsbCtrlRequest ( Direction, Buf, &Len, - 50 * USB_STALL_1_MS, + USB_GENERAL_DEVICE_REQUEST_TIMEOUT, &UsbDev->Translator, &Result ); @@ -554,7 +554,7 @@ UsbGetMaxPacketSize0 ( return EFI_SUCCESS; } - gBS->Stall (100 * USB_STALL_1_MS); + gBS->Stall (USB_RETRY_MAX_PACK_SIZE_STALL); } return EFI_DEVICE_ERROR; @@ -981,7 +981,7 @@ UsbIoClearFeature ( UsbIo, &DevReq, EfiUsbNoData, - 10 * USB_STALL_1_MS, + USB_CLEAR_FEATURE_REQUEST_TIMEOUT, NULL, 0, &UsbResult diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c index b92e9e072e..65eb2dd77f 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c @@ -656,13 +656,9 @@ UsbEnumerateNewDev ( Parent = HubIf->Device; Bus = Parent->Bus; HubApi = HubIf->HubApi; - - - // - // Wait at least 100 ms for the power on port to stable - // - gBS->Stall (100 * USB_STALL_1_MS); - + + gBS->Stall (USB_WAIT_PORT_STABLE_STALL); + // // Hub resets the device for at least 10 milliseconds. // Host learns device speed. If device is of low/full speed @@ -774,11 +770,8 @@ UsbEnumerateNewDev ( DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to set device address - %r\n", Status)); goto ON_ERROR; } - - // - // Wait 20ms for set address to complete - // - gBS->Stall (20 * USB_STALL_1_MS); + + gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL); DEBUG ((EFI_D_INFO, "UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address)); @@ -886,47 +879,44 @@ UsbEnumeratePort ( if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) { // - // Both OverCurrent and OverCurrentChange set, means over current occurs, - // which probably is caused by short circuit. It has to wait system hardware - // to perform recovery. + // Case1: + // Both OverCurrent and OverCurrentChange set, means over current occurs, + // which probably is caused by short circuit. It has to wait system hardware + // to perform recovery. // DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: Critical Over Current\n", Port)); return EFI_DEVICE_ERROR; - } else { - // - // Only OverCurrentChange set, means system has been recoveried from - // over current. As a result, all ports are nearly power-off, so - // it's necessary to detach and enumerate all ports again. - // - DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port)); - goto ON_ENUMERATE; - - } + } + // + // Case2: + // Only OverCurrentChange set, means system has been recoveried from + // over current. As a result, all ports are nearly power-off, so + // it's necessary to detach and enumerate all ports again. + // + DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port)); } if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) { // - // 1.1 roothub port reg doesn't reflect over-current state, while its counterpart - // on 2.0 roothub does. When over-current has influence on 1.1 device, the port - // would be disabled, so it's also necessary to detach and enumerate again. + // Case3: + // 1.1 roothub port reg doesn't reflect over-current state, while its counterpart + // on 2.0 roothub does. When over-current has influence on 1.1 device, the port + // would be disabled, so it's also necessary to detach and enumerate again. // DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 1.1 device Recovery Over Current\n", Port)); - goto ON_ENUMERATE; } if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) { // - // Device connected or disconnected normally. + // Case4: + // Device connected or disconnected normally. // - goto ON_ENUMERATE; + DEBUG ((EFI_D_ERROR, "UsbEnumeratePort: Device Connect/Discount Normally\n", Port)); } -ON_ENUMERATE: - // - // In case there is already a device on this port logically, it's safety to remove - // and enumerate again. + // Following as the above cases, it's safety to remove and create again. // Child = UsbFindChild (HubIf, Port); diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c index 795f545b77..8a69ca6ece 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c @@ -745,7 +745,7 @@ UsbHubInit ( UsbHubCtrlSetPortFeature (HubIf->Device, Index, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER); } - gBS->Stall (HubDesc.PwrOn2PwrGood * 2 * USB_STALL_1_MS); + gBS->Stall (HubDesc.PwrOn2PwrGood * USB_SET_PORT_POWER_STALL); UsbHubAckHubStatus (HubIf->Device); DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d initialized\n", HubDev->Address)); @@ -915,14 +915,14 @@ UsbHubResetPort ( // Drive the reset signal for at least 10ms. Check USB 2.0 Spec // section 7.1.7.5 for timing requirements. // - gBS->Stall (20 * USB_STALL_1_MS); + 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 < 20; Index++) { + for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) { Status = UsbHubGetPortStatus (HubIf, Port, &PortState); if (!EFI_ERROR (Status) && @@ -931,7 +931,7 @@ UsbHubResetPort ( return EFI_SUCCESS; } - gBS->Stall (5 * USB_STALL_1_MS); + gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL); } return EFI_TIMEOUT; @@ -1228,7 +1228,7 @@ UsbRootHubResetPort ( // Drive the reset signal for at least 50ms. Check USB 2.0 Spec // section 7.1.7.5 for timing requirements. // - gBS->Stall (50 * USB_STALL_1_MS); + gBS->Stall (USB_SET_ROOT_PORT_RESET_STALL); Status = UsbHcClearRootHubPortFeature (Bus, Port, EfiUsbPortReset); @@ -1237,7 +1237,7 @@ UsbRootHubResetPort ( return Status; } - gBS->Stall (USB_STALL_1_MS); + gBS->Stall (USB_CLR_ROOT_PORT_RESET_STALL); // // USB host controller won't clear the RESET bit until @@ -1245,7 +1245,7 @@ UsbRootHubResetPort ( // ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS)); - for (Index = 0; Index < USB_HUB_LOOP; Index++) { + for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) { Status = UsbHcGetRootHubPortStatus (Bus, Port, &PortState); if (EFI_ERROR (Status)) { @@ -1256,11 +1256,11 @@ UsbRootHubResetPort ( break; } - gBS->Stall (10 * USB_STALL_1_MS); + gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL); } - if (Index == USB_HUB_LOOP) { - DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port)); + if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) { + DEBUG ((EFI_D_ERROR, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port)); return EFI_TIMEOUT; } @@ -1286,7 +1286,7 @@ UsbRootHubResetPort ( return Status; } - gBS->Stall (20 * USB_STALL_1_MS); + gBS->Stall (USB_SET_ROOT_PORT_ENABLE_STALL); } } diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.h b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.h index a5bcbb2623..36b6a43482 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.h +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.h @@ -90,8 +90,11 @@ enum { USB_HUB_CLASS_CODE = 0x09, USB_HUB_SUBCLASS_CODE = 0x00, - - USB_HUB_LOOP = 50 + // + // Host software return timeout if port status doesn't change + // after 500ms(LOOP * STALL = 100 * 5ms), set by experience + // + USB_WAIT_PORT_STS_CHANGE_LOOP = 100, }; #pragma pack(1) @@ -112,7 +115,7 @@ typedef struct { typedef struct { UINT16 ChangedBit; - UINT8 Feature; + EFI_USB_PORT_FEATURE Feature; } USB_CHANGE_FEATURE_MAP; diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c index 2e2333aa7c..910ebc5d23 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c @@ -1142,6 +1142,24 @@ UsbBusControllerDriverStart ( goto CLOSE_HC; } + UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL); + UsbHcSetState (UsbBus, EfiUsbHcStateOperational); + + // + // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it. + // + Status = gBS->InstallProtocolInterface ( + &Controller, + &mUsbBusProtocolGuid, + EFI_NATIVE_INTERFACE, + &UsbBus->BusId + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status)); + goto CLOSE_HC; + } + // // Create a fake usb device for root hub // @@ -1149,7 +1167,7 @@ UsbBusControllerDriverStart ( if (RootHub == NULL) { Status = EFI_OUT_OF_RESOURCES; - goto CLOSE_HC; + goto UNINSTALL_USBBUS; } RootIf = AllocateZeroPool (sizeof (USB_INTERFACE)); @@ -1157,7 +1175,7 @@ UsbBusControllerDriverStart ( if (RootIf == NULL) { gBS->FreePool (RootHub); Status = EFI_OUT_OF_RESOURCES; - goto CLOSE_HC; + goto FREE_ROOTHUB; } RootHub->Bus = UsbBus; @@ -1166,11 +1184,7 @@ UsbBusControllerDriverStart ( RootIf->Signature = USB_INTERFACE_SIGNATURE; RootIf->Device = RootHub; RootIf->DevicePath = UsbBus->DevicePath; - - UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL); - UsbHcSetState (UsbBus, EfiUsbHcStateOperational); - Status = mUsbRootHubApi.Init (RootIf); if (EFI_ERROR (Status)) { @@ -1180,31 +1194,20 @@ UsbBusControllerDriverStart ( UsbBus->Devices[0] = RootHub; - // - // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it. - // - Status = gBS->InstallProtocolInterface ( - &Controller, - &mUsbBusProtocolGuid, - EFI_NATIVE_INTERFACE, - &UsbBus->BusId - ); - - if (EFI_ERROR (Status)) { - DEBUG (( EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status)); - - mUsbRootHubApi.Release (RootIf); - goto FREE_ROOTHUB; - } - - DEBUG (( EFI_D_INFO, "UsbBusStart: usb bus started on %x, root hub %x\n", Controller, RootIf)); return EFI_SUCCESS; - + FREE_ROOTHUB: - gBS->FreePool (RootIf); - gBS->FreePool (RootHub); - + if (RootIf != NULL) { + gBS->FreePool (RootIf); + } + if (RootHub != NULL) { + gBS->FreePool (RootHub); + } + +UNINSTALL_USBBUS: + gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId); + CLOSE_HC: if (UsbBus->Usb2Hc != NULL) { gBS->CloseProtocol ( @@ -1214,7 +1217,6 @@ CLOSE_HC: Controller ); } - if (UsbBus->UsbHc != NULL) { gBS->CloseProtocol ( Controller, @@ -1223,14 +1225,12 @@ CLOSE_HC: Controller ); } - gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); - gBS->FreePool (UsbBus); DEBUG (( EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status)); diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.h b/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.h index 4bf9d53015..971e01b47a 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.h +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.h @@ -55,21 +55,77 @@ typedef struct _USB_HUB_API USB_HUB_API; #include "UsbEnumer.h" enum { + USB_MAX_LANG_ID = 16, + USB_MAX_INTERFACE = 16, + USB_MAX_DEVICES = 128, + + USB_BUS_1_MILLISECOND = 1000, + // - // Time definition + // Roothub and hub's polling interval, set by experience, + // The unit of roothub is 100us, means 1s as interval, and + // the unit of hub is 1ms, means 64ms as interval. // - USB_STALL_1_MS = 1000, - TICKS_PER_MS = 10000U, - USB_ROOTHUB_POLL_INTERVAL = 1000 * TICKS_PER_MS, + USB_ROOTHUB_POLL_INTERVAL = 1000 * 10000U, USB_HUB_POLL_INTERVAL = 64, // - // Maximum definition + // Wait for port stable to work, refers to specification + // [USB20-9.1.2] // - USB_MAX_LANG_ID = 16, - USB_MAX_INTERFACE = 16, - USB_MAX_DEVICES = 128, + USB_WAIT_PORT_STABLE_STALL = 100 * USB_BUS_1_MILLISECOND, + + // + // Wait for port statue reg change, set by experience + // + USB_WAIT_PORT_STS_CHANGE_STALL = 5 * USB_BUS_1_MILLISECOND, + + // + // Wait for set device address, refers to specification + // [USB20-9.2.6.3, it says 2ms] + // + USB_SET_DEVICE_ADDRESS_STALL = 20 * USB_BUS_1_MILLISECOND, + + // + // Wait for retry max packet size, set by experience + // + USB_RETRY_MAX_PACK_SIZE_STALL = 100 * USB_BUS_1_MILLISECOND, + // + // Wait for hub port power-on, refers to specification + // [USB20-11.23.2] + // + USB_SET_PORT_POWER_STALL = 2 * USB_BUS_1_MILLISECOND, + + // + // Wait for port reset, refers to specification + // [USB20-7.1.7.5, it says 10ms for hub and 50ms for + // root hub] + // + USB_SET_PORT_RESET_STALL = 20 * USB_BUS_1_MILLISECOND, + USB_SET_ROOT_PORT_RESET_STALL = 50 * USB_BUS_1_MILLISECOND, + + // + // Wait for clear roothub port reset, set by experience + // + USB_CLR_ROOT_PORT_RESET_STALL = 1 * USB_BUS_1_MILLISECOND, + + // + // Wait for set roothub port enable, set by experience + // + USB_SET_ROOT_PORT_ENABLE_STALL = 20 * USB_BUS_1_MILLISECOND, + + // + // Send general device request timeout, refers to + // specification[USB20-11.24.1] + // + USB_GENERAL_DEVICE_REQUEST_TIMEOUT = 50 * USB_BUS_1_MILLISECOND, + + // + // Send clear feature request timeout, set by experience + // + USB_CLEAR_FEATURE_REQUEST_TIMEOUT = 10 * USB_BUS_1_MILLISECOND, + // // Bus raises TPL to TPL_NOTIFY to serialize all its operations // to protect shared data structures. diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMass.h b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMass.h index 77dcbb720b..3e7c700510 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMass.h +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMass.h @@ -73,8 +73,8 @@ enum { USB_MASS_STORE_CBI1 = 0x01, // CBI protocol without command completion interrupt USB_MASS_STORE_BOT = 0x50, // Bulk-Only Transport - USB_MASS_STALL_1_MS = 1000, - USB_MASS_STALL_1_S = 1000 * USB_MASS_STALL_1_MS, + USB_MASS_1_MILLISECOND = 1000, + USB_MASS_1_SECOND = 1000 * USB_MASS_1_MILLISECOND, USB_MASS_CMD_SUCCESS = 0, USB_MASS_CMD_FAIL, diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c index 9b8dfd01dd..91fcbec33b 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c @@ -935,7 +935,7 @@ UsbClearEndpointStall ( Request.Value = USB_FEATURE_ENDPOINT_HALT; Request.Index = EndpointAddr; Request.Length = 0; - Timeout = USB_BOOT_GENERAL_CMD_TIMEOUT / USB_MASS_STALL_1_MS; + Timeout = USB_BOOT_GENERAL_CMD_TIMEOUT / USB_MASS_1_MILLISECOND; Status = UsbIo->UsbControlTransfer ( UsbIo, diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h index bfef2609ad..136276a515 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h @@ -31,14 +31,13 @@ enum { // The opcodes of various usb boot commands: // INQUIRY/REQUEST_SENSE are "No Timeout Commands" as specified // by MMC command set. Others are "Group 1 Timeout Commands". That - // is they should be retried if driver is ready. - // We can't use the Peripheral Device Type in Inquiry data to + // is they should be retried if driver is ready. + // We can't use the Peripheral Device Type in Inquiry data to // determine the timeout used. For example, both floppy and flash // are likely set their PDT to 0, or Direct Access Device. // USB_BOOT_INQUIRY_OPCODE = 0x12, USB_BOOT_REQUEST_SENSE_OPCODE = 0x03, - USB_BOOT_MODE_SENSE10_OPCODE = 0x5A, USB_BOOT_READ_CAPACITY_OPCODE = 0x25, USB_BOOT_TEST_UNIT_READY_OPCODE = 0x00, @@ -70,45 +69,45 @@ enum { USB_BOOT_ASC_MEDIA_CHANGE = 0x28, // - // Other parameters + // Supported PDT codes, or Peripheral Device Type + // + USB_PDT_DIRECT_ACCESS = 0x00, // Direct access device + USB_PDT_CDROM = 0x05, // CDROM + USB_PDT_OPTICAL = 0x07, // Non-CD optical disks + USB_PDT_SIMPLE_DIRECT = 0x0E, // Simplified direct access device + + // + // Other parameters, Max carried size is 512B * 128 = 64KB // - USB_BOOT_IO_BLOCKS = 64, + USB_BOOT_IO_BLOCKS = 128, // - // Boot Retry times + // Retry mass command times, set by experience // USB_BOOT_COMMAND_RETRY = 5, - USB_BOOT_WAIT_RETRY = 5, + USB_BOOT_INIT_MEDIA_RETRY = 5, // - // Boot Stall time + // Wait for unit ready command, set by experience // - USB_BOOT_UNIT_READY_STALL = 50 * USB_MASS_STALL_1_MS, + USB_BOOT_RETRY_UNIT_READY_STALL = 500 * USB_MASS_1_MILLISECOND, // - // Boot Transfer timeout + // Mass command timeout, refers to specification[USB20-9.2.6.1] // // USB2.0 Spec define the up-limit timeout 5s for all command. USB floppy, // USB CD-Rom and iPod devices are much slower than USB key when reponse // most of commands, So we set 5s as timeout here. // // - USB_BOOT_GENERAL_CMD_TIMEOUT = 5 * USB_MASS_STALL_1_S, - - // - // Supported PDT codes, or Peripheral Device Type - // - USB_PDT_DIRECT_ACCESS = 0x00, // Direct access device - USB_PDT_CDROM = 0x05, // CDROM - USB_PDT_OPTICAL = 0x07, // Non-CD optical disks - USB_PDT_SIMPLE_DIRECT = 0x0E // Simplified direct access device + USB_BOOT_GENERAL_CMD_TIMEOUT = 5 * USB_MASS_1_SECOND, }; // // The required commands are INQUIRY, READ CAPACITY, TEST UNIT READY, // READ10, WRITE10, and REQUEST SENSE. The BLOCK_IO protocol uses LBA // so it isn't necessary to issue MODE SENSE / READ FORMAT CAPACITY -// command to retrieve the disk gemotrics. +// command to retrieve the disk gemotrics. // #pragma pack(1) typedef struct { @@ -221,7 +220,7 @@ typedef struct { typedef struct { UINT8 ModeDataLen; - UINT8 MediumType; + UINT8 MediumType; UINT8 DevicePara; UINT8 BlkDesLen; } USB_SCSI_MODE_SENSE6_PARA_HEADER; @@ -245,7 +244,7 @@ typedef struct { // #define USB_BOOT_SWAP32(Data32) \ ((((Data32) & 0x000000ff) << 24) | (((Data32) & 0xff000000) >> 24) | \ - (((Data32) & 0x0000ff00) << 8) | (((Data32) & 0x00ff0000) >> 8)) + (((Data32) & 0x0000ff00) << 8) | (((Data32) & 0x00ff0000) >> 8)) #define USB_BOOT_SWAP16(Data16) \ ((((Data16) & 0x00ff) << 8) | (((Data16) & 0xff00) >> 8)) diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.c b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.c index 6c92da9c71..3f4d0fc4d3 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.c +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.c @@ -191,7 +191,7 @@ UsbBotSendCommand ( Result = 0; DataLen = sizeof (USB_BOT_CBW); - Timeout = USB_BOT_CBW_TIMEOUT / USB_MASS_STALL_1_MS; + Timeout = USB_BOT_SEND_CBW_TIMEOUT / USB_MASS_1_MILLISECOND; // // Use the UsbIo to send the command to the device. The default @@ -266,7 +266,7 @@ UsbBotDataTransfer ( } Result = 0; - Timeout = Timeout / USB_MASS_STALL_1_MS; + Timeout = Timeout / USB_MASS_1_MILLISECOND; Status = UsbBot->UsbIo->UsbBulkTransfer ( UsbBot->UsbIo, @@ -323,14 +323,14 @@ UsbBotGetStatus ( EFI_USB_IO_PROTOCOL *UsbIo; UINT32 Index; UINTN Timeout; - + *CmdStatus = USB_BOT_COMMAND_ERROR; Status = EFI_DEVICE_ERROR; Endpoint = UsbBot->BulkInEndpoint->EndpointAddress; UsbIo = UsbBot->UsbIo; - Timeout = USB_BOT_CSW_TIMEOUT / USB_MASS_STALL_1_MS; + Timeout = USB_BOT_RECV_CSW_TIMEOUT / USB_MASS_1_MILLISECOND; - for (Index = 0; Index < USB_BOT_GET_STATUS_RETRY; Index++) { + for (Index = 0; Index < USB_BOT_RECV_CSW_RETRY; Index++) { // // Attemp to the read CSW from bulk in endpoint // @@ -499,7 +499,7 @@ UsbBotResetDevice ( Request.Value = 0; Request.Index = UsbBot->Interface.InterfaceNumber; Request.Length = 0; - Timeout = USB_BOT_RESET_TIMEOUT / USB_MASS_STALL_1_MS; + Timeout = USB_BOT_RESET_DEVICE_TIMEOUT / USB_MASS_1_MILLISECOND; Status = UsbBot->UsbIo->UsbControlTransfer ( UsbBot->UsbIo, @@ -521,7 +521,7 @@ UsbBotResetDevice ( // complete. We can use this to sync the device and host. For // now just stall 100ms to wait the device. // - gBS->Stall (USB_BOT_RESET_STALL); + gBS->Stall (USB_BOT_RESET_DEVICE_STALL); // // Clear the Bulk-In and Bulk-Out stall condition. diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.h b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.h index 8ccc48be23..341ffd0931 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.h +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.h @@ -46,21 +46,21 @@ enum { USB_BOT_COMMAND_ERROR = 0x02, // Phase error, need to reset the device // - // Usb Bot retry times + // Usb Bot retry to get CSW, refers to specification[BOT10-5.3, it says 2 times] // - USB_BOT_GET_STATUS_RETRY = 3, + USB_BOT_RECV_CSW_RETRY = 3, // - // Usb Bot stall time + // Usb Bot wait device reset complete, set by experience + // + USB_BOT_RESET_DEVICE_STALL = 100 * USB_MASS_1_MILLISECOND, + // - USB_BOT_RESET_STALL = 100 * USB_MASS_STALL_1_MS, - - // - // Usb Bot transfer timeout + // Usb Bot transport timeout, set by experience // - USB_BOT_CBW_TIMEOUT = 1 * USB_MASS_STALL_1_S, - USB_BOT_CSW_TIMEOUT = 1 * USB_MASS_STALL_1_S, - USB_BOT_RESET_TIMEOUT = 3 * USB_MASS_STALL_1_S + USB_BOT_SEND_CBW_TIMEOUT = 3 * USB_MASS_1_SECOND, + USB_BOT_RECV_CSW_TIMEOUT = 3 * USB_MASS_1_SECOND, + USB_BOT_RESET_DEVICE_TIMEOUT = 3 * USB_MASS_1_SECOND, }; // diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.c b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.c index 5c07c548b9..016235055b 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.c +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.c @@ -194,7 +194,7 @@ UsbCbiSendCommand ( Request.Length = CmdLen; Status = EFI_SUCCESS; - Timeout = Timeout / USB_MASS_STALL_1_MS; + Timeout = Timeout / USB_MASS_1_MILLISECOND; for (Retry = 0; Retry < USB_CBI_MAX_RETRY; Retry++) { // @@ -281,7 +281,7 @@ UsbCbiDataTransfer ( Remain = *TransLen; Retry = 0; Status = EFI_SUCCESS; - Timeout = Timeout / USB_MASS_STALL_1_MS; + Timeout = Timeout / USB_MASS_1_MILLISECOND; // // Transfer the data, if the device returns NAK, retry it. @@ -376,7 +376,7 @@ UsbCbiGetStatus ( Endpoint = UsbCbi->InterruptEndpoint->EndpointAddress; Status = EFI_SUCCESS; - Timeout = Timeout / USB_MASS_STALL_1_MS; + Timeout = Timeout / USB_MASS_1_MILLISECOND; // // Attemp to the read the result from interrupt endpoint @@ -555,7 +555,7 @@ UsbCbiResetDevice ( ResetCmd[0] = 0x1D; ResetCmd[1] = 0x04; - Timeout = USB_CBI_RESET_TIMEOUT / USB_MASS_STALL_1_MS; + Timeout = USB_CBI_RESET_DEVICE_TIMEOUT / USB_MASS_1_MILLISECOND; // // Send the command to the device. Don't use UsbCbiExecCommand here. @@ -570,7 +570,7 @@ UsbCbiResetDevice ( // 50ms to wait it complete // UsbCbiGetStatus (UsbCbi, Timeout, &Result); - gBS->Stall (50 * 1000); + gBS->Stall (USB_CBI_RESET_DEVICE_STALL); // // Clear the Bulk-In and Bulk-Out stall condition and diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.h b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.h index 61954e6be9..7933c71bf0 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.h +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.h @@ -30,14 +30,19 @@ enum { USB_CBI_RESET_CMD_LEN = 12, // - // Usb CBI retry times + // Usb Cbi retry C/B/I transport times, set by experience // USB_CBI_MAX_RETRY = 3, // - // Usb Cbi transfer timeout + // Usb Cbi wait device reset complete, set by experience + // + USB_CBI_RESET_DEVICE_STALL = 50 * USB_MASS_1_MILLISECOND, + + // + // Usb Cbi transport timeout, set by experience // - USB_CBI_RESET_TIMEOUT = 1 * USB_MASS_STALL_1_S + USB_CBI_RESET_DEVICE_TIMEOUT = 1 * USB_MASS_1_SECOND, }; // diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c index e3f5c76390..f077e2aaad 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c @@ -91,7 +91,7 @@ UsbMassInitMedia ( // Status = EFI_SUCCESS; - for (Index = 0; Index < USB_BOOT_WAIT_RETRY; Index++) { + for (Index = 0; Index < USB_BOOT_INIT_MEDIA_RETRY; Index++) { Status = UsbBootGetParams (UsbMass); if ((Status != EFI_MEDIA_CHANGED) @@ -102,7 +102,7 @@ UsbMassInitMedia ( Status = UsbBootIsUnitReady (UsbMass); if (EFI_ERROR (Status)) { - gBS->Stall (USB_BOOT_UNIT_READY_STALL * (Index + 1)); + gBS->Stall (USB_BOOT_RETRY_UNIT_READY_STALL * (Index + 1)); } } @@ -128,9 +128,17 @@ UsbMassReset ( ) { USB_MASS_DEVICE *UsbMass; + EFI_TPL OldTpl; + EFI_STATUS Status; + + OldTpl = gBS->RaiseTPL (USB_MASS_TPL); UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (This); - return UsbMass->Transport->Reset (UsbMass->Context, ExtendedVerification); + Status = UsbMass->Transport->Reset (UsbMass->Context, ExtendedVerification); + + gBS->RestoreTPL (OldTpl); + + return Status; } @@ -165,8 +173,10 @@ UsbMassReadBlocks ( USB_MASS_DEVICE *UsbMass; EFI_BLOCK_IO_MEDIA *Media; EFI_STATUS Status; + EFI_TPL OldTpl; UINTN TotalBlock; - + + OldTpl = gBS->RaiseTPL (USB_MASS_TPL); UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (This); Media = &UsbMass->BlockIoMedia; @@ -174,40 +184,47 @@ UsbMassReadBlocks ( // First, validate the parameters // if ((Buffer == NULL) || (BufferSize == 0)) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; } - - // - // If it is a remoable media, such as CD-Rom or Usb-Floppy, - // if, need to detect the media before each rw, while Usb-Flash - // needn't. However, it's hard to identify Usb-Floppy between - // Usb-Flash by now, so detect media every time. - // - Status = UsbBootDetectMedia (UsbMass); - if (EFI_ERROR (Status)) { - DEBUG ((mUsbMscError, "UsbMassReadBlocks: UsbBootDetectMedia (%r)\n", Status)); - return Status; + + // + // If it is a removable media, such as CD-Rom or Usb-Floppy, + // need to detect the media before each rw. While some of + // Usb-Flash is marked as removable media. + // + // + if (Media->RemovableMedia == TRUE) { + Status = UsbBootDetectMedia (UsbMass); + if (EFI_ERROR (Status)) { + DEBUG ((mUsbMscError, "UsbMassReadBlocks: UsbBootDetectMedia (%r)\n", Status)); + goto ON_EXIT; + } } - + // // Make sure BlockSize and LBA is consistent with BufferSize // if ((BufferSize % Media->BlockSize) != 0) { - return EFI_BAD_BUFFER_SIZE; + Status = EFI_BAD_BUFFER_SIZE; + goto ON_EXIT; } TotalBlock = BufferSize / Media->BlockSize; if (Lba + TotalBlock - 1 > Media->LastBlock) { - return EFI_BAD_BUFFER_SIZE; + Status = EFI_BAD_BUFFER_SIZE; + goto ON_EXIT; } - + Status = UsbBootReadBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer); if (EFI_ERROR (Status)) { DEBUG ((mUsbMscError, "UsbMassReadBlocks: UsbBootReadBlocks (%r) -> Reset\n", Status)); UsbMassReset (This, TRUE); } +ON_EXIT: + gBS->RestoreTPL (OldTpl); return Status; } @@ -243,8 +260,10 @@ UsbMassWriteBlocks ( USB_MASS_DEVICE *UsbMass; EFI_BLOCK_IO_MEDIA *Media; EFI_STATUS Status; + EFI_TPL OldTpl; UINTN TotalBlock; + OldTpl = gBS->RaiseTPL (USB_MASS_TPL); UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (This); Media = &UsbMass->BlockIoMedia; @@ -252,34 +271,39 @@ UsbMassWriteBlocks ( // First, validate the parameters // if ((Buffer == NULL) || (BufferSize == 0)) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; } - - // - // If it is a remoable media, such as CD-Rom or Usb-Floppy, - // if, need to detect the media before each rw, while Usb-Flash - // needn't. However, it's hard to identify Usb-Floppy between - // Usb-Flash by now, so detect media every time. - // - Status = UsbBootDetectMedia (UsbMass); - if (EFI_ERROR (Status)) { - DEBUG ((mUsbMscError, "UsbMassWriteBlocks: UsbBootDetectMedia (%r)\n", Status)); - return Status; + + // + // If it is a removable media, such as CD-Rom or Usb-Floppy, + // need to detect the media before each rw. While some of + // Usb-Flash is marked as removable media. + // + // + if (Media->RemovableMedia == TRUE) { + Status = UsbBootDetectMedia (UsbMass); + if (EFI_ERROR (Status)) { + DEBUG ((mUsbMscError, "UsbMassWriteBlocks: UsbBootDetectMedia (%r)\n", Status)); + goto ON_EXIT; + } } - + // // Make sure BlockSize and LBA is consistent with BufferSize // if ((BufferSize % Media->BlockSize) != 0) { - return EFI_BAD_BUFFER_SIZE; + Status = EFI_BAD_BUFFER_SIZE; + goto ON_EXIT; } TotalBlock = BufferSize / Media->BlockSize; if (Lba + TotalBlock - 1 > Media->LastBlock) { - return EFI_BAD_BUFFER_SIZE; + Status = EFI_BAD_BUFFER_SIZE; + goto ON_EXIT; } - + // // Try to write the data even the device is marked as ReadOnly, // and clear the status should the write succeed. @@ -289,7 +313,9 @@ UsbMassWriteBlocks ( DEBUG ((mUsbMscError, "UsbMassWriteBlocks: UsbBootWriteBlocks (%r) -> Reset\n", Status)); UsbMassReset (This, TRUE); } - + +ON_EXIT: + gBS->RestoreTPL (OldTpl); return Status; } diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.h b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.h index eeff1edcda..732861c3ec 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.h +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.h @@ -33,7 +33,13 @@ typedef struct _USB_MASS_DEVICE USB_MASS_DEVICE; #include "UsbMassBoot.h" enum { - USB_MASS_SIGNATURE= EFI_SIGNATURE_32 ('U', 's', 'b', 'K') + // + // MassStorage raises TPL to TPL_NOTIFY to serialize all its operations + // to protect shared data structures. + // + USB_MASS_TPL = TPL_NOTIFY, + + USB_MASS_SIGNATURE = EFI_SIGNATURE_32 ('U', 's', 'b', 'M'), }; struct _USB_MASS_DEVICE {