]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
Enabling usb3.0 XHCI support.
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbBus.c
index b4231079ce311ea1d368175782cfe5cb4c094a5b..b592913bd3b2e80bc0a51437dcfbd7cb13cf3dc3 100644 (file)
@@ -2,8 +2,8 @@
 \r
     Usb Bus Driver Binding and Bus IO Protocol.\r
 \r
-Copyright (c) 2004 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
 http://opensource.org/licenses/bsd-license.php\r
@@ -20,6 +20,32 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 //\r
 EFI_GUID  mUsbBusProtocolGuid = EFI_USB_BUS_PROTOCOL_GUID;\r
 \r
+EFI_USB_IO_PROTOCOL mUsbIoProtocol = {\r
+  UsbIoControlTransfer,\r
+  UsbIoBulkTransfer,\r
+  UsbIoAsyncInterruptTransfer,\r
+  UsbIoSyncInterruptTransfer,\r
+  UsbIoIsochronousTransfer,\r
+  UsbIoAsyncIsochronousTransfer,\r
+  UsbIoGetDeviceDescriptor,\r
+  UsbIoGetActiveConfigDescriptor,\r
+  UsbIoGetInterfaceDescriptor,\r
+  UsbIoGetEndpointDescriptor,\r
+  UsbIoGetStringDescriptor,\r
+  UsbIoGetSupportedLanguages,\r
+  UsbIoPortReset\r
+};\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding = {\r
+  UsbBusControllerDriverSupported,\r
+  UsbBusControllerDriverStart,\r
+  UsbBusControllerDriverStop,\r
+  0xa,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+UINT16 mMaxUsbDeviceNum = USB_MAX_DEVICES;\r
 \r
 /**\r
   USB_IO function to execute a control transfer. This\r
@@ -36,7 +62,7 @@ EFI_GUID  mUsbBusProtocolGuid = EFI_USB_BUS_PROTOCOL_GUID;
   @param  UsbStatus              USB result\r
 \r
   @retval EFI_INVALID_PARAMETER  The parameters are invalid\r
-  @retval EFI_SUCCESS            The control transfer succeded.\r
+  @retval EFI_SUCCESS            The control transfer succeeded.\r
   @retval Others                 Failed to execute the transfer\r
 \r
 **/\r
@@ -86,6 +112,7 @@ UsbIoControlTransfer (
     // Clear TT buffer when CTRL/BULK split transaction failes\r
     // Clear the TRANSLATOR TT buffer, not parent's buffer\r
     //\r
+    ASSERT (Dev->Translator.TranslatorHubAddress < mMaxUsbDeviceNum);\r
     if (Dev->Translator.TranslatorHubAddress != 0) {\r
       UsbHubCtrlClearTTBuffer (\r
         Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],\r
@@ -127,7 +154,7 @@ UsbIoControlTransfer (
   // should stop use its current UsbIo after calling this driver. The old\r
   // UsbIo will be uninstalled and new UsbIo be installed. We can't use\r
   // ReinstallProtocol since interfaces in different configuration may be\r
-  // completely irrellvant.\r
+  // completely irrelevant.\r
   //\r
   if ((Request->Request == USB_REQ_SET_CONFIG) &&\r
       (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
@@ -170,6 +197,7 @@ UsbIoControlTransfer (
     Status = UsbSelectSetting (UsbIf->IfDesc, (UINT8) Request->Value);\r
 \r
     if (!EFI_ERROR (Status)) {\r
+      ASSERT (UsbIf->IfDesc->ActiveIndex < USB_MAX_INTERFACE_SETTING);\r
       UsbIf->IfSetting = UsbIf->IfDesc->Settings[UsbIf->IfDesc->ActiveIndex];\r
     }\r
   }\r
@@ -257,6 +285,7 @@ UsbIoBulkTransfer (
     // Clear TT buffer when CTRL/BULK split transaction failes.\r
     // Clear the TRANSLATOR TT buffer, not parent's buffer\r
     //\r
+    ASSERT (Dev->Translator.TranslatorHubAddress < mMaxUsbDeviceNum);\r
     if (Dev->Translator.TranslatorHubAddress != 0) {\r
       UsbHubCtrlClearTTBuffer (\r
         Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],\r
@@ -652,7 +681,7 @@ UsbIoGetEndpointDescriptor (
 \r
   @param  This                   The USB IO instance.\r
   @param  LangIDTable            The table to return the language IDs.\r
-  @param  TableSize              The number of supported languanges.\r
+  @param  TableSize              The size, in bytes, of the table LangIDTable.\r
 \r
   @retval EFI_SUCCESS            The language ID is return.\r
 \r
@@ -675,7 +704,7 @@ UsbIoGetSupportedLanguages (
   Dev           = UsbIf->Device;\r
 \r
   *LangIDTable  = Dev->LangId;\r
-  *TableSize    = Dev->TotalLangId;\r
+  *TableSize    = (UINT16) (Dev->TotalLangId * sizeof (UINT16));\r
 \r
   gBS->RestoreTPL (OldTpl);\r
   return EFI_SUCCESS;\r
@@ -726,6 +755,7 @@ UsbIoGetStringDescriptor (
   Status = EFI_NOT_FOUND;\r
 \r
   for (Index = 0; Index < Dev->TotalLangId; Index++) {\r
+    ASSERT (Index < USB_MAX_LANG_ID);\r
     if (Dev->LangId[Index] == LangID) {\r
       break;\r
     }\r
@@ -820,7 +850,8 @@ UsbIoPortReset (
   Address       = Dev->Address;\r
   Dev->Address  = 0;\r
   Status        = UsbSetAddress (Dev, Address);\r
-  Dev->Address  = Address;\r
+\r
+  gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);\r
   \r
   if (EFI_ERROR (Status)) {\r
     DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set address for device %d - %r\n",\r
@@ -829,7 +860,7 @@ UsbIoPortReset (
     goto ON_EXIT;\r
   }\r
 \r
-  gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);\r
+  Dev->Address  = Address;\r
 \r
   DEBUG (( EFI_D_INFO, "UsbIoPortReset: device is now ADDRESSED at %d\n", Address));\r
   \r
@@ -899,13 +930,13 @@ UsbBusBuildProtocol (
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open device path %r\n", Status));\r
 \r
-    gBS->FreePool (UsbBus);\r
+    FreePool (UsbBus);\r
     return Status;\r
   }\r
 \r
   //\r
   // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).\r
-  // This is for backward compatbility with EFI 1.x. In UEFI\r
+  // This is for backward compatibility with EFI 1.x. In UEFI\r
   // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2\r
   // and USB_HC because EHCI driver will install both protocols\r
   // (for the same reason). If we don't consume both of them,\r
@@ -936,11 +967,21 @@ UsbBusBuildProtocol (
     goto CLOSE_HC;\r
   }\r
 \r
+  if (!EFI_ERROR (Status)) {\r
+    if (UsbBus->Usb2Hc->MajorRevision == 0x3) {\r
+      //\r
+      // The EFI_USB2_HC_PROTOCOL is produced for XHCI support.\r
+      // Then its max supported devices are 256.\r
+      //\r
+      mMaxUsbDeviceNum = 256;\r
+    }\r
+  }\r
+\r
   UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);\r
   UsbHcSetState (UsbBus, EfiUsbHcStateOperational);\r
 \r
   //\r
-  // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it.\r
+  // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.\r
   //\r
   Status = gBS->InstallProtocolInterface (\r
                   &Controller,\r
@@ -973,7 +1014,7 @@ UsbBusBuildProtocol (
   RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));\r
 \r
   if (RootIf == NULL) {\r
-    gBS->FreePool (RootHub);\r
+    FreePool (RootHub);\r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto FREE_ROOTHUB;\r
   }\r
@@ -981,6 +1022,7 @@ UsbBusBuildProtocol (
   RootHub->Bus            = UsbBus;\r
   RootHub->NumOfInterface = 1;\r
   RootHub->Interfaces[0]  = RootIf;\r
+  RootHub->Tier           = 0;\r
   RootIf->Signature       = USB_INTERFACE_SIGNATURE;\r
   RootIf->Device          = RootHub;\r
   RootIf->DevicePath      = UsbBus->DevicePath;\r
@@ -994,15 +1036,15 @@ UsbBusBuildProtocol (
 \r
   UsbBus->Devices[0] = RootHub;\r
 \r
-  DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %x, root hub %x\n", Controller, RootIf));\r
+  DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller, RootIf));\r
   return EFI_SUCCESS;\r
 \r
 FREE_ROOTHUB:\r
   if (RootIf != NULL) {\r
-    gBS->FreePool (RootIf);\r
+    FreePool (RootIf);\r
   }\r
   if (RootHub != NULL) {\r
-    gBS->FreePool (RootHub);\r
+    FreePool (RootHub);\r
   }\r
 \r
 UNINSTALL_USBBUS:\r
@@ -1031,28 +1073,12 @@ CLOSE_HC:
          This->DriverBindingHandle,\r
          Controller\r
          );\r
-  gBS->FreePool (UsbBus);\r
+  FreePool (UsbBus);\r
 \r
   DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));\r
   return Status;\r
 }\r
 \r
-EFI_USB_IO_PROTOCOL mUsbIoProtocol = {\r
-  UsbIoControlTransfer,\r
-  UsbIoBulkTransfer,\r
-  UsbIoAsyncInterruptTransfer,\r
-  UsbIoSyncInterruptTransfer,\r
-  UsbIoIsochronousTransfer,\r
-  UsbIoAsyncIsochronousTransfer,\r
-  UsbIoGetDeviceDescriptor,\r
-  UsbIoGetActiveConfigDescriptor,\r
-  UsbIoGetInterfaceDescriptor,\r
-  UsbIoGetEndpointDescriptor,\r
-  UsbIoGetStringDescriptor,\r
-  UsbIoGetSupportedLanguages,\r
-  UsbIoPortReset\r
-};\r
-\r
 \r
 /**\r
   The USB bus driver entry pointer.\r
@@ -1111,42 +1137,28 @@ UsbBusControllerDriverSupported (
   // Check whether device path is valid\r
   //\r
   if (RemainingDevicePath != NULL) {\r
-    DevicePathNode.DevPath = RemainingDevicePath;\r
-\r
-    if ((DevicePathNode.DevPath->Type    != MESSAGING_DEVICE_PATH) ||\r
-        (DevicePathNode.DevPath->SubType != MSG_USB_DP &&\r
-         DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP\r
-         && DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP\r
-         )) {\r
-\r
-      return EFI_UNSUPPORTED;\r
+    //\r
+    // Check if RemainingDevicePath is the End of Device Path Node, \r
+    // if yes, go on checking other conditions\r
+    //\r
+    if (!IsDevicePathEnd (RemainingDevicePath)) {\r
+      //\r
+      // If RemainingDevicePath isn't the End of Device Path Node,\r
+      // check its validation\r
+      //\r
+      DevicePathNode.DevPath = RemainingDevicePath;\r
+      \r
+      if ((DevicePathNode.DevPath->Type    != MESSAGING_DEVICE_PATH) ||\r
+          (DevicePathNode.DevPath->SubType != MSG_USB_DP &&\r
+           DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP\r
+           && DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP\r
+           )) {\r
+      \r
+        return EFI_UNSUPPORTED;\r
+      }\r
     }\r
   }\r
 \r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &ParentDevicePath,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                  );\r
-\r
-  if (Status == EFI_ALREADY_STARTED) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  gBS->CloseProtocol (\r
-         Controller,\r
-         &gEfiDevicePathProtocolGuid,\r
-         This->DriverBindingHandle,\r
-         Controller\r
-         );\r
-\r
   //\r
   // Check whether USB_HC2 protocol is installed\r
   //\r
@@ -1158,45 +1170,80 @@ UsbBusControllerDriverSupported (
                   Controller,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
                   );\r
-\r
   if (Status == EFI_ALREADY_STARTED) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
-  if (!EFI_ERROR (Status)) {\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // If failed to open USB_HC2, fall back to USB_HC\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    Controller,\r
+                    &gEfiUsbHcProtocolGuid,\r
+                    (VOID **) &UsbHc,\r
+                    This->DriverBindingHandle,\r
+                    Controller,\r
+                    EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                    );\r
+    if (Status == EFI_ALREADY_STARTED) {\r
+      return EFI_SUCCESS;\r
+    }\r
+  \r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Close the USB_HC used to perform the supported test\r
+    //\r
     gBS->CloseProtocol (\r
           Controller,\r
-          &gEfiUsb2HcProtocolGuid,\r
+          &gEfiUsbHcProtocolGuid,\r
           This->DriverBindingHandle,\r
           Controller\r
           );\r
 \r
-    return EFI_SUCCESS;\r
-  }\r
+  } else {\r
 \r
+    //\r
+    // Close the USB_HC2 used to perform the supported test\r
+    //\r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiUsb2HcProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+  }\r
\r
   //\r
-  // If failed to open USB_HC2, fall back to USB_HC\r
+  // Open the EFI Device Path protocol needed to perform the supported test\r
   //\r
   Status = gBS->OpenProtocol (\r
                   Controller,\r
-                  &gEfiUsbHcProtocolGuid,\r
-                  (VOID **) &UsbHc,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &ParentDevicePath,\r
                   This->DriverBindingHandle,\r
                   Controller,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
                   );\r
-\r
   if (Status == EFI_ALREADY_STARTED) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
   if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Close protocol, don't use device path protocol in the Support() function\r
+    //\r
     gBS->CloseProtocol (\r
           Controller,\r
-          &gEfiUsbHcProtocolGuid,\r
+          &gEfiDevicePathProtocolGuid,\r
           This->DriverBindingHandle,\r
           Controller\r
           );\r
+\r
+    return EFI_SUCCESS;\r
   }\r
 \r
   return Status;\r
@@ -1242,8 +1289,9 @@ UsbBusControllerDriverStart (
 \r
   if (EFI_ERROR (Status)) {\r
     //\r
-    // If first start, build the bus execute enviorment and install bus protocol\r
+    // If first start, build the bus execute environment and install bus protocol\r
     //\r
+    REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_IO_BUS_USB | EFI_P_PC_ENABLE));\r
     Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
@@ -1270,6 +1318,16 @@ UsbBusControllerDriverStart (
     //\r
     // Save the passed in RemainingDevicePath this time\r
     //\r
+    if (RemainingDevicePath != NULL) {\r
+      if (IsDevicePathEnd (RemainingDevicePath)) {\r
+        //\r
+        // If RemainingDevicePath is the End of Device Path Node,\r
+        // skip enumerate any device and return EFI_SUCESSS\r
+        // \r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+\r
     Status = UsbBusAddWantedUsbIoDP (UsbBusId, RemainingDevicePath);\r
     ASSERT (!EFI_ERROR (Status));\r
     //\r
@@ -1355,7 +1413,7 @@ UsbBusControllerDriverStop (
     return EFI_SUCCESS;\r
   }\r
 \r
-  DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %x\n", Controller));\r
+  DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %p\n", Controller));\r
 \r
   //\r
   // Locate USB_BUS for the current host controller\r
@@ -1388,7 +1446,7 @@ UsbBusControllerDriverStop (
 \r
   mUsbRootHubApi.Release (RootIf);\r
 \r
-  for (Index = 1; Index < USB_MAX_DEVICES; Index++) {\r
+  for (Index = 1; Index < mMaxUsbDeviceNum; Index++) {\r
     if (Bus->Devices[Index] != NULL) {\r
       UsbRemoveDevice (Bus->Devices[Index]);\r
     }\r
@@ -1435,12 +1493,3 @@ UsbBusControllerDriverStop (
 \r
   return Status;\r
 }\r
-\r
-EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding = {\r
-  UsbBusControllerDriverSupported,\r
-  UsbBusControllerDriverStart,\r
-  UsbBusControllerDriverStop,\r
-  0xa,\r
-  NULL,\r
-  NULL\r
-};\r