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
This commit is contained in:
yshang1
2007-10-08 06:14:13 +00:00
parent ba5711102a
commit 41e8ff2781
22 changed files with 386 additions and 262 deletions

View File

@ -126,7 +126,7 @@ EhcReset (
// Host Controller must be Halt when Reset it // Host Controller must be Halt when Reset it
// //
if (!EhcIsHalt (Ehc)) { if (!EhcIsHalt (Ehc)) {
Status = EhcHaltHC (Ehc, EHC_GENERIC_TIME); Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR; Status = EFI_DEVICE_ERROR;
@ -142,7 +142,7 @@ EhcReset (
EhcAckAllInterrupt (Ehc); EhcAckAllInterrupt (Ehc);
EhcFreeSched (Ehc); EhcFreeSched (Ehc);
Status = EhcResetHC (Ehc, EHC_STALL_1_SECOND); Status = EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
goto ON_EXIT; goto ON_EXIT;
@ -251,7 +251,7 @@ EhcSetState (
switch (State) { switch (State) {
case EfiUsbHcStateHalt: case EfiUsbHcStateHalt:
Status = EhcHaltHC (Ehc, EHC_GENERIC_TIME); Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
break; break;
case EfiUsbHcStateOperational: case EfiUsbHcStateOperational:
@ -260,7 +260,17 @@ EhcSetState (
break; 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; break;
case EfiUsbHcStateSuspend: case EfiUsbHcStateSuspend:
@ -437,7 +447,7 @@ EhcSetRootHubPortFeature (
// Make sure Host Controller not halt before reset it // Make sure Host Controller not halt before reset it
// //
if (EhcIsHalt (Ehc)) { if (EhcIsHalt (Ehc)) {
Status = EhcRunHC (Ehc, EHC_GENERIC_TIME); Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
EHC_DEBUG (("EhcSetRootHubPortFeature :failed to start HC - %r\n", Status)); EHC_DEBUG (("EhcSetRootHubPortFeature :failed to start HC - %r\n", Status));
@ -1539,7 +1549,7 @@ EhcDriverBindingStart (
// Robustnesss improvement such as for UoL // Robustnesss improvement such as for UoL
// //
EhcClearLegacySupport (Ehc); EhcClearLegacySupport (Ehc);
EhcResetHC (Ehc, EHC_STALL_1_SECOND); EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
Status = EhcInitHC (Ehc); Status = EhcInitHC (Ehc);
@ -1551,12 +1561,12 @@ EhcDriverBindingStart (
// //
// Start the asynchronous interrupt monitor // 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)) { if (EFI_ERROR (Status)) {
EHC_ERROR (("EhcDriverBindingStart: failed to start async interrupt monitor\n")); EHC_ERROR (("EhcDriverBindingStart: failed to start async interrupt monitor\n"));
EhcHaltHC (Ehc, EHC_GENERIC_TIME); EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
goto UNINSTALL_USBHC; goto UNINSTALL_USBHC;
} }
@ -1659,8 +1669,8 @@ EhcDriverBindingStop (
// Stop AsyncRequest Polling timer then stop the EHCI driver // Stop AsyncRequest Polling timer then stop the EHCI driver
// and uninstall the EHCI protocl. // and uninstall the EHCI protocl.
// //
gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_TIME); gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL);
EhcHaltHC (Ehc, EHC_GENERIC_TIME); EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
Status = gBS->UninstallProtocolInterface ( Status = gBS->UninstallProtocolInterface (
Controller, Controller,

View File

@ -49,18 +49,35 @@ typedef struct _USB2_HC_DEV USB2_HC_DEV;
#include "EhciDebug.h" #include "EhciDebug.h"
enum { enum {
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'), 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
}; };
// //

View File

@ -214,12 +214,12 @@ EhcWaitOpRegBit (
{ {
UINT32 Index; 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) { if (EHC_REG_BIT_IS_SET (Ehc, Offset, Bit) == WaitToSet) {
return EFI_SUCCESS; return EFI_SUCCESS;
} }
gBS->Stall (EHC_SYNC_POLL_TIME); gBS->Stall (EHC_SYNC_POLL_INTERVAL);
} }
return EFI_TIMEOUT; return EFI_TIMEOUT;
@ -614,14 +614,19 @@ EhcInitHC (
// //
EhcSetOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC); 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)) { if (EFI_ERROR (Status)) {
EHC_ERROR (("EhcInitHC: failed to enable period schedule\n")); EHC_ERROR (("EhcInitHC: failed to enable period schedule\n"));
return Status; return Status;
} }
Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIME); Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIMEOUT);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
EHC_ERROR (("EhcInitHC: failed to enable async schedule\n")); EHC_ERROR (("EhcInitHC: failed to enable async schedule\n"));

View File

@ -342,7 +342,7 @@ EhcUnlinkQhFromAsync (
// //
// Set and wait the door bell to synchronize with the hardware // 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)) { if (EFI_ERROR (Status)) {
EHC_ERROR (("EhcUnlinkQhFromAsync: Failed to synchronize with doorbell\n")); EHC_ERROR (("EhcUnlinkQhFromAsync: Failed to synchronize with doorbell\n"));
@ -659,7 +659,7 @@ EhcExecTransfer (
BOOLEAN Finished; BOOLEAN Finished;
Status = EFI_SUCCESS; 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; Finished = FALSE;
for (Index = 0; Index < Loop; Index++) { for (Index = 0; Index < Loop; Index++) {
@ -669,7 +669,7 @@ EhcExecTransfer (
break; break;
} }
gBS->Stall (EHC_SYNC_POLL_TIME); gBS->Stall (EHC_SYNC_POLL_INTERVAL);
} }
if (!Finished) { if (!Finished) {

View File

@ -56,38 +56,27 @@ UhciReset (
// //
// Stop schedule and set the Global Reset bit in the command register // 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); UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET);
// gBS->Stall (UHC_ROOT_PORT_RESET_STALL);
// Wait 50ms for root port to let reset complete
// See UHCI spec page122 Reset signaling
//
gBS->Stall (ROOT_PORT_REST_TIME);
// //
// Clear the Global Reset bit to zero. // Clear the Global Reset bit to zero.
// //
UhciClearRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET); UhciClearRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET);
// gBS->Stall (UHC_ROOT_PORT_RECOVERY_STALL);
// UHCI spec page120 reset recovery time
//
gBS->Stall (PORT_RESET_RECOVERY_TIME);
break; break;
case EFI_USB_HC_RESET_HOST_CONTROLLER: case EFI_USB_HC_RESET_HOST_CONTROLLER:
// //
// Stop schedule and set Host Controller Reset bit to 1 // 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); UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_HCRESET);
// gBS->Stall (UHC_ROOT_PORT_RECOVERY_STALL);
// this bit will be reset by Host Controller when reset is completed.
// wait 10ms to let reset complete
//
gBS->Stall (PORT_RESET_RECOVERY_TIME);
break; break;
default: default:
@ -202,7 +191,7 @@ UhciSetState (
switch (State) { switch (State) {
case EfiUsbHcStateHalt: case EfiUsbHcStateHalt:
Status = UhciStopHc (Uhc, STALL_1_SECOND); Status = UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);
break; break;
case EfiUsbHcStateOperational: case EfiUsbHcStateOperational:
@ -228,7 +217,7 @@ UhciSetState (
// //
// wait 20ms to let resume complete (20ms is specified by UHCI spec) // 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 // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0
@ -2084,7 +2073,7 @@ UhciCleanDevUp (
// Uninstall the USB_HC and USB_HC2 protocol, then disable the controller // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller
// //
Uhc = UHC_FROM_USB_HC_PROTO (This); Uhc = UHC_FROM_USB_HC_PROTO (This);
UhciStopHc (Uhc, STALL_1_SECOND); UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);
gBS->UninstallProtocolInterface ( gBS->UninstallProtocolInterface (
Controller, Controller,
@ -2188,7 +2177,7 @@ UhciDriverBindingStart (
Status = gBS->SetTimer ( Status = gBS->SetTimer (
Uhc->AsyncIntMonitor, Uhc->AsyncIntMonitor,
TimerPeriodic, TimerPeriodic,
INTERRUPT_POLLING_TIME UHC_ASYNC_POLL_INTERVAL
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {

View File

@ -51,17 +51,35 @@ typedef struct _USB_HC_DEV USB_HC_DEV;
#include "UhciDebug.h" #include "UhciDebug.h"
enum { enum {
// UHC_1_MICROSECOND = 1,
// Stall times UHC_1_MILLISECOND = 1000 * UHC_1_MICROSECOND,
// UHC_1_SECOND = 1000 * UHC_1_MILLISECOND,
STALL_1_MS = 1000,
STALL_1_SECOND = 1000 *STALL_1_MS,
UHC_SYN_POLL = 50, //
FORCE_GLOBAL_RESUME_TIME = 20 *STALL_1_MS, // UHCI register operation timeout, set by experience
ROOT_PORT_REST_TIME = 50 *STALL_1_MS, //
PORT_RESET_RECOVERY_TIME = 10 *STALL_1_MS, UHC_GENERIC_TIMEOUT = UHC_1_SECOND,
INTERRUPT_POLLING_TIME = 50 * 10000UL,
//
// Wait for force global resume(FGR) complete, refers to
// specification[UHCI11-2.1.1]
//
UHC_FORCE_GLOBAL_RESUME_STALL = 20 * UHC_1_MILLISECOND,
//
// 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 // UHC raises TPL to TPL_NOTIFY to serialize all its operations
@ -69,7 +87,7 @@ enum {
// //
UHCI_TPL = TPL_NOTIFY, 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) #pragma pack(1)

View File

@ -575,7 +575,7 @@ UhciExecuteTransfer (
Finished = FALSE; Finished = FALSE;
Status = EFI_SUCCESS; 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++) { for (Index = 0; Index < Delay; Index++) {
Finished = UhciCheckTdStatus (Uhc, Td, IsLow, QhResult); Finished = UhciCheckTdStatus (Uhc, Td, IsLow, QhResult);
@ -587,7 +587,7 @@ UhciExecuteTransfer (
break; break;
} }
gBS->Stall (UHC_SYN_POLL); gBS->Stall (UHC_SYNC_POLL_INTERVAL);
} }
if (!Finished) { if (!Finished) {

View File

@ -464,7 +464,7 @@ UsbCtrlRequest (
Direction, Direction,
Buf, Buf,
&Len, &Len,
50 * USB_STALL_1_MS, USB_GENERAL_DEVICE_REQUEST_TIMEOUT,
&UsbDev->Translator, &UsbDev->Translator,
&Result &Result
); );
@ -554,7 +554,7 @@ UsbGetMaxPacketSize0 (
return EFI_SUCCESS; return EFI_SUCCESS;
} }
gBS->Stall (100 * USB_STALL_1_MS); gBS->Stall (USB_RETRY_MAX_PACK_SIZE_STALL);
} }
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
@ -981,7 +981,7 @@ UsbIoClearFeature (
UsbIo, UsbIo,
&DevReq, &DevReq,
EfiUsbNoData, EfiUsbNoData,
10 * USB_STALL_1_MS, USB_CLEAR_FEATURE_REQUEST_TIMEOUT,
NULL, NULL,
0, 0,
&UsbResult &UsbResult

View File

@ -657,11 +657,7 @@ UsbEnumerateNewDev (
Bus = Parent->Bus; Bus = Parent->Bus;
HubApi = HubIf->HubApi; HubApi = HubIf->HubApi;
gBS->Stall (USB_WAIT_PORT_STABLE_STALL);
//
// Wait at least 100 ms for the power on port to stable
//
gBS->Stall (100 * USB_STALL_1_MS);
// //
// Hub resets the device for at least 10 milliseconds. // Hub resets the device for at least 10 milliseconds.
@ -775,10 +771,7 @@ UsbEnumerateNewDev (
goto ON_ERROR; goto ON_ERROR;
} }
// gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);
// Wait 20ms for set address to complete
//
gBS->Stall (20 * USB_STALL_1_MS);
DEBUG ((EFI_D_INFO, "UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address)); DEBUG ((EFI_D_INFO, "UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address));
@ -886,6 +879,7 @@ UsbEnumeratePort (
if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) { if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) {
// //
// Case1:
// Both OverCurrent and OverCurrentChange set, means over current occurs, // Both OverCurrent and OverCurrentChange set, means over current occurs,
// which probably is caused by short circuit. It has to wait system hardware // which probably is caused by short circuit. It has to wait system hardware
// to perform recovery. // to perform recovery.
@ -893,40 +887,36 @@ UsbEnumeratePort (
DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: Critical Over Current\n", Port)); DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: Critical Over Current\n", Port));
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} else { }
// //
// Case2:
// Only OverCurrentChange set, means system has been recoveried from // Only OverCurrentChange set, means system has been recoveried from
// over current. As a result, all ports are nearly power-off, so // over current. As a result, all ports are nearly power-off, so
// it's necessary to detach and enumerate all ports again. // it's necessary to detach and enumerate all ports again.
// //
DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port)); DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port));
goto ON_ENUMERATE;
}
} }
if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) { if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) {
// //
// Case3:
// 1.1 roothub port reg doesn't reflect over-current state, while its counterpart // 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 // 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. // 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)); 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)) { if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) {
// //
// Case4:
// Device connected or disconnected normally. // 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 // Following as the above cases, it's safety to remove and create again.
// and enumerate again.
// //
Child = UsbFindChild (HubIf, Port); Child = UsbFindChild (HubIf, Port);

View File

@ -745,7 +745,7 @@ UsbHubInit (
UsbHubCtrlSetPortFeature (HubIf->Device, Index, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER); 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); UsbHubAckHubStatus (HubIf->Device);
DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d initialized\n", HubDev->Address)); 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 // Drive the reset signal for at least 10ms. Check USB 2.0 Spec
// section 7.1.7.5 for timing requirements. // 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. // USB hub will clear RESET bit if reset is actually finished.
// //
ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS)); 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); Status = UsbHubGetPortStatus (HubIf, Port, &PortState);
if (!EFI_ERROR (Status) && if (!EFI_ERROR (Status) &&
@ -931,7 +931,7 @@ UsbHubResetPort (
return EFI_SUCCESS; return EFI_SUCCESS;
} }
gBS->Stall (5 * USB_STALL_1_MS); gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL);
} }
return EFI_TIMEOUT; return EFI_TIMEOUT;
@ -1228,7 +1228,7 @@ UsbRootHubResetPort (
// Drive the reset signal for at least 50ms. Check USB 2.0 Spec // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
// section 7.1.7.5 for timing requirements. // 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); Status = UsbHcClearRootHubPortFeature (Bus, Port, EfiUsbPortReset);
@ -1237,7 +1237,7 @@ UsbRootHubResetPort (
return Status; 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 // USB host controller won't clear the RESET bit until
@ -1245,7 +1245,7 @@ UsbRootHubResetPort (
// //
ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS)); 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); Status = UsbHcGetRootHubPortStatus (Bus, Port, &PortState);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
@ -1256,10 +1256,10 @@ UsbRootHubResetPort (
break; break;
} }
gBS->Stall (10 * USB_STALL_1_MS); gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL);
} }
if (Index == USB_HUB_LOOP) { if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
DEBUG ((EFI_D_ERROR, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port)); DEBUG ((EFI_D_ERROR, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port));
return EFI_TIMEOUT; return EFI_TIMEOUT;
} }
@ -1286,7 +1286,7 @@ UsbRootHubResetPort (
return Status; return Status;
} }
gBS->Stall (20 * USB_STALL_1_MS); gBS->Stall (USB_SET_ROOT_PORT_ENABLE_STALL);
} }
} }

