]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
Enhance the Usb bus driver to support Star with Remaining device path.
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbEnumer.c
index 95ad8701af725892ff65123c05426180f7817b1b..6b46e5c3ce4548ef91f249a29b394e9f3d31a015 100644 (file)
@@ -143,7 +143,7 @@ UsbCreateInterface (
   UsbIf->DevicePath = AppendDevicePathNode (HubIf->DevicePath, &UsbNode.Header);\r
 \r
   if (UsbIf->DevicePath == NULL) {\r
-    USB_ERROR (("UsbCreateInterface: failed to create device path\n"));\r
+    DEBUG ((EFI_D_ERROR, "UsbCreateInterface: failed to create device path\n"));\r
 \r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto ON_ERROR;\r
@@ -159,7 +159,7 @@ UsbCreateInterface (
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    USB_ERROR (("UsbCreateInterface: failed to install UsbIo - %r\n", Status));\r
+    DEBUG ((EFI_D_ERROR, "UsbCreateInterface: failed to install UsbIo - %r\n", Status));\r
     goto ON_ERROR;\r
   }\r
 \r
@@ -178,7 +178,7 @@ UsbCreateInterface (
            NULL\r
            );\r
 \r
-    USB_ERROR (("UsbCreateInterface: failed to open host for child - %r\n", Status));\r
+    DEBUG ((EFI_D_ERROR, "UsbCreateInterface: failed to open host for child - %r\n", Status));\r
     goto ON_ERROR;\r
   }\r
 \r
@@ -277,7 +277,7 @@ UsbConnectDriver (
   // connect drivers with this interface\r
   //\r
   if (UsbIsHubInterface (UsbIf)) {\r
-    USB_DEBUG (("UsbConnectDriver: found a hub device\n"));\r
+    DEBUG ((EFI_D_INFO, "UsbConnectDriver: found a hub device\n"));\r
     Status = mUsbHubApi.Init (UsbIf);\r
 \r
   } else {\r
@@ -288,18 +288,24 @@ UsbConnectDriver (
     // twisted TPL used. It should be no problem for us to connect\r
     // or disconnect at CALLBACK.\r
     //\r
-    OldTpl            = UsbGetCurrentTpl ();\r
-    USB_DEBUG (("UsbConnectDriver: TPL before connect is %d\n", OldTpl));\r
+    \r
+    //\r
+    // Only recursively wanted usb child device\r
+    //\r
+    if (UsbBusIsWantedUsbIO (UsbIf->Device->Bus, UsbIf)) {\r
+      OldTpl            = UsbGetCurrentTpl ();\r
+      DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL before connect is %d\n", OldTpl));\r
 \r
-    gBS->RestoreTPL (TPL_CALLBACK);\r
+      gBS->RestoreTPL (TPL_CALLBACK);\r
 \r
-    Status            = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);\r
-    UsbIf->IsManaged  = (BOOLEAN)!EFI_ERROR (Status);\r
+      Status            = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);\r
+      UsbIf->IsManaged  = (BOOLEAN)!EFI_ERROR (Status);\r
 \r
-    USB_DEBUG (("UsbConnectDriver: TPL after connect is %d\n", UsbGetCurrentTpl()));\r
-    ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);\r
+      DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL after connect is %d\n", UsbGetCurrentTpl()));\r
+      ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);\r
 \r
-    gBS->RaiseTPL (OldTpl);\r
+      gBS->RaiseTPL (OldTpl);\r
+    }\r
   }\r
 \r
   return Status;\r
