\r
UsbIoPpi = &PeiUsbDevice->UsbIoPpi;\r
\r
+ DEBUG ((EFI_D_INFO, "PeiHubEnumeration: DownStreamPortNo: %x\n", PeiUsbDevice->DownStreamPortNo));\r
+\r
for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {\r
\r
Status = PeiHubGetPortStatus (\r
continue;\r
}\r
\r
- if (IsPortConnectChange (PortStatus.PortChangeStatus)) {\r
- PeiHubClearPortFeature (\r
- PeiServices,\r
- UsbIoPpi,\r
- (UINT8) (Index + 1),\r
- EfiUsbPortConnectChange\r
- );\r
-\r
- MicroSecondDelay (100 * 1000);\r
-\r
+ DEBUG ((EFI_D_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));\r
+ //\r
+ // Only handle connection/enable/overcurrent/reset change.\r
+ //\r
+ if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {\r
+ continue;\r
+ } else {\r
if (IsPortConnect (PortStatus.PortStatus)) {\r
-\r
- PeiHubGetPortStatus (\r
- PeiServices,\r
- UsbIoPpi,\r
- (UINT8) (Index + 1),\r
- (UINT32 *) &PortStatus\r
- );\r
-\r
//\r
// Begin to deal with the new device\r
//\r
NewPeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;\r
NewPeiUsbDevice->UsbHcPpi = PeiUsbDevice->UsbHcPpi;\r
NewPeiUsbDevice->Usb2HcPpi = PeiUsbDevice->Usb2HcPpi;\r
+ NewPeiUsbDevice->Tier = (UINT8) (PeiUsbDevice->Tier + 1);\r
NewPeiUsbDevice->IsHub = 0x0;\r
NewPeiUsbDevice->DownStreamPortNo = 0x0;\r
\r
- PeiResetHubPort (PeiServices, UsbIoPpi, (UINT8)(Index + 1));\r
+ if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) || \r
+ ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0)) {\r
+ //\r
+ // If the port already has reset change flag and is connected and enabled, skip the port reset logic. \r
+ //\r
+ PeiResetHubPort (PeiServices, UsbIoPpi, (UINT8)(Index + 1));\r
+ \r
+ PeiHubGetPortStatus (\r
+ PeiServices,\r
+ UsbIoPpi,\r
+ (UINT8) (Index + 1),\r
+ (UINT32 *) &PortStatus\r
+ );\r
+ } else {\r
+ PeiHubClearPortFeature (\r
+ PeiServices,\r
+ UsbIoPpi,\r
+ (UINT8) (Index + 1),\r
+ EfiUsbPortResetChange\r
+ );\r
+ }\r
\r
- PeiHubGetPortStatus (\r
- PeiServices,\r
- UsbIoPpi,\r
- (UINT8) (Index + 1),\r
- (UINT32 *) &PortStatus\r
- );\r
+ NewPeiUsbDevice->DeviceSpeed = (UINT8) PeiUsbGetDeviceSpeed (PortStatus.PortStatus);\r
+ DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));\r
\r
- NewPeiUsbDevice->DeviceSpeed = (UINT8)IsPortLowSpeedDeviceAttached (PortStatus.PortStatus);\r
+ if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)){\r
+ NewPeiUsbDevice->MaxPacketSize0 = 512;\r
+ } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {\r
+ NewPeiUsbDevice->MaxPacketSize0 = 64;\r
+ } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {\r
+ NewPeiUsbDevice->MaxPacketSize0 = 8;\r
+ } else {\r
+ NewPeiUsbDevice->MaxPacketSize0 = 8;\r
+ }\r
\r
if(NewPeiUsbDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {\r
if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_HIGH) {\r
if (EFI_ERROR (Status)) {\r
continue;\r
}\r
+ DEBUG ((EFI_D_INFO, "PeiHubEnumeration: PeiConfigureUsbDevice Success\n"));\r
\r
Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);\r
\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ DEBUG ((EFI_D_INFO, "PeiUsbEnumeration: NumOfRootPort: %x\n", NumOfRootPort));\r
+\r
for (Index = 0; Index < NumOfRootPort; Index++) {\r
//\r
// First get root port status to detect changes happen\r
&PortStatus\r
);\r
}\r
- DEBUG ((EFI_D_INFO, "USB Status --- ConnectChange[%04x] Status[%04x]\n", PortStatus.PortChangeStatus, PortStatus.PortStatus));\r
- if (IsPortConnectChange (PortStatus.PortChangeStatus)) {\r
- //\r
- // Changes happen, first clear this change status\r
- //\r
- if (Usb2HcPpi != NULL) {\r
- Usb2HcPpi->ClearRootHubPortFeature (\r
- PeiServices,\r
- Usb2HcPpi,\r
- (UINT8) Index,\r
- EfiUsbPortConnectChange\r
- ); \r
- } else {\r
- UsbHcPpi->ClearRootHubPortFeature (\r
- PeiServices,\r
- UsbHcPpi,\r
- (UINT8) Index,\r
- EfiUsbPortConnectChange\r
- );\r
- }\r
- MicroSecondDelay (100 * 1000);\r
-\r
+ DEBUG ((EFI_D_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));\r
+ //\r
+ // Only handle connection/enable/overcurrent/reset change.\r
+ //\r
+ if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {\r
+ continue;\r
+ } else {\r
if (IsPortConnect (PortStatus.PortStatus)) {\r
- if (Usb2HcPpi != NULL) {\r
- Usb2HcPpi->GetRootHubPortStatus (\r
- PeiServices,\r
- Usb2HcPpi,\r
- (UINT8) Index,\r
- &PortStatus\r
- );\r
- } else {\r
- UsbHcPpi->GetRootHubPortStatus (\r
- PeiServices,\r
- UsbHcPpi,\r
- (UINT8) Index,\r
- &PortStatus\r
- );\r
- }\r
-\r
- //\r
- // Connect change happen\r
- //\r
MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;\r
Status = PeiServicesAllocatePages (\r
EfiBootServicesCode,\r
PeiUsbDevice->IsHub = 0x0;\r
PeiUsbDevice->DownStreamPortNo = 0x0;\r
\r
- ResetRootPort (\r
- PeiServices,\r
- PeiUsbDevice->UsbHcPpi,\r
- PeiUsbDevice->Usb2HcPpi,\r
- Index,\r
- 0\r
- );\r
+ if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) || \r
+ ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0)) {\r
+ //\r
+ // If the port already has reset change flag and is connected and enabled, skip the port reset logic. \r
+ //\r
+ ResetRootPort (\r
+ PeiServices,\r
+ PeiUsbDevice->UsbHcPpi,\r
+ PeiUsbDevice->Usb2HcPpi,\r
+ Index,\r
+ 0\r
+ );\r
\r
- if (Usb2HcPpi != NULL) {\r
- Usb2HcPpi->GetRootHubPortStatus (\r
- PeiServices,\r
- Usb2HcPpi,\r
- (UINT8) Index,\r
- &PortStatus\r
- );\r
+ if (Usb2HcPpi != NULL) {\r
+ Usb2HcPpi->GetRootHubPortStatus (\r
+ PeiServices,\r
+ Usb2HcPpi,\r
+ (UINT8) Index,\r
+ &PortStatus\r
+ );\r
+ } else {\r
+ UsbHcPpi->GetRootHubPortStatus (\r
+ PeiServices,\r
+ UsbHcPpi,\r
+ (UINT8) Index,\r
+ &PortStatus\r
+ );\r
+ }\r
} else {\r
- UsbHcPpi->GetRootHubPortStatus (\r
- PeiServices,\r
- UsbHcPpi,\r
- (UINT8) Index,\r
- &PortStatus\r
- );\r
+ if (Usb2HcPpi != NULL) {\r
+ Usb2HcPpi->ClearRootHubPortFeature (\r
+ PeiServices,\r
+ Usb2HcPpi,\r
+ (UINT8) Index,\r
+ EfiUsbPortResetChange\r
+ ); \r
+ } else {\r
+ UsbHcPpi->ClearRootHubPortFeature (\r
+ PeiServices,\r
+ UsbHcPpi,\r
+ (UINT8) Index,\r
+ EfiUsbPortResetChange\r
+ );\r
+ }\r
}\r
\r
- PeiUsbDevice->DeviceSpeed = (UINT8)IsPortLowSpeedDeviceAttached (PortStatus.PortStatus);\r
+ PeiUsbDevice->DeviceSpeed = (UINT8) PeiUsbGetDeviceSpeed (PortStatus.PortStatus);\r
DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));\r
\r
+ if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)){\r
+ PeiUsbDevice->MaxPacketSize0 = 512;\r
+ } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {\r
+ PeiUsbDevice->MaxPacketSize0 = 64;\r
+ } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {\r
+ PeiUsbDevice->MaxPacketSize0 = 8;\r
+ } else {\r
+ PeiUsbDevice->MaxPacketSize0 = 8;\r
+ }\r
+\r
//\r
// Configure that Usb Device\r
//\r
if (EFI_ERROR (Status)) {\r
continue;\r
}\r
- DEBUG ((EFI_D_INFO, "PeiConfigureUsbDevice Success\n"));\r
+ DEBUG ((EFI_D_INFO, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n"));\r
\r
Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);\r
\r
//\r
\r
for (Retry = 0; Retry < 3; Retry ++) {\r
-\r
- PeiUsbDevice->MaxPacketSize0 = 8;\r
-\r
Status = PeiUsbGetDescriptor (\r
PeiServices,\r
UsbIoPpi,\r
);\r
\r
if (!EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_INFO, "PeiUsbGet Device Descriptor the %d time Sucess\n", Retry));\r
+ DEBUG ((EFI_D_INFO, "PeiUsbGet Device Descriptor the %d time Success\n", Retry));\r
break;\r
}\r
}\r
\r
if (Retry == 3) {\r
- DEBUG ((EFI_D_ERROR, "PeiUsbGet Device Descriptor fail\n", Retry));\r
+ DEBUG ((EFI_D_ERROR, "PeiUsbGet Device Descriptor fail: %x %r\n", Retry, Status));\r
return Status;\r
}\r
\r
- PeiUsbDevice->MaxPacketSize0 = DeviceDescriptor.MaxPacketSize0;\r
+ if ((DeviceDescriptor.BcdUSB == 0x0300) && (DeviceDescriptor.MaxPacketSize0 == 9)) {\r
+ PeiUsbDevice->MaxPacketSize0 = 1 << 9;\r
+ } else {\r
+ PeiUsbDevice->MaxPacketSize0 = DeviceDescriptor.MaxPacketSize0;\r
+ }\r
\r
(*DeviceAddress) ++;\r
\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "PeiUsbSetDeviceAddress Failed\n"));\r
+ DEBUG ((EFI_D_ERROR, "PeiUsbSetDeviceAddress Failed: %r\n", Status));\r
return Status;\r
}\r
\r
)\r
{\r
EFI_STATUS Status;\r
+ UINTN Index;\r
+ EFI_USB_PORT_STATUS PortStatus;\r
\r
\r
if (Usb2HcPpi != NULL) {\r
return;\r
}\r
\r
- MicroSecondDelay (200 * 1000);\r
- \r
+ //\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
+ MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);\r
+\r
//\r
// clear reset root port\r
//\r
DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));\r
return;\r
}\r
- \r
- MicroSecondDelay (1 * 1000);\r
- \r
+\r
+ MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);\r
+\r
+ //\r
+ // USB host controller won't clear the RESET bit until\r
+ // reset is actually finished.\r
+ //\r
+ ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));\r
+\r
+ for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
+ Status = Usb2HcPpi->GetRootHubPortStatus (\r
+ PeiServices,\r
+ Usb2HcPpi,\r
+ PortNum,\r
+ &PortStatus\r
+ ); \r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {\r
+ break;\r
+ }\r
+\r
+ MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);\r
+ }\r
+\r
+ if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {\r
+ DEBUG ((EFI_D_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));\r
+ return;\r
+ }\r
+\r
+ Usb2HcPpi->ClearRootHubPortFeature (\r
+ PeiServices,\r
+ Usb2HcPpi,\r
+ PortNum,\r
+ EfiUsbPortResetChange\r
+ );\r
+\r
Usb2HcPpi->ClearRootHubPortFeature (\r
PeiServices,\r
Usb2HcPpi,\r
return;\r
}\r
\r
- MicroSecondDelay (200 * 1000);\r
+ //\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
+ MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);\r
\r
//\r
// clear reset root port\r
return;\r
}\r
\r
- MicroSecondDelay (1 * 1000);\r
- \r
+ MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);\r
+\r
+ //\r
+ // USB host controller won't clear the RESET bit until\r
+ // reset is actually finished.\r
+ //\r
+ ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));\r
+\r
+ for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
+ Status = UsbHcPpi->GetRootHubPortStatus (\r
+ PeiServices,\r
+ UsbHcPpi,\r
+ PortNum,\r
+ &PortStatus\r
+ ); \r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {\r
+ break;\r
+ }\r
+\r
+ MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);\r
+ }\r
+\r
+ if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {\r
+ DEBUG ((EFI_D_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));\r
+ return;\r
+ }\r
+\r
+ UsbHcPpi->ClearRootHubPortFeature (\r
+ PeiServices,\r
+ UsbHcPpi,\r
+ PortNum,\r
+ EfiUsbPortResetChange\r
+ );\r
+\r
UsbHcPpi->ClearRootHubPortFeature (\r
PeiServices,\r
UsbHcPpi,\r