View File

@ -90,8 +90,11 @@ enum {
USB_HUB_CLASS_CODE = 0x09, USB_HUB_CLASS_CODE = 0x09,
USB_HUB_SUBCLASS_CODE = 0x00, 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) #pragma pack(1)
@ -112,7 +115,7 @@ typedef struct {
typedef struct { typedef struct {
UINT16 ChangedBit; UINT16 ChangedBit;
UINT8 Feature; EFI_USB_PORT_FEATURE Feature;
} USB_CHANGE_FEATURE_MAP; } USB_CHANGE_FEATURE_MAP;

View File

@ -1142,44 +1142,9 @@ UsbBusControllerDriverStart (
goto CLOSE_HC; goto CLOSE_HC;
} }
//
// Create a fake usb device for root hub
//
RootHub = AllocateZeroPool (sizeof (USB_DEVICE));
if (RootHub == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto CLOSE_HC;
}
RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));
if (RootIf == NULL) {
gBS->FreePool (RootHub);
Status = EFI_OUT_OF_RESOURCES;
goto CLOSE_HC;
}
RootHub->Bus = UsbBus;
RootHub->NumOfInterface = 1;
RootHub->Interfaces[0] = RootIf;
RootIf->Signature = USB_INTERFACE_SIGNATURE;
RootIf->Device = RootHub;
RootIf->DevicePath = UsbBus->DevicePath;
UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL); UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);
UsbHcSetState (UsbBus, EfiUsbHcStateOperational); UsbHcSetState (UsbBus, EfiUsbHcStateOperational);
Status = mUsbRootHubApi.Init (RootIf);
if (EFI_ERROR (Status)) {
DEBUG (( EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));
goto FREE_ROOTHUB;
}
UsbBus->Devices[0] = RootHub;
// //
// Install an EFI_USB_BUS_PROTOCOL to host controler to identify it. // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it.
// //
@ -1192,18 +1157,56 @@ UsbBusControllerDriverStart (
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status)); DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));
goto CLOSE_HC;
}
mUsbRootHubApi.Release (RootIf); //
// Create a fake usb device for root hub
//
RootHub = AllocateZeroPool (sizeof (USB_DEVICE));
if (RootHub == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto UNINSTALL_USBBUS;
}
RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));
if (RootIf == NULL) {
gBS->FreePool (RootHub);
Status = EFI_OUT_OF_RESOURCES;
goto FREE_ROOTHUB; goto FREE_ROOTHUB;
} }
RootHub->Bus = UsbBus;
RootHub->NumOfInterface = 1;
RootHub->Interfaces[0] = RootIf;
RootIf->Signature = USB_INTERFACE_SIGNATURE;
RootIf->Device = RootHub;
RootIf->DevicePath = UsbBus->DevicePath;
Status = mUsbRootHubApi.Init (RootIf);
if (EFI_ERROR (Status)) {
DEBUG (( EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));
goto FREE_ROOTHUB;
}
UsbBus->Devices[0] = RootHub;
DEBUG (( EFI_D_INFO, "UsbBusStart: usb bus started on %x, root hub %x\n", Controller, RootIf)); DEBUG (( EFI_D_INFO, "UsbBusStart: usb bus started on %x, root hub %x\n", Controller, RootIf));
return EFI_SUCCESS; return EFI_SUCCESS;
FREE_ROOTHUB: FREE_ROOTHUB:
if (RootIf != NULL) {
gBS->FreePool (RootIf); gBS->FreePool (RootIf);
}
if (RootHub != NULL) {
gBS->FreePool (RootHub); gBS->FreePool (RootHub);
}
UNINSTALL_USBBUS:
gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId);
CLOSE_HC: CLOSE_HC:
if (UsbBus->Usb2Hc != NULL) { if (UsbBus->Usb2Hc != NULL) {
@ -1214,7 +1217,6 @@ CLOSE_HC:
Controller Controller
); );
} }
if (UsbBus->UsbHc != NULL) { if (UsbBus->UsbHc != NULL) {
gBS->CloseProtocol ( gBS->CloseProtocol (
Controller, Controller,
@ -1223,14 +1225,12 @@ CLOSE_HC:
Controller Controller
); );
} }
gBS->CloseProtocol ( gBS->CloseProtocol (
Controller, Controller,
&gEfiDevicePathProtocolGuid, &gEfiDevicePathProtocolGuid,
This->DriverBindingHandle, This->DriverBindingHandle,
Controller Controller
); );
gBS->FreePool (UsbBus); gBS->FreePool (UsbBus);
DEBUG (( EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status)); DEBUG (( EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));