@@ -347,7 +353,7 @@ UsbSelectSetting (
 \r
   IfDesc->ActiveIndex = Index;\r
 \r
-  USB_DEBUG (("UsbSelectSetting: setting %d selected for interface %d\n",\r
+  DEBUG ((EFI_D_INFO, "UsbSelectSetting: setting %d selected for interface %d\n",\r
               Alternate, Setting->Desc.InterfaceNumber));\r
 \r
   //\r
@@ -406,7 +412,7 @@ UsbSelectConfig (
 \r
   Device->ActiveConfig = ConfigDesc;\r
 \r
-  USB_DEBUG (("UsbSelectConfig: config %d selected for device %d\n",\r
+  DEBUG ((EFI_D_INFO, "UsbSelectConfig: config %d selected for device %d\n",\r
               ConfigValue, Device->Address));\r
 \r
   //\r
@@ -439,7 +445,7 @@ UsbSelectConfig (
     Status = UsbConnectDriver (UsbIf);\r
 \r
     if (EFI_ERROR (Status)) {\r
-      USB_ERROR (("UsbSelectConfig: failed to connect driver %r, ignored\n", Status));\r
+      DEBUG ((EFI_D_ERROR, "UsbSelectConfig: failed to connect driver %r, ignored\n", Status));\r
     }\r
   }\r
 \r
@@ -482,14 +488,14 @@ UsbDisconnectDriver (
     // or disconnect at CALLBACK.\r
     //\r
     OldTpl           = UsbGetCurrentTpl ();\r
-    USB_DEBUG (("UsbDisconnectDriver: old TPL is %d\n", OldTpl));\r
+    DEBUG ((EFI_D_INFO, "UsbDisconnectDriver: old TPL is %d\n", OldTpl));\r
 \r
     gBS->RestoreTPL (TPL_CALLBACK);\r
 \r
     gBS->DisconnectController (UsbIf->Handle, NULL, NULL);\r
     UsbIf->IsManaged = FALSE;\r
 \r
-    USB_DEBUG (("UsbDisconnectDriver: TPL after disconnect is %d\n", UsbGetCurrentTpl()));\r
+    DEBUG (( EFI_D_INFO, "UsbDisconnectDriver: TPL after disconnect is %d\n", UsbGetCurrentTpl()));\r
     ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);\r
 \r
     gBS->RaiseTPL (OldTpl);\r
@@ -569,14 +575,14 @@ UsbRemoveDevice (
     Status = UsbRemoveDevice (Child);\r
 \r
     if (EFI_ERROR (Status)) {\r
-      USB_ERROR (("UsbRemoveDevice: failed to remove child, ignore error\n"));\r
+      DEBUG ((EFI_D_ERROR, "UsbRemoveDevice: failed to remove child, ignore error\n"));\r
       Bus->Devices[Index] = NULL;\r
     }\r
   }\r
 \r
   UsbRemoveConfig (Device);\r
 \r
-  USB_DEBUG (("UsbRemoveDevice: device %d removed\n", Device->Address));\r
+  DEBUG (( EFI_D_INFO, "UsbRemoveDevice: device %d removed\n", Device->Address));\r
 \r
   Bus->Devices[Device->Address] = NULL;\r
   UsbFreeDevice (Device);\r
@@ -656,13 +662,9 @@ UsbEnumerateNewDev (
   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
@@ -672,12 +674,12 @@ UsbEnumerateNewDev (
   Status = HubApi->ResetPort (HubIf, Port);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    USB_ERROR (("UsbEnumerateNewDev: failed to reset port %d - %r\n", Port, Status));\r
+    DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to reset port %d - %r\n", Port, Status));\r
 \r
     return Status;\r
   }\r
 \r
-  USB_DEBUG (("UsbEnumerateNewDev: hub port %d is reset\n", Port));\r
+  DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: hub port %d is reset\n", Port));\r
 \r
   Child = UsbCreateDevice (HubIf, Port);\r
 \r
@@ -692,7 +694,7 @@ UsbEnumerateNewDev (
   Status = HubApi->GetPortStatus (HubIf, Port, &PortState);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    USB_ERROR (("UsbEnumerateNewDev: failed to get speed of port %d\n", Port));\r
+    DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to get speed of port %d\n", Port));\r
     goto ON_ERROR;\r
   }\r
 \r
@@ -706,7 +708,7 @@ UsbEnumerateNewDev (
     Child->Speed = EFI_USB_SPEED_FULL;\r
   }\r
 \r
-  USB_DEBUG (("UsbEnumerateNewDev: device is of %d speed\n", Child->Speed));\r
+  DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device is of %d speed\n", Child->Speed));\r
 \r
   if (Child->Speed != EFI_USB_SPEED_HIGH) {\r
     //\r
@@ -723,7 +725,7 @@ UsbEnumerateNewDev (
       Child->Translator = Parent->Translator;\r
     }\r
 \r
-    USB_DEBUG (("UsbEnumerateNewDev: device uses translator (%d, %d)\n",\r
+    DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device uses translator (%d, %d)\n",\r
                 Child->Translator.TranslatorHubAddress,\r
                 Child->Translator.TranslatorPortNumber));\r
   }\r
@@ -742,11 +744,11 @@ UsbEnumerateNewDev (
   Status = UsbGetMaxPacketSize0 (Child);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    USB_ERROR (("UsbEnumerateNewDev: failed to get max packet for EP 0 - %r\n", Status));\r
+    DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to get max packet for EP 0 - %r\n", Status));\r
     goto ON_ERROR;\r
   }\r
 \r
-  USB_DEBUG (("UsbEnumerateNewDev: max packet size for EP 0 is %d\n", Child->MaxPacket0));\r
+  DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: max packet size for EP 0 is %d\n", Child->MaxPacket0));\r
 \r
   //\r
   // Host assigns an address to the device. Device completes the\r
@@ -760,7 +762,7 @@ UsbEnumerateNewDev (
   }\r
 \r
   if (Address == USB_MAX_DEVICES) {\r
-    USB_ERROR (("UsbEnumerateNewDev: address pool is full for port %d\n", Port));\r
+    DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: address pool is full for port %d\n", Port));\r
 \r
     Status = EFI_ACCESS_DENIED;\r
     goto ON_ERROR;\r
@@ -771,16 +773,13 @@ UsbEnumerateNewDev (
   Child->Address        = Address;\r
 \r
   if (EFI_ERROR (Status)) {\r
-    USB_ERROR (("UsbEnumerateNewDev: failed to set device address - %r\n", Status));\r
+    DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to set device address - %r\n", Status));\r
     goto ON_ERROR;\r
   }\r
+  \r
+  gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);\r
 \r
-  //\r
-  // Wait 20ms for set address to complete\r
-  //\r
-  gBS->Stall (20 * USB_STALL_1_MS);\r
-\r
-  USB_DEBUG (("UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address));\r
+  DEBUG ((EFI_D_INFO, "UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address));\r
 \r
   //\r
   // Host learns about the device¡¯s abilities by requesting device's\r
@@ -789,7 +788,7 @@ UsbEnumerateNewDev (
   Status = UsbBuildDescTable (Child);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    USB_ERROR (("UsbEnumerateNewDev: failed to build descriptor table - %r\n", Status));\r
+    DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to build descriptor table - %r\n", Status));\r
     goto ON_ERROR;\r
   }\r
 \r
@@ -801,11 +800,11 @@ UsbEnumerateNewDev (
   Status = UsbSetConfig (Child, Config);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    USB_ERROR (("UsbEnumerateNewDev: failed to set configure %d - %r\n", Config, Status));\r
+    DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to set configure %d - %r\n", Config, Status));\r
     goto ON_ERROR;\r
   }\r
 \r
-  USB_DEBUG (("UsbEnumerateNewDev: device %d is now in CONFIGED state\n", Address));\r
+  DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device %d is now in CONFIGED state\n", Address));\r
 \r
   //\r
   // Host assigns and loads a device driver.\r
@@ -813,7 +812,7 @@ UsbEnumerateNewDev (
   Status = UsbSelectConfig (Child, Config);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    USB_ERROR (("UsbEnumerateNewDev: failed to create interfaces - %r\n", Status));\r
+    DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to create interfaces - %r\n", Status));\r
     goto ON_ERROR;\r
   }\r
 \r
@@ -865,7 +864,7 @@ UsbEnumeratePort (
   Status = HubApi->GetPortStatus (HubIf, Port, &PortState);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    USB_ERROR (("UsbEnumeratePort: failed to get state of port %d\n", Port));\r
+    DEBUG ((EFI_D_ERROR, "UsbEnumeratePort: failed to get state of port %d\n", Port));\r
     return Status;\r
   }\r
 \r
@@ -873,7 +872,7 @@ UsbEnumeratePort (
     return EFI_SUCCESS;\r
   }\r
 \r
-  USB_DEBUG (("UsbEnumeratePort: port %d state - %x, change - %x\n",\r
+  DEBUG (( EFI_D_INFO, "UsbEnumeratePort: port %d state - %x, change - %x\n",\r
               Port, PortState.PortStatus, PortState.PortChangeStatus));\r
 \r
   //\r
@@ -881,40 +880,68 @@ UsbEnumeratePort (
   // 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
+    if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) {\r
+      //\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
+    } \r
     //\r
-    // If overcurrent condition is cleared, enable the port again\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
-    if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) {\r
-      HubApi->SetPortFeature (HubIf, Port, USB_HUB_PORT_POWER);\r
-    }\r
+    DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port)); \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
+    // 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
-    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
-    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
+    DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 1.1 device Recovery Over Current\n", Port));\r
+  }\r
+  \r
+  if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) {\r
+    //\r
+    // Case4:\r
+    //   Device connected or disconnected normally. \r
+    //\r
+    DEBUG ((EFI_D_ERROR, "UsbEnumeratePort: Device Connect/Discount Normally\n", Port));\r
   }\r
 \r
+  // \r
+  // Following as the above cases, it's safety to remove and create again.\r
+  //\r
+  Child = UsbFindChild (HubIf, Port);\r
+  \r
+  if (Child != NULL) {\r
+    DEBUG (( EFI_D_INFO, "UsbEnumeratePort: device at port %d removed from system\n", Port));\r
+    UsbRemoveDevice (Child);\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
+    DEBUG (( EFI_D_INFO, "UsbEnumeratePort: new device connected at port %d\n", Port));\r
+    Status = UsbEnumerateNewDev (HubIf, Port);\r
+  \r
+  } else {\r
+    DEBUG (( EFI_D_INFO, "UsbEnumeratePort: device disconnected event on port %d\n", Port));\r
+  }\r
+  \r
   HubApi->ClearPortChange (HubIf, Port);\r
   return Status;\r
 }\r
@@ -980,6 +1007,7 @@ UsbHubEnumeration (
 \r
 **/\r
 VOID\r
+EFIAPI\r
 UsbRootHubEnumeration (\r
   IN EFI_EVENT            Event,\r
   IN VOID                 *Context\r