]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c
MdeModulePkg XhciPei/UsbBusPei: Add XHCI recovery support.
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusPei / UsbIoPeim.c
index 897b22896a2bc5d9a706df58ccfcc70697d354d4..d13a7ee0a336fc9240f2e6b5982f070ee73c7821 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 The module is used to implement Usb Io PPI interfaces.\r
 \r
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. <BR>\r
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved. <BR>\r
   \r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
@@ -24,7 +24,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
   @param  This                   The pointer of PEI_USB_IO_PPI.\r
   @param  Request                USB device request to send.\r
   @param  Direction              Specifies the data direction for the data stage.\r
-  @param  Timeout                Indicates the maximum timeout, in millisecond.\r
+  @param  Timeout                Indicates the maximum timeout, in millisecond. If Timeout\r
+                                 is 0, then the caller must wait for the function to be\r
+                                 completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.\r
   @param  Data                   Data buffer to be transmitted or received from USB device.\r
   @param  DataLength             The size (in bytes) of the data buffer.\r
 \r
@@ -50,9 +52,38 @@ PeiUsbControlTransfer (
   EFI_STATUS                  Status;\r
   PEI_USB_DEVICE              *PeiUsbDev;\r
   UINT32                      TransferResult;\r
+  EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;\r
+  UINT8                       EndpointIndex;\r
 \r
   PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);\r
 \r
+  EndpointDescriptor = NULL;\r
+  EndpointIndex = 0;\r
+\r
+  if ((Request->Request     == USB_REQ_CLEAR_FEATURE) &&\r
+      (Request->RequestType == USB_DEV_CLEAR_FEATURE_REQ_TYPE_E) &&\r
+      (Request->Value       == USB_FEATURE_ENDPOINT_HALT)) {\r
+    //\r
+    // Request->Index is the Endpoint Address, use it to get the Endpoint Index.\r
+    //\r
+    while (EndpointIndex < MAX_ENDPOINT) {\r
+      Status = PeiUsbGetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);\r
+      if (EFI_ERROR (Status)) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+      if (EndpointDescriptor->EndpointAddress == Request->Index) {\r
+        break;\r
+      }\r
+\r
+      EndpointIndex++;\r
+    }\r
+\r
+    if (EndpointIndex == MAX_ENDPOINT) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+\r
   if (PeiUsbDev->Usb2HcPpi != NULL) {\r
     Status = PeiUsbDev->Usb2HcPpi->ControlTransfer (\r
                         PeiServices,\r
@@ -74,7 +105,7 @@ PeiUsbControlTransfer (
                         PeiUsbDev->UsbHcPpi,\r
                         PeiUsbDev->DeviceAddress,\r
                         PeiUsbDev->DeviceSpeed,\r
-                        PeiUsbDev->MaxPacketSize0,\r
+                        (UINT8) PeiUsbDev->MaxPacketSize0,\r
                         Request,\r
                         Direction,\r
                         Data,\r
@@ -83,6 +114,19 @@ PeiUsbControlTransfer (
                         &TransferResult\r
                         );\r
   }\r
+\r
+  //\r
+  // Reset the endpoint toggle when endpoint stall is cleared\r
+  //\r
+  if ((Request->Request     == USB_REQ_CLEAR_FEATURE) &&\r
+      (Request->RequestType == USB_DEV_CLEAR_FEATURE_REQ_TYPE_E) &&\r
+      (Request->Value       == USB_FEATURE_ENDPOINT_HALT)) {\r
+    if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {\r
+      PeiUsbDev->DataToggle = (UINT16) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));\r
+    }\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "PeiUsbControlTransfer: %r\n", Status));\r
   return Status;\r
 }\r
 \r
@@ -96,7 +140,9 @@ PeiUsbControlTransfer (
                                 from or receive into.\r
   @param  DataLength            The lenght of the data buffer.\r
   @param  Timeout               Indicates the maximum time, in millisecond, which the\r
-                                transfer is allowed to complete.\r
+                                transfer is allowed to complete. If Timeout is 0, then\r
+                                the caller must wait for the function to be completed\r
+                                until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.\r
 \r
   @retval EFI_SUCCESS           The transfer was completed successfully.\r
   @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.\r
@@ -190,9 +236,10 @@ PeiUsbBulkTransfer (
   }\r
 \r
   if (OldToggle != DataToggle) {\r
-    PeiUsbDev->DataToggle = (UINT8) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));\r
+    PeiUsbDev->DataToggle = (UINT16) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));\r
   }\r
 \r
+  DEBUG ((EFI_D_INFO, "PeiUsbBulkTransfer: %r\n", Status));\r
   return Status;\r
 }\r
 \r