]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
MdeModulePkg/XhciDxe: Usb legacy support feature is optional. For those usb 3.0 devic...
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / XhciDxe / Xhci.c
index 762da3e0a13520e40c8fabb636c2665531a8ebf1..443df729d2edfc56bd8144eb1823f63e74a750af 100644 (file)
@@ -1,7 +1,7 @@
 /** @file
   The XHCI controller driver.
 
-Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD License
 which accompanies this distribution.  The full text of the license may be found at
@@ -140,30 +140,35 @@ XhcReset (
   )
 {
   USB_XHCI_INSTANCE  *Xhc;
-  EFI_STATUS         Status;\r
-  EFI_TPL            OldTpl;\r
-\r
-  Xhc = XHC_FROM_THIS (This);\r
-  \r
-  if (Xhc->DevicePath != NULL) {\r
-    //\r
-    // Report Status Code to indicate reset happens\r
-    //\r
-    REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
-      EFI_PROGRESS_CODE,\r
-      (EFI_IO_BUS_USB | EFI_IOB_PC_RESET),\r
-      Xhc->DevicePath\r
-      );\r
-  }  \r
-\r
-  OldTpl = gBS->RaiseTPL (XHC_TPL);\r
-\r
-  switch (Attributes) {\r
-  case EFI_USB_HC_RESET_GLOBAL:\r
-  //\r
+  EFI_STATUS         Status;
+  EFI_TPL            OldTpl;
+
+  Xhc = XHC_FROM_THIS (This);
+  
+  if (Xhc->DevicePath != NULL) {
+    //
+    // Report Status Code to indicate reset happens
+    //
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_PROGRESS_CODE,
+      (EFI_IO_BUS_USB | EFI_IOB_PC_RESET),
+      Xhc->DevicePath
+      );
+  }  
+
+  OldTpl = gBS->RaiseTPL (XHC_TPL);
+
+  switch (Attributes) {
+  case EFI_USB_HC_RESET_GLOBAL:
+  //
   // Flow through, same behavior as Host Controller Reset
   //
   case EFI_USB_HC_RESET_HOST_CONTROLLER:
+    if ((Xhc->DebugCapSupOffset != 0xFFFFFFFF) && ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset) & 0xFF) == XHC_CAP_USB_DEBUG) &&
+        ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset + XHC_DC_DCCTRL) & BIT0) != 0)) {
+      Status = EFI_SUCCESS;
+      goto ON_EXIT;
+    }
     //
     // Host Controller must be Halt when Reset it
     //
@@ -900,13 +905,26 @@ XhcControlTransfer (
     Status = EFI_SUCCESS;
   } else if (*TransferResult == EFI_USB_ERR_STALL) {
     RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
-    ASSERT_EFI_ERROR (RecoveryStatus);
+    if (EFI_ERROR (RecoveryStatus)) {
+      DEBUG ((EFI_D_ERROR, "XhcControlTransfer: XhcRecoverHaltedEndpoint failed\n"));
+    }
     Status = EFI_DEVICE_ERROR;
     goto FREE_URB;
   } else {
     goto FREE_URB;
   }
 
+  Xhc->PciIo->Flush (Xhc->PciIo);
+  
+  if (Urb->DataMap != NULL) {
+    Status = Xhc->PciIo->Unmap (Xhc->PciIo, Urb->DataMap);
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR (Status)) {
+      Status = EFI_DEVICE_ERROR;
+      goto FREE_URB;
+    }  
+  }
+
   //
   // Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.
   // Hook Get_Status request form UsbBus as we need trace device attach/detach event happened at hub.
@@ -916,7 +934,7 @@ XhcControlTransfer (
       ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)) || 
       ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_DEVICE))))) {
     DescriptorType = (UINT8)(Request->Value >> 8);
-    if ((DescriptorType == USB_DESC_TYPE_DEVICE) && (*DataLength == sizeof (EFI_USB_DEVICE_DESCRIPTOR))) {
+    if ((DescriptorType == USB_DESC_TYPE_DEVICE) && ((*DataLength == sizeof (EFI_USB_DEVICE_DESCRIPTOR)) || ((DeviceSpeed == EFI_USB_SPEED_FULL) && (*DataLength == 8)))) {
         ASSERT (Data != NULL);
         //
         // Store a copy of device scriptor as hub device need this info to configure endpoint.
@@ -936,7 +954,6 @@ XhcControlTransfer (
         } else {
           Status = XhcEvaluateContext64 (Xhc, SlotId, MaxPacket0);
         }
-        ASSERT_EFI_ERROR (Status);
     } else if (DescriptorType == USB_DESC_TYPE_CONFIG) {
       ASSERT (Data != NULL);
       if (*DataLength == ((UINT16 *)Data)[1]) {
@@ -972,7 +989,6 @@ XhcControlTransfer (
       } else {
         Status = XhcConfigHubContext64 (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);
       }
-      ASSERT_EFI_ERROR (Status);
     }
   } else if ((Request->Request     == USB_REQ_SET_CONFIG) &&
              (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {
@@ -986,7 +1002,6 @@ XhcControlTransfer (
         } else {
           Status = XhcSetConfigCmd64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
         }
-        ASSERT_EFI_ERROR (Status);
         break;
       }
     }
@@ -1007,17 +1022,15 @@ XhcControlTransfer (
       if ((State & XHC_PORTSC_PS) >> 10 == 0) {
         PortStatus.PortStatus |= USB_PORT_STAT_SUPER_SPEED;
       }
-    } else if (DeviceSpeed == EFI_USB_SPEED_HIGH) {
+    } else {
       //
-      // For high speed hub, its bit9~10 presents the attached device speed.
+      // For high or full/low speed hub, its bit9~10 presents the attached device speed.
       //
       if (XHC_BIT_IS_SET (State, BIT9)) {
         PortStatus.PortStatus |= USB_PORT_STAT_LOW_SPEED;
       } else if (XHC_BIT_IS_SET (State, BIT10)) {
         PortStatus.PortStatus |= USB_PORT_STAT_HIGH_SPEED;
       }
-    } else {
-      ASSERT (0);
     }
 
     //
@@ -1183,11 +1196,14 @@ XhcBulkTransfer (
     Status = EFI_SUCCESS;
   } else if (*TransferResult == EFI_USB_ERR_STALL) {
     RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
-    ASSERT_EFI_ERROR (RecoveryStatus);
+    if (EFI_ERROR (RecoveryStatus)) {
+      DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: XhcRecoverHaltedEndpoint failed\n"));
+    }
     Status = EFI_DEVICE_ERROR;
   }
 
-  FreePool (Urb);
+  Xhc->PciIo->Flush (Xhc->PciIo);
+  XhcFreeUrb (Xhc, Urb);
 
 ON_EXIT:
 
@@ -1353,6 +1369,7 @@ XhcAsyncInterruptTransfer (
   Status = RingIntTransferDoorBell (Xhc, Urb);
 
 ON_EXIT:
+  Xhc->PciIo->Flush (Xhc->PciIo);
   gBS->RestoreTPL (OldTpl);
 
   return Status;
@@ -1480,11 +1497,14 @@ XhcSyncInterruptTransfer (
     Status = EFI_SUCCESS;
   } else if (*TransferResult == EFI_USB_ERR_STALL) {
     RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
-    ASSERT_EFI_ERROR (RecoveryStatus);
+    if (EFI_ERROR (RecoveryStatus)) {
+      DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: XhcRecoverHaltedEndpoint failed\n"));
+    }
     Status = EFI_DEVICE_ERROR;
   }
 
-  FreePool (Urb);
+  Xhc->PciIo->Flush (Xhc->PciIo);
+  XhcFreeUrb (Xhc, Urb);
 
 ON_EXIT:
   if (EFI_ERROR (Status)) {
@@ -1684,20 +1704,21 @@ ON_EXIT:
   Create and initialize a USB_XHCI_INSTANCE structure.
 
   @param  PciIo                  The PciIo on this device.
+  @param  DevicePath             The device path of host controller.
   @param  OriginalPciAttributes  Original PCI attributes.
 
   @return The allocated and initialized USB_XHCI_INSTANCE structure if created,
           otherwise NULL.
 
-**/\r
-USB_XHCI_INSTANCE*\r
-XhcCreateUsbHc (\r
-  IN EFI_PCI_IO_PROTOCOL       *PciIo,\r
-  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
-  IN UINT64                    OriginalPciAttributes\r
-  )\r
-{\r
-  USB_XHCI_INSTANCE       *Xhc;\r
+**/
+USB_XHCI_INSTANCE*
+XhcCreateUsbHc (
+  IN EFI_PCI_IO_PROTOCOL       *PciIo,
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
+  IN UINT64                    OriginalPciAttributes
+  )
+{
+  USB_XHCI_INSTANCE       *Xhc;
   EFI_STATUS              Status;
   UINT32                  PageSize;
   UINT16                  ExtCapReg;
@@ -1710,13 +1731,13 @@ XhcCreateUsbHc (
 
   //
   // Initialize private data structure
-  //\r
-  Xhc->Signature             = XHCI_INSTANCE_SIG;\r
-  Xhc->PciIo                 = PciIo;\r
-  Xhc->DevicePath            = DevicePath;\r
-  Xhc->OriginalPciAttributes = OriginalPciAttributes;\r
-  CopyMem (&Xhc->Usb2Hc, &gXhciUsb2HcTemplate, sizeof (EFI_USB2_HC_PROTOCOL));\r
-\r
+  //
+  Xhc->Signature             = XHCI_INSTANCE_SIG;
+  Xhc->PciIo                 = PciIo;
+  Xhc->DevicePath            = DevicePath;
+  Xhc->OriginalPciAttributes = OriginalPciAttributes;
+  CopyMem (&Xhc->Usb2Hc, &gXhciUsb2HcTemplate, sizeof (EFI_USB2_HC_PROTOCOL));
+
   InitializeListHead (&Xhc->AsyncIntTransfers);
 
   //
@@ -1739,7 +1760,8 @@ XhcCreateUsbHc (
 
   ExtCapReg            = (UINT16) (Xhc->HcCParams.Data.ExtCapReg);
   Xhc->ExtCapRegBase   = ExtCapReg << 2;
-  Xhc->UsbLegSupOffset = XhcGetLegSupCapAddr (Xhc);
+  Xhc->UsbLegSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_LEGACY);
+  Xhc->DebugCapSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_DEBUG);
 
   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: Capability length 0x%x\n", Xhc->CapLength));
   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcSParams1 0x%x\n", Xhc->HcSParams1));
@@ -1748,6 +1770,7 @@ XhcCreateUsbHc (
   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: DBOff 0x%x\n", Xhc->DBOff));
   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: RTSOff 0x%x\n", Xhc->RTSOff));
   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: UsbLegSupOffset 0x%x\n", Xhc->UsbLegSupOffset));
+  DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: DebugCapSupOffset 0x%x\n", Xhc->DebugCapSupOffset));
 
   //
   // Create AsyncRequest Polling Timer
@@ -1803,6 +1826,8 @@ XhcExitBootService (
     gBS->CloseEvent (Xhc->PollTimer);
   }
 
+  XhcClearBiosOwnership (Xhc);
+
   //
   // Restore original PCI attributes
   //
@@ -1812,8 +1837,6 @@ XhcExitBootService (
                   Xhc->OriginalPciAttributes,
                   NULL
                   );
-
-  XhcClearBiosOwnership (Xhc);
 }
 
 /**
@@ -1840,13 +1863,13 @@ XhcDriverBindingStart (
   EFI_STATUS              Status;
   EFI_PCI_IO_PROTOCOL     *PciIo;
   UINT64                  Supports;
-  UINT64                  OriginalPciAttributes;\r
-  BOOLEAN                 PciAttributesSaved;\r
-  USB_XHCI_INSTANCE       *Xhc;\r
-  EFI_DEVICE_PATH_PROTOCOL  *HcDevicePath;\r
-\r
-  //\r
-  // Open the PciIo Protocol, then enable the USB host controller\r
+  UINT64                  OriginalPciAttributes;
+  BOOLEAN                 PciAttributesSaved;
+  USB_XHCI_INSTANCE       *Xhc;
+  EFI_DEVICE_PATH_PROTOCOL  *HcDevicePath;
+
+  //
+  // Open the PciIo Protocol, then enable the USB host controller
   //
   Status = gBS->OpenProtocol (
                   Controller,
@@ -1858,25 +1881,25 @@ XhcDriverBindingStart (
                   );
 
   if (EFI_ERROR (Status)) {
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Open Device Path Protocol for on USB host controller\r
-  //\r
-  HcDevicePath = NULL;\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &HcDevicePath,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                  );\r
-\r
-  PciAttributesSaved = FALSE;\r
-  //\r
-  // Save original PCI attributes\r
+    return Status;
+  }
+
+  //
+  // Open Device Path Protocol for on USB host controller
+  //
+  HcDevicePath = NULL;
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &HcDevicePath,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+
+  PciAttributesSaved = FALSE;
+  //
+  // Save original PCI attributes
   //
   Status = PciIo->Attributes (
                     PciIo,
@@ -1911,13 +1934,13 @@ XhcDriverBindingStart (
     goto CLOSE_PCIIO;
   }
 
-  //\r
-  // Create then install USB2_HC_PROTOCOL\r
-  //\r
-  Xhc = XhcCreateUsbHc (PciIo, HcDevicePath, OriginalPciAttributes);\r
-\r
-  if (Xhc == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to create USB2_HC\n"));\r
+  //
+  // Create then install USB2_HC_PROTOCOL
+  //
+  Xhc = XhcCreateUsbHc (PciIo, HcDevicePath, OriginalPciAttributes);
+
+  if (Xhc == NULL) {
+    DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to create USB2_HC\n"));
     return EFI_OUT_OF_RESOURCES;
   }