View File

@ -55,21 +55,77 @@ typedef struct _USB_HUB_API USB_HUB_API;
#include "UsbEnumer.h" #include "UsbEnumer.h"
enum { enum {
//
// Time definition
//
USB_STALL_1_MS = 1000,
TICKS_PER_MS = 10000U,
USB_ROOTHUB_POLL_INTERVAL = 1000 * TICKS_PER_MS,
USB_HUB_POLL_INTERVAL = 64,
//
// Maximum definition
//
USB_MAX_LANG_ID = 16, USB_MAX_LANG_ID = 16,
USB_MAX_INTERFACE = 16, USB_MAX_INTERFACE = 16,
USB_MAX_DEVICES = 128, USB_MAX_DEVICES = 128,
USB_BUS_1_MILLISECOND = 1000,
//
// 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_ROOTHUB_POLL_INTERVAL = 1000 * 10000U,
USB_HUB_POLL_INTERVAL = 64,
//
// Wait for port stable to work, refers to specification
// [USB20-9.1.2]
//
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 // Bus raises TPL to TPL_NOTIFY to serialize all its operations
// to protect shared data structures. // to protect shared data structures.

View File

@ -73,8 +73,8 @@ enum {
USB_MASS_STORE_CBI1 = 0x01, // CBI protocol without command completion interrupt USB_MASS_STORE_CBI1 = 0x01, // CBI protocol without command completion interrupt
USB_MASS_STORE_BOT = 0x50, // Bulk-Only Transport USB_MASS_STORE_BOT = 0x50, // Bulk-Only Transport
USB_MASS_STALL_1_MS = 1000, USB_MASS_1_MILLISECOND = 1000,
USB_MASS_STALL_1_S = 1000 * USB_MASS_STALL_1_MS, USB_MASS_1_SECOND = 1000 * USB_MASS_1_MILLISECOND,
USB_MASS_CMD_SUCCESS = 0, USB_MASS_CMD_SUCCESS = 0,
USB_MASS_CMD_FAIL, USB_MASS_CMD_FAIL,

View File

@ -935,7 +935,7 @@ UsbClearEndpointStall (
Request.Value = USB_FEATURE_ENDPOINT_HALT; Request.Value = USB_FEATURE_ENDPOINT_HALT;
Request.Index = EndpointAddr; Request.Index = EndpointAddr;
Request.Length = 0; 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 ( Status = UsbIo->UsbControlTransfer (
UsbIo, UsbIo,

View File

@ -38,7 +38,6 @@ enum {
// //
USB_BOOT_INQUIRY_OPCODE = 0x12, USB_BOOT_INQUIRY_OPCODE = 0x12,
USB_BOOT_REQUEST_SENSE_OPCODE = 0x03, USB_BOOT_REQUEST_SENSE_OPCODE = 0x03,
USB_BOOT_MODE_SENSE10_OPCODE = 0x5A, USB_BOOT_MODE_SENSE10_OPCODE = 0x5A,
USB_BOOT_READ_CAPACITY_OPCODE = 0x25, USB_BOOT_READ_CAPACITY_OPCODE = 0x25,
USB_BOOT_TEST_UNIT_READY_OPCODE = 0x00, USB_BOOT_TEST_UNIT_READY_OPCODE = 0x00,
@ -70,38 +69,38 @@ enum {
USB_BOOT_ASC_MEDIA_CHANGE = 0x28, USB_BOOT_ASC_MEDIA_CHANGE = 0x28,
// //
// Other parameters // Supported PDT codes, or Peripheral Device Type
// //
USB_BOOT_IO_BLOCKS = 64, 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
// //
// Boot Retry times // Other parameters, Max carried size is 512B * 128 = 64KB
//
USB_BOOT_IO_BLOCKS = 128,
//
// Retry mass command times, set by experience
// //
USB_BOOT_COMMAND_RETRY = 5, 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, // 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 // USB CD-Rom and iPod devices are much slower than USB key when reponse
// most of commands, So we set 5s as timeout here. // most of commands, So we set 5s as timeout here.
// //
// //
USB_BOOT_GENERAL_CMD_TIMEOUT = 5 * USB_MASS_STALL_1_S, USB_BOOT_GENERAL_CMD_TIMEOUT = 5 * USB_MASS_1_SECOND,
//
// 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
}; };
// //

View File

@ -191,7 +191,7 @@ UsbBotSendCommand (
Result = 0; Result = 0;
DataLen = sizeof (USB_BOT_CBW); 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 // Use the UsbIo to send the command to the device. The default
@ -266,7 +266,7 @@ UsbBotDataTransfer (
} }
Result = 0; Result = 0;
Timeout = Timeout / USB_MASS_STALL_1_MS; Timeout = Timeout / USB_MASS_1_MILLISECOND;
Status = UsbBot->UsbIo->UsbBulkTransfer ( Status = UsbBot->UsbIo->UsbBulkTransfer (
UsbBot->UsbIo, UsbBot->UsbIo,
@ -328,9 +328,9 @@ UsbBotGetStatus (
Status = EFI_DEVICE_ERROR; Status = EFI_DEVICE_ERROR;
Endpoint = UsbBot->BulkInEndpoint->EndpointAddress; Endpoint = UsbBot->BulkInEndpoint->EndpointAddress;
UsbIo = UsbBot->UsbIo; 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 // Attemp to the read CSW from bulk in endpoint
// //
@ -499,7 +499,7 @@ UsbBotResetDevice (
Request.Value = 0; Request.Value = 0;
Request.Index = UsbBot->Interface.InterfaceNumber; Request.Index = UsbBot->Interface.InterfaceNumber;
Request.Length = 0; 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 ( Status = UsbBot->UsbIo->UsbControlTransfer (
UsbBot->UsbIo, UsbBot->UsbIo,
@ -521,7 +521,7 @@ UsbBotResetDevice (
// complete. We can use this to sync the device and host. For // complete. We can use this to sync the device and host. For
// now just stall 100ms to wait the device. // 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. // Clear the Bulk-In and Bulk-Out stall condition.

View File

@ -46,21 +46,21 @@ enum {
USB_BOT_COMMAND_ERROR = 0x02, // Phase error, need to reset the device 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_STALL = 100 * USB_MASS_STALL_1_MS, USB_BOT_RESET_DEVICE_STALL = 100 * USB_MASS_1_MILLISECOND,
// //
// Usb Bot transfer timeout // Usb Bot transport timeout, set by experience
// //
USB_BOT_CBW_TIMEOUT = 1 * USB_MASS_STALL_1_S, USB_BOT_SEND_CBW_TIMEOUT = 3 * USB_MASS_1_SECOND,
USB_BOT_CSW_TIMEOUT = 1 * USB_MASS_STALL_1_S, USB_BOT_RECV_CSW_TIMEOUT = 3 * USB_MASS_1_SECOND,
USB_BOT_RESET_TIMEOUT = 3 * USB_MASS_STALL_1_S USB_BOT_RESET_DEVICE_TIMEOUT = 3 * USB_MASS_1_SECOND,
}; };
// //

View File

@ -194,7 +194,7 @@ UsbCbiSendCommand (
Request.Length = CmdLen; Request.Length = CmdLen;
Status = EFI_SUCCESS; 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++) { for (Retry = 0; Retry < USB_CBI_MAX_RETRY; Retry++) {
// //
@ -281,7 +281,7 @@ UsbCbiDataTransfer (
Remain = *TransLen; Remain = *TransLen;
Retry = 0; Retry = 0;
Status = EFI_SUCCESS; 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. // Transfer the data, if the device returns NAK, retry it.
@ -376,7 +376,7 @@ UsbCbiGetStatus (
Endpoint = UsbCbi->InterruptEndpoint->EndpointAddress; Endpoint = UsbCbi->InterruptEndpoint->EndpointAddress;
Status = EFI_SUCCESS; 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 // Attemp to the read the result from interrupt endpoint
@ -555,7 +555,7 @@ UsbCbiResetDevice (
ResetCmd[0] = 0x1D; ResetCmd[0] = 0x1D;
ResetCmd[1] = 0x04; 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. // Send the command to the device. Don't use UsbCbiExecCommand here.
@ -570,7 +570,7 @@ UsbCbiResetDevice (
// 50ms to wait it complete // 50ms to wait it complete
// //
UsbCbiGetStatus (UsbCbi, Timeout, &Result); 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 // Clear the Bulk-In and Bulk-Out stall condition and

View File

@ -30,14 +30,19 @@ enum {
USB_CBI_RESET_CMD_LEN = 12, 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_MAX_RETRY = 3,
// //
// Usb Cbi transfer timeout // Usb Cbi wait device reset complete, set by experience
// //
USB_CBI_RESET_TIMEOUT = 1 * USB_MASS_STALL_1_S USB_CBI_RESET_DEVICE_STALL = 50 * USB_MASS_1_MILLISECOND,
//
// Usb Cbi transport timeout, set by experience
//
USB_CBI_RESET_DEVICE_TIMEOUT = 1 * USB_MASS_1_SECOND,
}; };
// //

View File

@ -91,7 +91,7 @@ UsbMassInitMedia (
// //
Status = EFI_SUCCESS; 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); Status = UsbBootGetParams (UsbMass);
if ((Status != EFI_MEDIA_CHANGED) if ((Status != EFI_MEDIA_CHANGED)
@ -102,7 +102,7 @@ UsbMassInitMedia (
Status = UsbBootIsUnitReady (UsbMass); Status = UsbBootIsUnitReady (UsbMass);
if (EFI_ERROR (Status)) { 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; USB_MASS_DEVICE *UsbMass;
EFI_TPL OldTpl;
EFI_STATUS Status;
OldTpl = gBS->RaiseTPL (USB_MASS_TPL);
UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (This); 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; USB_MASS_DEVICE *UsbMass;
EFI_BLOCK_IO_MEDIA *Media; EFI_BLOCK_IO_MEDIA *Media;
EFI_STATUS Status; EFI_STATUS Status;
EFI_TPL OldTpl;
UINTN TotalBlock; UINTN TotalBlock;
OldTpl = gBS->RaiseTPL (USB_MASS_TPL);
UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (This); UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (This);
Media = &UsbMass->BlockIoMedia; Media = &UsbMass->BlockIoMedia;
@ -174,32 +184,37 @@ UsbMassReadBlocks (
// First, validate the parameters // First, validate the parameters
// //
if ((Buffer == NULL) || (BufferSize == 0)) { 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 it is a removable media, such as CD-Rom or Usb-Floppy,
// if, need to detect the media before each rw, while Usb-Flash // need to detect the media before each rw. While some of
// needn't. However, it's hard to identify Usb-Floppy between // Usb-Flash is marked as removable media.
// Usb-Flash by now, so detect media every time.
// //
//
if (Media->RemovableMedia == TRUE) {
Status = UsbBootDetectMedia (UsbMass); Status = UsbBootDetectMedia (UsbMass);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
DEBUG ((mUsbMscError, "UsbMassReadBlocks: UsbBootDetectMedia (%r)\n", Status)); DEBUG ((mUsbMscError, "UsbMassReadBlocks: UsbBootDetectMedia (%r)\n", Status));
return Status; goto ON_EXIT;
}
} }
// //
// Make sure BlockSize and LBA is consistent with BufferSize // Make sure BlockSize and LBA is consistent with BufferSize
// //
if ((BufferSize % Media->BlockSize) != 0) { if ((BufferSize % Media->BlockSize) != 0) {
return EFI_BAD_BUFFER_SIZE; Status = EFI_BAD_BUFFER_SIZE;
goto ON_EXIT;
} }
TotalBlock = BufferSize / Media->BlockSize; TotalBlock = BufferSize / Media->BlockSize;
if (Lba + TotalBlock - 1 > Media->LastBlock) { 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); Status = UsbBootReadBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);
@ -208,6 +223,8 @@ UsbMassReadBlocks (
UsbMassReset (This, TRUE); UsbMassReset (This, TRUE);
} }
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status; return Status;
} }
@ -243,8 +260,10 @@ UsbMassWriteBlocks (
USB_MASS_DEVICE *UsbMass; USB_MASS_DEVICE *UsbMass;
EFI_BLOCK_IO_MEDIA *Media; EFI_BLOCK_IO_MEDIA *Media;
EFI_STATUS Status; EFI_STATUS Status;
EFI_TPL OldTpl;
UINTN TotalBlock; UINTN TotalBlock;
OldTpl = gBS->RaiseTPL (USB_MASS_TPL);
UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (This); UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (This);
Media = &UsbMass->BlockIoMedia; Media = &UsbMass->BlockIoMedia;
@ -252,32 +271,37 @@ UsbMassWriteBlocks (
// First, validate the parameters // First, validate the parameters
// //
if ((Buffer == NULL) || (BufferSize == 0)) { 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 it is a removable media, such as CD-Rom or Usb-Floppy,
// if, need to detect the media before each rw, while Usb-Flash // need to detect the media before each rw. While some of
// needn't. However, it's hard to identify Usb-Floppy between // Usb-Flash is marked as removable media.
// Usb-Flash by now, so detect media every time.
// //
//
if (Media->RemovableMedia == TRUE) {
Status = UsbBootDetectMedia (UsbMass); Status = UsbBootDetectMedia (UsbMass);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
DEBUG ((mUsbMscError, "UsbMassWriteBlocks: UsbBootDetectMedia (%r)\n", Status)); DEBUG ((mUsbMscError, "UsbMassWriteBlocks: UsbBootDetectMedia (%r)\n", Status));
return Status; goto ON_EXIT;
}
} }
// //
// Make sure BlockSize and LBA is consistent with BufferSize // Make sure BlockSize and LBA is consistent with BufferSize
// //
if ((BufferSize % Media->BlockSize) != 0) { if ((BufferSize % Media->BlockSize) != 0) {
return EFI_BAD_BUFFER_SIZE; Status = EFI_BAD_BUFFER_SIZE;
goto ON_EXIT;
} }
TotalBlock = BufferSize / Media->BlockSize; TotalBlock = BufferSize / Media->BlockSize;
if (Lba + TotalBlock - 1 > Media->LastBlock) { if (Lba + TotalBlock - 1 > Media->LastBlock) {
return EFI_BAD_BUFFER_SIZE; Status = EFI_BAD_BUFFER_SIZE;
goto ON_EXIT;
} }
// //
@ -290,6 +314,8 @@ UsbMassWriteBlocks (
UsbMassReset (This, TRUE); UsbMassReset (This, TRUE);
} }
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status; return Status;
} }

View File

@ -33,7 +33,13 @@ typedef struct _USB_MASS_DEVICE USB_MASS_DEVICE;
#include "UsbMassBoot.h" #include "UsbMassBoot.h"
enum { 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 { struct _USB_MASS_DEVICE {