]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassCbi.c
Update the copyright notice format
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbMassStorageDxe / UsbMassCbi.c
index 5c07c548b9081631b3946a30cc10c3a475f3a3d8..f9c56e24e8dc0664fa6202b6dbccc064eb0fff8f 100644 (file)
@@ -1,7 +1,11 @@
 /** @file\r
+  Implementation of the USB mass storage Control/Bulk/Interrupt transport,\r
+  according to USB Mass Storage Class Control/Bulk/Interrupt (CBI) Transport, Revision 1.1.\r
+  Notice: it is being obsoleted by the standard body in favor of the BOT\r
+  (Bulk-Only Transport).\r
 \r
-Copyright (c) 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2007 - 2008, 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
@@ -9,53 +13,53 @@ http://opensource.org/licenses/bsd-license.php
 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 \r
-Module Name:\r
-\r
-  UsbMassCbi.c\r
-\r
-Abstract:\r
-\r
-  Implementation of the USB mass storage Control/Bulk/Interrupt transpor.\r
-  Notice: it is being obseleted by the standard body in favor of the BOT\r
-  (Bulk-Only Transport).\r
-\r
-Revision History\r
-\r
-\r
 **/\r
 \r
-#include "UsbMass.h"\r
+#include "UsbMassBoot.h"\r
 #include "UsbMassCbi.h"\r
 \r
-UINTN mUsbCbiInfo  = DEBUG_INFO;\r
-UINTN mUsbCbiError = DEBUG_ERROR;\r
-\r
-STATIC\r
-EFI_STATUS\r
-UsbCbiResetDevice (\r
-  IN  VOID                    *Context,\r
-  IN  BOOLEAN                  ExtendedVerification\r
-  );\r
+//\r
+// Definition of USB CBI0 Transport Protocol\r
+//\r
+USB_MASS_TRANSPORT mUsbCbi0Transport = {\r
+  USB_MASS_STORE_CBI0,\r
+  UsbCbiInit,\r
+  UsbCbiExecCommand,\r
+  UsbCbiResetDevice,\r
+  NULL,\r
+  UsbCbiCleanUp\r
+};\r
 \r
