// 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
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
\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
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
// 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
// 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
//\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
// 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
#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
{\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
//\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
//\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
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
break;\r
}\r
\r
- gBS->Stall (EHC_SYNC_POLL_TIME);\r
+ gBS->Stall (EHC_SYNC_POLL_INTERVAL);\r
}\r
\r
if (!Finished) {\r
//\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
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
\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
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
Status = EFI_DEVICE_ERROR;\r
goto ON_EXIT;\r
}\r
-\r
+ \r
//\r
// Set Enter Global Suspend Mode bit to 1.\r
//\r
// 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
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
#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
\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
break;\r
}\r
\r
- gBS->Stall (UHC_SYN_POLL);\r
+ gBS->Stall (UHC_SYNC_POLL_INTERVAL);\r
}\r
\r
if (!Finished) {\r
Direction,\r
Buf,\r
&Len,\r
- 50 * USB_STALL_1_MS,\r
+ USB_GENERAL_DEVICE_REQUEST_TIMEOUT,\r
&UsbDev->Translator,\r
&Result\r
);\r
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
UsbIo,\r
&DevReq,\r
EfiUsbNoData,\r
- 10 * USB_STALL_1_MS,\r
+ USB_CLEAR_FEATURE_REQUEST_TIMEOUT,\r
NULL,\r
0,\r
&UsbResult\r
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
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
\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
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
// 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
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
// 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
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
//\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
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
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
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
\r
typedef struct {\r
UINT16 ChangedBit;\r
- UINT8 Feature;\r
+ EFI_USB_PORT_FEATURE Feature;\r
} USB_CHANGE_FEATURE_MAP;\r
\r
\r
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
\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
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
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
\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
Controller\r
);\r
}\r
-\r
if (UsbBus->UsbHc != NULL) {\r
gBS->CloseProtocol (\r
Controller,\r
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
#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
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
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
// 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
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
\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
//\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
\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
}\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
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
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
// 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
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
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
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
\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
\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
// 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
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
//\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
\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
)\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
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
// 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
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
// 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
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
#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