]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c
MdeModulePkg/UsbMassStorage: Add 16 byte SCSI cmds support if the last LBA can not...
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbMassStorageDxe / UsbMassImpl.c
index 15fdad573d91f2c151175f2ba098cba47e5d2e67..4cbedfade6caec49755982f504f5f2fe59f7d00b 100644 (file)
@@ -1,8 +1,8 @@
 /** @file\r
   USB Mass Storage Driver that manages USB Mass Storage Device and produces Block I/O Protocol.\r
 \r
-Copyright (c) 2007 - 2008, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2007 - 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
@@ -12,16 +12,16 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 **/\r
 \r
-#include "UsbMassImpl.h"\r
+#include "UsbMass.h"\r
 \r
+#define USB_MASS_TRANSPORT_COUNT    3\r
 //\r
 // Array of USB transport interfaces. \r
 //\r
-USB_MASS_TRANSPORT *mUsbMassTransport[] = {\r
+USB_MASS_TRANSPORT *mUsbMassTransport[USB_MASS_TRANSPORT_COUNT] = {\r
   &mUsbCbi0Transport,\r
   &mUsbCbi1Transport,\r
   &mUsbBotTransport,\r
-  NULL\r
 };\r
 \r
 EFI_DRIVER_BINDING_PROTOCOL gUSBMassDriverBinding = {\r
@@ -113,13 +113,6 @@ UsbMassReadBlocks (
   EFI_TPL             OldTpl;\r
   UINTN               TotalBlock;\r
 \r
-  //\r
-  // First, validate the parameters\r
-  //\r
-  if ((Buffer == NULL) || (BufferSize == 0)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
   //\r
   // Raise TPL to TPL_NOTIFY to serialize all its operations\r
   // to protect shared data structures.\r
@@ -140,6 +133,26 @@ UsbMassReadBlocks (
     }\r
   }\r
 \r
+  if (!(Media->MediaPresent)) {\r
+    Status = EFI_NO_MEDIA;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (MediaId != Media->MediaId) {\r
+    Status = EFI_MEDIA_CHANGED;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (BufferSize == 0) {\r
+    Status = EFI_SUCCESS;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (Buffer == NULL) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+\r
   //\r
   // BufferSize must be a multiple of the intrinsic block size of the device.\r
   //\r
@@ -158,17 +171,12 @@ UsbMassReadBlocks (
     goto ON_EXIT;\r
   }\r
 \r
-  if (!(Media->MediaPresent)) {\r
-    Status = EFI_NO_MEDIA;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  if (MediaId != Media->MediaId) {\r
-    Status = EFI_MEDIA_CHANGED;\r
-    goto ON_EXIT;\r
+  if (UsbMass->Cdb16Byte) {\r
+    Status = UsbBootReadBlocks16 (UsbMass, Lba, TotalBlock, Buffer);\r
+  } else {\r
+    Status = UsbBootReadBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);\r
   }\r
 \r
-  Status = UsbBootReadBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);\r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "UsbMassReadBlocks: UsbBootReadBlocks (%r) -> Reset\n", Status));\r
     UsbMassReset (This, TRUE);\r
@@ -221,13 +229,6 @@ UsbMassWriteBlocks (
   EFI_TPL             OldTpl;\r
   UINTN               TotalBlock;\r
 \r
-  //\r
-  // First, validate the parameters\r
-  //\r
-  if ((Buffer == NULL) || (BufferSize == 0)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
   //\r
   // Raise TPL to TPL_NOTIFY to serialize all its operations\r
   // to protect shared data structures.\r
@@ -248,6 +249,26 @@ UsbMassWriteBlocks (
     }\r
   }\r
 \r
+  if (!(Media->MediaPresent)) {\r
+    Status = EFI_NO_MEDIA;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (MediaId != Media->MediaId) {\r
+    Status = EFI_MEDIA_CHANGED;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (BufferSize == 0) {\r
+    Status = EFI_SUCCESS;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (Buffer == NULL) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+\r
   //\r
   // BufferSize must be a multiple of the intrinsic block size of the device.\r
   //\r
@@ -266,21 +287,16 @@ UsbMassWriteBlocks (
     goto ON_EXIT;\r
   }\r
 \r
-  if (!(Media->MediaPresent)) {\r
-    Status = EFI_NO_MEDIA;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  if (MediaId != Media->MediaId) {\r
-    Status = EFI_MEDIA_CHANGED;\r
-    goto ON_EXIT;\r
-  }\r
-\r
   //\r
   // Try to write the data even the device is marked as ReadOnly,\r
   // and clear the status should the write succeed.\r
   //\r
-  Status = UsbBootWriteBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);\r
+  if (UsbMass->Cdb16Byte) {\r
+    Status = UsbBootWriteBlocks16 (UsbMass, Lba, TotalBlock, Buffer);\r
+  } else {\r
+    Status = UsbBootWriteBlocks (UsbMass, (UINT32) Lba, TotalBlock, Buffer);\r
+  }  \r
+\r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "UsbMassWriteBlocks: UsbBootWriteBlocks (%r) -> Reset\n", Status));\r
     UsbMassReset (This, TRUE);\r
@@ -330,7 +346,6 @@ UsbMassInitMedia (
 {\r
   EFI_BLOCK_IO_MEDIA          *Media;\r
   EFI_STATUS                  Status;\r
-  UINTN                       Index;\r
 \r
   Media = &UsbMass->BlockIoMedia;\r
 \r
@@ -345,25 +360,7 @@ UsbMassInitMedia (
   Media->IoAlign          = 0;\r
   Media->MediaId          = 1;\r
 \r
-  //\r
-  // Some device may spend several seconds before it is ready.\r
-  // Try several times before giving up. Wait 5s at most.\r
-  //\r
-  Status = EFI_SUCCESS;\r
-\r
-  for (Index = 0; Index < USB_BOOT_INIT_MEDIA_RETRY; Index++) {\r
-\r
-    Status = UsbBootGetParams (UsbMass);\r
-    if ((Status != EFI_MEDIA_CHANGED) && (Status != EFI_NOT_READY) && (Status != EFI_TIMEOUT)) {\r
-      break;\r
-    }\r
-\r
-    Status = UsbBootIsUnitReady (UsbMass);\r
-    if (EFI_ERROR (Status)) {\r
-      gBS->Stall (USB_BOOT_RETRY_UNIT_READY_STALL * (Index + 1));\r
-    }\r
-  }\r
-\r
+  Status = UsbBootGetParams (UsbMass);\r
   return Status;\r
 }\r
 \r
@@ -424,7 +421,7 @@ UsbMassInitTransport (
   // If not found, return EFI_UNSUPPORTED.\r
   // If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.\r
   //\r
-  for (Index = 0; mUsbMassTransport[Index] != NULL; Index++) {\r
+  for (Index = 0; Index < USB_MASS_TRANSPORT_COUNT; Index++) {\r
     *Transport = mUsbMassTransport[Index];\r
 \r
     if (Interface.InterfaceProtocol == (*Transport)->Protocol) {\r
@@ -548,6 +545,8 @@ UsbMassInitMultiLun (
       goto ON_ERROR;\r
     }\r
 \r
+    InitializeDiskInfo (UsbMass);\r
+\r
     //\r
     // Create a new handle for each LUN, and install Block I/O Protocol and Device Path Protocol.\r
     //\r
@@ -557,6 +556,8 @@ UsbMassInitMultiLun (
                     UsbMass->DevicePath,\r
                     &gEfiBlockIoProtocolGuid,\r
                     &UsbMass->BlockIo,\r
+                    &gEfiDiskInfoProtocolGuid,\r
+                    &UsbMass->DiskInfo,\r
                     NULL\r
                     );\r
     \r
@@ -585,6 +586,8 @@ UsbMassInitMultiLun (
              UsbMass->DevicePath,\r
              &gEfiBlockIoProtocolGuid,\r
              &UsbMass->BlockIo,\r
+             &gEfiDiskInfoProtocolGuid,\r
+             &UsbMass->DiskInfo,\r
              NULL\r
              );\r
       goto ON_ERROR;\r
@@ -696,11 +699,15 @@ UsbMassInitNonLun (
     goto ON_ERROR;\r
   }\r
     \r
-  Status = gBS->InstallProtocolInterface (\r
+  InitializeDiskInfo (UsbMass);\r
+\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
                   &Controller,\r
                   &gEfiBlockIoProtocolGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  &UsbMass->BlockIo\r
+                  &UsbMass->BlockIo,\r
+                  &gEfiDiskInfoProtocolGuid,\r
+                  &UsbMass->DiskInfo,\r
+                  NULL\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     goto ON_ERROR;\r
@@ -712,12 +719,14 @@ ON_ERROR:
   if (UsbMass != NULL) {\r
     FreePool (UsbMass);\r
   }\r
-  gBS->CloseProtocol (\r
-         Controller,\r
-         &gEfiUsbIoProtocolGuid,\r
-         This->DriverBindingHandle,\r
-         Controller\r
-         );\r
+  if (UsbIo != NULL) {\r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiUsbIoProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+  }\r
   return Status;  \r
 }\r
 \r
@@ -780,7 +789,7 @@ USBMassDriverBindingSupported (
   // If not found, return EFI_UNSUPPORTED.\r
   // If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.\r
   //\r
-  for (Index = 0; mUsbMassTransport[Index] != NULL; Index++) {\r
+  for (Index = 0; Index < USB_MASS_TRANSPORT_COUNT; Index++) {\r
     Transport = mUsbMassTransport[Index];\r
     if (Interface.InterfaceProtocol == Transport->Protocol) {\r
       Status = Transport->Init (UsbIo, NULL);\r
@@ -830,7 +839,11 @@ USBMassDriverBindingStart (
   VOID                          *Context;\r
   UINT8                         MaxLun;\r
   EFI_STATUS                    Status;\r
-  \r
+  EFI_USB_IO_PROTOCOL           *UsbIo; \r
+  EFI_TPL                       OldTpl;\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
   Transport = NULL;\r
   Context   = NULL;\r
   MaxLun    = 0;\r
@@ -839,7 +852,7 @@ USBMassDriverBindingStart (
 \r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitTransport (%r)\n", Status));\r
-    return Status;\r
+    goto Exit;\r
   }\r
   if (MaxLun == 0) {\r
     //\r
@@ -864,7 +877,27 @@ USBMassDriverBindingStart (
   \r
     if (EFI_ERROR (Status)) {\r
       DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: OpenDevicePathProtocol By Driver (%r)\n", Status));\r
-      return Status;\r
+      goto Exit;\r
+    }\r
+\r
+    Status = gBS->OpenProtocol (\r
+                    Controller,\r
+                    &gEfiUsbIoProtocolGuid,\r
+                    (VOID **) &UsbIo,\r
+                    This->DriverBindingHandle,\r
+                    Controller,\r
+                    EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                    );\r
+  \r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: OpenUsbIoProtocol By Driver (%r)\n", Status));\r
+      gBS->CloseProtocol (\r
+             Controller,\r
+             &gEfiDevicePathProtocolGuid,\r
+             This->DriverBindingHandle,\r
+             Controller\r
+             );\r
+      goto Exit;\r
     }\r
 \r
     //\r
@@ -873,15 +906,23 @@ USBMassDriverBindingStart (
     //\r
     Status = UsbMassInitMultiLun (This, Controller, Transport, Context, DevicePath, MaxLun);\r
     if (EFI_ERROR (Status)) {\r
-     gBS->CloseProtocol (\r
-            Controller,\r
-            &gEfiDevicePathProtocolGuid,\r
-            This->DriverBindingHandle,\r
-            Controller\r
-            );\r
+      gBS->CloseProtocol (\r
+              Controller,\r
+              &gEfiDevicePathProtocolGuid,\r
+              This->DriverBindingHandle,\r
+              Controller\r
+              );\r
+      gBS->CloseProtocol (\r
+              Controller,\r
+              &gEfiUsbIoProtocolGuid,\r
+              This->DriverBindingHandle,\r
+              Controller\r
+              );\r
       DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitMultiLun (%r) with Maxlun=%d\n", Status, MaxLun));\r
     }\r
   }\r
+Exit:\r
+  gBS->RestoreTPL (OldTpl);\r
   return Status;\r
 }\r
 \r
@@ -919,9 +960,9 @@ USBMassDriverBindingStop (
   //\r
   // This is a bus driver stop function since multi-lun is supported.\r
   // There are three kinds of device handles that might be passed:\r
-  // 1st is a handle with Device Path & USB I/O & Block I/O installed (non-multi-lun)\r
+  // 1st is a handle with USB I/O & Block I/O installed (non-multi-lun)\r
   // 2nd is a handle with Device Path & USB I/O installed (multi-lun root)\r
-  // 3rd is a handle with Device Path & Block I/O installed (multi-lun).\r
+  // 3rd is a handle with Device Path & USB I/O & Block I/O installed (multi-lun).\r
   //\r
   if (NumberOfChildren == 0) {\r
     //\r
@@ -938,8 +979,8 @@ USBMassDriverBindingStop (
   \r
     if (EFI_ERROR(Status)) {\r
       //\r
-      // This is a 2nd type handle(multi-lun root), which only needs to close \r
-      // Device Path Protocol.\r
+      // This is a 2nd type handle(multi-lun root), it needs to close devicepath\r
+      // and usbio protocol.\r
       //\r
       gBS->CloseProtocol (\r
             Controller,\r
@@ -947,6 +988,12 @@ USBMassDriverBindingStop (
             This->DriverBindingHandle,\r
             Controller\r
             );\r
+      gBS->CloseProtocol (\r
+            Controller,\r
+            &gEfiUsbIoProtocolGuid,\r
+            This->DriverBindingHandle,\r
+            Controller\r
+            );\r
       DEBUG ((EFI_D_INFO, "Success to stop multi-lun root handle\n"));\r
       return EFI_SUCCESS;\r
     }\r
@@ -961,10 +1008,13 @@ USBMassDriverBindingStop (
     // Uninstall Block I/O protocol from the device handle,\r
     // then call the transport protocol to stop itself.\r
     //\r
-    Status = gBS->UninstallProtocolInterface (\r
+    Status = gBS->UninstallMultipleProtocolInterfaces (\r
                     Controller,\r
                     &gEfiBlockIoProtocolGuid,\r
-                    &UsbMass->BlockIo\r
+                    &UsbMass->BlockIo,\r
+                    &gEfiDiskInfoProtocolGuid,\r
+                    &UsbMass->DiskInfo,\r
+                    NULL\r
                     );\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
@@ -1022,6 +1072,8 @@ USBMassDriverBindingStop (
                     UsbMass->DevicePath,\r
                     &gEfiBlockIoProtocolGuid,\r
                     &UsbMass->BlockIo,\r
+                    &gEfiDiskInfoProtocolGuid,\r
+                    &UsbMass->DiskInfo,\r
                     NULL\r
                     );\r
     \r