+//\r
+// Definition of USB CBI1 Transport Protocol\r
+//\r
+USB_MASS_TRANSPORT mUsbCbi1Transport = {\r
+  USB_MASS_STORE_CBI1,\r
+  UsbCbiInit,\r
+  UsbCbiExecCommand,\r
+  UsbCbiResetDevice,\r
+  NULL,\r
+  UsbCbiCleanUp\r
+};\r
 \r
 /**\r
-  Initialize the USB mass storage class CBI transport protocol.\r
-  If Context isn't NULL, it will save its context in it.\r
+  Initializes USB CBI protocol.\r
+\r
+  This function initializes the USB mass storage class CBI protocol.\r
+  It will save its context which is a USB_CBI_PROTOCOL structure\r
+  in the Context if Context isn't NULL.\r
 \r
-  @param  UsbIo                 The USB IO to use\r
-  @param  Controller            The device controller\r
-  @param  Context               The variable to save context in\r
+  @param  UsbIo                 The USB I/O Protocol instance\r
+  @param  Context               The buffer to save the context to\r
 \r
-  @retval EFI_OUT_OF_RESOURCES  Failed to allocate memory\r
-  @retval EFI_UNSUPPORTED       The device isn't supported\r
-  @retval EFI_SUCCESS           The CBI protocol is initialized.\r
+  @retval EFI_SUCCESS           The device is successfully initialized.\r
+  @retval EFI_UNSUPPORTED       The transport protocol doesn't support the device.\r
+  @retval Other                 The USB CBI initialization fails.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 UsbCbiInit (\r
   IN  EFI_USB_IO_PROTOCOL   *UsbIo,\r
-  IN  EFI_HANDLE            Controller,\r
   OUT VOID                  **Context       OPTIONAL\r
   )\r
 {\r
@@ -66,21 +70,18 @@ UsbCbiInit (
   UINT8                         Index;\r
 \r
   //\r
-  // Allocate the CBI context\r
+  // Allocate the CBI context for USB_CBI_PROTOCOL and 3 endpoint descriptors.\r
   //\r
   UsbCbi = AllocateZeroPool (\r
              sizeof (USB_CBI_PROTOCOL) + 3 * sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)\r
              );\r
-\r
-  if (UsbCbi == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
+  ASSERT (UsbCbi != NULL);\r
 \r
   UsbCbi->UsbIo = UsbIo;\r
 \r
   //\r
-  // Get the interface descriptor and validate that it is a USB mass\r
-  // storage class CBI interface.\r
+  // Get the interface descriptor and validate that it\r
+  // is a USB Mass Storage CBI interface.\r
   //\r
   Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &UsbCbi->Interface);\r
   if (EFI_ERROR (Status)) {\r
@@ -120,7 +121,6 @@ UsbCbiInit (
         UsbCbi->BulkOutEndpoint   = (EFI_USB_ENDPOINT_DESCRIPTOR *) (UsbCbi + 1) + 1;\r
         CopyMem(UsbCbi->BulkOutEndpoint, &EndPoint, sizeof (EndPoint));\r
       }\r
-\r
     } else if (USB_IS_INTERRUPT_ENDPOINT (EndPoint.Attributes)) {\r
       //\r
       // Use the first interrupt endpoint if it is CBI0\r
@@ -134,10 +134,11 @@ UsbCbiInit (
     }\r
   }\r
 \r
-  if ((UsbCbi->BulkInEndpoint == NULL)\r
-      || (UsbCbi->BulkOutEndpoint == NULL)\r
-      || ((Interface->InterfaceProtocol == USB_MASS_STORE_CBI0)\r
-          && (UsbCbi->InterruptEndpoint == NULL))) {\r
+  if ((UsbCbi->BulkInEndpoint == NULL) || (UsbCbi->BulkOutEndpoint == NULL)) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto ON_ERROR;\r
+  }\r
+  if ((Interface->InterfaceProtocol == USB_MASS_STORE_CBI0) && (UsbCbi->InterruptEndpoint == NULL)) {\r
     Status = EFI_UNSUPPORTED;\r
     goto ON_ERROR;\r
   }\r
@@ -145,30 +146,31 @@ UsbCbiInit (
   if (Context != NULL) {\r
     *Context = UsbCbi;\r
   } else {\r
-    gBS->FreePool (UsbCbi);\r
+    FreePool (UsbCbi);\r
   }\r
\r
   return EFI_SUCCESS;\r
 \r
 ON_ERROR:\r
-  gBS->FreePool (UsbCbi);\r
+  FreePool (UsbCbi);\r
   return Status;\r
 }\r
 \r
-\r
-\r
 /**\r
   Send the command to the device using class specific control transfer.\r
 \r
+  This function sends command to the device using class specific control transfer.\r
+  The CBI contains three phases: Command, Data, and Status. This is Command phase.\r
+\r
   @param  UsbCbi                The USB CBI protocol\r
   @param  Cmd                   The high level command to transfer to device\r
   @param  CmdLen                The length of the command\r
   @param  Timeout               The time to wait the command to finish\r
 \r
-  @retval EFI_SUCCESS           The command is transferred to device\r
+  @retval EFI_SUCCESS           The command is sent to the device.\r
   @retval Others                The command failed to transfer to device\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 UsbCbiSendCommand (\r
   IN USB_CBI_PROTOCOL       *UsbCbi,\r
@@ -185,7 +187,7 @@ UsbCbiSendCommand (
 \r
   //\r
   // Fill in the device request, CBI use the "Accept Device-Specific\r
-  // Cmd" (ADSC) class specific request to send commands\r
+  // Cmd" (ADSC) class specific request to send commands.\r
   //\r
   Request.RequestType = 0x21;\r
   Request.Request     = 0;\r
@@ -194,11 +196,11 @@ UsbCbiSendCommand (
   Request.Length      = CmdLen;\r
 \r
   Status              = EFI_SUCCESS;\r
-  Timeout             = Timeout / USB_MASS_STALL_1_MS;\r
+  Timeout             = Timeout / USB_MASS_1_MILLISECOND;\r
 \r
   for (Retry = 0; Retry < USB_CBI_MAX_RETRY; Retry++) {\r
     //\r
-    // Use the UsbIo to send the command to the device\r
+    // Use USB I/O Protocol to send the command to the device\r
     //\r
     TransStatus = 0;\r
     DataLen     = CmdLen;\r
@@ -230,20 +232,23 @@ UsbCbiSendCommand (
 \r
 \r
 /**\r
-  Transfer data between the device and host. The CBI contains three phase,\r
-  command, data, and status. This is data phase.\r
+  Transfer data between the device and host.\r
+\r
+  This function transfers data between the device and host.\r
+  The CBI contains three phases: Command, Data, and Status. This is Data phase.\r
 \r
   @param  UsbCbi                The USB CBI device\r
   @param  DataDir               The direction of the data transfer\r
-  @param  Data                  The buffer to hold the data\r
-  @param  TransLen              The expected transfer length\r
-  @param  Timeout               The time to wait the command to execute\r
+  @param  Data                  The buffer to hold the data for input or output.\r
+  @param  TransLen              On input, the expected transfer length.\r
+                                On output, the length of data actually transferred.\r
+  @param  Timeout               The time to wait for the command to execute\r
 \r
-  @retval EFI_SUCCESS           The data transfer succeeded\r
+  @retval EFI_SUCCESS           The data transferred successfully.\r
+  @retval EFI_SUCCESS           No data to transfer\r
   @retval Others                Failed to transfer all the data\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 UsbCbiDataTransfer (\r
   IN USB_CBI_PROTOCOL         *UsbCbi,\r
@@ -262,7 +267,7 @@ UsbCbiDataTransfer (
   UINTN                       Retry;\r
 \r
   //\r
-  // It's OK if no data to transfer\r
+  // If no data to transfer, just return EFI_SUCCESS.\r
   //\r
   if ((DataDir == EfiUsbNoData) || (*TransLen == 0)) {\r
     return EFI_SUCCESS;\r
@@ -281,10 +286,10 @@ UsbCbiDataTransfer (
   Remain  = *TransLen;\r
   Retry   = 0;\r
   Status  = EFI_SUCCESS;\r
-  Timeout = Timeout / USB_MASS_STALL_1_MS;\r
+  Timeout = Timeout / USB_MASS_1_MILLISECOND;\r
 \r
   //\r
-  // Transfer the data, if the device returns NAK, retry it.\r
+  // Transfer the data with a loop. The length of data transferred once is restricted.\r
   //\r
   while (Remain > 0) {\r
     TransStatus = 0;\r
@@ -307,15 +312,15 @@ UsbCbiDataTransfer (
       if (TransStatus == EFI_USB_ERR_NAK) {\r
         //\r
         // The device can NAK the host if either the data/buffer isn't\r
-        // aviable or the command is in-progress. The data can be partly\r
-        // transferred. The transfer is aborted if several succssive data\r
-        // transfer commands are NAKed.\r
+        // aviable or the command is in-progress.\r
+        // If data are partially transferred, we just ignore NAK and continue.\r
+        // If all data have been transferred and status is NAK, then we retry for several times.\r
+        // If retry exceeds the USB_CBI_MAX_RETRY, then return error status.\r
         //\r
         if (Increment == 0) {\r
           if (++Retry > USB_CBI_MAX_RETRY) {\r
             goto ON_EXIT;\r
           }\r
-\r
         } else {\r
           Next   += Increment;\r
           Remain -= Increment;\r
@@ -347,20 +352,21 @@ ON_EXIT:
 \r
 \r
 /**\r
-  Get the result of high level command execution from interrupt\r
-  endpoint. This function returns the USB transfer status, and\r
-  put the high level command execution result in Result.\r
+  Gets the result of high level command execution from interrupt endpoint.\r
+\r
+  This function returns the USB transfer status, and put the high level\r
+  command execution result in Result.\r
+  The CBI contains three phases: Command, Data, and Status. This is Status phase.\r
 \r
   @param  UsbCbi                The USB CBI protocol\r
-  @param  Timeout               The time to wait the command to execute\r
-  @param  Result                GC_TODO: add argument description\r
+  @param  Timeout               The time to wait for the command to execute\r
+  @param  Result                The result of the command execution.\r
 \r
   @retval EFI_SUCCESS           The high level command execution result is\r
                                 retrieved in Result.\r
   @retval Others                Failed to retrieve the result.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 UsbCbiGetStatus (\r
   IN  USB_CBI_PROTOCOL        *UsbCbi,\r
@@ -376,7 +382,7 @@ UsbCbiGetStatus (
 \r
   Endpoint  = UsbCbi->InterruptEndpoint->EndpointAddress;\r
   Status    = EFI_SUCCESS;\r
-  Timeout   = Timeout / USB_MASS_STALL_1_MS;\r
+  Timeout   = Timeout / USB_MASS_1_MILLISECOND;\r
 \r
   //\r
   // Attemp to the read the result from interrupt endpoint\r
@@ -408,22 +414,22 @@ UsbCbiGetStatus (
 \r
 \r
 /**\r
-  Execute USB mass storage command through the CBI0/CBI1 transport protocol\r
+  Execute USB mass storage command through the CBI0/CBI1 transport protocol.\r
 \r
-  @param  Context               The USB CBI device\r
+  @param  Context               The USB CBI Protocol.\r
   @param  Cmd                   The command to transfer to device\r
   @param  CmdLen                The length of the command\r
   @param  DataDir               The direction of data transfer\r
   @param  Data                  The buffer to hold the data\r
   @param  DataLen               The length of the buffer\r
+  @param  Lun                   Should be 0, this field for bot only\r
   @param  Timeout               The time to wait\r
   @param  CmdStatus             The result of the command execution\r
 \r
-  @retval EFI_SUCCESS           The command is executed OK and result in CmdStatus.\r
-  @retval EFI_DEVICE_ERROR      Failed to execute the command\r
+  @retval EFI_SUCCESS           The command is executed successfully.\r
+  @retval Other                 Failed to execute the command\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 UsbCbiExecCommand (\r
   IN  VOID                    *Context,\r
@@ -432,6 +438,7 @@ UsbCbiExecCommand (
   IN  EFI_USB_DATA_DIRECTION  DataDir,\r
   IN  VOID                    *Data,\r
   IN  UINT32                  DataLen,\r
+  IN  UINT8                   Lun,\r
   IN  UINT32                  Timeout,\r
   OUT UINT32                  *CmdStatus\r
   )\r
@@ -450,39 +457,42 @@ UsbCbiExecCommand (
   //\r
   Status = UsbCbiSendCommand (UsbCbi, Cmd, CmdLen, Timeout);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((mUsbCbiError, "UsbCbiExecCommand: UsbCbiSendCommand (%r)\n",Status));\r
+    gBS->Stall(10 * USB_MASS_1_MILLISECOND);\r
+    DEBUG ((EFI_D_ERROR, "UsbCbiExecCommand: UsbCbiSendCommand (%r)\n",Status));\r
     return Status;\r
   }\r
 \r
   //\r
-  // Transfer the data, return this status if no interrupt endpoint\r
+  // Transfer the data. Return this status if no interrupt endpoint\r
   // is used to report the transfer status.\r
   //\r
   TransLen = (UINTN) DataLen;\r
 \r
   Status   = UsbCbiDataTransfer (UsbCbi, DataDir, Data, &TransLen, Timeout);\r
   if (UsbCbi->InterruptEndpoint == NULL) {\r
-    DEBUG ((mUsbCbiError, "UsbCbiExecCommand: UsbCbiDataTransfer (%r)\n",Status));\r
+    DEBUG ((EFI_D_ERROR, "UsbCbiExecCommand: UsbCbiDataTransfer (%r)\n",Status));\r
     return Status;\r
   }\r
 \r
   //\r
-  // Get the status, if that succeeds, interpret the result\r
+  // Get the status. If it succeeds, interpret the result.\r
   //\r
   Status = UsbCbiGetStatus (UsbCbi, Timeout, &Result);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((mUsbCbiError, "UsbCbiExecCommand: UsbCbiGetStatus (%r)\n",Status));\r
-    return EFI_DEVICE_ERROR;\r
+    DEBUG ((EFI_D_ERROR, "UsbCbiExecCommand: UsbCbiGetStatus (%r)\n",Status));\r
+    return Status;\r
   }\r
 \r
   if (UsbCbi->Interface.InterfaceSubClass == USB_MASS_STORE_UFI) {\r
     //\r
     // For UFI device, ASC and ASCQ are returned.\r
     //\r
-    if (Result.Type != 0) {\r
+    // Do not set the USB_MASS_CMD_FAIL for a request sense command\r
+    // as a bad result type doesn't mean a cmd failure\r
+    //\r
+    if (Result.Type != 0 && *(UINT8*)Cmd != 0x03) {\r
       *CmdStatus = USB_MASS_CMD_FAIL;\r
     }\r
-\r
   } else {\r
     //\r
     // Check page 27, CBI spec 1.1 for vaious reture status.\r
@@ -497,7 +507,8 @@ UsbCbiExecCommand (
 \r
     case 0x02:\r
       //\r
-      // Phase Error, response with reset. Fall through to Fail.\r
+      // Phase Error, response with reset.\r
+      // No break here to fall through to "Fail".\r
       //\r
       UsbCbiResetDevice (UsbCbi, FALSE);\r
 \r
@@ -510,7 +521,7 @@ UsbCbiExecCommand (
 \r
     case 0x03:\r
       //\r
-      // Persistent Fail, need to send REQUEST SENSE.\r
+      // Persistent Fail. Need to send REQUEST SENSE.\r
       //\r
       *CmdStatus = USB_MASS_CMD_PERSISTENT;\r
       break;\r
@@ -522,18 +533,20 @@ UsbCbiExecCommand (
 \r
 \r
 /**\r
-  Call the Usb mass storage class transport protocol to\r
-  reset the device. The reset is defined as a Non-Data\r
-  command. Don't use UsbCbiExecCommand to send the command\r
-  to device because that may introduce recursive loop.\r
+  Reset the USB mass storage device by CBI protocol.\r
+\r
+  This function resets the USB mass storage device by CBI protocol.\r
+  The reset is defined as a non-data command. Don't use UsbCbiExecCommand\r
+  to send the command to device because that may introduce recursive loop.\r
 \r
-  @param  Context               The USB CBI device protocol\r
+  @param  Context               The USB CBI protocol\r
+  @param  ExtendedVerification  The flag controlling the rule of reset.\r
+                                Not used here.\r
 \r
-  @retval EFI_SUCCESS           the device is reset\r
-  @retval Others                Failed to reset the device\r
+  @retval EFI_SUCCESS           The device is reset.\r
+  @retval Others                Failed to reset the device.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 UsbCbiResetDevice (\r
   IN  VOID                    *Context,\r
@@ -555,7 +568,7 @@ UsbCbiResetDevice (
 \r
   ResetCmd[0] = 0x1D;\r
   ResetCmd[1] = 0x04;\r
-  Timeout     = USB_CBI_RESET_TIMEOUT / USB_MASS_STALL_1_MS;\r
+  Timeout     = USB_CBI_RESET_DEVICE_TIMEOUT / USB_MASS_1_MILLISECOND;\r
 \r
   //\r
   // Send the command to the device. Don't use UsbCbiExecCommand here.\r
@@ -567,53 +580,34 @@ UsbCbiResetDevice (
 \r
   //\r
   // Just retrieve the status and ignore that. Then stall\r
-  // 50ms to wait it complete\r
+  // 50ms to wait for it to complete.\r
   //\r
   UsbCbiGetStatus (UsbCbi, Timeout, &Result);\r
-  gBS->Stall (50 * 1000);\r
+  gBS->Stall (USB_CBI_RESET_DEVICE_STALL);\r
 \r
   //\r
-  // Clear the Bulk-In and Bulk-Out stall condition and\r
-  // init data toggle.\r
+  // Clear the Bulk-In and Bulk-Out stall condition and init data toggle.\r
   //\r
   UsbClearEndpointStall (UsbCbi->UsbIo, UsbCbi->BulkInEndpoint->EndpointAddress);\r
   UsbClearEndpointStall (UsbCbi->UsbIo, UsbCbi->BulkOutEndpoint->EndpointAddress);\r
+\r
   return Status;\r
 }\r
 \r
 \r
 /**\r
-  Clean up the CBI protocol's resource\r
+  Clean up the CBI protocol's resource.\r
 \r
-  @param  Context               The CBI protocol\r
+  @param  Context               The instance of CBI protocol.\r
 \r
   @retval EFI_SUCCESS           The resource is cleaned up.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
-UsbCbiFini (\r
+UsbCbiCleanUp (\r
   IN  VOID                   *Context\r
   )\r
 {\r
-  gBS->FreePool (Context);\r
+  FreePool (Context);\r
   return EFI_SUCCESS;\r
 }\r
-\r
-USB_MASS_TRANSPORT\r
-mUsbCbi0Transport = {\r
-  USB_MASS_STORE_CBI0,\r
-  UsbCbiInit,\r
-  UsbCbiExecCommand,\r
-  UsbCbiResetDevice,\r
-  UsbCbiFini\r
-};\r
-\r
-USB_MASS_TRANSPORT\r
-mUsbCbi1Transport = {\r
-  USB_MASS_STORE_CBI1,\r
-  UsbCbiInit,\r
-  UsbCbiExecCommand,\r
-  UsbCbiResetDevice,\r
-  UsbCbiFini\r
-};\r