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:
@@ -464,7 +464,7 @@ UsbCtrlRequest (
|
||||
Direction,
|
||||
Buf,
|
||||
&Len,
|
||||
50 * USB_STALL_1_MS,
|
||||
USB_GENERAL_DEVICE_REQUEST_TIMEOUT,
|
||||
&UsbDev->Translator,
|
||||
&Result
|
||||
);
|
||||
@@ -554,7 +554,7 @@ UsbGetMaxPacketSize0 (
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
gBS->Stall (100 * USB_STALL_1_MS);
|
||||
gBS->Stall (USB_RETRY_MAX_PACK_SIZE_STALL);
|
||||
}
|
||||
|
||||
return EFI_DEVICE_ERROR;
|
||||
@@ -981,7 +981,7 @@ UsbIoClearFeature (
|
||||
UsbIo,
|
||||
&DevReq,
|
||||
EfiUsbNoData,
|
||||
10 * USB_STALL_1_MS,
|
||||
USB_CLEAR_FEATURE_REQUEST_TIMEOUT,
|
||||
NULL,
|
||||
0,
|
||||
&UsbResult
|
||||
|
@@ -656,13 +656,9 @@ UsbEnumerateNewDev (
|
||||
Parent = HubIf->Device;
|
||||
Bus = Parent->Bus;
|
||||
HubApi = HubIf->HubApi;
|
||||
|
||||
|
||||
//
|
||||
// Wait at least 100 ms for the power on port to stable
|
||||
//
|
||||
gBS->Stall (100 * USB_STALL_1_MS);
|
||||
|
||||
|
||||
gBS->Stall (USB_WAIT_PORT_STABLE_STALL);
|
||||
|
||||
//
|
||||
// Hub resets the device for at least 10 milliseconds.
|
||||
// Host learns device speed. If device is of low/full speed
|
||||
@@ -774,11 +770,8 @@ UsbEnumerateNewDev (
|
||||
DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to set device address - %r\n", Status));
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Wait 20ms for set address to complete
|
||||
//
|
||||
gBS->Stall (20 * USB_STALL_1_MS);
|
||||
|
||||
gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);
|
||||
|
||||
DEBUG ((EFI_D_INFO, "UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address));
|
||||
|
||||
@@ -886,47 +879,44 @@ UsbEnumeratePort (
|
||||
|
||||
if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) {
|
||||
//
|
||||
// Both OverCurrent and OverCurrentChange set, means over current occurs,
|
||||
// which probably is caused by short circuit. It has to wait system hardware
|
||||
// to perform recovery.
|
||||
// Case1:
|
||||
// Both OverCurrent and OverCurrentChange set, means over current occurs,
|
||||
// which probably is caused by short circuit. It has to wait system hardware
|
||||
// to perform recovery.
|
||||
//
|
||||
DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: Critical Over Current\n", Port));
|
||||
return EFI_DEVICE_ERROR;
|
||||
|
||||
} else {
|
||||
//
|
||||
// Only OverCurrentChange set, means system has been recoveried from
|
||||
// over current. As a result, all ports are nearly power-off, so
|
||||
// it's necessary to detach and enumerate all ports again.
|
||||
//
|
||||
DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port));
|
||||
goto ON_ENUMERATE;
|
||||
|
||||
}
|
||||
}
|
||||
//
|
||||
// Case2:
|
||||
// Only OverCurrentChange set, means system has been recoveried from
|
||||
// over current. As a result, all ports are nearly power-off, so
|
||||
// it's necessary to detach and enumerate all ports again.
|
||||
//
|
||||
DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port));
|
||||
}
|
||||
|
||||
if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) {
|
||||
//
|
||||
// 1.1 roothub port reg doesn't reflect over-current state, while its counterpart
|
||||
// on 2.0 roothub does. When over-current has influence on 1.1 device, the port
|
||||
// would be disabled, so it's also necessary to detach and enumerate again.
|
||||
// Case3:
|
||||
// 1.1 roothub port reg doesn't reflect over-current state, while its counterpart
|
||||
// on 2.0 roothub does. When over-current has influence on 1.1 device, the port
|
||||
// would be disabled, so it's also necessary to detach and enumerate again.
|
||||
//
|
||||
DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 1.1 device Recovery Over Current\n", Port));
|
||||
goto ON_ENUMERATE;
|
||||
}
|
||||
|
||||
if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) {
|
||||
//
|
||||
// Device connected or disconnected normally.
|
||||
// Case4:
|
||||
// Device connected or disconnected normally.
|
||||
//
|
||||
goto ON_ENUMERATE;
|
||||
DEBUG ((EFI_D_ERROR, "UsbEnumeratePort: Device Connect/Discount Normally\n", Port));
|
||||
}
|
||||
|
||||
ON_ENUMERATE:
|
||||
|
||||
//
|
||||
// In case there is already a device on this port logically, it's safety to remove
|
||||
// and enumerate again.
|
||||
// Following as the above cases, it's safety to remove and create again.
|
||||
//
|
||||
Child = UsbFindChild (HubIf, Port);
|
||||
|
||||
|
@@ -745,7 +745,7 @@ UsbHubInit (
|
||||
UsbHubCtrlSetPortFeature (HubIf->Device, Index, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER);
|
||||
}
|
||||
|
||||
gBS->Stall (HubDesc.PwrOn2PwrGood * 2 * USB_STALL_1_MS);
|
||||
gBS->Stall (HubDesc.PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);
|
||||
UsbHubAckHubStatus (HubIf->Device);
|
||||
|
||||
DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d initialized\n", HubDev->Address));
|
||||
@@ -915,14 +915,14 @@ UsbHubResetPort (
|
||||
// Drive the reset signal for at least 10ms. Check USB 2.0 Spec
|
||||
// section 7.1.7.5 for timing requirements.
|
||||
//
|
||||
gBS->Stall (20 * USB_STALL_1_MS);
|
||||
gBS->Stall (USB_SET_PORT_RESET_STALL);
|
||||
|
||||
//
|
||||
// USB hub will clear RESET bit if reset is actually finished.
|
||||
//
|
||||
ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS));
|
||||
|
||||
for (Index = 0; Index < 20; Index++) {
|
||||
for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
|
||||
Status = UsbHubGetPortStatus (HubIf, Port, &PortState);
|
||||
|
||||
if (!EFI_ERROR (Status) &&
|
||||
@@ -931,7 +931,7 @@ UsbHubResetPort (
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
gBS->Stall (5 * USB_STALL_1_MS);
|
||||
gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL);
|
||||
}
|
||||
|
||||
return EFI_TIMEOUT;
|
||||
@@ -1228,7 +1228,7 @@ UsbRootHubResetPort (
|
||||
// Drive the reset signal for at least 50ms. Check USB 2.0 Spec
|
||||
// section 7.1.7.5 for timing requirements.
|
||||
//
|
||||
gBS->Stall (50 * USB_STALL_1_MS);
|
||||
gBS->Stall (USB_SET_ROOT_PORT_RESET_STALL);
|
||||
|
||||
Status = UsbHcClearRootHubPortFeature (Bus, Port, EfiUsbPortReset);
|
||||
|
||||
@@ -1237,7 +1237,7 @@ UsbRootHubResetPort (
|
||||
return Status;
|
||||
}
|
||||
|
||||
gBS->Stall (USB_STALL_1_MS);
|
||||
gBS->Stall (USB_CLR_ROOT_PORT_RESET_STALL);
|
||||
|
||||
//
|
||||
// USB host controller won't clear the RESET bit until
|
||||
@@ -1245,7 +1245,7 @@ UsbRootHubResetPort (
|
||||
//
|
||||
ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS));
|
||||
|
||||
for (Index = 0; Index < USB_HUB_LOOP; Index++) {
|
||||
for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
|
||||
Status = UsbHcGetRootHubPortStatus (Bus, Port, &PortState);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
@@ -1256,11 +1256,11 @@ UsbRootHubResetPort (
|
||||
break;
|
||||
}
|
||||
|
||||
gBS->Stall (10 * USB_STALL_1_MS);
|
||||
gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL);
|
||||
}
|
||||
|
||||
if (Index == USB_HUB_LOOP) {
|
||||
DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port));
|
||||
if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
|
||||
DEBUG ((EFI_D_ERROR, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port));
|
||||
return EFI_TIMEOUT;
|
||||
}
|
||||
|
||||
@@ -1286,7 +1286,7 @@ UsbRootHubResetPort (
|
||||
return Status;
|
||||
}
|
||||
|
||||
gBS->Stall (20 * USB_STALL_1_MS);
|
||||
gBS->Stall (USB_SET_ROOT_PORT_ENABLE_STALL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -90,8 +90,11 @@ enum {
|
||||
USB_HUB_CLASS_CODE = 0x09,
|
||||
USB_HUB_SUBCLASS_CODE = 0x00,
|
||||
|
||||
|
||||
USB_HUB_LOOP = 50
|
||||
//
|
||||
// Host software return timeout if port status doesn't change
|
||||
// after 500ms(LOOP * STALL = 100 * 5ms), set by experience
|
||||
//
|
||||
USB_WAIT_PORT_STS_CHANGE_LOOP = 100,
|
||||
};
|
||||
|
||||
#pragma pack(1)
|
||||
@@ -112,7 +115,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
UINT16 ChangedBit;
|
||||
UINT8 Feature;
|
||||
EFI_USB_PORT_FEATURE Feature;
|
||||
} USB_CHANGE_FEATURE_MAP;
|
||||
|
||||
|
||||
|
@@ -1142,44 +1142,9 @@ UsbBusControllerDriverStart (
|
||||
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);
|
||||
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.
|
||||
//
|
||||
@@ -1191,20 +1156,58 @@ UsbBusControllerDriverStart (
|
||||
);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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));
|
||||
return EFI_SUCCESS;
|
||||
|
||||
|
||||
FREE_ROOTHUB:
|
||||
gBS->FreePool (RootIf);
|
||||
gBS->FreePool (RootHub);
|
||||
|
||||
if (RootIf != NULL) {
|
||||
gBS->FreePool (RootIf);
|
||||
}
|
||||
if (RootHub != NULL) {
|
||||
gBS->FreePool (RootHub);
|
||||
}
|
||||
|
||||
UNINSTALL_USBBUS:
|
||||
gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId);
|
||||
|
||||
CLOSE_HC:
|
||||
if (UsbBus->Usb2Hc != NULL) {
|
||||
gBS->CloseProtocol (
|
||||
@@ -1214,7 +1217,6 @@ CLOSE_HC:
|
||||
Controller
|
||||
);
|
||||
}
|
||||
|
||||
if (UsbBus->UsbHc != NULL) {
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
@@ -1223,14 +1225,12 @@ CLOSE_HC:
|
||||
Controller
|
||||
);
|
||||
}
|
||||
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
gBS->FreePool (UsbBus);
|
||||
|
||||
DEBUG (( EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));
|
||||
|
@@ -55,21 +55,77 @@ typedef struct _USB_HUB_API USB_HUB_API;
|
||||
#include "UsbEnumer.h"
|
||||
|
||||
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_INTERFACE = 16,
|
||||
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
|
||||
// to protect shared data structures.
|
||||
|
Reference in New Issue
Block a user