UsbIf->Device = Device;\r
UsbIf->IfDesc = IfDesc;\r
UsbIf->IfSetting = IfDesc->Settings[IfDesc->ActiveIndex];\r
- UsbIf->UsbIo = mUsbIoProtocol;\r
+\r
+ CopyMem (\r
+ &(UsbIf->UsbIo),\r
+ &mUsbIoProtocol,\r
+ sizeof (EFI_USB_IO_PROTOCOL)\r
+ );\r
\r
//\r
// Install protocols for USBIO and device path\r
// connect/disconnect. Other three events are: ENABLE, SUSPEND, RESET.\r
// ENABLE/RESET is used to reset port. SUSPEND isn't supported.\r
//\r
- Status = EFI_SUCCESS;\r
+ \r
+ if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_OVERCURRENT)) { \r
\r
- if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_OVERCURRENT)) {\r
- //\r
- // If overcurrent condition is cleared, enable the port again\r
- //\r
- if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) {\r
- HubApi->SetPortFeature (HubIf, Port, USB_HUB_PORT_POWER);\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
+ //\r
+ USB_DEBUG (("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
+ USB_DEBUG (("UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port)); \r
+ goto ON_ENUMERATE;\r
+ \r
}\r
+ }\r
\r
- } else if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) {\r
+ if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) { \r
//\r
- // Device connected or disconnected. Either way, if there is\r
- // already a device present in the bus, need to remove it.\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
- Child = UsbFindChild (HubIf, Port);\r
-\r
- if (Child != NULL) {\r
- USB_DEBUG (("UsbEnumeratePort: device at port %d removed from system\n", Port));\r
- UsbRemoveDevice (Child);\r
- }\r
+ USB_DEBUG (("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
+ //\r
+ goto ON_ENUMERATE;\r
+ }\r
\r
- if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) {\r
- //\r
- // Now, new device connected, enumerate and configure the device\r
- //\r
- USB_DEBUG (("UsbEnumeratePort: new device connected at port %d\n", Port));\r
- Status = UsbEnumerateNewDev (HubIf, Port);\r
+ON_ENUMERATE:\r
\r
- } else {\r
- USB_DEBUG (("UsbEnumeratePort: device disconnected event on port %d\n", Port));\r
- }\r
+ // \r
+ // In case there is already a device on this port logically, it's safety to remove\r
+ // and enumerate again.\r
+ //\r
+ Child = UsbFindChild (HubIf, Port);\r
+ \r
+ if (Child != NULL) {\r
+ USB_DEBUG (("UsbEnumeratePort: device at port %d removed from system\n", Port));\r
+ UsbRemoveDevice (Child);\r
}\r
-\r
+ \r
+ if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) {\r
+ //\r
+ // Now, new device connected, enumerate and configure the device \r
+ //\r
+ USB_DEBUG (("UsbEnumeratePort: new device connected at port %d\n", Port));\r
+ Status = UsbEnumerateNewDev (HubIf, Port);\r
+ \r
+ } else {\r
+ USB_DEBUG (("UsbEnumeratePort: device disconnected event on port %d\n", Port));\r
+ }\r
+ \r
HubApi->ClearPortChange (HubIf, Port);\r
return Status;\r
}\r