Fixed unexpected timeout in Usb MassStorage Driver.
authoryshang1 <yshang1@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 8 Oct 2007 06:14:13 +0000 (06:14 +0000)
committeryshang1 <yshang1@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 8 Oct 2007 06:14:13 +0000 (06:14 +0000)
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

22 files changed:
MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h
MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c
MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c
MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c
MdeModulePkg/Bus/Pci/UhciDxe/Uhci.h
MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c
MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c
MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.h
MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c
MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.h
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMass.h
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.c
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.h
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.c
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.h
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.h

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