]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Add BlockIO2 Protocol.
authorqianouyang <qianouyang@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 3 May 2011 10:31:41 +0000 (10:31 +0000)
committerqianouyang <qianouyang@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 3 May 2011 10:31:41 +0000 (10:31 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11606 6f19259b-4bc3-4df7-8a09-765794883524

17 files changed:
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.h
MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c
MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.h
MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c
MdeModulePkg/Universal/Disk/PartitionDxe/ElTorito.c
MdeModulePkg/Universal/Disk/PartitionDxe/Gpt.c
MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c
MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
MdeModulePkg/Universal/Disk/PartitionDxe/Partition.h
MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
MdePkg/MdePkg.dec

index 8ba0201563478f68b945668cb9842d13bd9fbdd2..7765bfc75c892ba5acf0064aea10f5b7ff456c7a 100644 (file)
@@ -184,9 +184,50 @@ AhciWaitMemSet (
   return EFI_DEVICE_ERROR;\r
 }\r
 \r
+/**\r
+  Check the memory status to the test value.\r
+    \r
+  @param[in]       PciIo             The PCI IO protocol instance.\r
+  @param[in]       Offset            The memory address to test.\r
+  @param[in]       MaskValue         The mask value of memory.\r
+  @param[in]       TestValue         The test value of memory.\r
+  @param[in, out]  RetryTimes        The retry times value for waitting memory set.\r
+\r
+  @retval EFI_NOTREADY      The memory is not set.\r
+  @retval EFI_TIMEOUT       The memory setting retry times out.\r
+  @retval EFI_SUCCESS       The memory is correct set.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AhciCheckMemSet (\r
+  IN  EFI_PCI_IO_PROTOCOL       *PciIo,\r
+  IN  UINT32                    Offset,\r
+  IN  UINT32                    MaskValue,\r
+  IN  UINT32                    TestValue,\r
+  IN  UINTN                     *RetryTimes\r
+  )\r
+{\r
+  UINT32     Value;\r
+\r
+  (*RetryTimes) --;\r
+  \r
+  Value = AhciReadReg (PciIo, Offset) & MaskValue;\r
+\r
+  if (Value == TestValue) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if ((*RetryTimes) == 0) {\r
+    return EFI_TIMEOUT;\r
+  } else {\r
+    return EFI_NOT_READY;\r
+  }\r
+}\r
+\r
 /**\r
   Check if the device is still on port. It also checks if the AHCI controller \r
-  supports the address and data count will be transfered.\r
+  supports the address and data count will be transferred.\r
 \r
   @param  PciIo            The PCI IO protocol instance.\r
   @param  Port             The number of port.\r
@@ -206,7 +247,7 @@ AhciCheckDeviceStatus (
   IN  UINT8                  Port\r
   )\r
 {\r
-  UINT32      Data; \r
+  UINT32      Data;\r
   UINT32      Offset;\r
 \r
   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;\r
@@ -214,7 +255,7 @@ AhciCheckDeviceStatus (
   Data   = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_SSTS_DET_MASK;\r
 \r
   if (Data == EFI_AHCI_PORT_SSTS_DET_PCE) {\r
-    return EFI_SUCCESS;      \r
+    return EFI_SUCCESS;\r
   }\r
 \r
   return EFI_NOT_READY;\r
@@ -240,7 +281,7 @@ AhciClearPortStatus (
 \r
   //\r
   // Clear any error status\r
-  //  \r
+  //\r
   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;\r
   AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));\r
 \r
@@ -310,8 +351,8 @@ AhciEnableFisReceive (
   IN  EFI_PCI_IO_PROTOCOL       *PciIo,\r
   IN  UINT8                     Port,\r
   IN  UINT64                    Timeout\r
-  )     \r
-{ \r
+  )\r
+{\r
   UINT32 Offset;\r
 \r
   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
@@ -370,12 +411,12 @@ AhciDisableFisReceive (
   AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE));\r
 \r
   return AhciWaitMemSet (\r
-           PciIo, \r
+           PciIo,\r
            Offset,\r
            EFI_AHCI_PORT_CMD_FR,\r
            0,\r
            Timeout\r
-           ); \r
+           );\r
 }\r
 \r
 \r
@@ -412,7 +453,7 @@ AhciBuildCommand (
   IN     UINT64                     DataLength\r
   )   \r
 {\r
-  UINT64     BaseAddr; \r
+  UINT64     BaseAddr;\r
   UINT64     PrdtNumber;\r
   UINT64     PrdtIndex;\r
   UINTN      RemainedData;\r
@@ -436,7 +477,7 @@ AhciBuildCommand (
 \r
   BaseAddr = Data64.Uint64;\r
   \r
-  ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));  \r
+  ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));\r
     \r
   ZeroMem (AhciRegisters->AhciCommandTable, sizeof (EFI_AHCI_COMMAND_TABLE));\r
 \r
@@ -466,7 +507,7 @@ AhciBuildCommand (
   CommandList->AhciCmdPrdtl = (UINT32)PrdtNumber;\r
   \r
   for (PrdtIndex = 0; PrdtIndex < PrdtNumber; PrdtIndex++) {\r
-    if (RemainedData < EFI_AHCI_MAX_DATA_PER_PRDT) {     \r
+    if (RemainedData < EFI_AHCI_MAX_DATA_PER_PRDT) {\r
       AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbc = (UINT32)RemainedData - 1;\r
     } else {\r
       AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbc = EFI_AHCI_MAX_DATA_PER_PRDT - 1;\r
@@ -475,7 +516,7 @@ AhciBuildCommand (
     Data64.Uint64 = (UINT64)MemAddr;\r
     AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDba  = Data64.Uint32.Lower32;\r
     AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbau = Data64.Uint32.Upper32;\r
-    RemainedData -= EFI_AHCI_MAX_DATA_PER_PRDT;    \r
+    RemainedData -= EFI_AHCI_MAX_DATA_PER_PRDT;\r
     MemAddr      += EFI_AHCI_MAX_DATA_PER_PRDT;\r
   }\r
 \r
@@ -543,18 +584,21 @@ AhciBuildCommandFis (
 /**\r
   Start a PIO data transfer on specific port.\r
     \r
-  @param  PciIo               The PCI IO protocol instance.\r
-  @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.\r
-  @param  Port                The number of port.\r
-  @param  PortMultiplier      The timeout value of stop.\r
-  @param  AtapiCommand        The atapi command will be used for the transfer.\r
-  @param  AtapiCommandLength  The length of the atapi command.\r
-  @param  Read                The transfer direction.\r
-  @param  AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK data.\r
-  @param  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK data.\r
-  @param  MemoryAddr          The pointer to the data buffer.\r
-  @param  DataCount           The data count to be transferred.\r
-  @param  Timeout             The timeout value of non data transfer.\r
+  @param[in]       PciIo               The PCI IO protocol instance.\r
+  @param[in]       AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.\r
+  @param[in]       Port                The number of port.\r
+  @param[in]       PortMultiplier      The timeout value of stop.\r
+  @param[in]       AtapiCommand        The atapi command will be used for the\r
+                                       transfer.\r
+  @param[in]       AtapiCommandLength  The length of the atapi command.\r
+  @param[in]       Read                The transfer direction.\r
+  @param[in]       AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK data.\r
+  @param[in, out]  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK data.\r
+  @param[in, out]  MemoryAddr          The pointer to the data buffer.\r
+  @param[in]       DataCount           The data count to be transferred.\r
+  @param[in]       Timeout             The timeout value of non data transfer.\r
+  @param[in]       Task                Optional. Pointer to the ATA_NONBLOCK_TASK\r
+                                       used by non-blocking mode.\r
 \r
   @retval EFI_DEVICE_ERROR    The PIO data transfer abort with error occurs.\r
   @retval EFI_TIMEOUT         The operation is time out.\r
@@ -576,7 +620,8 @@ AhciPioTransfer (
   IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,\r
   IN OUT VOID                       *MemoryAddr,\r
   IN     UINT32                     DataCount,\r
-  IN     UINT64                     Timeout \r
+  IN     UINT64                     Timeout,\r
+  IN     ATA_NONBLOCK_TASK          *Task\r
   )\r
 {\r
   EFI_STATUS                    Status;\r
@@ -639,17 +684,17 @@ AhciPioTransfer (
     );    \r
   \r
   Status = AhciStartCommand (\r
-             PciIo, \r
-             Port, \r
+             PciIo,\r
+             Port,\r
              0,\r
              Timeout\r
              );\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
-  \r
+\r
   //\r
-  // Checking the status and wait the driver sending data\r
+  // Check the status and wait the driver sending data\r
   //\r
   FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);\r
   //\r
@@ -668,7 +713,7 @@ AhciPioTransfer (
     //\r
     MicroSecondDelay(100);\r
 \r
-    Delay--;    \r
+    Delay--;\r
   } while (Delay > 0);\r
 \r
   if (Delay == 0) {\r
@@ -689,30 +734,30 @@ AhciPioTransfer (
              );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    goto Exit;   \r
+    goto Exit;\r
   }\r
 \r
   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;\r
   Status = AhciWaitMemSet (\r
              PciIo,\r
-             Offset,            \r
+             Offset,\r
              EFI_AHCI_PORT_IS_PSS,\r
              EFI_AHCI_PORT_IS_PSS,\r
              Timeout\r
-             );  \r
+             );\r
   if (EFI_ERROR (Status)) {\r
-    goto Exit;  \r
+    goto Exit;\r
   }\r
 \r
-Exit: \r
+Exit:\r
   AhciStopCommand (\r
-    PciIo, \r
+    PciIo,\r
     Port,\r
     Timeout\r
     );\r
   \r
   AhciDisableFisReceive (\r
-    PciIo, \r
+    PciIo,\r
     Port,\r
     Timeout\r
     );\r
@@ -730,29 +775,32 @@ Exit:
 /**\r
   Start a DMA data transfer on specific port\r
 \r
-  @param  PciIo               The PCI IO protocol instance.\r
-  @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.\r
-  @param  Port                The number of port.\r
-  @param  PortMultiplier      The timeout value of stop.\r
-  @param  AtapiCommand        The atapi command will be used for the transfer.\r
-  @param  AtapiCommandLength  The length of the atapi command.\r
-  @param  Read                The transfer direction.\r
-  @param  AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK data.\r
-  @param  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK data.\r
-  @param  MemoryAddr          The pointer to the data buffer.\r
-  @param  DataCount           The data count to be transferred.\r
-  @param  Timeout             The timeout value of non data transfer.\r
+  @param[in]       Instance            The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.\r
+  @param[in]       AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.\r
+  @param[in]       Port                The number of port.\r
+  @param[in]       PortMultiplier      The timeout value of stop.\r
+  @param[in]       AtapiCommand        The atapi command will be used for the\r
+                                       transfer.\r
+  @param[in]       AtapiCommandLength  The length of the atapi command.\r
+  @param[in]       Read                The transfer direction.\r
+  @param[in]       AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK data.\r
+  @param[in, out]  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK data.\r
+  @param[in, out]  MemoryAddr          The pointer to the data buffer.\r
+  @param[in]       DataCount           The data count to be transferred.\r
+  @param[in]       Timeout             The timeout value of non data transfer.\r
+  @param[in]       Task                Optional. Pointer to the ATA_NONBLOCK_TASK\r
+                                       used by non-blocking mode.\r
 \r
   @retval EFI_DEVICE_ERROR    The DMA data transfer abort with error occurs.\r
   @retval EFI_TIMEOUT         The operation is time out.\r
   @retval EFI_UNSUPPORTED     The device is not ready for transfer.\r
   @retval EFI_SUCCESS         The DMA data transfer executes successfully.\r
-   \r
+\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 AhciDmaTransfer (\r
-  IN     EFI_PCI_IO_PROTOCOL        *PciIo,\r
+  IN     ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
   IN     EFI_AHCI_REGISTERS         *AhciRegisters,\r
   IN     UINT8                      Port,\r
   IN     UINT8                      PortMultiplier,\r
@@ -763,7 +811,8 @@ AhciDmaTransfer (
   IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,\r
   IN OUT VOID                       *MemoryAddr,\r
   IN     UINTN                      DataCount,\r
-  IN     UINT64                     Timeout\r
+  IN     UINT64                     Timeout,\r
+  IN     ATA_NONBLOCK_TASK          *Task\r
   )\r
 {\r
   EFI_STATUS                    Status;\r
@@ -775,141 +824,224 @@ AhciDmaTransfer (
   EFI_AHCI_COMMAND_FIS          CFis;\r
   EFI_AHCI_COMMAND_LIST         CmdList;\r
 \r
-  if (Read) {\r
-    Flag = EfiPciIoOperationBusMasterWrite;\r
-  } else {\r
-    Flag = EfiPciIoOperationBusMasterRead;\r
-  }\r
+  EFI_PCI_IO_PROTOCOL          *PciIo;\r
+  EFI_TPL                      OldTpl;\r
 \r
-  //\r
-  // construct command list and command table with pci bus address\r
-  //\r
-  MapLength = DataCount;\r
-  Status = PciIo->Map (\r
-                    PciIo,\r
-                    Flag,\r
-                    MemoryAddr,\r
-                    &MapLength,\r
-                    &PhyAddr,\r
-                    &Map\r
-                    );\r
+  Map   = NULL;\r
+  PciIo = Instance->PciIo;\r
 \r
-  if (EFI_ERROR (Status) || (DataCount != MapLength)) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+  if (PciIo == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   //\r
-  // Package read needed\r
+  // Before starting the Blocking BlockIO operation, push to finish all non-blocking\r
+  // BlockIO tasks.\r
+  // Delay 100us to simulate the blocking time out checking.\r
   //\r
-  AhciBuildCommandFis (&CFis, AtaCommandBlock);\r
+  while ((Task == NULL) && (!IsListEmpty (&Instance->NonBlockingTaskList))) {\r
+    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+    AsyncNonBlockingTransferRoutine (NULL, Instance);\r
+    gBS->RestoreTPL (OldTpl);  \r
+    //\r
+    // Stall for 100us.\r
+    //\r
+    MicroSecondDelay (100);\r
+  }\r
 \r
-  ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));\r
+  if ((Task == NULL) || ((Task != NULL) && (!Task->IsStart))) {\r
+    //\r
+    // Mark the Task to indicate that it has been started.\r
+    //\r
+    if (Task != NULL) {\r
+      Task->IsStart      = TRUE;\r
+      Task->RetryTimes   = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
+    }\r
+    if (Read) {\r
+      Flag = EfiPciIoOperationBusMasterWrite;\r
+    } else {\r
+      Flag = EfiPciIoOperationBusMasterRead;\r
+    }\r
 \r
-  CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;\r
-  CmdList.AhciCmdW   = Read ? 0 : 1;\r
+    //\r
+    // Construct command list and command table with pci bus address.\r
+    //\r
+    MapLength = DataCount;\r
+    Status = PciIo->Map (\r
+                      PciIo,\r
+                      Flag,\r
+                      MemoryAddr,\r
+                      &MapLength,\r
+                      &PhyAddr,\r
+                      &Map\r
+                      );\r
+\r
+    if (EFI_ERROR (Status) || (DataCount != MapLength)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
 \r
-  AhciBuildCommand (\r
-    PciIo,\r
-    AhciRegisters,\r
-    Port,\r
-    PortMultiplier,\r
-    &CFis,\r
-    &CmdList,\r
-    AtapiCommand,\r
-    AtapiCommandLength,\r
-    0,\r
-    (VOID *)(UINTN)PhyAddr,\r
-    DataCount\r
-    ); \r
-  \r
-  Status = AhciStartCommand (\r
-             PciIo, \r
-             Port, \r
-             0,\r
-             Timeout\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    goto Exit;\r
-  }\r
-  \r
-  //\r
-  // Wait device PRD processed\r
-  //\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;\r
-  Status = AhciWaitMemSet (\r
-             PciIo,\r
-             Offset,\r
-             EFI_AHCI_PORT_IS_DPS,\r
-             EFI_AHCI_PORT_IS_DPS,\r
-             Timeout\r
-             ); \r
-  \r
-  if (EFI_ERROR (Status)) {\r
-    goto Exit;\r
+    if (Task != NULL) {\r
+      Task->Map = Map;\r
+    }\r
+    //\r
+    // Package read needed\r
+    //\r
+    AhciBuildCommandFis (&CFis, AtaCommandBlock);\r
+\r
+    ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));\r
+\r
+    CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;\r
+    CmdList.AhciCmdW   = Read ? 0 : 1;\r
+\r
+    AhciBuildCommand (\r
+      PciIo,\r
+      AhciRegisters,\r
+      Port,\r
+      PortMultiplier,\r
+      &CFis,\r
+      &CmdList,\r
+      AtapiCommand,\r
+      AtapiCommandLength,\r
+      0,\r
+      (VOID *)(UINTN)PhyAddr,\r
+      DataCount\r
+      );\r
+\r
+    Status = AhciStartCommand (\r
+               PciIo,\r
+               Port,\r
+               0,\r
+               Timeout\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
+\r
+    //\r
+    // Wait device PRD processed\r
+    //\r
+    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;\r
+    Status = AhciWaitMemSet (\r
+               PciIo,\r
+               Offset,\r
+               EFI_AHCI_PORT_IS_DPS,\r
+               EFI_AHCI_PORT_IS_DPS,\r
+               Timeout\r
+               );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
   }\r
 \r
   //\r
   // Wait for command compelte\r
   //\r
   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;\r
-  Status = AhciWaitMemSet (\r
-             PciIo,\r
-             Offset,\r
-             0xFFFFFFFF,\r
-             0,\r
-             Timeout\r
-             );\r
+  if (Task != NULL) {\r
+    //\r
+    // For Non-blocking\r
+    //\r
+    Status = AhciCheckMemSet (\r
+               PciIo,\r
+               Offset,\r
+               0xFFFFFFFF,\r
+               0,\r
+               (UINTN *) (&Task->RetryTimes)\r
+               );\r
+  } else {\r
+    Status = AhciWaitMemSet (\r
+               PciIo,\r
+               Offset,\r
+               0xFFFFFFFF,\r
+               0,\r
+               Timeout\r
+               );\r
+  }\r
+\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
 \r
   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;\r
-  Status = AhciWaitMemSet (\r
-             PciIo,\r
-             Offset,\r
-             EFI_AHCI_PORT_IS_DHRS,\r
-             EFI_AHCI_PORT_IS_DHRS,\r
-             Timeout\r
-             );  \r
+\r
+  if (Task != NULL) {\r
+    //\r
+    // For Non-blocking\r
+    //\r
+    Status = AhciCheckMemSet (\r
+               PciIo,\r
+               Offset,\r
+               EFI_AHCI_PORT_IS_DHRS,\r
+               EFI_AHCI_PORT_IS_DHRS,\r
+               (UINTN *) (&Task->RetryTimes)\r
+             );\r
+  } else {\r
+    Status = AhciWaitMemSet (\r
+               PciIo,\r
+               Offset,\r
+               EFI_AHCI_PORT_IS_DHRS,\r
+               EFI_AHCI_PORT_IS_DHRS,\r
+               Timeout\r
+               );\r
+  }\r
+\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
 \r
-Exit: \r
-  AhciStopCommand (\r
-    PciIo, \r
-    Port,\r
-    Timeout\r
-    );\r
+Exit:\r
+  //\r
+  // For Blocking mode, the command should be stopped, the Fis should be disabled\r
+  // and the PciIo should be unmapped.\r
+  // For non-blocking mode, only when a error is happened (if the return status is \r
+  // EFI_NOT_READY that means the command doesn't finished, try again.), first do the \r
+  // context cleanup, then set the packet's Asb status.\r
+  //\r
+  if (Task == NULL ||\r
+      ((Task != NULL) && (Status != EFI_NOT_READY))\r
+     ) {\r
+    AhciStopCommand (\r
+      PciIo, \r
+      Port,\r
+      Timeout\r
+      );\r
 \r
-  AhciDisableFisReceive (\r
-    PciIo, \r
-    Port,\r
-    Timeout\r
-    );\r
+    AhciDisableFisReceive (\r
+      PciIo, \r
+      Port,\r
+      Timeout\r
+      );\r
 \r
-  PciIo->Unmap (\r
-           PciIo,\r
-           Map\r
-           );  \r
-  \r
-  AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);\r
+    PciIo->Unmap (\r
+             PciIo,\r
+             (Task != NULL) ? Task->Map : Map\r
+             );\r
 \r
+    if (Task != NULL) {\r
+      Task->Packet->Asb->AtaStatus = 0x01;\r
+    }\r
+  }\r
+\r
+  AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);\r
   return Status;\r
 }\r
 \r
 /**\r
   Start a non data transfer on specific port.\r
     \r
-  @param  PciIo               The PCI IO protocol instance.\r
-  @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.\r
-  @param  Port                The number of port.\r
-  @param  PortMultiplier      The timeout value of stop.\r
-  @param  AtapiCommand        The atapi command will be used for the transfer.\r
-  @param  AtapiCommandLength  The length of the atapi command.\r
-  @param  AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK data.\r
-  @param  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK data.\r
-  @param  Timeout             The timeout value of non data transfer.\r
+  @param[in]       PciIo               The PCI IO protocol instance.\r
+  @param[in]       AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.\r
+  @param[in]       Port                The number of port.\r
+  @param[in]       PortMultiplier      The timeout value of stop.\r
+  @param[in]       AtapiCommand        The atapi command will be used for the\r
+                                       transfer.\r
+  @param[in]       AtapiCommandLength  The length of the atapi command.\r
+  @param[in]       AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK data.\r
+  @param[in, out]  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK data.\r
+  @param[in]       Timeout             The timeout value of non data transfer.\r
+  @param[in]       Task                Optional. Pointer to the ATA_NONBLOCK_TASK\r
+                                       used by non-blocking mode.\r
 \r
   @retval EFI_DEVICE_ERROR    The non data transfer abort with error occurs.\r
   @retval EFI_TIMEOUT         The operation is time out.\r
@@ -928,15 +1060,16 @@ AhciNonDataTransfer (
   IN     UINT8                         AtapiCommandLength,\r
   IN     EFI_ATA_COMMAND_BLOCK         *AtaCommandBlock,\r
   IN OUT EFI_ATA_STATUS_BLOCK          *AtaStatusBlock,\r
-  IN     UINT64                        Timeout\r
-  ) \r
+  IN     UINT64                        Timeout,\r
+  IN     ATA_NONBLOCK_TASK             *Task\r
+  )\r
 {\r
-  EFI_STATUS                   Status;  \r
+  EFI_STATUS                   Status;\r
   UINTN                        FisBaseAddr;\r
   UINT32                       Offset;\r
   UINT32                       Value;\r
   UINT32                       Delay;\r
-  \r
+\r
   EFI_AHCI_COMMAND_FIS         CFis;\r
   EFI_AHCI_COMMAND_LIST        CmdList;\r
 \r
@@ -961,18 +1094,18 @@ AhciNonDataTransfer (
     0,\r
     NULL,\r
     0\r
-    ); \r
-  \r
+    );\r
+\r
   Status = AhciStartCommand (\r
-             PciIo, \r
-             Port, \r
+             PciIo,\r
+             Port,\r
              0,\r
              Timeout\r
              );\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
-  \r
+\r
   //\r
   // Wait device sends the Response Fis\r
   //\r
@@ -993,7 +1126,7 @@ AhciNonDataTransfer (
     //\r
     MicroSecondDelay(100);\r
 \r
-    Delay --;    \r
+    Delay --;\r
   } while (Delay > 0);\r
 \r
   if (Delay == 0) {\r
@@ -1009,17 +1142,17 @@ AhciNonDataTransfer (
              0xFFFFFFFF,\r
              0,\r
              Timeout\r
-             );  \r
-  \r
-Exit:  \r
+             );\r
+\r
+Exit:\r
   AhciStopCommand (\r
-    PciIo, \r
+    PciIo,\r
     Port,\r
     Timeout\r
     );\r
 \r
   AhciDisableFisReceive (\r
-    PciIo, \r
+    PciIo,\r
     Port,\r
     Timeout\r
     );\r
@@ -1056,7 +1189,7 @@ AhciStopCommand (
   Data   = AhciReadReg (PciIo, Offset);\r
 \r
   if ((Data & (EFI_AHCI_PORT_CMD_ST |  EFI_AHCI_PORT_CMD_CR)) == 0) {\r
-    return EFI_SUCCESS;    \r
+    return EFI_SUCCESS;\r
   }\r
 \r
   if ((Data & EFI_AHCI_PORT_CMD_ST) != 0) {\r
@@ -1064,22 +1197,22 @@ AhciStopCommand (
   }\r
 \r
   return AhciWaitMemSet (\r
-           PciIo, \r
+           PciIo,\r
            Offset,\r
            EFI_AHCI_PORT_CMD_CR,\r
            0,\r
            Timeout\r
-           ); \r
+           );\r
 }\r
 \r
 /**\r
   Start command for give slot on specific port.\r
-    \r
+\r
   @param  PciIo              The PCI IO protocol instance.\r
   @param  Port               The number of port.\r
-  @param  CommandSlot        The number of CommandSlot.\r
+  @param  CommandSlot        The number of Command Slot.\r
   @param  Timeout            The timeout value of start.\r
-   \r
+\r
   @retval EFI_DEVICE_ERROR   The command start unsuccessfully.\r
   @retval EFI_TIMEOUT        The operation is time out.\r
   @retval EFI_SUCCESS        The command start successfully.\r
@@ -1119,14 +1252,14 @@ AhciStartCommand (
              Port,\r
              Timeout\r
              );\r
-  \r
+\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
   PortStatus = AhciReadReg (PciIo, Offset);\r
-  \r
+\r
   StartCmd = 0;\r
   if ((PortStatus & EFI_AHCI_PORT_CMD_ALPE) != 0) {\r
     StartCmd = AhciReadReg (PciIo, Offset);\r
@@ -1143,12 +1276,12 @@ AhciStartCommand (
       AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_COL);\r
 \r
       AhciWaitMemSet (\r
-        PciIo, \r
+        PciIo,\r
         Offset,\r
         EFI_AHCI_PORT_CMD_COL,\r
         0,\r
         Timeout\r
-        ); \r
+        );\r
     }\r
   }\r
 \r
@@ -1190,8 +1323,8 @@ AhciPortReset (
   )\r
 {\r
   EFI_STATUS      Status;\r
-  UINT32          Offset;  \r
-  \r
+  UINT32          Offset;\r
+\r
   AhciClearPortStatus (PciIo, Port);\r
 \r
   AhciStopCommand (PciIo, Port, Timeout);\r
@@ -1205,14 +1338,14 @@ AhciPortReset (
   AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_DET_INIT);\r
 \r
   //\r
-  // wait 5 milliseceond before de-assert DET  \r
+  // wait 5 millisecond before de-assert DET\r
   //\r
   MicroSecondDelay (5000);\r
 \r
   AhciAndReg (PciIo, Offset, (UINT32)EFI_AHCI_PORT_SCTL_MASK);\r
 \r
   //\r
-  // wait 5 milliseceond before de-assert DET  \r
+  // wait 5 millisecond before de-assert DET\r
   //\r
   MicroSecondDelay (5000);\r
 \r
@@ -1226,7 +1359,7 @@ AhciPortReset (
              EFI_AHCI_PORT_SSTS_DET_MASK,\r
              EFI_AHCI_PORT_SSTS_DET_PCE,\r
              Timeout\r
-             ); \r
+             );\r
 \r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -1240,11 +1373,10 @@ AhciPortReset (
 \r
 /**\r
   Do AHCI HBA reset.\r
-    \r
+\r
   @param  PciIo              The PCI IO protocol instance.\r
   @param  Timeout            The timeout value of reset.\r
\r
-   \r
+\r
   @retval EFI_DEVICE_ERROR   AHCI controller is failed to complete hardware reset.\r
   @retval EFI_TIMEOUT        The reset operation is time out.\r
   @retval EFI_SUCCESS        AHCI controller is reset successfully.\r
@@ -1340,7 +1472,8 @@ AhciAtaSmartReturnStatusCheck (
              0,\r
              &AtaCommandBlock,\r
              AtaStatusBlock,\r
-             ATA_ATAPI_TIMEOUT\r
+             ATA_ATAPI_TIMEOUT,\r
+             NULL\r
              );\r
 \r
   if (EFI_ERROR (Status)) {\r
@@ -1390,7 +1523,7 @@ AhciAtaSmartSupport (
   IN EFI_AHCI_REGISTERS            *AhciRegisters,\r
   IN UINT8                         Port,\r
   IN UINT8                         PortMultiplier,\r
-  IN EFI_IDENTIFY_DATA             *IdentifyData,  \r
+  IN EFI_IDENTIFY_DATA             *IdentifyData,\r
   IN OUT EFI_ATA_STATUS_BLOCK      *AtaStatusBlock\r
   )\r
 {\r
@@ -1430,7 +1563,8 @@ AhciAtaSmartSupport (
                  0,\r
                  &AtaCommandBlock,\r
                  AtaStatusBlock,\r
-                 ATA_ATAPI_TIMEOUT\r
+                 ATA_ATAPI_TIMEOUT,\r
+                 NULL\r
                  );\r
 \r
 \r
@@ -1455,7 +1589,8 @@ AhciAtaSmartSupport (
                    0,\r
                    &AtaCommandBlock,\r
                    AtaStatusBlock,\r
-                   ATA_ATAPI_TIMEOUT\r
+                   ATA_ATAPI_TIMEOUT,\r
+                   NULL\r
                    );\r
 \r
         if (!EFI_ERROR (Status)) {\r
@@ -1469,7 +1604,7 @@ AhciAtaSmartSupport (
         }\r
       }\r
     }\r
-    DEBUG ((EFI_D_INFO, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n", \r
+    DEBUG ((EFI_D_INFO, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",\r
             Port, PortMultiplier));\r
   }\r
 \r
@@ -1511,7 +1646,7 @@ AhciIdentify (
 \r
   ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
   ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));\r
-  \r
+\r
   AtaCommandBlock.AtaCommand     = ATA_CMD_IDENTIFY_DRIVE;\r
   AtaCommandBlock.AtaSectorCount = 1;\r
 \r
@@ -1527,7 +1662,8 @@ AhciIdentify (
              &AtaStatusBlock,\r
              Buffer,\r
              sizeof (EFI_IDENTIFY_DATA),\r
-             ATA_ATAPI_TIMEOUT\r
+             ATA_ATAPI_TIMEOUT, \r
+             NULL\r
              );\r
 \r
   return Status;\r
@@ -1565,7 +1701,7 @@ AhciIdentifyPacket (
   if (PciIo == NULL || AhciRegisters == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
-  \r
+\r
   ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
   ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));\r
 \r
@@ -1584,7 +1720,8 @@ AhciIdentifyPacket (
              &AtaStatusBlock,\r
              Buffer,\r
              sizeof (EFI_IDENTIFY_DATA),\r
-             ATA_ATAPI_TIMEOUT\r
+             ATA_ATAPI_TIMEOUT,\r
+             NULL\r
              );\r
 \r
   return Status;\r
@@ -1623,7 +1760,7 @@ AhciDeviceSetFeature (
 \r
   ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
   ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));\r
-  \r
+\r
   AtaCommandBlock.AtaCommand      = ATA_CMD_SET_FEATURES;\r
   AtaCommandBlock.AtaFeatures     = (UINT8) Feature;\r
   AtaCommandBlock.AtaFeaturesExp  = (UINT8) (Feature >> 8);\r
@@ -1641,7 +1778,8 @@ AhciDeviceSetFeature (
              0,\r
              &AtaCommandBlock,\r
              &AtaStatusBlock,\r
-             ATA_ATAPI_TIMEOUT\r
+             ATA_ATAPI_TIMEOUT, \r
+             NULL\r
              );\r
 \r
   return Status;\r
@@ -1708,7 +1846,7 @@ AhciPacketCommandExecute (
     Read = FALSE;\r
   }\r
 \r
-  if (Length == 0) {    \r
+  if (Length == 0) {\r
     Status = AhciNonDataTransfer (\r
                PciIo,\r
                AhciRegisters,\r
@@ -1718,7 +1856,8 @@ AhciPacketCommandExecute (
                Packet->CdbLength,\r
                &AtaCommandBlock,\r
                &AtaStatusBlock,\r
-               Packet->Timeout\r
+               Packet->Timeout, \r
+               NULL\r
                );\r
   } else {\r
     //\r
@@ -1742,7 +1881,8 @@ AhciPacketCommandExecute (
                  &AtaStatusBlock,\r
                  Buffer,\r
                  Length,\r
-                 Packet->Timeout\r
+                 Packet->Timeout, \r
+                 NULL\r
                  );\r
       if (!EFI_ERROR (Status)) {\r
         break;\r
index 1efe0ebe7349c89d0508a8e0eb45b65aab23080a..9c4a9397e9a84400f60cebc158cae5602592abd4 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Header file for AHCI mode of ATA host controller.\r
   \r
-  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 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
@@ -154,7 +154,7 @@ typedef union {
 #define   EFI_AHCI_PORT_SERR_BDE               BIT19\r
 #define   EFI_AHCI_PORT_SERR_DE                BIT20\r
 #define   EFI_AHCI_PORT_SERR_CRCE              BIT21\r
-#define   EFI_AHCI_PORT_SERR_HE                BIT22          \r
+#define   EFI_AHCI_PORT_SERR_HE                BIT22\r
 #define   EFI_AHCI_PORT_SERR_LSE               BIT23\r
 #define   EFI_AHCI_PORT_SERR_TSTE              BIT24\r
 #define   EFI_AHCI_PORT_SERR_UFT               BIT25\r
@@ -348,117 +348,5 @@ AhciStopCommand (
   IN  UINT64                    Timeout\r
   );\r
 \r
-/**\r
-  Start a non data transfer on specific port.\r
-    \r
-  @param  PciIo               The PCI IO protocol instance.\r
-  @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.\r
-  @param  Port                The number of port.\r
-  @param  PortMultiplier      The timeout value of stop.\r
-  @param  AtapiCommand        The atapi command will be used for the transfer.\r
-  @param  AtapiCommandLength  The length of the atapi command.\r
-  @param  AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK data.\r
-  @param  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK data.\r
-  @param  Timeout             The timeout value of non data transfer.\r
-\r
-  @retval EFI_DEVICE_ERROR    The non data transfer abort with error occurs.\r
-  @retval EFI_TIMEOUT         The operation is time out.\r
-  @retval EFI_UNSUPPORTED     The device is not ready for transfer.\r
-  @retval EFI_SUCCESS         The non data transfer executes successfully.\r
-\r
-**/ \r
-EFI_STATUS\r
-EFIAPI\r
-AhciNonDataTransfer (\r
-  IN     EFI_PCI_IO_PROTOCOL           *PciIo,\r
-  IN     EFI_AHCI_REGISTERS            *AhciRegisters,\r
-  IN     UINT8                         Port,\r
-  IN     UINT8                         PortMultiplier,\r
-  IN     EFI_AHCI_ATAPI_COMMAND        *AtapiCommand OPTIONAL,\r
-  IN     UINT8                         AtapiCommandLength,\r
-  IN     EFI_ATA_COMMAND_BLOCK         *AtaCommandBlock,\r
-  IN OUT EFI_ATA_STATUS_BLOCK          *AtaStatusBlock,\r
-  IN     UINT64                        Timeout\r
-  );\r
-\r
-/**\r
-  Start a DMA data transfer on specific port\r
-\r
-  @param  PciIo               The PCI IO protocol instance.\r
-  @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.\r
-  @param  Port                The number of port.\r
-  @param  PortMultiplier      The timeout value of stop.\r
-  @param  AtapiCommand        The atapi command will be used for the transfer.\r
-  @param  AtapiCommandLength  The length of the atapi command.\r
-  @param  Read                The transfer direction.\r
-  @param  AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK data.\r
-  @param  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK data.\r
-  @param  MemoryAddr          The pointer to the data buffer.\r
-  @param  DataCount           The data count to be transferred.\r
-  @param  Timeout             The timeout value of non data transfer.\r
-\r
-  @retval EFI_DEVICE_ERROR    The DMA data transfer abort with error occurs.\r
-  @retval EFI_TIMEOUT         The operation is time out.\r
-  @retval EFI_UNSUPPORTED     The device is not ready for transfer.\r
-  @retval EFI_SUCCESS         The DMA data transfer executes successfully.\r
-   \r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciDmaTransfer (\r
-  IN     EFI_PCI_IO_PROTOCOL        *PciIo,\r
-  IN     EFI_AHCI_REGISTERS         *AhciRegisters,\r
-  IN     UINT8                      Port,\r
-  IN     UINT8                      PortMultiplier,\r
-  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,\r
-  IN     UINT8                      AtapiCommandLength,\r
-  IN     BOOLEAN                    Read,  \r
-  IN     EFI_ATA_COMMAND_BLOCK      *AtaCommandBlock,\r
-  IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,\r
-  IN OUT VOID                       *MemoryAddr,\r
-  IN     UINTN                      DataCount,\r
-  IN     UINT64                     Timeout\r
-  );\r
-\r
-/**\r
-  Start a PIO data transfer on specific port.\r
-    \r
-  @param  PciIo               The PCI IO protocol instance.\r
-  @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.\r
-  @param  Port                The number of port.\r
-  @param  PortMultiplier      The timeout value of stop.\r
-  @param  AtapiCommand        The atapi command will be used for the transfer.\r
-  @param  AtapiCommandLength  The length of the atapi command.\r
-  @param  Read                The transfer direction.\r
-  @param  AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK data.\r
-  @param  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK data.\r
-  @param  MemoryAddr          The pointer to the data buffer.\r
-  @param  DataCount           The data count to be transferred.\r
-  @param  Timeout             The timeout value of non data transfer.\r
-\r
-  @retval EFI_DEVICE_ERROR    The PIO data transfer abort with error occurs.\r
-  @retval EFI_TIMEOUT         The operation is time out.\r
-  @retval EFI_UNSUPPORTED     The device is not ready for transfer.\r
-  @retval EFI_SUCCESS         The PIO data transfer executes successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciPioTransfer (\r
-  IN     EFI_PCI_IO_PROTOCOL        *PciIo,\r
-  IN     EFI_AHCI_REGISTERS         *AhciRegisters,\r
-  IN     UINT8                      Port,\r
-  IN     UINT8                      PortMultiplier,\r
-  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,\r
-  IN     UINT8                      AtapiCommandLength,  \r
-  IN     BOOLEAN                    Read,  \r
-  IN     EFI_ATA_COMMAND_BLOCK      *AtaCommandBlock,\r
-  IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,\r
-  IN OUT VOID                       *MemoryAddr,\r
-  IN     UINT32                     DataCount,\r
-  IN     UINT64                     Timeout \r
-  );\r
-\r
-\r
 #endif\r
 \r
index ca64df7f6bbf3f21d142ea9fa76cfdc3f59a8294..3e135d74ec60068882c30d3a323faf88fb77ba6c 100644 (file)
@@ -39,7 +39,7 @@ ATA_ATAPI_PASS_THRU_INSTANCE gAtaAtapiPassThruInstanceTemplate = {
     // bits.\r
     // Note that the driver doesn't support AtaPassThru non blocking I/O.\r
     //\r
-    EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL,\r
+    EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL | EFI_ATA_PASS_THRU_ATTRIBUTES_NONBLOCKIO,\r
     //\r
     // IoAlign\r
     //\r
@@ -98,7 +98,12 @@ ATA_ATAPI_PASS_THRU_INSTANCE gAtaAtapiPassThruInstanceTemplate = {
   0,                  // PreviousPort\r
   0,                  // PreviousPortMultiplier\r
   0,                  // PreviousTargetId\r
-  0                   // PreviousLun\r
+  0,                  // PreviousLun\r
+  NULL,               // Timer event\r
+  {                   // NonBlocking TaskList\r
+    NULL,             \r
+    NULL\r
+  }\r
 };\r
 \r
 ATAPI_DEVICE_PATH    mAtapiDevicePathTemplate = {\r
@@ -132,12 +137,304 @@ UINT8 mScsiId[TARGET_MAX_BYTES] = {
   0xFF, 0xFF, 0xFF, 0xFF\r
 };\r
 \r
+/**\r
+  Sends an ATA command to an ATA device that is attached to the ATA controller. This function\r
+  supports both blocking I/O and non-blocking I/O. The blocking I/O functionality is required,\r
+  and the non-blocking I/O functionality is optional.\r
+\r
+  @param[in]      Port               The port number of the ATA device to send the command. \r
+  @param[in]      PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
+                                     If there is no port multiplier, then specify 0.\r
+  @param[in, out] Packet             A pointer to the ATA command to send to the ATA device specified by Port\r
+                                     and PortMultiplierPort.\r
+  @param[in]      Instance           Pointer to the ATA_ATAPI_PASS_THRU_INSTANCE.\r
+  @param[in]      Task               Optional. Pointer to the ATA_NONBLOCK_TASK\r
+                                     used by non-blocking mode.\r
+\r
+  @retval EFI_SUCCESS                The ATA command was sent by the host. For\r
+                                     bi-directional commands, InTransferLength bytes\r
+                                     were transferred from InDataBuffer. For\r
+                                     write and bi-directional commands, OutTransferLength\r
+                                     bytes were transferred by OutDataBuffer.\r
+  @retval EFI_BAD_BUFFER_SIZE        The ATA command was not executed. The number\r
+                                     of bytes that could be transferred is returned\r
+                                     in InTransferLength. For write and bi-directional\r
+                                     commands, OutTransferLength bytes were transferred\r
+                                     by OutDataBuffer.\r
+  @retval EFI_NOT_READY              The ATA command could not be sent because\r
+                                     there are too many ATA commands already\r
+                                     queued. The caller may retry again later.\r
+  @retval EFI_DEVICE_ERROR           A device error occurred while attempting\r
+                                     to send the ATA command.\r
+  @retval EFI_INVALID_PARAMETER      Port, PortMultiplierPort, or the contents\r
+                                     of Acb are invalid. The ATA command was\r
+                                     not sent, so no additional status information\r
+                                     is available.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaPassThruPassThruExecute (\r
+  IN     UINT16                           Port,\r
+  IN     UINT16                           PortMultiplierPort,\r
+  IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet,\r
+  IN     ATA_ATAPI_PASS_THRU_INSTANCE     *Instance, \r
+  IN     ATA_NONBLOCK_TASK                *Task OPTIONAL\r
+  )\r
+{\r
+  EFI_ATA_PASS_THRU_CMD_PROTOCOL  Protocol;\r
+  EFI_ATA_HC_WORK_MODE            Mode;\r
+  EFI_STATUS                      Status;\r
+  \r
+  Protocol = Packet->Protocol;\r
+\r
+  Mode = Instance->Mode;\r
+  switch (Mode) {\r
+    case EfiAtaIdeMode:\r
+      //\r
+      // Reassign IDE mode io port registers' base addresses\r
+      //\r
+      Status = GetIdeRegisterIoAddr (Instance->PciIo, Instance->IdeRegisters);\r
+      \r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      \r
+      switch (Protocol) {\r
+        case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:\r
+          Status = AtaNonDataCommandIn (\r
+                     Instance->PciIo,\r
+                     &Instance->IdeRegisters[Port],\r
+                     Packet->Acb,\r
+                     Packet->Asb,\r
+                     Packet->Timeout, \r
+                     Task\r
+                     );\r
+          break;\r
+        case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN:\r
+          Status = AtaPioDataInOut (\r
+                     Instance->PciIo,\r
+                     &Instance->IdeRegisters[Port],\r
+                     Packet->InDataBuffer,\r
+                     Packet->InTransferLength,\r
+                     TRUE,\r
+                     Packet->Acb,\r
+                     Packet->Asb,\r
+                     Packet->Timeout,\r
+                     Task\r
+                     );\r
+          break;\r
+        case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT:\r
+          Status = AtaPioDataInOut (\r
+                     Instance->PciIo,\r
+                     &Instance->IdeRegisters[Port],\r
+                     Packet->OutDataBuffer,\r
+                     Packet->OutTransferLength,\r
+                     FALSE,\r
+                     Packet->Acb,\r
+                     Packet->Asb,\r
+                     Packet->Timeout,\r
+                     Task\r
+                     );\r
+          break;\r
+        case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN:\r
+          Status = AtaUdmaInOut (\r
+                     Instance,\r
+                     &Instance->IdeRegisters[Port],\r
+                     TRUE,\r
+                     Packet->InDataBuffer,\r
+                     Packet->InTransferLength,\r
+                     Packet->Acb,\r
+                     Packet->Asb,\r
+                     Packet->Timeout,\r
+                     Task\r
+                     );\r
+          break;\r
+        case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT:\r
+          Status = AtaUdmaInOut (\r
+                     Instance,\r
+                     &Instance->IdeRegisters[Port],\r
+                     FALSE,\r
+                     Packet->OutDataBuffer,\r
+                     Packet->OutTransferLength,\r
+                     Packet->Acb,\r
+                     Packet->Asb,\r
+                     Packet->Timeout,\r
+                     Task\r
+                     );\r
+          break;\r
+        default :\r
+          return EFI_UNSUPPORTED;\r
+      }\r
+      break;\r
+    case EfiAtaAhciMode :\r
+      switch (Protocol) {\r
+        case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:\r
+          Status = AhciNonDataTransfer (\r
+                     Instance->PciIo,\r
+                     &Instance->AhciRegisters,\r
+                     (UINT8)Port,\r
+                     (UINT8)PortMultiplierPort,\r
+                     NULL,\r
+                     0,\r
+                     Packet->Acb,\r
+                     Packet->Asb,\r
+                     Packet->Timeout,\r
+                     Task\r
+                     );\r
+          break;\r
+        case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN:\r
+          Status = AhciPioTransfer (\r
+                     Instance->PciIo,\r
+                     &Instance->AhciRegisters,\r
+                     (UINT8)Port,\r
+                     (UINT8)PortMultiplierPort,\r
+                     NULL,\r
+                     0,\r
+                     TRUE,\r
+                     Packet->Acb,\r
+                     Packet->Asb,\r
+                     Packet->InDataBuffer,\r
+                     Packet->InTransferLength,\r
+                     Packet->Timeout,\r
+                     Task\r
+                     );\r
+          break;\r
+        case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT:\r
+          Status = AhciPioTransfer (\r
+                     Instance->PciIo,\r
+                     &Instance->AhciRegisters,\r
+                     (UINT8)Port,\r
+                     (UINT8)PortMultiplierPort,\r
+                     NULL,\r
+                     0,\r
+                     FALSE,\r
+                     Packet->Acb,\r
+                     Packet->Asb,\r
+                     Packet->OutDataBuffer,\r
+                     Packet->OutTransferLength,\r
+                     Packet->Timeout, \r
+                     Task\r
+                     );\r
+          break;\r
+        case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN:\r
+          Status = AhciDmaTransfer (\r
+                     Instance,\r
+                     &Instance->AhciRegisters,\r
+                     (UINT8)Port,\r
+                     (UINT8)PortMultiplierPort,\r
+                     NULL,\r
+                     0,\r
+                     TRUE,\r
+                     Packet->Acb,\r
+                     Packet->Asb,\r
+                     Packet->InDataBuffer,\r
+                     Packet->InTransferLength,\r
+                     Packet->Timeout,\r
+                     Task\r
+                     );\r
+          break;\r
+        case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT:\r
+          Status = AhciDmaTransfer (\r
+                     Instance,\r
+                     &Instance->AhciRegisters,\r
+                     (UINT8)Port,\r
+                     (UINT8)PortMultiplierPort,\r
+                     NULL,\r
+                     0,\r
+                     FALSE,\r
+                     Packet->Acb,\r
+                     Packet->Asb,\r
+                     Packet->OutDataBuffer,\r
+                     Packet->OutTransferLength,\r
+                     Packet->Timeout,\r
+                     Task\r
+                     );\r
+          break;\r
+        default :\r
+          return EFI_UNSUPPORTED;\r
+      }\r
+      break;\r
+\r
+    default:\r
+      Status = EFI_DEVICE_ERROR;\r
+      break;\r
+  }\r
+  \r
+  return Status;\r
+}\r
+\r
+/**\r
+  Call back function when the timer event is signaled.\r
+\r
+  @param[in]  Event     The Event this notify function registered to.\r
+  @param[in]  Context   Pointer to the context data registered to the\r
+                        Event. \r
\r
+**/\r
+VOID\r
+EFIAPI \r
+AsyncNonBlockingTransferRoutine (\r
+  EFI_EVENT  Event,\r
+  VOID*      Context\r
+  )\r
+{\r
+  LIST_ENTRY                   *Entry;\r
+  LIST_ENTRY                   *EntryHeader;\r
+  ATA_NONBLOCK_TASK            *Task;\r
+  EFI_STATUS                   Status;\r
+  ATA_ATAPI_PASS_THRU_INSTANCE *Instance;\r
+\r
+  Instance   = (ATA_ATAPI_PASS_THRU_INSTANCE *) Context;\r
+  EntryHeader = &Instance->NonBlockingTaskList;\r
+  //\r
+  // Get the Taks from the Taks List and execute it, until there is \r
+  // no task in the list or the device is busy with task (EFI_NOT_READY).\r
+  //\r
+  while (TRUE) {\r
+    if (!IsListEmpty (EntryHeader)) {\r
+      Entry = GetFirstNode (EntryHeader);\r
+      Task  = ATA_NON_BLOCK_TASK_FROM_ENTRY (Entry);\r
+    } else {\r
+      return;\r
+    }\r
+\r
+    Status = AtaPassThruPassThruExecute (\r
+               Task->Port,\r
+               Task->PortMultiplier,\r
+               Task->Packet,\r
+               Instance,\r
+               Task\r
+               );\r
+\r
+    //\r
+    // If the data transfer meet a error which is not dumped into the status block\r
+    // set the Status block related bit.\r
+    //\r
+    if ((Status != EFI_NOT_READY) && (Status != EFI_SUCCESS)) {\r
+      Task->Packet->Asb->AtaStatus = 0x01;\r
+    }\r
+    //\r
+    // For Non blocking mode, the Status of EFI_NOT_READY means the operation\r
+    // is not finished yet. Other Status indicate the operation is either\r
+    // successful or failed. \r
+    //\r
+    if (Status != EFI_NOT_READY) {\r
+      RemoveEntryList (&Task->Link);\r
+      gBS->SignalEvent (Task->Event);\r
+      FreePool (Task);\r
+    } else {\r
+      break;\r
+    }\r
+  }\r
+}\r
+\r
 /**\r
   The Entry Point of module.\r
 \r
-  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  \r
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
   @param[in] SystemTable    A pointer to the EFI System Table.\r
-  \r
+\r
   @retval EFI_SUCCESS       The entry point is executed successfully.\r
   @retval other             Some error occurs when executing this entry point.\r
 \r
@@ -266,7 +563,7 @@ AtaAtapiPassThruSupported (
     //\r
     return Status;\r
   }\r
-  \r
+\r
   //\r
   // Close the I/O Abstraction(s) used to perform the supported test\r
   //\r
@@ -324,7 +621,7 @@ AtaAtapiPassThruSupported (
   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
      EFI_DEVICE_PATH_PROTOCOL.\r
   3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
-     have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.  \r
+     have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.\r
 \r
   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
   @param[in]  ControllerHandle     The handle of the controller to start. This handle \r
@@ -333,7 +630,7 @@ AtaAtapiPassThruSupported (
   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This \r
                                    parameter is ignored by device drivers, and is optional for bus \r
                                    drivers. For a bus driver, if this parameter is NULL, then handles \r
-                                   for all the children of Controller are created by this driver.  \r
+                                   for all the children of Controller are created by this driver.\r
                                    If this parameter is not NULL and the first Device Path Node is \r
                                    not the End of Device Path Node, then only the handle for the \r
                                    child device specified by the first Device Path Node of \r
@@ -446,6 +743,28 @@ AtaAtapiPassThruStart (
   Instance->AtaPassThru.Mode      = &Instance->AtaPassThruMode;\r
   Instance->ExtScsiPassThru.Mode  = &Instance->ExtScsiPassThruMode;\r
   InitializeListHead(&Instance->DeviceList);\r
+  InitializeListHead(&Instance->NonBlockingTaskList);\r
+\r
+  Instance->TimerEvent = NULL;\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  AsyncNonBlockingTransferRoutine,\r
+                  Instance,\r
+                  &Instance->TimerEvent\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ErrorExit;\r
+  }\r
+  \r
+  //\r
+  // Set 1ms timer.\r
+  //\r
+  Status = gBS->SetTimer (Instance->TimerEvent, TimerPeriodic, 10000);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ErrorExit;\r
+  }\r
 \r
   //\r
   // Enumerate all inserted ATA devices.\r
@@ -475,6 +794,10 @@ ErrorExit:
            );\r
   }\r
 \r
+  if (Instance->TimerEvent != NULL) {\r
+    gBS->CloseEvent (Instance->TimerEvent);\r
+  }\r
+\r
   //\r
   // Remove all inserted ATA devices.\r
   //\r
@@ -542,13 +865,22 @@ AtaAtapiPassThruStop (
   if (EFI_ERROR (Status)) {\r
     return EFI_DEVICE_ERROR;\r
   }\r
-  \r
-  Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS(AtaPassThru);\r
-  PciIo    = Instance->PciIo;\r
+\r
+  Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (AtaPassThru);\r
+\r
+  //\r
+  // Close Non-Blocking timer and free Task list.\r
+  //\r
+  if (Instance->TimerEvent != NULL) {\r
+    gBS->CloseEvent (Instance->TimerEvent);\r
+    Instance->TimerEvent = NULL;\r
+  }\r
+  DestroyAsynTaskList (Instance);\r
 \r
   //\r
   // Disable this ATA host controller.\r
   //\r
+  PciIo  = Instance->PciIo;\r
   Status = PciIo->Attributes (\r
                     PciIo,\r
                     EfiPciIoAttributeOperationSupported,\r
@@ -672,7 +1004,7 @@ SearchDeviceInfoList (
     }\r
 \r
     Node = GetNextNode (&Instance->DeviceList, Node);\r
-  }  \r
+  }\r
 \r
   return NULL;\r
 }\r
@@ -757,6 +1089,42 @@ DestroyDeviceInfoList (
   }\r
 }\r
 \r
+/**\r
+  Destroy all pending non blocking tasks.\r
+  \r
+  @param[in]  Instance  A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DestroyAsynTaskList (\r
+  IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance\r
+  )\r
+{\r
+  LIST_ENTRY           *Entry;\r
+  LIST_ENTRY           *DelEntry;\r
+  ATA_NONBLOCK_TASK    *Task;\r
+  EFI_TPL              OldTpl;\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+  if (!IsListEmpty (&Instance->NonBlockingTaskList)) {\r
+    //\r
+    // Free the Subtask list.\r
+    //\r
+    for (Entry = (&Instance->NonBlockingTaskList)->ForwardLink; \r
+        Entry != (&Instance->NonBlockingTaskList);\r
+       ) {\r
+      DelEntry = Entry;\r
+      Entry    = Entry->ForwardLink;\r
+      Task     = ATA_NON_BLOCK_TASK_FROM_ENTRY (DelEntry);\r
+\r
+      RemoveEntryList (DelEntry);\r
+      FreePool (Task);\r
+    }\r
+  }\r
+  gBS->RestoreTPL (OldTpl);\r
+}\r
+\r
 /**\r
   Enumerate all attached ATA devices at IDE mode or AHCI mode separately.\r
   \r
@@ -863,17 +1231,16 @@ AtaPassThruPassThru (
   IN     UINT16                           PortMultiplierPort,\r
   IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet,\r
   IN     EFI_EVENT                        Event OPTIONAL\r
-  ) \r
+  )\r
 {\r
-  EFI_STATUS                      Status;\r
   ATA_ATAPI_PASS_THRU_INSTANCE    *Instance;\r
-  EFI_ATA_PASS_THRU_CMD_PROTOCOL  Protocol;\r
-  EFI_ATA_HC_WORK_MODE            Mode;\r
   LIST_ENTRY                      *Node;\r
   EFI_ATA_DEVICE_INFO             *DeviceInfo;\r
   EFI_IDENTIFY_DATA               *IdentifyData;\r
   UINT64                          Capacity;\r
   UINT32                          MaxSectorCount;\r
+  ATA_NONBLOCK_TASK               *Task;\r
+  EFI_TPL                         OldTpl;\r
 \r
   Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);\r
 \r
@@ -940,173 +1307,37 @@ AtaPassThruPassThru (
     return EFI_BAD_BUFFER_SIZE;\r
   }\r
 \r
-  Status   = EFI_UNSUPPORTED;\r
-  Protocol = Packet->Protocol;\r
-\r
-  Mode = Instance->Mode;\r
-  switch (Mode) {\r
-    case EfiAtaIdeMode:\r
-      //\r
-      // Reassign IDE mode io port registers' base addresses\r
-      //\r
-      Status = GetIdeRegisterIoAddr (Instance->PciIo, Instance->IdeRegisters);\r
-      \r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-      \r
-      switch (Protocol) {\r
-        case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:\r
-          Status = AtaNonDataCommandIn(\r
-                     Instance->PciIo,\r
-                     &Instance->IdeRegisters[Port],\r
-                     Packet->Acb,\r
-                     Packet->Asb,\r
-                     Packet->Timeout\r
-                     );\r
-          break;\r
-        case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN:\r
-          Status = AtaPioDataInOut(\r
-                     Instance->PciIo,\r
-                     &Instance->IdeRegisters[Port],\r
-                     Packet->InDataBuffer,\r
-                     Packet->InTransferLength,\r
-                     TRUE,\r
-                     Packet->Acb,\r
-                     Packet->Asb,\r
-                     Packet->Timeout\r
-                     );\r
-          break;\r
-        case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT:\r
-          Status = AtaPioDataInOut(\r
-                     Instance->PciIo,\r
-                     &Instance->IdeRegisters[Port],\r
-                     Packet->OutDataBuffer,\r
-                     Packet->OutTransferLength,\r
-                     FALSE,\r
-                     Packet->Acb,\r
-                     Packet->Asb,\r
-                     Packet->Timeout\r
-                     );\r
-          break;\r
-        case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN:\r
-          Status = AtaUdmaInOut(\r
-                     Instance->PciIo,\r
-                     &Instance->IdeRegisters[Port],\r
-                     TRUE,\r
-                     Packet->InDataBuffer,\r
-                     Packet->InTransferLength,\r
-                     Packet->Acb,\r
-                     Packet->Asb,\r
-                     Packet->Timeout\r
-                     );\r
-          break;\r
-        case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT:\r
-          Status = AtaUdmaInOut(\r
-                     Instance->PciIo,\r
-                     &Instance->IdeRegisters[Port],\r
-                     FALSE,\r
-                     Packet->OutDataBuffer,\r
-                     Packet->OutTransferLength,\r
-                     Packet->Acb,\r
-                     Packet->Asb,\r
-                     Packet->Timeout\r
-                     );\r
-          break;\r
-        default :\r
-          return EFI_UNSUPPORTED;\r
-      }\r
-      break;\r
-    case EfiAtaAhciMode :\r
-      switch (Protocol) {\r
-        case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:\r
-          Status = AhciNonDataTransfer(\r
-                     Instance->PciIo,\r
-                     &Instance->AhciRegisters,\r
-                     (UINT8)Port,\r
-                     (UINT8)PortMultiplierPort,\r
-                     NULL,\r
-                     0,\r
-                     Packet->Acb,\r
-                     Packet->Asb,\r
-                     Packet->Timeout\r
-                     );\r
-          break;\r
-        case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN:\r
-          Status = AhciPioTransfer(\r
-                     Instance->PciIo,\r
-                     &Instance->AhciRegisters,\r
-                     (UINT8)Port,\r
-                     (UINT8)PortMultiplierPort,\r
-                     NULL,\r
-                     0,\r
-                     TRUE,\r
-                     Packet->Acb,\r
-                     Packet->Asb,\r
-                     Packet->InDataBuffer,\r
-                     Packet->InTransferLength,\r
-                     Packet->Timeout\r
-                     );\r
-          break;\r
-        case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT:\r
-          Status = AhciPioTransfer(\r
-                     Instance->PciIo,\r
-                     &Instance->AhciRegisters,\r
-                     (UINT8)Port,\r
-                     (UINT8)PortMultiplierPort,\r
-                     NULL,\r
-                     0,\r
-                     FALSE,\r
-                     Packet->Acb,\r
-                     Packet->Asb,\r
-                     Packet->OutDataBuffer,\r
-                     Packet->OutTransferLength,\r
-                     Packet->Timeout\r
-                     );\r
-          break;\r
-        case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN:\r
-          Status = AhciDmaTransfer(\r
-                     Instance->PciIo,\r
-                     &Instance->AhciRegisters,\r
-                     (UINT8)Port,\r
-                     (UINT8)PortMultiplierPort,\r
-                     NULL,\r
-                     0,\r
-                     TRUE,\r
-                     Packet->Acb,\r
-                     Packet->Asb,\r
-                     Packet->InDataBuffer,\r
-                     Packet->InTransferLength,\r
-                     Packet->Timeout\r
-                     );\r
-          break;\r
-        case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT:\r
-          Status = AhciDmaTransfer(\r
-                     Instance->PciIo,\r
-                     &Instance->AhciRegisters,\r
-                     (UINT8)Port,\r
-                     (UINT8)PortMultiplierPort,\r
-                     NULL,\r
-                     0,\r
-                     FALSE,\r
-                     Packet->Acb,\r
-                     Packet->Asb,\r
-                     Packet->OutDataBuffer,\r
-                     Packet->OutTransferLength,\r
-                     Packet->Timeout\r
-                     );\r
-          break;\r
-        default :\r
-          return EFI_UNSUPPORTED;\r
-      }\r
-      break;\r
+  //\r
+  // For non-blocking mode, queue the Task into the list.\r
+  //\r
+  if (Event != NULL) {\r
+    Task = AllocateZeroPool (sizeof (ATA_NONBLOCK_TASK));\r
+    if (Task == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    \r
+    Task->Signature      = ATA_NONBLOCKING_TASK_SIGNATURE;\r
+    Task->Port           = Port;\r
+    Task->PortMultiplier = PortMultiplierPort;\r
+    Task->Packet         = Packet;\r
+    Task->Event          = Event;\r
+    Task->IsStart        = FALSE;\r
+    Task->RetryTimes     = 0;\r
+\r
+    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+    InsertTailList (&Instance->NonBlockingTaskList, &Task->Link);\r
+    gBS->RestoreTPL (OldTpl);\r
 \r
-    default:\r
-      Status = EFI_DEVICE_ERROR;\r
-      break;\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    return AtaPassThruPassThruExecute (\r
+             Port,\r
+             PortMultiplierPort,\r
+             Packet,\r
+             Instance,\r
+             NULL\r
+             );\r
   }\r
-\r
-  return Status;\r
 }\r
 \r
 /**\r
@@ -1197,7 +1428,7 @@ AtaPassThruGetNextPort (
     //\r
     return EFI_INVALID_PARAMETER;\r
   }\r
-  \r
+\r
 Exit:\r
   //\r
   // Update the PreviousPort and PreviousPortMultiplier.\r
@@ -1216,20 +1447,20 @@ Exit:
 \r
   The GetNextDevice() function retrieves the port multiplier port number of an ATA device \r
   present on a port of an ATA controller.\r
-  \r
+\r
   If PortMultiplierPort points to a port multiplier port number value that was returned on a \r
   previous call to GetNextDevice(), then the port multiplier port number of the next ATA device\r
   on the port of the ATA controller is returned in PortMultiplierPort, and EFI_SUCCESS is\r
   returned.\r
-  \r
+\r
   If PortMultiplierPort points to 0xFFFF, then the port multiplier port number of the first \r
   ATA device on port of the ATA controller is returned in PortMultiplierPort and \r
   EFI_SUCCESS is returned.\r
-  \r
+\r
   If PortMultiplierPort is not 0xFFFF and the value pointed to by PortMultiplierPort\r
   was not returned on a previous call to GetNextDevice(), then EFI_INVALID_PARAMETER\r
   is returned.\r
-  \r
+\r
   If PortMultiplierPort is the port multiplier port number of the last ATA device on the port of \r
   the ATA controller, then EFI_NOT_FOUND is returned.\r
 \r
@@ -1309,7 +1540,7 @@ AtaPassThruGetNextDevice (
     //\r
     return EFI_INVALID_PARAMETER;\r
   }\r
-  \r
+\r
 Exit:\r
   //\r
   // Update the PreviousPort and PreviousPortMultiplier.\r
@@ -1377,7 +1608,7 @@ AtaPassThruBuildDevicePath (
   if (Node == NULL) {\r
     return EFI_NOT_FOUND;\r
   }\r
-  \r
+\r
   if (Instance->Mode == EfiAtaIdeMode) {\r
     DevicePathNode = AllocateCopyPool (sizeof (ATAPI_DEVICE_PATH), &mAtapiDevicePathTemplate);\r
     if (DevicePathNode == NULL) {\r
@@ -1719,7 +1950,7 @@ ExtScsiPassThruPassThru (
   can either be the list SCSI devices that are actually present on the SCSI channel, or the list of legal\r
   Target Ids and LUNs for the SCSI channel. Regardless, the caller of this function must probe the       \r
   Target ID and LUN returned to see if a SCSI device is actually present at that location on the SCSI    \r
-  channel.                                                                                               \r
+  channel.\r
 \r
   @param  This   A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.\r
   @param  Target On input, a pointer to the Target ID (an array of size\r
@@ -1840,7 +2071,7 @@ Exit:
   Instance->PreviousLun      = *Lun;\r
   \r
   return EFI_SUCCESS;\r
-}   \r
+}\r
 \r
 /**\r
   Used to allocate and build a device path node for a SCSI device on a SCSI channel.\r
@@ -2031,8 +2262,8 @@ ExtScsiPassThruResetChannel (
   )\r
 {\r
   return EFI_UNSUPPORTED;\r
-}    \r
-  \r
+}\r
+\r
 /**\r
   Resets a SCSI logical unit that is connected to a SCSI channel.\r
 \r
@@ -2061,7 +2292,7 @@ ExtScsiPassThruResetTargetLun (
   )\r
 {\r
   return EFI_UNSUPPORTED;\r
-}         \r
+}\r
 \r
 /**\r
   Used to retrieve the list of legal Target IDs for SCSI devices on a SCSI channel. These can either     \r
@@ -2176,5 +2407,5 @@ Exit:
   Instance->PreviousTargetId = *Target16;\r
 \r
   return EFI_SUCCESS;\r
-}    \r
+}\r
 \r
index e1401867bb3336a53f00697e41020a96e38c9639..0987478564ac3d4e4939b48f9ab7d4b95c6d4808 100644 (file)
@@ -1,7 +1,7 @@
 /** @file
   Header file for ATA/ATAPI PASS THRU driver.
   
-  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2010 - 2011, 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        
@@ -47,6 +47,9 @@ extern EFI_COMPONENT_NAME2_PROTOCOL gAtaAtapiPassThruComponentName2;
 
 #define ATA_ATAPI_PASS_THRU_SIGNATURE  SIGNATURE_32 ('a', 'a', 'p', 't')
 #define ATA_ATAPI_DEVICE_SIGNATURE     SIGNATURE_32 ('a', 'd', 'e', 'v')
+#define ATA_NONBLOCKING_TASK_SIGNATURE  SIGNATURE_32 ('a', 't', 's', 'k')
+
+typedef struct _ATA_NONBLOCK_TASK ATA_NONBLOCK_TASK;
 
 typedef enum {
   EfiAtaIdeMode,
@@ -111,9 +114,33 @@ typedef struct {
   //
   UINT16                            PreviousTargetId;
   UINT64                            PreviousLun;
-
+  //
+  // For Non-blocking.
+  //
+  EFI_EVENT                         TimerEvent;
+  LIST_ENTRY                        NonBlockingTaskList;
 } ATA_ATAPI_PASS_THRU_INSTANCE;
 
+//
+// Task for Non-blocking mode.
+//
+struct _ATA_NONBLOCK_TASK {
+  UINT32                            Signature;
+  LIST_ENTRY                        Link;
+
+  UINT16                            Port;
+  UINT16                            PortMultiplier;
+  EFI_ATA_PASS_THRU_COMMAND_PACKET  *Packet;
+  BOOLEAN                           IsStart;
+  EFI_EVENT                         Event;
+  UINT64                            RetryTimes;
+  VOID                              *Map; // Pointer to map.
+  VOID                              *TableMap;// Pointer to PRD table map. 
+  EFI_ATA_DMA_PRD                   *MapBaseAddress; //  Pointer to range Base address for Map.
+  UINTN                             PageCount;      //  The page numbers used by PCIO freebuffer.
+};
+
 //
 // Timeout value which uses 100ns as a unit.
 // It means 3 second span.
@@ -142,6 +169,14 @@ typedef struct {
       Link, \
       ATA_ATAPI_DEVICE_SIGNATURE \
       );
+
+#define ATA_NON_BLOCK_TASK_FROM_ENTRY(a) \
+  CR (a, \
+      ATA_NONBLOCK_TASK, \
+      Link, \
+      ATA_NONBLOCKING_TASK_SIGNATURE \
+      );
+
 /**
   Retrieves a Unicode string that is the user readable name of the driver.
 
@@ -453,6 +488,18 @@ DestroyDeviceInfoList (
   IN  ATA_ATAPI_PASS_THRU_INSTANCE  *Instance
   );
 
+/**
+  Destroy all pending non blocking tasks.
+  
+  @param[in]  Instance  A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
+
+**/
+VOID
+EFIAPI
+DestroyAsynTaskList (
+  IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance
+  );
+
 /**
   Enumerate all attached ATA devices at IDE mode or AHCI mode separately.
   
@@ -470,6 +517,21 @@ EnumerateAttachedDevice (
   IN  ATA_ATAPI_PASS_THRU_INSTANCE      *Instance
   );
 
+/**
+  Call back funtion when the timer event is signaled.
+
+  @param[in]  Event     The Event this notify function registered to.
+  @param[in]  Context   Pointer to the context data registered to the
+                        Event.
+
+**/
+VOID
+EFIAPI 
+AsyncNonBlockingTransferRoutine (
+  EFI_EVENT  Event, 
+  VOID*      Context
+  );
+
 /**
   Sends an ATA command to an ATA device that is attached to the ATA controller. This function
   supports both blocking I/O and non-blocking I/O. The blocking I/O functionality is required,
@@ -556,16 +618,16 @@ AtaPassThruGetNextPort (
 
   The GetNextDevice() function retrieves the port multiplier port number of an ATA device 
   present on a port of an ATA controller.
-  
+
   If PortMultiplierPort points to a port multiplier port number value that was returned on a 
   previous call to GetNextDevice(), then the port multiplier port number of the next ATA device
   on the port of the ATA controller is returned in PortMultiplierPort, and EFI_SUCCESS is
   returned.
-  
+
   If PortMultiplierPort points to 0xFFFF, then the port multiplier port number of the first 
   ATA device on port of the ATA controller is returned in PortMultiplierPort and 
   EFI_SUCCESS is returned.
-  
+
   If PortMultiplierPort is not 0xFFFF and the value pointed to by PortMultiplierPort
   was not returned on a previous call to GetNextDevice(), then EFI_INVALID_PARAMETER
   is returned.
@@ -673,6 +735,7 @@ AtaPassThruBuildDevicePath (
   @retval EFI_UNSUPPORTED         This driver does not support the device path node type in DevicePath.
   @retval EFI_NOT_FOUND           A valid translation from DevicePath to a port number and port multiplier
                                   port number does not exist.
+
 **/
 EFI_STATUS
 EFIAPI
@@ -809,7 +872,7 @@ ExtScsiPassThruPassThru (
   can either be the list SCSI devices that are actually present on the SCSI channel, or the list of legal
   Target Ids and LUNs for the SCSI channel. Regardless, the caller of this function must probe the       
   Target ID and LUN returned to see if a SCSI device is actually present at that location on the SCSI    
-  channel.                                                                                               
+  channel.
 
   @param  This   A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
   @param  Target On input, a pointer to the Target ID (an array of size
@@ -918,7 +981,7 @@ EFIAPI
 ExtScsiPassThruResetChannel (
   IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL   *This
   );
-  
+
 /**
   Resets a SCSI logical unit that is connected to a SCSI channel.
 
@@ -1003,5 +1066,231 @@ AhciModeInitialization (
   IN  ATA_ATAPI_PASS_THRU_INSTANCE    *Instance
   );
 
+/**
+  Start a non data transfer on specific port.
+    
+  @param[in]       PciIo               The PCI IO protocol instance.
+  @param[in]       AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
+  @param[in]       Port                The number of port.
+  @param[in]       PortMultiplier      The timeout value of stop.
+  @param[in]       AtapiCommand        The atapi command will be used for the
+                                       transfer.
+  @param[in]       AtapiCommandLength  The length of the atapi command.
+  @param[in]       AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK data.
+  @param[in, out]  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK data.
+  @param[in]       Timeout             The timeout value of non data transfer.
+  @param[in]       Task                Optional. Pointer to the ATA_NONBLOCK_TASK
+                                       used by non-blocking mode.
+
+  @retval EFI_DEVICE_ERROR    The non data transfer abort with error occurs.
+  @retval EFI_TIMEOUT         The operation is time out.
+  @retval EFI_UNSUPPORTED     The device is not ready for transfer.
+  @retval EFI_SUCCESS         The non data transfer executes successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciNonDataTransfer (
+  IN     EFI_PCI_IO_PROTOCOL           *PciIo,
+  IN     EFI_AHCI_REGISTERS            *AhciRegisters,
+  IN     UINT8                         Port,
+  IN     UINT8                         PortMultiplier,
+  IN     EFI_AHCI_ATAPI_COMMAND        *AtapiCommand OPTIONAL,
+  IN     UINT8                         AtapiCommandLength,
+  IN     EFI_ATA_COMMAND_BLOCK         *AtaCommandBlock,
+  IN OUT EFI_ATA_STATUS_BLOCK          *AtaStatusBlock,
+  IN     UINT64                        Timeout, 
+  IN     ATA_NONBLOCK_TASK             *Task
+  );
+
+/**
+  Start a DMA data transfer on specific port
+
+  @param[in]       Instance            The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
+  @param[in]       AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
+  @param[in]       Port                The number of port.
+  @param[in]       PortMultiplier      The timeout value of stop.
+  @param[in]       AtapiCommand        The atapi command will be used for the
+                                       transfer.
+  @param[in]       AtapiCommandLength  The length of the atapi command.
+  @param[in]       Read                The transfer direction.
+  @param[in]       AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK data.
+  @param[in, out]  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK data.
+  @param[in, out]  MemoryAddr          The pointer to the data buffer.
+  @param[in]       DataCount           The data count to be transferred.
+  @param[in]       Timeout             The timeout value of non data transfer.
+  @param[in]       Task                Optional. Pointer to the ATA_NONBLOCK_TASK
+                                       used by non-blocking mode.
+
+  @retval EFI_DEVICE_ERROR    The DMA data transfer abort with error occurs.
+  @retval EFI_TIMEOUT         The operation is time out.
+  @retval EFI_UNSUPPORTED     The device is not ready for transfer.
+  @retval EFI_SUCCESS         The DMA data transfer executes successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciDmaTransfer (
+  IN     ATA_ATAPI_PASS_THRU_INSTANCE *Instance, 
+  IN     EFI_AHCI_REGISTERS           *AhciRegisters,
+  IN     UINT8                        Port,
+  IN     UINT8                        PortMultiplier,
+  IN     EFI_AHCI_ATAPI_COMMAND       *AtapiCommand OPTIONAL,
+  IN     UINT8                        AtapiCommandLength,
+  IN     BOOLEAN                      Read,  
+  IN     EFI_ATA_COMMAND_BLOCK        *AtaCommandBlock,
+  IN OUT EFI_ATA_STATUS_BLOCK         *AtaStatusBlock,
+  IN OUT VOID                         *MemoryAddr,
+  IN     UINTN                        DataCount,
+  IN     UINT64                       Timeout, 
+  IN     ATA_NONBLOCK_TASK            *Task
+  );
+
+/**
+  Start a PIO data transfer on specific port.
+    
+  @param[in]       PciIo               The PCI IO protocol instance.
+  @param[in]       AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
+  @param[in]       Port                The number of port.
+  @param[in]       PortMultiplier      The timeout value of stop.
+  @param[in]       AtapiCommand        The atapi command will be used for the
+                                       transfer.
+  @param[in]       AtapiCommandLength  The length of the atapi command.
+  @param[in]       Read                The transfer direction.
+  @param[in]       AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK data.
+  @param[in, out]  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK data.
+  @param[in, out]  MemoryAddr          The pointer to the data buffer.
+  @param[in]       DataCount           The data count to be transferred.
+  @param[in]       Timeout             The timeout value of non data transfer.
+  @param[in]       Task                Optional. Pointer to the ATA_NONBLOCK_TASK
+                                       used by non-blocking mode.
+
+  @retval EFI_DEVICE_ERROR    The PIO data transfer abort with error occurs.
+  @retval EFI_TIMEOUT         The operation is time out.
+  @retval EFI_UNSUPPORTED     The device is not ready for transfer.
+  @retval EFI_SUCCESS         The PIO data transfer executes successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciPioTransfer (
+  IN     EFI_PCI_IO_PROTOCOL        *PciIo,
+  IN     EFI_AHCI_REGISTERS         *AhciRegisters,
+  IN     UINT8                      Port,
+  IN     UINT8                      PortMultiplier,
+  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
+  IN     UINT8                      AtapiCommandLength,  
+  IN     BOOLEAN                    Read,  
+  IN     EFI_ATA_COMMAND_BLOCK      *AtaCommandBlock,
+  IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,
+  IN OUT VOID                       *MemoryAddr,
+  IN     UINT32                     DataCount,
+  IN     UINT64                     Timeout, 
+  IN     ATA_NONBLOCK_TASK          *Task
+  );
+
+/**
+  Send ATA command into device with NON_DATA protocol
+
+  @param[in]      PciIo            A pointer to ATA_ATAPI_PASS_THRU_INSTANCE
+                                   data structure.
+  @param[in]      IdeRegisters     A pointer to EFI_IDE_REGISTERS data structure.
+  @param[in]      AtaCommandBlock  A pointer to EFI_ATA_COMMAND_BLOCK data
+                                   structure.
+  @param[in, out] AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK data structure.
+  @param[in]      Timeout          The time to complete the command.
+  @param[in]      Task             Optional. Pointer to the ATA_NONBLOCK_TASK
+                                   used by non-blocking mode.
+
+  @retval  EFI_SUCCESS Reading succeed
+  @retval  EFI_ABORTED Command failed
+  @retval  EFI_DEVICE_ERROR Device status error.
+
+**/
+EFI_STATUS
+EFIAPI
+AtaNonDataCommandIn (
+  IN     EFI_PCI_IO_PROTOCOL       *PciIo,
+  IN     EFI_IDE_REGISTERS         *IdeRegisters,
+  IN     EFI_ATA_COMMAND_BLOCK     *AtaCommandBlock,
+  IN OUT EFI_ATA_STATUS_BLOCK      *AtaStatusBlock,
+  IN     UINT64                    Timeout,
+  IN     ATA_NONBLOCK_TASK         *Task
+  );
+
+/**
+  Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).
+
+  @param[in]      Instance         A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data
+                                   structure.
+  @param[in]      IdeRegisters     A pointer to EFI_IDE_REGISTERS data structure.
+  @param[in]      Read             Flag used to determine the data transfer
+                                   direction. Read equals 1, means data transferred
+                                   from device to host;Read equals 0, means data
+                                   transferred from host to device.
+  @param[in]      DataBuffer       A pointer to the source buffer for the data.
+  @param[in]      DataLength       The length of  the data.
+  @param[in]      AtaCommandBlock  A pointer to EFI_ATA_COMMAND_BLOCK data structure.
+  @param[in, out] AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK data structure.
+  @param[in]      Timeout          The time to complete the command.
+  @param[in]      Task             Optional. Pointer to the ATA_NONBLOCK_TASK
+                                   used by non-blocking mode.
+
+  @retval EFI_SUCCESS          the operation is successful.
+  @retval EFI_OUT_OF_RESOURCES Build PRD table failed
+  @retval EFI_UNSUPPORTED      Unknown channel or operations command
+  @retval EFI_DEVICE_ERROR     Ata command execute failed
+
+**/
+EFI_STATUS
+EFIAPI
+AtaUdmaInOut (
+  IN     ATA_ATAPI_PASS_THRU_INSTANCE  *Instance,
+  IN     EFI_IDE_REGISTERS             *IdeRegisters,
+  IN     BOOLEAN                       Read,
+  IN     VOID                          *DataBuffer,
+  IN     UINT64                        DataLength,
+  IN     EFI_ATA_COMMAND_BLOCK         *AtaCommandBlock,
+  IN OUT EFI_ATA_STATUS_BLOCK          *AtaStatusBlock,
+  IN     UINT64                        Timeout,
+  IN     ATA_NONBLOCK_TASK             *Task
+  );
+
+/**
+  This function is used to send out ATA commands conforms to the PIO Data In Protocol.
+
+  @param[in]      PciIo            A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data
+                                   structure.
+  @param[in]      IdeRegisters     A pointer to EFI_IDE_REGISTERS data structure.
+  @param[in, out] Buffer           A pointer to the source buffer for the data.
+  @param[in]      ByteCount        The length of  the data.
+  @param[in] Read                  Flag used to determine the data transfer direction.
+                                   Read equals 1, means data transferred from device
+                                   to host;Read equals 0, means data transferred
+                                   from host to device.
+  @param[in]      AtaCommandBlock  A pointer to EFI_ATA_COMMAND_BLOCK data structure.
+  @param[in]      AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK data structure.
+  @param[in]      Timeout          The time to complete the command.
+  @param[in]      Task             Optional. Pointer to the ATA_NONBLOCK_TASK
+                                   used by non-blocking mode.
+  
+  @retval EFI_SUCCESS      send out the ATA command and device send required data successfully.
+  @retval EFI_DEVICE_ERROR command sent failed.
+
+**/
+EFI_STATUS
+EFIAPI
+AtaPioDataInOut (
+  IN     EFI_PCI_IO_PROTOCOL       *PciIo,
+  IN     EFI_IDE_REGISTERS         *IdeRegisters,
+  IN OUT VOID                      *Buffer,
+  IN     UINT64                    ByteCount,
+  IN     BOOLEAN                   Read,
+  IN     EFI_ATA_COMMAND_BLOCK     *AtaCommandBlock,
+  IN OUT EFI_ATA_STATUS_BLOCK      *AtaStatusBlock,
+  IN     UINT64                    Timeout, 
+  IN     ATA_NONBLOCK_TASK         *Task
+  );
+
 #endif
 
index 50b95a6713263bb2d00e8d6c2e49c52b339d91f8..915e4bb296fd3cab4ed4c6307b940e9c6619443f 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Header file for AHCI mode of ATA host controller.\r
   \r
-  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 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
@@ -1123,16 +1123,20 @@ AtaIssueCommand (
 /**\r
   This function is used to send out ATA commands conforms to the PIO Data In Protocol.\r
 \r
-  @param PciIo            A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS data structure.\r
-  @param Buffer           A pointer to the source buffer for the data.\r
-  @param ByteCount        The length of  the data.\r
-  @param Read             Flag used to determine the data transfer direction.\r
-                          Read equals 1, means data transferred from device to host;\r
-                          Read equals 0, means data transferred from host to device.  \r
-  @param AtaCommandBlock  A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
-  @param AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
-  @param Timeout          The time to complete the command.\r
+  @param[in]      PciIo            A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data\r
+                                   structure.\r
+  @param[in]      IdeRegisters     A pointer to EFI_IDE_REGISTERS data structure.\r
+  @param[in, out] Buffer           A pointer to the source buffer for the data.\r
+  @param[in]      ByteCount        The length of the data.\r
+  @param[in] Read                  Flag used to determine the data transfer direction.\r
+                                   Read equals 1, means data transferred from device\r
+                                   to host;Read equals 0, means data transferred\r
+                                   from host to device.\r
+  @param[in]      AtaCommandBlock  A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
+  @param[in]      AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
+  @param[in]      Timeout          The time to complete the command.\r
+  @param[in]      Task             Optional. Pointer to the ATA_NONBLOCK_TASK\r
+                                   used by non-blocking mode.\r
   \r
   @retval EFI_SUCCESS      send out the ATA command and device send required data successfully.\r
   @retval EFI_DEVICE_ERROR command sent failed.\r
@@ -1148,7 +1152,8 @@ AtaPioDataInOut (
   IN     BOOLEAN                   Read,\r
   IN     EFI_ATA_COMMAND_BLOCK     *AtaCommandBlock,\r
   IN OUT EFI_ATA_STATUS_BLOCK      *AtaStatusBlock,\r
-  IN     UINT64                    Timeout\r
+  IN     UINT64                    Timeout,\r
+  IN     ATA_NONBLOCK_TASK         *Task\r
   )\r
 {\r
   UINTN       WordCount;\r
@@ -1248,17 +1253,24 @@ Exit:
   //\r
   DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);\r
 \r
+  //\r
+  // Not support the Non-blocking now,just do the blocking process.\r
+  //\r
   return Status;\r
 }\r
 \r
 /**\r
   Send ATA command into device with NON_DATA protocol\r
 \r
-  @param PciIo            A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS data structure.\r
-  @param AtaCommandBlock  A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
-  @param AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
-  @param Timeout          The time to complete the command.\r
+  @param[in]      PciIo            A pointer to ATA_ATAPI_PASS_THRU_INSTANCE\r
+                                   data structure.\r
+  @param[in]      IdeRegisters     A pointer to EFI_IDE_REGISTERS data structure.\r
+  @param[in]      AtaCommandBlock  A pointer to EFI_ATA_COMMAND_BLOCK data\r
+                                   structure.\r
+  @param[in, out] AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
+  @param[in]      Timeout          The time to complete the command.\r
+  @param[in]      Task             Optional. Pointer to the ATA_NONBLOCK_TASK\r
+                                   used by non-blocking mode.\r
 \r
   @retval  EFI_SUCCESS Reading succeed\r
   @retval  EFI_ABORTED Command failed\r
@@ -1272,7 +1284,8 @@ AtaNonDataCommandIn (
   IN     EFI_IDE_REGISTERS         *IdeRegisters,\r
   IN     EFI_ATA_COMMAND_BLOCK     *AtaCommandBlock,\r
   IN OUT EFI_ATA_STATUS_BLOCK      *AtaStatusBlock,\r
-  IN     UINT64                    Timeout\r
+  IN     UINT64                    Timeout,\r
+  IN     ATA_NONBLOCK_TASK         *Task\r
   )\r
 {\r
   EFI_STATUS  Status;\r
@@ -1310,24 +1323,123 @@ Exit:
   // Dump All Ide registers to ATA_STATUS_BLOCK\r
   //\r
   DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);\r
+  \r
+  //\r
+  // Not support the Non-blocking now,just do the blocking process.\r
+  //\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Wait for memory to be set.\r
+    \r
+  @param[in]  PciIo           The PCI IO protocol instance.\r
+  @param[in]  PortNum         The IDE Port number.\r
+\r
+  @retval EFI_DEVICE_ERROR  The memory is not set.\r
+  @retval EFI_TIMEOUT       The memory setting is time out.\r
+  @retval EFI_SUCCESS       The memory is correct set.\r
+\r
+**/\r
+EFI_STATUS\r
+AtaUdmStatusWait (\r
+  IN     EFI_PCI_IO_PROTOCOL       *PciIo,\r
+  IN     UINT16                    PortNum\r
+ ) \r
+{\r
+  UINT8                         RegisterValue;\r
+  EFI_STATUS                    Status;\r
+  UINT64                        Timeout;\r
+\r
+  Timeout = 2000;\r
+\r
+  while (TRUE) {\r
+    RegisterValue  = IdeReadPortB (PciIo, PortNum);\r
+\r
+    if (((RegisterValue & BMIS_ERROR) != 0) || (Timeout == 0)) {\r
+      DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));\r
+      Status = EFI_DEVICE_ERROR;\r
+      break;\r
+    }\r
+\r
+    if ((RegisterValue & BMIS_INTERRUPT) != 0) {\r
+      Status = EFI_SUCCESS;\r
+      DEBUG ((DEBUG_INFO, "Task->RetryTimes = %x\n", Timeout));      \r
+      break;\r
+    }\r
+    //\r
+    // Stall for 1 milliseconds.\r
+    //\r
+    MicroSecondDelay (1000);\r
+    Timeout--;\r
+  }\r
 \r
   return Status;\r
 }\r
 \r
+/**\r
+  Check if the memory to be set.\r
+    \r
+  @param[in]  PciIo           The PCI IO protocol instance.\r
+  @param[in]  Task            Optional. Pointer to the ATA_NONBLOCK_TASK\r
+                              used by non-blocking mode.\r
+  @param[in]  PortForBit      The bit to be checked.\r
+\r
+  @retval EFI_DEVICE_ERROR  The memory setting met a issue.\r
+  @retval EFI_NOT_READY     The memory is not set.\r
+  @retval EFI_TIMEOUT       The memory setting is time out.\r
+  @retval EFI_SUCCESS       The memory is correct set.\r
+\r
+**/\r
+EFI_STATUS\r
+AtaUdmStatusCheck (\r
+  IN     EFI_PCI_IO_PROTOCOL        *PciIo,\r
+  IN     ATA_NONBLOCK_TASK          *Task,\r
+  IN     UINT16                     PortForBit\r
+ )\r
+{\r
+  UINT8                         RegisterValue;\r
+\r
+  Task->RetryTimes--;\r
+  RegisterValue  = IdeReadPortB(PciIo, PortForBit);\r
+\r
+  if ((RegisterValue & BMIS_ERROR) != 0) {\r
+    DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  if ((RegisterValue & BMIS_INTERRUPT) != 0) {\r
+    DEBUG ((DEBUG_INFO, "Task->RetryTimes = %x\n", Task->RetryTimes));\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (Task->RetryTimes == 0) {\r
+    return EFI_TIMEOUT;\r
+  } else {\r
+    //\r
+    // The memory is not set.\r
+    //\r
+    return EFI_NOT_READY;\r
+  }\r
+}\r
 \r
 /**\r
   Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).\r
 \r
-  @param PciIo            A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS data structure.\r
-  @param Read             Flag used to determine the data transfer direction.\r
-                          Read equals 1, means data transferred from device to host;\r
-                          Read equals 0, means data transferred from host to device.\r
-  @param DataBuffer       A pointer to the source buffer for the data.\r
-  @param DataLength       The length of  the data.\r
-  @param AtaCommandBlock  A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
-  @param AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
-  @param Timeout          The time to complete the command.\r
+  @param[in]      Instance         A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data\r
+                                   structure.\r
+  @param[in]      IdeRegisters     A pointer to EFI_IDE_REGISTERS data structure.\r
+  @param[in]      Read             Flag used to determine the data transfer\r
+                                   direction. Read equals 1, means data transferred\r
+                                   from device to host;Read equals 0, means data\r
+                                   transferred from host to device.\r
+  @param[in]      DataBuffer       A pointer to the source buffer for the data.\r
+  @param[in]      DataLength       The length of  the data.\r
+  @param[in]      AtaCommandBlock  A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
+  @param[in, out] AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
+  @param[in]      Timeout          The time to complete the command.\r
+  @param[in]      Task             Optional. Pointer to the ATA_NONBLOCK_TASK\r
+                                   used by non-blocking mode.\r
 \r
   @retval EFI_SUCCESS          the operation is successful.\r
   @retval EFI_OUT_OF_RESOURCES Build PRD table failed\r
@@ -1338,14 +1450,15 @@ Exit:
 EFI_STATUS\r
 EFIAPI\r
 AtaUdmaInOut (\r
-  IN     EFI_PCI_IO_PROTOCOL       *PciIo,\r
-  IN     EFI_IDE_REGISTERS         *IdeRegisters,\r
-  IN     BOOLEAN                   Read,\r
-  IN     VOID                      *DataBuffer,\r
-  IN     UINT64                    DataLength,\r
-  IN     EFI_ATA_COMMAND_BLOCK     *AtaCommandBlock,\r
-  IN OUT EFI_ATA_STATUS_BLOCK      *AtaStatusBlock,\r
-  IN     UINT64                    Timeout\r
+  IN     ATA_ATAPI_PASS_THRU_INSTANCE  *Instance,\r
+  IN     EFI_IDE_REGISTERS             *IdeRegisters,\r
+  IN     BOOLEAN                       Read,\r
+  IN     VOID                          *DataBuffer,\r
+  IN     UINT64                        DataLength,\r
+  IN     EFI_ATA_COMMAND_BLOCK         *AtaCommandBlock,\r
+  IN OUT EFI_ATA_STATUS_BLOCK          *AtaStatusBlock,\r
+  IN     UINT64                        Timeout,\r
+  IN     ATA_NONBLOCK_TASK             *Task\r
   )\r
 {\r
   EFI_STATUS                    Status;\r
@@ -1353,18 +1466,16 @@ AtaUdmaInOut (
   UINT16                        IoPortForBmis;\r
   UINT16                        IoPortForBmid;\r
 \r
-  UINT8                         RegisterValue;\r
-\r
-  EFI_ATA_DMA_PRD               *PrdBaseAddr;\r
-  UINTN                         PrdTableNum;\r
   UINTN                         PrdTableSize;\r
   EFI_PHYSICAL_ADDRESS          PrdTableMapAddr;\r
   VOID                          *PrdTableMap;\r
+  EFI_ATA_DMA_PRD               *PrdBaseAddr;\r
+  UINTN                         PrdTableNum;\r
 \r
+  UINT8                         RegisterValue;\r
   UINTN                         PageCount;\r
   UINTN                         ByteCount;\r
   UINTN                         ByteRemaining;\r
-\r
   UINT8                         DeviceControl;\r
 \r
   VOID                          *BufferMap;\r
@@ -1373,14 +1484,36 @@ AtaUdmaInOut (
 \r
   UINT8                         DeviceHead;\r
   UINT8                         AtaCommand;\r
+  EFI_PCI_IO_PROTOCOL           *PciIo;\r
+  EFI_TPL                       OldTpl;\r
 \r
-  Status      = EFI_SUCCESS;\r
-  PrdBaseAddr = NULL;\r
+\r
+  Status        = EFI_SUCCESS;\r
+  PrdBaseAddr   = NULL;\r
+  PrdTableMap   = NULL;\r
+  BufferMap     = NULL;\r
+  PageCount     = 0;\r
+  PciIo         = Instance->PciIo;\r
 \r
   if ((PciIo == NULL) || (IdeRegisters == NULL) || (DataBuffer == NULL) || (AtaCommandBlock == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  //\r
+  // Before starting the Blocking BlockIO operation, push to finish all non-blocking\r
+  // BlockIO tasks.\r
+  // Delay 1ms to simulate the blocking time out checking.\r
+  //\r
+  while ((Task == NULL) && (!IsListEmpty (&Instance->NonBlockingTaskList))) {\r
+    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+    AsyncNonBlockingTransferRoutine (NULL, Instance);\r
+    gBS->RestoreTPL (OldTpl);\r
+    //\r
+    // Stall for 1 milliseconds.\r
+    //\r
+    MicroSecondDelay (1000);\r
+  } \r
+\r
   //\r
   // The data buffer should be even alignment\r
   //\r
@@ -1389,234 +1522,260 @@ AtaUdmaInOut (
   }\r
 \r
   //\r
-  // Calculate the number of PRD entry.\r
-  // Every entry in PRD table can specify a 64K memory region.\r
+  // Set relevant IO Port address.\r
   //\r
-  PrdTableNum   = (UINTN)(RShiftU64(DataLength, 16) + 1);\r
+  IoPortForBmic = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIC_OFFSET);\r
+  IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET);\r
+  IoPortForBmid = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMID_OFFSET);\r
 \r
   //\r
-  // Make sure that the memory region of PRD table is not cross 64K boundary\r
-  //\r
-  PrdTableSize = PrdTableNum * sizeof (EFI_ATA_DMA_PRD);\r
-  if (PrdTableSize > 0x10000) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
+  // For Blocking mode, start the command. \r
+  // For non-blocking mode, when the command is not started, start it, otherwise\r
+  // go to check the status.\r
+  //  \r
+  if (((Task != NULL) && (!Task->IsStart)) || (Task == NULL)) {\r
+    //\r
+    // Calculate the number of PRD entry.\r
+    // Every entry in PRD table can specify a 64K memory region.\r
+    //\r
+    PrdTableNum   = (UINTN)(RShiftU64(DataLength, 16) + 1);\r
 \r
-  //\r
-  // Allocate buffer for PRD table initialization.\r
-  //\r
-  PageCount = EFI_SIZE_TO_PAGES (PrdTableSize);\r
-  Status    = PciIo->AllocateBuffer (\r
-                       PciIo,\r
-                       AllocateAnyPages,\r
-                       EfiBootServicesData,\r
-                       PageCount,\r
-                       (VOID **)&PrdBaseAddr,\r
-                       0\r
-                       );\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
+    //\r
+    // Make sure that the memory region of PRD table is not cross 64K boundary\r
+    //\r
+    PrdTableSize = PrdTableNum * sizeof (EFI_ATA_DMA_PRD);\r
+    if (PrdTableSize > 0x10000) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
 \r
-  ByteCount = EFI_PAGES_TO_SIZE (PageCount);\r
-  Status    = PciIo->Map (\r
-                       PciIo,\r
-                       EfiPciIoOperationBusMasterCommonBuffer,\r
-                       PrdBaseAddr,\r
-                       &ByteCount,\r
-                       &PrdTableMapAddr,\r
-                       &PrdTableMap\r
-                       );\r
-  if (EFI_ERROR (Status) || (ByteCount != EFI_PAGES_TO_SIZE (PageCount))) {\r
-    //\r
-    // If the data length actually mapped is not equal to the requested amount,\r
-    // it means the DMA operation may be broken into several discontinuous smaller chunks.\r
-    // Can't handle this case.\r
-    //\r
-    PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
+    //\r
+    // Allocate buffer for PRD table initialization.\r
+    //\r
+    PageCount = EFI_SIZE_TO_PAGES (PrdTableSize);\r
+    Status    = PciIo->AllocateBuffer (\r
+                         PciIo,\r
+                         AllocateAnyPages,\r
+                         EfiBootServicesData,\r
+                         PageCount,\r
+                         (VOID **)&PrdBaseAddr,\r
+                         0\r
+                         );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
 \r
-  ZeroMem ((VOID *) ((UINTN) PrdBaseAddr), ByteCount);\r
+    ByteCount = EFI_PAGES_TO_SIZE (PageCount);\r
+    Status    = PciIo->Map (\r
+                         PciIo,\r
+                         EfiPciIoOperationBusMasterCommonBuffer,\r
+                         PrdBaseAddr,\r
+                         &ByteCount,\r
+                         &PrdTableMapAddr,\r
+                         &PrdTableMap\r
+                         );\r
+    if (EFI_ERROR (Status) || (ByteCount != EFI_PAGES_TO_SIZE (PageCount))) {\r
+      //\r
+      // If the data length actually mapped is not equal to the requested amount,\r
+      // it means the DMA operation may be broken into several discontinuous smaller chunks.\r
+      // Can't handle this case.\r
+      //\r
+      PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
 \r
-  //\r
-  // Map the host address of DataBuffer to DMA master address.\r
-  //\r
-  if (Read) {\r
-    PciIoOperation = EfiPciIoOperationBusMasterWrite;\r
-  } else {\r
-    PciIoOperation = EfiPciIoOperationBusMasterRead;\r
-  }\r
+    ZeroMem ((VOID *) ((UINTN) PrdBaseAddr), ByteCount);\r
 \r
-  ByteCount = (UINTN)DataLength;\r
-  Status    = PciIo->Map (\r
-                       PciIo,\r
-                       PciIoOperation,\r
-                       DataBuffer,\r
-                       &ByteCount,\r
-                       &BufferMapAddress,\r
-                       &BufferMap\r
-                       );\r
-  if (EFI_ERROR (Status) || (ByteCount != DataLength)) {\r
-    PciIo->Unmap (PciIo, PrdTableMap);\r
-    PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
+    //\r
+    // Map the host address of DataBuffer to DMA master address.\r
+    //\r
+    if (Read) {\r
+      PciIoOperation = EfiPciIoOperationBusMasterWrite;\r
+    } else {\r
+      PciIoOperation = EfiPciIoOperationBusMasterRead;\r
+    }\r
 \r
-  //\r
-  // According to Ata spec, it requires the buffer address and size to be even.\r
-  //\r
-  ASSERT ((BufferMapAddress & 0x1) == 0);\r
-  ASSERT ((ByteCount & 0x1) == 0);\r
+    ByteCount = (UINTN)DataLength;\r
+    Status    = PciIo->Map (\r
+                         PciIo,\r
+                         PciIoOperation,\r
+                         DataBuffer,\r
+                         &ByteCount,\r
+                         &BufferMapAddress,\r
+                         &BufferMap\r
+                         );\r
+    if (EFI_ERROR (Status) || (ByteCount != DataLength)) {\r
+      PciIo->Unmap (PciIo, PrdTableMap);\r
+      PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    //\r
+    // According to Ata spec, it requires the buffer address and size to be even.\r
+    //\r
+    ASSERT ((BufferMapAddress & 0x1) == 0);\r
+    ASSERT ((ByteCount & 0x1) == 0);\r
+\r
+    //\r
+    // Fill the PRD table with appropriate bus master address of data buffer and data length.\r
+    //\r
+    ByteRemaining = ByteCount;\r
+    while (ByteRemaining != 0) {\r
+      if (ByteRemaining <= 0x10000) {\r
+        PrdBaseAddr->RegionBaseAddr = (UINT32) ((UINTN) BufferMapAddress);\r
+        PrdBaseAddr->ByteCount      = (UINT16) ByteRemaining;\r
+        PrdBaseAddr->EndOfTable     = 0x8000;\r
+        break;\r
+      }\r
 \r
-  //\r
-  // Fill the PRD table with appropriate bus master address of data buffer and data length.\r
-  //\r
-  ByteRemaining = ByteCount;\r
-  while (ByteRemaining != 0) {\r
-    if (ByteRemaining <= 0x10000) {\r
       PrdBaseAddr->RegionBaseAddr = (UINT32) ((UINTN) BufferMapAddress);\r
-      PrdBaseAddr->ByteCount      = (UINT16) ByteRemaining;\r
-      PrdBaseAddr->EndOfTable     = 0x8000;\r
-      break;\r
-    }\r
+      PrdBaseAddr->ByteCount      = (UINT16) 0x0;\r
 \r
-    PrdBaseAddr->RegionBaseAddr = (UINT32) ((UINTN) BufferMapAddress);\r
-    PrdBaseAddr->ByteCount      = (UINT16) 0x0;\r
+      ByteRemaining    -= 0x10000;\r
+      BufferMapAddress += 0x10000;\r
+      PrdBaseAddr++;\r
+    }\r
 \r
-    ByteRemaining    -= 0x10000;\r
-    BufferMapAddress += 0x10000;\r
-    PrdBaseAddr++;\r
-  }\r
+    //\r
+    // Start to enable the DMA operation\r
+    //\r
+    DeviceHead = AtaCommandBlock->AtaDeviceHead;\r
+    AtaCommand = AtaCommandBlock->AtaCommand;\r
 \r
-  //\r
-  // Start to enable the DMA operation\r
-  //\r
-  DeviceHead = AtaCommandBlock->AtaDeviceHead;\r
-  AtaCommand = AtaCommandBlock->AtaCommand;\r
+    IdeWritePortB (PciIo, IdeRegisters->Head, (UINT8)(0xe0 | DeviceHead));\r
 \r
-  IdeWritePortB (PciIo, IdeRegisters->Head, (UINT8)(0xe0 | DeviceHead));\r
+    //\r
+    // Enable interrupt to support UDMA\r
+    //\r
+    DeviceControl = 0;\r
+    IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
 \r
-  //\r
-  // Enable interrupt to support UDMA\r
-  //\r
-  DeviceControl = 0;\r
-  IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
+    //\r
+    // Read BMIS register and clear ERROR and INTR bit\r
+    //\r
+    RegisterValue  = IdeReadPortB(PciIo, IoPortForBmis);\r
+    RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
+    IdeWritePortB(PciIo, IoPortForBmis, RegisterValue);\r
 \r
-  IoPortForBmic = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIC_OFFSET);\r
-  IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET);\r
-  IoPortForBmid = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMID_OFFSET);\r
+    //\r
+    // Set the base address to BMID register\r
+    //\r
+    IdeWritePortDW (PciIo, IoPortForBmid, (UINT32)PrdTableMapAddr);\r
 \r
-  //\r
-  // Read BMIS register and clear ERROR and INTR bit\r
-  //\r
-  RegisterValue  = IdeReadPortB(PciIo, IoPortForBmis);\r
-  RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
-  IdeWritePortB(PciIo, IoPortForBmis, RegisterValue);\r
+    //\r
+    // Set BMIC register to identify the operation direction\r
+    //\r
+    RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
+    if (Read) {\r
+      RegisterValue |= BMIC_NREAD;\r
+    } else {\r
+      RegisterValue &= ~((UINT8) BMIC_NREAD);\r
+    }\r
+    IdeWritePortB (PciIo, IoPortForBmic, RegisterValue);\r
 \r
-  //\r
-  // Set the base address to BMID register\r
-  //\r
-  IdeWritePortDW(PciIo, IoPortForBmid, (UINT32)PrdTableMapAddr);\r
+    //\r
+    // Issue ATA command\r
+    //\r
+    Status = AtaIssueCommand (PciIo, IdeRegisters, AtaCommandBlock, Timeout);\r
 \r
-  //\r
-  // Set BMIC register to identify the operation direction\r
-  //\r
-  RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
-  if (Read) {\r
-    RegisterValue |= BMIC_NREAD;\r
-  } else {\r
-    RegisterValue &= ~((UINT8) BMIC_NREAD);\r
-  }\r
-  IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto Exit;\r
+    }\r
 \r
-  //\r
-  // Issue ATA command\r
-  //\r
-  Status = AtaIssueCommand (PciIo, IdeRegisters, AtaCommandBlock, Timeout);\r
+    //\r
+    // Set START bit of BMIC register\r
+    //\r
+    RegisterValue  = IdeReadPortB(PciIo, IoPortForBmic);\r
+    RegisterValue |= BMIC_START;\r
+    IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    Status = EFI_DEVICE_ERROR;\r
-    goto Exit;\r
+    if (Task != NULL) {\r
+      //\r
+      // Max transfer number of sectors for one command is 65536(32Mbyte),\r
+      // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
+      // So set the variable Count to 2000, for about 2 second Timeout time.\r
+      //\r
+      Task->RetryTimes     = 2000;\r
+      Task->Map            = BufferMap;\r
+      Task->TableMap       = PrdTableMap;\r
+      Task->MapBaseAddress = PrdBaseAddr;\r
+      Task->PageCount      = PageCount;\r
+      Task->IsStart        = TRUE;\r
+    }\r
   }\r
 \r
-  //\r
-  // Set START bit of BMIC register\r
-  //\r
-  RegisterValue  = IdeReadPortB(PciIo, IoPortForBmic);\r
-  RegisterValue |= BMIC_START;\r
-  IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);\r
-\r
   //\r
   // Check the INTERRUPT and ERROR bit of BMIS\r
   // Max transfer number of sectors for one command is 65536(32Mbyte),\r
   // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
   // So set the variable Count to 2000, for about 2 second Timeout time.\r
   //\r
-  Timeout = 2000;\r
-  while (TRUE) {\r
-    RegisterValue  = IdeReadPortB(PciIo, IoPortForBmis);\r
-\r
-    if (((RegisterValue & BMIS_ERROR) != 0) || (Timeout == 0)) {\r
-      DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));\r
-      Status = EFI_DEVICE_ERROR;\r
-      break;\r
-    }\r
-\r
-    if ((RegisterValue & BMIS_INTERRUPT) != 0) {\r
-      Status = EFI_SUCCESS;\r
-      break;\r
-    }\r
-    //\r
-    // Stall for 1 milliseconds.\r
-    //\r
-    MicroSecondDelay (1000);\r
-    Timeout--;\r
+  if (Task != NULL) {\r
+    Status = AtaUdmStatusCheck (PciIo, Task, IoPortForBmis);\r
+  } else {\r
+    Status = AtaUdmStatusWait (PciIo, IoPortForBmis);\r
   }\r
 \r
   //\r
-  // Read BMIS register and clear ERROR and INTR bit\r
+  // For blocking mode, clear registers and free buffers.\r
+  // For non blocking mode, when the related registers have been set or time\r
+  // out, or a error has been happened, it needs to clear the register and free\r
+  // buffer.\r
   //\r
-  RegisterValue  = IdeReadPortB(PciIo, IoPortForBmis);\r
-  RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
-  IdeWritePortB(PciIo, IoPortForBmis, RegisterValue);\r
+  if ((Task == NULL) || Status != EFI_NOT_READY) {\r
+    //\r
+    // Read BMIS register and clear ERROR and INTR bit\r
+    //\r
+    RegisterValue  = IdeReadPortB (PciIo, IoPortForBmis);\r
+    RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
+    IdeWritePortB (PciIo, IoPortForBmis, RegisterValue);\r
 \r
-  //\r
-  // Read Status Register of IDE device to clear interrupt\r
-  //\r
-  RegisterValue  = IdeReadPortB(PciIo, IdeRegisters->CmdOrStatus);\r
+    //\r
+    // Read Status Register of IDE device to clear interrupt\r
+    //\r
+    RegisterValue  = IdeReadPortB(PciIo, IdeRegisters->CmdOrStatus);\r
 \r
-  //\r
-  // Clear START bit of BMIC register\r
-  //\r
-  RegisterValue  = IdeReadPortB(PciIo, IoPortForBmic);\r
-  RegisterValue &= ~((UINT8) BMIC_START);\r
-  IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);\r
+    //\r
+    // Clear START bit of BMIC register\r
+    //\r
+    RegisterValue  = IdeReadPortB(PciIo, IoPortForBmic);\r
+    RegisterValue &= ~((UINT8) BMIC_START);\r
+    IdeWritePortB (PciIo, IoPortForBmic, RegisterValue);\r
 \r
-  //\r
-  // Disable interrupt of Select device\r
-  //\r
-  DeviceControl  = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
-  DeviceControl |= ATA_CTLREG_IEN_L;\r
-  IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
-  //\r
-  // Stall for 10 milliseconds.\r
-  //\r
-  MicroSecondDelay (10000);\r
+    //\r
+    // Disable interrupt of Select device\r
+    //\r
+    DeviceControl  = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
+    DeviceControl |= ATA_CTLREG_IEN_L;\r
+    IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
+    //\r
+    // Stall for 10 milliseconds.\r
+    //\r
+    MicroSecondDelay (10000);\r
+\r
+  }\r
 \r
 Exit:\r
   //\r
   // Free all allocated resource\r
   //\r
-  PciIo->Unmap (PciIo, PrdTableMap);\r
-  PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
-  PciIo->Unmap (PciIo, BufferMap);\r
-\r
-  //\r
-  // Dump All Ide registers to ATA_STATUS_BLOCK\r
-  //\r
-  DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);\r
+  if ((Task == NULL) || Status != EFI_NOT_READY) {\r
+    if (Task != NULL) {\r
+      PciIo->Unmap (PciIo, Task->TableMap);\r
+      PciIo->FreeBuffer (PciIo, Task->PageCount, Task->MapBaseAddress);\r
+      PciIo->Unmap (PciIo, Task->Map);\r
+    } else {\r
+      PciIo->Unmap (PciIo, PrdTableMap);\r
+      PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
+      PciIo->Unmap (PciIo, BufferMap);\r
+    }\r
 \r
+    //\r
+    // Dump All Ide registers to ATA_STATUS_BLOCK\r
+    //\r
+    DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);\r
+  }\r
+  \r
   return Status;\r
 }\r
 \r
@@ -2021,7 +2180,8 @@ SetDeviceTransferMode (
              &Instance->IdeRegisters[Channel],\r
              &AtaCommandBlock,\r
              AtaStatusBlock,\r
-             ATA_ATAPI_TIMEOUT\r
+             ATA_ATAPI_TIMEOUT,\r
+             NULL\r
              );\r
 \r
   return Status;\r
@@ -2069,7 +2229,8 @@ SetDriveParameters (
              &Instance->IdeRegisters[Channel],\r
              &AtaCommandBlock,\r
              AtaStatusBlock,\r
-             ATA_ATAPI_TIMEOUT\r
+             ATA_ATAPI_TIMEOUT, \r
+             NULL\r
              );\r
 \r
   //\r
@@ -2084,7 +2245,8 @@ SetDriveParameters (
              &Instance->IdeRegisters[Channel],\r
              &AtaCommandBlock,\r
              AtaStatusBlock,\r
-             ATA_ATAPI_TIMEOUT\r
+             ATA_ATAPI_TIMEOUT, \r
+             NULL\r
              );\r
 \r
   return Status;\r
@@ -2132,7 +2294,8 @@ IdeAtaSmartReturnStatusCheck (
              &Instance->IdeRegisters[Channel],\r
              &AtaCommandBlock,\r
              AtaStatusBlock,\r
-             ATA_ATAPI_TIMEOUT\r
+             ATA_ATAPI_TIMEOUT,\r
+             NULL\r
              );\r
 \r
   if (EFI_ERROR (Status)) {\r
@@ -2212,7 +2375,8 @@ IdeAtaSmartSupport (
                  &Instance->IdeRegisters[Channel],\r
                  &AtaCommandBlock,\r
                  AtaStatusBlock,\r
-                 ATA_ATAPI_TIMEOUT\r
+                 ATA_ATAPI_TIMEOUT,\r
+                 NULL\r
                  );\r
 \r
       if (!EFI_ERROR (Status)) {\r
@@ -2233,7 +2397,8 @@ IdeAtaSmartSupport (
                    &Instance->IdeRegisters[Channel],\r
                    &AtaCommandBlock,\r
                    AtaStatusBlock,\r
-                   ATA_ATAPI_TIMEOUT\r
+                   ATA_ATAPI_TIMEOUT,\r
+                   NULL\r
                    );\r
         if (!EFI_ERROR (Status)) {\r
           Status = IdeAtaSmartReturnStatusCheck (\r
@@ -2254,6 +2419,7 @@ IdeAtaSmartSupport (
   return ;\r
 }\r
 \r
+\r
 /**\r
   Sends out an ATA Identify Command to the specified device.\r
 \r
@@ -2274,6 +2440,7 @@ IdeAtaSmartSupport (
   @retval EFI_SUCCESS          Identify ATA device successfully.\r
   @retval EFI_DEVICE_ERROR     ATA Identify Device Command failed or device is not ATA device.\r
   @retval EFI_OUT_OF_RESOURCES Allocate memory failed.\r
+\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -2286,10 +2453,10 @@ AtaIdentify (
   )\r
 {\r
   EFI_STATUS             Status;\r
-  EFI_ATA_COMMAND_BLOCK  AtaCommandBlock;  \r
+  EFI_ATA_COMMAND_BLOCK  AtaCommandBlock;\r
 \r
   ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
-  \r
+\r
   AtaCommandBlock.AtaCommand    = ATA_CMD_IDENTIFY_DRIVE;\r
   AtaCommandBlock.AtaDeviceHead = (UINT8)(Device << 0x4);\r
 \r
@@ -2301,7 +2468,8 @@ AtaIdentify (
              TRUE,\r
              &AtaCommandBlock,\r
              AtaStatusBlock,\r
-             ATA_ATAPI_TIMEOUT\r
+             ATA_ATAPI_TIMEOUT,\r
+             NULL\r
              );\r
 \r
   return Status;\r
@@ -2368,7 +2536,8 @@ AtaIdentifyPacket (
              TRUE,\r
              &AtaCommandBlock,\r
              AtaStatusBlock,\r
-             ATA_ATAPI_TIMEOUT\r
+             ATA_ATAPI_TIMEOUT,\r
+             NULL\r
              );\r
 \r
   return Status;\r
@@ -2425,7 +2594,7 @@ DetectAndConfigIdeDevice (
   IdeInit      = Instance->IdeControllerInit;\r
   PciIo        = Instance->PciIo;\r
 \r
-  for (IdeDevice = 0; IdeDevice < EfiIdeMaxDevice; IdeDevice++) {    \r
+  for (IdeDevice = 0; IdeDevice < EfiIdeMaxDevice; IdeDevice++) {\r
     //\r
     // Send ATA Device Execut Diagnostic command.\r
     // This command should work no matter DRDY is ready or not\r
@@ -2483,7 +2652,7 @@ DetectAndConfigIdeDevice (
       if (EFI_ERROR (Status)) {\r
         DeviceType = EfiIdeHarddisk;\r
         Status     = AtaIdentify (Instance, IdeChannel, IdeDevice, &Buffer, NULL);\r
-      } \r
+      }\r
     }\r
 \r
     if (EFI_ERROR (Status)) {\r
@@ -2491,12 +2660,11 @@ DetectAndConfigIdeDevice (
       // No device is found at this port\r
       //\r
       continue;\r
-    } \r
-  \r
+    }\r
+\r
     DEBUG ((EFI_D_INFO, "[%a] channel [%a] [%a] device\n", \r
             (IdeChannel == 1) ? "secondary" : "primary  ", (IdeDevice == 1) ? "slave " : "master",\r
             DeviceType == EfiIdeCdrom ? "cdrom   " : "harddisk"));\r
-\r
     //\r
     // If the device is a hard disk, then try to enable S.M.A.R.T feature\r
     //\r
@@ -2548,7 +2716,7 @@ DetectAndConfigIdeDevice (
         continue;\r
       }\r
     }\r
-    \r
+\r
     //\r
     // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't\r
     // be set together. Only one DMA mode can be set to a device. If setting\r
@@ -2559,7 +2727,7 @@ DetectAndConfigIdeDevice (
       TransferMode.ModeCategory = EFI_ATA_MODE_UDMA;\r
       TransferMode.ModeNumber   = (UINT8) (SupportedModes->UdmaMode.Mode);\r
       Status = SetDeviceTransferMode (Instance, IdeChannel, IdeDevice, &TransferMode, NULL);\r
-    \r
+\r
       if (EFI_ERROR (Status)) {\r
         DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));\r
         continue;\r
@@ -2568,13 +2736,13 @@ DetectAndConfigIdeDevice (
       TransferMode.ModeCategory = EFI_ATA_MODE_MDMA;\r
       TransferMode.ModeNumber   = (UINT8) SupportedModes->MultiWordDmaMode.Mode;\r
       Status = SetDeviceTransferMode (Instance, IdeChannel, IdeDevice, &TransferMode, NULL);\r
-    \r
+\r
       if (EFI_ERROR (Status)) {\r
         DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));\r
         continue;\r
       }\r
     }\r
-    \r
+\r
     //\r
     // Set Parameters for the device:\r
     // 1) Init\r
@@ -2587,10 +2755,10 @@ DetectAndConfigIdeDevice (
       DriveParameters.Sector         = (UINT8) ((ATA5_IDENTIFY_DATA *)(&Buffer.AtaData))->sectors_per_track;\r
       DriveParameters.Heads          = (UINT8) (((ATA5_IDENTIFY_DATA *)(&Buffer.AtaData))->heads - 1);\r
       DriveParameters.MultipleSector = (UINT8) ((ATA5_IDENTIFY_DATA *)(&Buffer.AtaData))->multi_sector_cmd_max_sct_cnt;\r
-    \r
+\r
       Status = SetDriveParameters (Instance, IdeChannel, IdeDevice, &DriveParameters, NULL);\r
     }\r
-    \r
+\r
     //\r
     // Set IDE controller Timing Blocks in the PCI Configuration Space\r
     //\r
index b9c58c634192dee3ca606cecc59fb16154e52835..67fff646582cc21a488383069967cb0fe99911df 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Header file for IDE mode of ATA host controller.\r
   \r
-  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2010 - 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
@@ -200,94 +200,5 @@ AtaPacketCommandExecute (
   IN  EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET    *Packet\r
   );\r
 \r
-/**\r
-  Send ATA command into device with NON_DATA protocol\r
-\r
-  @param PciIo            A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS data structure.\r
-  @param AtaCommandBlock  A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
-  @param AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
-  @param Timeout          The time to complete the command.\r
-\r
-  @retval  EFI_SUCCESS Reading succeed\r
-  @retval  EFI_ABORTED Command failed\r
-  @retval  EFI_DEVICE_ERROR Device status error.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AtaNonDataCommandIn (  \r
-  IN     EFI_PCI_IO_PROTOCOL       *PciIo,\r
-  IN     EFI_IDE_REGISTERS         *IdeRegisters,\r
-  IN     EFI_ATA_COMMAND_BLOCK     *AtaCommandBlock,\r
-  IN OUT EFI_ATA_STATUS_BLOCK      *AtaStatusBlock,\r
-  IN     UINT64                    Timeout\r
-  );\r
-\r
-/**\r
-  Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).\r
-\r
-  @param PciIo            A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS data structure.\r
-  @param Read             Flag used to determine the data transfer direction.\r
-                          Read equals 1, means data transferred from device to host;\r
-                          Read equals 0, means data transferred from host to device.\r
-  @param DataBuffer       A pointer to the source buffer for the data.\r
-  @param DataLength       The length of  the data.\r
-  @param AtaCommandBlock  A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
-  @param AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
-  @param Timeout          The time to complete the command.\r
-\r
-  @retval EFI_SUCCESS          the operation is successful.\r
-  @retval EFI_OUT_OF_RESOURCES Build PRD table failed\r
-  @retval EFI_UNSUPPORTED      Unknown channel or operations command\r
-  @retval EFI_DEVICE_ERROR     Ata command execute failed\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AtaUdmaInOut (\r
-  IN     EFI_PCI_IO_PROTOCOL       *PciIo,\r
-  IN     EFI_IDE_REGISTERS         *IdeRegisters,\r
-  IN     BOOLEAN                   Read,\r
-  IN     VOID                      *DataBuffer,\r
-  IN     UINT64                    DataLength,\r
-  IN     EFI_ATA_COMMAND_BLOCK     *AtaCommandBlock,\r
-  IN OUT EFI_ATA_STATUS_BLOCK      *AtaStatusBlock,\r
-  IN     UINT64                    Timeout\r
-  );\r
-\r
-/**\r
-  This function is used to send out ATA commands conforms to the PIO Data In Protocol.\r
-\r
-  @param PciIo            A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
-  @param IdeRegisters     A pointer to EFI_IDE_REGISTERS data structure.\r
-  @param Buffer           A pointer to the source buffer for the data.\r
-  @param ByteCount        The length of  the data.\r
-  @param Read             Flag used to determine the data transfer direction.\r
-                          Read equals 1, means data transferred from device to host;\r
-                          Read equals 0, means data transferred from host to device.  \r
-  @param AtaCommandBlock  A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
-  @param AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
-  @param Timeout          The time to complete the command.\r
-  \r
-  @retval EFI_SUCCESS      send out the ATA command and device send required data successfully.\r
-  @retval EFI_DEVICE_ERROR command sent failed.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AtaPioDataInOut (  \r
-  IN     EFI_PCI_IO_PROTOCOL       *PciIo,\r
-  IN     EFI_IDE_REGISTERS         *IdeRegisters,\r
-  IN OUT VOID                      *Buffer,\r
-  IN     UINT64                    ByteCount,\r
-  IN     BOOLEAN                   Read,\r
-  IN     EFI_ATA_COMMAND_BLOCK     *AtaCommandBlock,\r
-  IN OUT EFI_ATA_STATUS_BLOCK      *AtaStatusBlock,\r
-  IN     UINT64                    Timeout\r
-  );\r
-\r
-\r
 #endif\r
 \r
index a3c0670c98c744df6332279cb358095e913c43ef..437eca725c596db0a2b632b8ca6758f8d64777be 100644 (file)
@@ -44,6 +44,13 @@ ATA_DEVICE gAtaDeviceTemplate = {
     AtaBlockIoWriteBlocks,\r
     AtaBlockIoFlushBlocks\r
   },\r
+  {                            // BlockIo2\r
+    NULL,\r
+    AtaBlockIoResetEx,\r
+    AtaBlockIoReadBlocksEx,\r
+    AtaBlockIoWriteBlocksEx,\r
+    AtaBlockIoFlushBlocksEx\r
+  },\r
   {                            // BlockMedia\r
     0,                         // MediaId\r
     FALSE,                     // RemovableMedia\r
@@ -75,7 +82,8 @@ ATA_DEVICE gAtaDeviceTemplate = {
   FALSE,                       // Lba48Bit\r
   NULL,                        // IdentifyData\r
   NULL,                        // ControllerNameTable\r
-  {L'\0', }                    // ModelName\r
+  {L'\0', },                   // ModelName\r
+  {NULL, NULL}                 // AtaTaskList\r
 };\r
 \r
 /**\r
@@ -135,12 +143,34 @@ ReleaseAtaResources (
   IN ATA_DEVICE  *AtaDevice\r
   )\r
 {\r
+  ATA_BUS_ASYN_TASK *Task;\r
+  LIST_ENTRY        *Entry;\r
+  LIST_ENTRY        *DelEntry;\r
+  EFI_TPL           OldTpl;\r
+\r
   FreeUnicodeStringTable (AtaDevice->ControllerNameTable);\r
   FreeAlignedBuffer (AtaDevice->Asb, sizeof (*AtaDevice->Asb));\r
   FreeAlignedBuffer (AtaDevice->IdentifyData, sizeof (*AtaDevice->IdentifyData));\r
   if (AtaDevice->DevicePath != NULL) {\r
     FreePool (AtaDevice->DevicePath);\r
   }\r
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+  if (!IsListEmpty (&AtaDevice->AtaTaskList)) {\r
+    //\r
+    // Free the Subtask list.\r
+    //\r
+    for(Entry = (&AtaDevice->AtaTaskList)->ForwardLink; \r
+        Entry != (&AtaDevice->AtaTaskList);\r
+       ) {\r
+      DelEntry = Entry;\r
+      Entry    = Entry->ForwardLink;\r
+      Task     = ATA_AYNS_TASK_FROM_ENTRY (DelEntry);\r
+      \r
+      RemoveEntryList (DelEntry);\r
+      FreeAtaSubTask (Task);\r
+    }\r
+  }\r
+  gBS->RestoreTPL (OldTpl);\r
   FreePool (AtaDevice);\r
 }\r
 \r
@@ -218,10 +248,11 @@ RegisterAtaDevice (
   //\r
   // Initializes ATA device structures and allocates the required buffer.\r
   //\r
-  AtaDevice->BlockIo.Media = &AtaDevice->BlockMedia;\r
-  AtaDevice->AtaBusDriverData = AtaBusDriverData;\r
-  AtaDevice->DevicePath = DevicePath;\r
-  AtaDevice->Port = Port;\r
+  AtaDevice->BlockIo.Media      = &AtaDevice->BlockMedia;\r
+  AtaDevice->BlockIo2.Media     = &AtaDevice->BlockMedia;\r
+  AtaDevice->AtaBusDriverData   = AtaBusDriverData;\r
+  AtaDevice->DevicePath         = DevicePath;\r
+  AtaDevice->Port               = Port;\r
   AtaDevice->PortMultiplierPort = PortMultiplierPort;\r
   AtaDevice->Asb = AllocateAlignedBuffer (AtaDevice, sizeof (*AtaDevice->Asb));\r
   if (AtaDevice->Asb == NULL) {\r
@@ -234,6 +265,11 @@ RegisterAtaDevice (
     goto Done;\r
   }\r
 \r
+  //\r
+  // Initial Ata Task List\r
+  //\r
+  InitializeListHead (&AtaDevice->AtaTaskList);\r
+\r
   //\r
   // Try to identify the ATA device via the ATA pass through command. \r
   //\r
@@ -241,7 +277,7 @@ RegisterAtaDevice (
   if (EFI_ERROR (Status)) {\r
     goto Done;\r
   }\r
-  \r
+\r
   //\r
   // Build controller name for Component Name (2) protocol.\r
   //\r
@@ -281,6 +317,8 @@ RegisterAtaDevice (
                   AtaDevice->DevicePath,\r
                   &gEfiBlockIoProtocolGuid,\r
                   &AtaDevice->BlockIo,\r
+                  &gEfiBlockIo2ProtocolGuid,\r
+                  &AtaDevice->BlockIo2,\r
                   &gEfiDiskInfoProtocolGuid,\r
                   &AtaDevice->DiskInfo,\r
                   NULL\r
@@ -334,8 +372,11 @@ UnregisterAtaDevice (
 {\r
   EFI_STATUS                  Status;\r
   EFI_BLOCK_IO_PROTOCOL       *BlockIo;\r
+  EFI_BLOCK_IO2_PROTOCOL      *BlockIo2;\r
   ATA_DEVICE                  *AtaDevice;\r
   EFI_ATA_PASS_THRU_PROTOCOL  *AtaPassThru;\r
+  BlockIo2 = NULL;\r
+  BlockIo  = NULL;\r
 \r
   Status = gBS->OpenProtocol (\r
                   Handle,\r
@@ -346,10 +387,30 @@ UnregisterAtaDevice (
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                   );\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    //\r
+    // Locate BlockIo2 protocol\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    Handle,\r
+                    &gEfiBlockIo2ProtocolGuid,\r
+                    (VOID **) &BlockIo2,\r
+                    This->DriverBindingHandle,\r
+                    Controller,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
   }\r
 \r
-  AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (BlockIo);\r
+  //\r
+  // Get AtaDevice data.\r
+  //\r
+  if (BlockIo != NULL) {\r
+    AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (BlockIo);\r
+  } else {\r
+    AtaDevice = ATA_DEVICE_FROM_BLOCK_IO2 (BlockIo2);\r
+  } \r
 \r
   //\r
   // Close the child handle\r
@@ -361,12 +422,18 @@ UnregisterAtaDevice (
          Handle\r
          );\r
 \r
+  //\r
+  // The Ata Bus driver installs the BlockIo and BlockIo2 in the DriverBindingStart().\r
+  // Here should uninstall both of them.\r
+  //\r
   Status = gBS->UninstallMultipleProtocolInterfaces (\r
                   Handle,\r
                   &gEfiDevicePathProtocolGuid,\r
                   AtaDevice->DevicePath,\r
                   &gEfiBlockIoProtocolGuid,\r
                   &AtaDevice->BlockIo,\r
+                  &gEfiBlockIo2ProtocolGuid,\r
+                  &AtaDevice->BlockIo2,\r
                   &gEfiDiskInfoProtocolGuid,\r
                   &AtaDevice->DiskInfo,\r
                   NULL\r
@@ -385,7 +452,6 @@ UnregisterAtaDevice (
   }\r
 \r
   ReleaseAtaResources (AtaDevice);\r
-\r
   return Status;\r
 }\r
 \r
@@ -446,7 +512,7 @@ AtaBusDriverBindingSupported (
   EFI_ATA_PASS_THRU_PROTOCOL        *AtaPassThru;\r
   UINT16                            Port;\r
   UINT16                            PortMultiplierPort;\r
\r
+\r
   //\r
   // Test EFI_ATA_PASS_THRU_PROTOCOL on controller handle.\r
   //\r
@@ -522,7 +588,7 @@ AtaBusDriverBindingSupported (
   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This \r
                                    parameter is ignored by device drivers, and is optional for bus \r
                                    drivers. For a bus driver, if this parameter is NULL, then handles \r
-                                   for all the children of Controller are created by this driver.  \r
+                                   for all the children of Controller are created by this driver.\r
                                    If this parameter is not NULL and the first Device Path Node is \r
                                    not the End of Device Path Node, then only the handle for the \r
                                    child device specified by the first Device Path Node of \r
@@ -589,7 +655,7 @@ AtaBusDriverBindingStart (
     }\r
 \r
     AtaBusDriverData->AtaPassThru = AtaPassThru;\r
-    AtaBusDriverData->Controller = Controller;\r
+    AtaBusDriverData->Controller  = Controller;\r
     AtaBusDriverData->ParentDevicePath = ParentDevicePath;\r
     AtaBusDriverData->DriverBindingHandle = This->DriverBindingHandle;\r
 \r
@@ -628,7 +694,7 @@ AtaBusDriverBindingStart (
         //\r
         break;\r
       }\r
-      \r
+\r
       PortMultiplierPort = 0xFFFF;\r
       while (TRUE) {\r
         Status = AtaPassThru->GetNextDevice (AtaPassThru, Port, &PortMultiplierPort);\r
@@ -649,7 +715,7 @@ AtaBusDriverBindingStart (
       Status = RegisterAtaDevice (AtaBusDriverData,Port, PortMultiplierPort);\r
     }\r
   }\r
-  \r
+\r
   return Status;\r
 \r
 ErrorExit:\r
@@ -789,7 +855,7 @@ AtaBlockIoReset (
 \r
   AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (This);\r
 \r
-  Status = ResetAtaDevice (AtaDevice);  \r
+  Status = ResetAtaDevice (AtaDevice);\r
 \r
   if (EFI_ERROR (Status)) {\r
     Status = EFI_DEVICE_ERROR;\r
@@ -803,13 +869,18 @@ AtaBlockIoReset (
 /**\r
   Read/Write BufferSize bytes from Lba from/into Buffer.\r
 \r
-  @param  This       Indicates a pointer to the calling context.\r
-  @param  MediaId    The media ID that the read/write request is for.\r
-  @param  Lba        The starting logical block address to be read/written. The caller is\r
-                     responsible for reading/writing to only legitimate locations.\r
-  @param  BufferSize Size of Buffer, must be a multiple of device block size.\r
-  @param  Buffer     A pointer to the destination/source buffer for the data.\r
-  @param  IsWrite    Indicates whether it is a write operation.\r
+  @param[in]       This       Indicates a pointer to the calling context. Either be\r
+                              block I/O or block I/O2. \r
+  @param[in]       MediaId    The media ID that the read/write request is for.\r
+  @param[in]       Lba        The starting logical block address to be read/written.\r
+                              The caller is responsible for reading/writing to only\r
+                              legitimate locations.\r
+  @param[in, out]  Token      A pointer to the token associated with the transaction.\r
+  @param[in]       BufferSize Size of Buffer, must be a multiple of device block size.\r
+  @param[out]      Buffer     A pointer to the destination/source buffer for the data.\r
+  @param[in]       IsBlockIo2 Indicate the calling is from BlockIO or BlockIO2. TURE is\r
+                              from BlockIO2, FALSE is for BlockIO.\r
+  @param[in]       IsWrite    Indicates whether it is a write operation.\r
 \r
   @retval EFI_SUCCESS           The data was read/written correctly to the device.\r
   @retval EFI_WRITE_PROTECTED   The device can not be read/written to.\r
@@ -823,12 +894,14 @@ AtaBlockIoReset (
 **/\r
 EFI_STATUS\r
 BlockIoReadWrite (\r
-  IN  EFI_BLOCK_IO_PROTOCOL   *This,\r
-  IN  UINT32                  MediaId,\r
-  IN  EFI_LBA                 Lba,\r
-  IN  UINTN                   BufferSize,\r
-  OUT VOID                    *Buffer,\r
-  IN  BOOLEAN                 IsWrite\r
+  IN     VOID                    *This,\r
+  IN     UINT32                  MediaId,\r
+  IN     EFI_LBA                 Lba,\r
+  IN OUT EFI_BLOCK_IO2_TOKEN     *Token,\r
+  IN     UINTN                   BufferSize,\r
+  OUT    VOID                    *Buffer,\r
+  IN     BOOLEAN                 IsBlockIo2,\r
+  IN     BOOLEAN                 IsWrite\r
   )\r
 {\r
   ATA_DEVICE                        *AtaDevice;\r
@@ -839,21 +912,28 @@ BlockIoReadWrite (
   UINTN                             NumberOfBlocks;\r
   UINTN                             IoAlign;\r
 \r
-  //\r
-  // Check parameters.\r
-  //\r
-  Media = This->Media;\r
+  if (IsBlockIo2) {\r
+   Media     = ((EFI_BLOCK_IO2_PROTOCOL *) This)->Media;\r
+   AtaDevice = ATA_DEVICE_FROM_BLOCK_IO2 (This);\r
+  } else {\r
+   Media     = ((EFI_BLOCK_IO_PROTOCOL *) This)->Media;\r
+   AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (This);\r
+  }\r
+\r
   if (MediaId != Media->MediaId) {\r
     return EFI_MEDIA_CHANGED;\r
   }\r
 \r
+  //\r
+  // Check parameters.\r
+  //\r
   if (Buffer == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   if (BufferSize == 0) {\r
     return EFI_SUCCESS;\r
-  }\r
+  }  \r
 \r
   BlockSize = Media->BlockSize;\r
   if ((BufferSize % BlockSize) != 0) {\r
@@ -871,13 +951,11 @@ BlockIoReadWrite (
   }\r
 \r
   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
-  AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (This);\r
   \r
   //\r
   // Invoke low level AtaDevice Access Routine.\r
   //\r
-  Status = AccessAtaDevice (AtaDevice, Buffer, Lba, NumberOfBlocks, IsWrite);\r
+  Status = AccessAtaDevice (AtaDevice, Buffer, Lba, NumberOfBlocks, IsWrite, Token);\r
  \r
   gBS->RestoreTPL (OldTpl);\r
 \r
@@ -914,7 +992,7 @@ AtaBlockIoReadBlocks (
   OUT VOID                    *Buffer\r
   )\r
 {\r
-  return BlockIoReadWrite (This, MediaId, Lba, BufferSize, Buffer, FALSE);\r
+  return BlockIoReadWrite ((VOID *) This, MediaId, Lba, NULL, BufferSize, Buffer, FALSE, FALSE);\r
 }\r
 \r
 \r
@@ -948,7 +1026,7 @@ AtaBlockIoWriteBlocks (
   IN  VOID                    *Buffer\r
   )\r
 {\r
-  return BlockIoReadWrite (This, MediaId, Lba, BufferSize, Buffer, TRUE);\r
+  return BlockIoReadWrite ((VOID *) This, MediaId, Lba, NULL, BufferSize, Buffer, FALSE, TRUE);\r
 }\r
 \r
 \r
@@ -974,7 +1052,147 @@ AtaBlockIoFlushBlocks (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Reset the Block Device.\r
+\r
+  @param[in]  This                 Indicates a pointer to the calling context.\r
+  @param[in]  ExtendedVerification Driver may perform diagnostics on reset.\r
+\r
+  @retval EFI_SUCCESS          The device was reset.\r
+  @retval EFI_DEVICE_ERROR     The device is not functioning properly and could\r
+                               not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaBlockIoResetEx (\r
+  IN  EFI_BLOCK_IO2_PROTOCOL  *This,\r
+  IN  BOOLEAN                 ExtendedVerification\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+  ATA_DEVICE      *AtaDevice;\r
+  EFI_TPL         OldTpl;\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+  AtaDevice = ATA_DEVICE_FROM_BLOCK_IO2 (This);\r
+\r
+  Status = ResetAtaDevice (AtaDevice);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Read BufferSize bytes from Lba into Buffer.\r
+\r
+  @param[in]       This       Indicates a pointer to the calling context.\r
+  @param[in]       MediaId    Id of the media, changes every time the media is replaced.\r
+  @param[in]       Lba        The starting Logical Block Address to read from.\r
+  @param[in, out]  Token      A pointer to the token associated with the transaction.\r
+  @param[in]       BufferSize Size of Buffer, must be a multiple of device block size.\r
+  @param[out]      Buffer     A pointer to the destination buffer for the data. The caller is\r
+                              responsible for either having implicit or explicit ownership of the buffer.\r
+\r
+  @retval EFI_SUCCESS           The read request was queued if Event is not NULL.\r
+                                The data was read correctly from the device if\r
+                                the Event is NULL.\r
+  @retval EFI_DEVICE_ERROR      The device reported an error while performing\r
+                                the read.\r
+  @retval EFI_NO_MEDIA          There is no media in the device.\r
+  @retval EFI_MEDIA_CHANGED     The MediaId is not for the current media.\r
+  @retval EFI_BAD_BUFFER_SIZE   The BufferSize parameter is not a multiple of the\r
+                                intrinsic block size of the device.\r
+  @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
+                                or the buffer is not on proper alignment.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack\r
+                                of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaBlockIoReadBlocksEx (\r
+  IN  EFI_BLOCK_IO2_PROTOCOL  *This,\r
+  IN  UINT32                  MediaId,\r
+  IN  EFI_LBA                 Lba,\r
+  IN OUT EFI_BLOCK_IO2_TOKEN  *Token,\r
+  IN  UINTN                   BufferSize,\r
+  OUT VOID                    *Buffer\r
+  )\r
+{\r
+  return BlockIoReadWrite ((VOID *) This, MediaId, Lba, Token, BufferSize, Buffer, TRUE, FALSE);\r
+}\r
+\r
+\r
+/**\r
+  Write BufferSize bytes from Lba into Buffer.\r
+\r
+  @param[in]       This       Indicates a pointer to the calling context.\r
+  @param[in]       MediaId    The media ID that the write request is for.\r
+  @param[in]       Lba        The starting logical block address to be written. The\r
+                              caller is responsible for writing to only legitimate\r
+                              locations.\r
+  @param[in, out]  Token      A pointer to the token associated with the transaction.\r
+  @param[in]       BufferSize Size of Buffer, must be a multiple of device block size.\r
+  @param[in]       Buffer     A pointer to the source buffer for the data.\r
 \r
+  @retval EFI_SUCCESS           The data was written correctly to the device.\r
+  @retval EFI_WRITE_PROTECTED   The device can not be written to.\r
+  @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.\r
+  @retval EFI_NO_MEDIA          There is no media in the device.\r
+  @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.\r
+  @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.\r
+  @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
+                                or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaBlockIoWriteBlocksEx (\r
+  IN  EFI_BLOCK_IO2_PROTOCOL  *This,\r
+  IN  UINT32                  MediaId,\r
+  IN  EFI_LBA                 Lba,\r
+  IN OUT EFI_BLOCK_IO2_TOKEN  *Token,\r
+  IN  UINTN                   BufferSize,\r
+  IN  VOID                    *Buffer\r
+  )\r
+{\r
+  return BlockIoReadWrite ((VOID *) This, MediaId, Lba, Token, BufferSize, Buffer, TRUE, TRUE);\r
+}\r
+\r
+\r
+/**\r
+  Flush the Block Device.\r
+\r
+  @param[in]       This       Indicates a pointer to the calling context.\r
+  @param[in, out]  Token      A pointer to the token associated with the transaction.\r
+\r
+  @retval EFI_SUCCESS       All outstanding data was written to the device\r
+  @retval EFI_DEVICE_ERROR  The device reported an error while writing back the data\r
+  @retval EFI_NO_MEDIA      There is no media in the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaBlockIoFlushBlocksEx (\r
+  IN  EFI_BLOCK_IO2_PROTOCOL  *This,\r
+  IN OUT EFI_BLOCK_IO2_TOKEN  *Token\r
+  )\r
+{\r
+  //\r
+  // Signla event and return directly.\r
+  //\r
+  if (Token != NULL && Token->Event != NULL) {\r
+    Token->TransactionStatus = EFI_SUCCESS;\r
+    gBS->SignalEvent (Token->Event);\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
 /**\r
   Provides inquiry information for the controller type.\r
   \r
index 4cda0e5cc4ca211ff5493d195a231d82dbfd59b5..4d036836e910f72e91ba404f34e1cea50734ca3e 100644 (file)
@@ -22,6 +22,7 @@
 \r
 #include <Protocol/AtaPassThru.h>\r
 #include <Protocol/BlockIo.h>\r
+#include <Protocol/BlockIo2.h>\r
 #include <Protocol/DiskInfo.h>\r
 #include <Protocol/DevicePath.h>\r
 \r
 //\r
 // The maximum ATA transaction sector count in 48 bit addressing mode. \r
 //\r
-#define MAX_48BIT_TRANSFER_BLOCK_NUM      0x10000\r
+//#define MAX_48BIT_TRANSFER_BLOCK_NUM      0x10000\r
+\r
+//\r
+// BugBug: if the TransferLength is equal with 0x10000 (the 48bit max length),\r
+// there is a bug that even the register interrupt bit has been sit, the buffer\r
+// seems not ready. Change the Maximum Sector Numbers to 0xFFFF to work round\r
+// this issue.\r
+//\r
+#define MAX_48BIT_TRANSFER_BLOCK_NUM      0xFFFF\r
 \r
 //\r
 // The maximum model name in ATA identify data  \r
 //\r
 #define MAX_MODEL_NAME_LEN                40\r
 \r
+#define ATA_TASK_SIGNATURE    SIGNATURE_32 ('A', 'T', 'S', 'K')\r
+#define ATA_DEVICE_SIGNATURE  SIGNATURE_32 ('A', 'B', 'I', 'D')\r
+\r
+#define IS_ALIGNED(addr, size)      (((UINTN) (addr) & (size - 1)) == 0)\r
+\r
+//\r
+// Task for the non blocking I/O\r
+//\r
+typedef struct {\r
+  UINT32                            Signature;\r
+  EFI_BLOCK_IO2_TOKEN               *Token;\r
+  UINTN                             *UnsignalledEventCount;\r
+  EFI_ATA_PASS_THRU_COMMAND_PACKET  Packet;\r
+  BOOLEAN                           *IsError;// Indicate whether meeting error during source allocation for new task.\r
+  LIST_ENTRY                        TaskEntry;\r
+} ATA_BUS_ASYN_TASK;\r
 \r
 //\r
 // ATA bus data structure for ATA controller\r
@@ -77,46 +102,48 @@ typedef struct {
   EFI_HANDLE                  DriverBindingHandle;\r
 } ATA_BUS_DRIVER_DATA;\r
 \r
-#define ATA_DEVICE_SIGNATURE  SIGNATURE_32 ('A', 'B', 'I', 'D')\r
-\r
 //\r
 // ATA device data structure for each child device\r
 //\r
 typedef struct {\r
-  UINT32                            Signature;\r
+  UINT32                                Signature;\r
 \r
-  EFI_HANDLE                        Handle;\r
-  EFI_BLOCK_IO_PROTOCOL             BlockIo;\r
-  EFI_BLOCK_IO_MEDIA                BlockMedia;\r
-  EFI_DISK_INFO_PROTOCOL            DiskInfo;\r
-  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;\r
+  EFI_HANDLE                            Handle;\r
+  EFI_BLOCK_IO_PROTOCOL                 BlockIo;\r
+  EFI_BLOCK_IO2_PROTOCOL                BlockIo2;\r
+  EFI_BLOCK_IO_MEDIA                    BlockMedia;\r
+  EFI_DISK_INFO_PROTOCOL                DiskInfo;\r
+  EFI_DEVICE_PATH_PROTOCOL              *DevicePath;\r
 \r
-  ATA_BUS_DRIVER_DATA               *AtaBusDriverData;\r
-  UINT16                            Port;\r
-  UINT16                            PortMultiplierPort;\r
+  ATA_BUS_DRIVER_DATA                   *AtaBusDriverData;\r
+  UINT16                                Port;\r
+  UINT16                                PortMultiplierPort;\r
 \r
   //\r
   // Buffer for the execution of ATA pass through protocol\r
   //\r
-  EFI_ATA_PASS_THRU_COMMAND_PACKET  Packet;\r
-  EFI_ATA_COMMAND_BLOCK             Acb;\r
-  EFI_ATA_STATUS_BLOCK              *Asb;\r
+  EFI_ATA_PASS_THRU_COMMAND_PACKET      Packet;\r
+  EFI_ATA_COMMAND_BLOCK                 Acb;\r
+  EFI_ATA_STATUS_BLOCK                  *Asb;\r
 \r
-  BOOLEAN                           UdmaValid;\r
-  BOOLEAN                           Lba48Bit;\r
+  BOOLEAN                               UdmaValid;\r
+  BOOLEAN                               Lba48Bit;\r
 \r
   //\r
   // Cached data for ATA identify data\r
   //\r
-  ATA_IDENTIFY_DATA                 *IdentifyData;\r
+  ATA_IDENTIFY_DATA                     *IdentifyData;\r
 \r
-  EFI_UNICODE_STRING_TABLE          *ControllerNameTable;\r
-  CHAR16                            ModelName[MAX_MODEL_NAME_LEN + 1];\r
+  EFI_UNICODE_STRING_TABLE              *ControllerNameTable;\r
+  CHAR16                                ModelName[MAX_MODEL_NAME_LEN + 1];\r
 \r
+  LIST_ENTRY                        AtaTaskList;\r
 } ATA_DEVICE;\r
 \r
-#define ATA_DEVICE_FROM_BLOCK_IO(a)  CR (a, ATA_DEVICE, BlockIo, ATA_DEVICE_SIGNATURE)\r
-#define ATA_DEVICE_FROM_DISK_INFO(a) CR (a, ATA_DEVICE, DiskInfo, ATA_DEVICE_SIGNATURE)\r
+#define ATA_DEVICE_FROM_BLOCK_IO(a)         CR (a, ATA_DEVICE, BlockIo, ATA_DEVICE_SIGNATURE)\r
+#define ATA_DEVICE_FROM_BLOCK_IO2(a)        CR (a, ATA_DEVICE, BlockIo2, ATA_DEVICE_SIGNATURE)\r
+#define ATA_DEVICE_FROM_DISK_INFO(a)        CR (a, ATA_DEVICE, DiskInfo, ATA_DEVICE_SIGNATURE)\r
+#define ATA_AYNS_TASK_FROM_ENTRY(a)         CR (a, ATA_BUS_ASYN_TASK, TaskEntry, ATA_TASK_SIGNATURE)\r
 \r
 //\r
 // Global Variables\r
@@ -125,6 +152,52 @@ extern EFI_DRIVER_BINDING_PROTOCOL        gAtaBusDriverBinding;
 extern EFI_COMPONENT_NAME_PROTOCOL        gAtaBusComponentName;\r
 extern EFI_COMPONENT_NAME2_PROTOCOL       gAtaBusComponentName2;\r
 \r
+/**\r
+  Allocates an aligned buffer for ATA device.\r
+\r
+  This function allocates an aligned buffer for the ATA device to perform\r
+  ATA pass through operations. The alignment requirement is from ATA pass\r
+  through interface.\r
+\r
+  @param  AtaDevice         The ATA child device involved for the operation.\r
+  @param  BufferSize        The request buffer size.\r
+\r
+  @return A pointer to the aligned buffer or NULL if the allocation fails.\r
+\r
+**/\r
+VOID *\r
+AllocateAlignedBuffer (\r
+  IN ATA_DEVICE               *AtaDevice,\r
+  IN UINTN                    BufferSize\r
+  );\r
+\r
+/**\r
+  Frees an aligned buffer for ATA device.\r
+\r
+  This function frees an aligned buffer for the ATA device to perform\r
+  ATA pass through operations.\r
+\r
+  @param  Buffer            The aligned buffer to be freed.\r
+  @param  BufferSize        The request buffer size.\r
+\r
+**/\r
+VOID\r
+FreeAlignedBuffer (\r
+  IN VOID                     *Buffer,\r
+  IN UINTN                    BufferSize\r
+  );\r
+\r
+/**\r
+  Free SubTask. \r
+\r
+  @param[in, out]  Task      Pointer to task to be freed.\r
\r
+**/\r
+VOID\r
+EFIAPI \r
+FreeAtaSubTask (\r
+  IN ATA_BUS_ASYN_TASK  *Task\r
+  );\r
 \r
 /**\r
   Wrapper for EFI_ATA_PASS_THRU_PROTOCOL.ResetDevice().\r
@@ -162,7 +235,6 @@ DiscoverAtaDevice (
   IN OUT ATA_DEVICE                 *AtaDevice\r
   );\r
 \r
-\r
 /**\r
   Read or write a number of blocks from ATA device.\r
 \r
@@ -170,11 +242,12 @@ DiscoverAtaDevice (
   ATA device. It may separate the read/write request into several ATA pass through\r
   transactions.\r
 \r
-  @param  AtaDevice         The ATA child device involved for the operation.\r
-  @param  Buffer            The pointer to the current transaction buffer.\r
-  @param  StartLba          The starting logical block address to be accessed.\r
-  @param  NumberOfBlocks    The block number or sector count of the transfer.\r
-  @param  IsWrite           Indicates whether it is a write operation.\r
+  @param[in, out]  AtaDevice       The ATA child device involved for the operation.\r
+  @param[in, out]  Buffer          The pointer to the current transaction buffer.\r
+  @param[in]       StartLba        The starting logical block address to be accessed.\r
+  @param[in]       NumberOfBlocks  The block number or sector count of the transfer.\r
+  @param[in]       IsWrite         Indicates whether it is a write operation.\r
+  @param[in, out]  Token           A pointer to the token associated with the transaction.\r
 \r
   @retval EFI_SUCCESS       The data transfer is complete successfully.\r
   @return others            Some error occurs when transferring data. \r
@@ -186,7 +259,8 @@ AccessAtaDevice(
   IN OUT UINT8                      *Buffer,\r
   IN EFI_LBA                        StartLba,\r
   IN UINTN                          NumberOfBlocks,\r
-  IN BOOLEAN                        IsWrite\r
+  IN BOOLEAN                        IsWrite,\r
+  IN OUT EFI_BLOCK_IO2_TOKEN        *Token\r
   );\r
 \r
 //\r
@@ -544,6 +618,111 @@ AtaBlockIoFlushBlocks (
   IN  EFI_BLOCK_IO_PROTOCOL   *This\r
   );\r
 \r
+/**\r
+  Reset the Block Device throught Block I/O2 protocol.\r
+\r
+  @param[in]  This                 Indicates a pointer to the calling context.\r
+  @param[in]  ExtendedVerification Driver may perform diagnostics on reset.\r
+\r
+  @retval EFI_SUCCESS          The device was reset.\r
+  @retval EFI_DEVICE_ERROR     The device is not functioning properly and could\r
+                               not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaBlockIoResetEx (\r
+  IN  EFI_BLOCK_IO2_PROTOCOL  *This,\r
+  IN  BOOLEAN                 ExtendedVerification\r
+  );\r
+\r
+/**\r
+  Read BufferSize bytes from Lba into Buffer.\r
+\r
+  @param[in]       This       Indicates a pointer to the calling context.\r
+  @param[in]       MediaId    Id of the media, changes every time the media is replaced.\r
+  @param[in]       Lba        The starting Logical Block Address to read from.\r
+  @param[in, out]  Token      A pointer to the token associated with the transaction.\r
+  @param[in]       BufferSize Size of Buffer, must be a multiple of device block size.\r
+  @param[out]      Buffer     A pointer to the destination buffer for the data. The caller is\r
+                              responsible for either having implicit or explicit ownership of the buffer.\r
+\r
+  @retval EFI_SUCCESS           The read request was queued if Event is not NULL.\r
+                                The data was read correctly from the device if\r
+                                the Event is NULL.\r
+  @retval EFI_DEVICE_ERROR      The device reported an error while performing\r
+                                the read.\r
+  @retval EFI_NO_MEDIA          There is no media in the device.\r
+  @retval EFI_MEDIA_CHANGED     The MediaId is not for the current media.\r
+  @retval EFI_BAD_BUFFER_SIZE   The BufferSize parameter is not a multiple of the\r
+                                intrinsic block size of the device.\r
+  @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
+                                or the buffer is not on proper alignment.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack\r
+                                of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaBlockIoReadBlocksEx (\r
+  IN  EFI_BLOCK_IO2_PROTOCOL  *This,\r
+  IN  UINT32                  MediaId,\r
+  IN  EFI_LBA                 Lba,\r
+  IN OUT EFI_BLOCK_IO2_TOKEN  *Token,\r
+  IN  UINTN                   BufferSize,\r
+  OUT VOID                    *Buffer\r
+  );\r
+\r
+/**\r
+  Write BufferSize bytes from Lba into Buffer.\r
+\r
+  @param[in]       This       Indicates a pointer to the calling context.\r
+  @param[in]       MediaId    The media ID that the write request is for.\r
+  @param[in]       Lba        The starting logical block address to be written. The\r
+                              caller is responsible for writing to only legitimate\r
+                              locations.\r
+  @param[in, out]  Token      A pointer to the token associated with the transaction.\r
+  @param[in]       BufferSize Size of Buffer, must be a multiple of device block size.\r
+  @param[in]       Buffer     A pointer to the source buffer for the data.\r
+\r
+  @retval EFI_SUCCESS           The data was written correctly to the device.\r
+  @retval EFI_WRITE_PROTECTED   The device can not be written to.\r
+  @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.\r
+  @retval EFI_NO_MEDIA          There is no media in the device.\r
+  @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.\r
+  @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.\r
+  @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
+                                or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaBlockIoWriteBlocksEx (\r
+  IN  EFI_BLOCK_IO2_PROTOCOL  *This,\r
+  IN  UINT32                  MediaId,\r
+  IN  EFI_LBA                 Lba,\r
+  IN OUT EFI_BLOCK_IO2_TOKEN  *Token,\r
+  IN  UINTN                   BufferSize,\r
+  IN  VOID                    *Buffer\r
+  );\r
+\r
+/**\r
+  Flush the Block Device.\r
+\r
+  @param[in]       This       Indicates a pointer to the calling context.\r
+  @param[in, out]  Token      A pointer to the token associated with the transaction.\r
+\r
+  @retval EFI_SUCCESS       All outstanding data was written to the device\r
+  @retval EFI_DEVICE_ERROR  The device reported an error while writing back the data\r
+  @retval EFI_NO_MEDIA      There is no media in the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaBlockIoFlushBlocksEx (\r
+  IN  EFI_BLOCK_IO2_PROTOCOL  *This,\r
+  IN OUT EFI_BLOCK_IO2_TOKEN  *Token\r
+  );\r
 \r
 /**\r
   Provides inquiry information for the controller type.\r
index 9ca1b4bbb43551f01955c0bdd4453ca91c0291c3..18ed39d42946bca3cb5534bebee8496571a27e46 100644 (file)
@@ -5,7 +5,7 @@
 #  in UEFI spec 2.2. It installs Block IO and Disk Info protocol for each ATA device\r
 #  it enumerates and identifies successfully.\r
 #\r
-#  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2009 - 2011, 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 of the BSD License\r
@@ -63,6 +63,7 @@
 [Protocols]\r
   gEfiDiskInfoProtocolGuid                      # BY_START\r
   gEfiBlockIoProtocolGuid                       # BY_START\r
+  gEfiBlockIo2ProtocolGuid                      # BY_START\r
   gEfiAtaPassThruProtocolGuid                   # TO_START\r
   gEfiDevicePathProtocolGuid                    # TO_START\r
   \r
index acfbd743943ae9829b6d3d2f132d41ecba99ff8e..1f204193fd39f7d0a1308fd2e967bb8ec7d030df 100644 (file)
@@ -5,7 +5,7 @@
   It transforms the high level identity, read/write, reset command to ATA pass\r
   through command and protocol. \r
     \r
-  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 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
@@ -75,14 +75,25 @@ UINTN mMaxTransferBlockNumber[] = {
   for an ATA device. It assembles the ATA pass through command packet for ATA\r
   transaction.\r
 \r
-  @param  AtaDevice         The ATA child device involved for the operation.\r
+  @param[in, out]  AtaDevice   The ATA child device involved for the operation.\r
+  @param[in, out]  TaskPacket  Pointer to a Pass Thru Command Packet. Optional, \r
+                               if it is NULL, blocking mode, and use the packet\r
+                               in AtaDevice. If it is not NULL, non blocking mode,\r
+                               and pass down this Packet.\r
+  @param[in]       Event       If Event is NULL, then blocking I/O is performed.\r
+                               If Event is not NULL and non-blocking I/O is\r
+                               supported,then non-blocking I/O is performed,\r
+                               and Event will be signaled when the write\r
+                               request is completed.\r
 \r
   @return The return status from EFI_ATA_PASS_THRU_PROTOCOL.PassThru().\r
 \r
 **/\r
 EFI_STATUS\r
 AtaDevicePassThru (\r
-  IN OUT ATA_DEVICE                       *AtaDevice\r
+  IN OUT ATA_DEVICE                       *AtaDevice,\r
+  IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *TaskPacket, OPTIONAL\r
+  IN OUT EFI_EVENT                        Event OPTIONAL\r
   )\r
 {\r
   EFI_STATUS                              Status;\r
@@ -90,12 +101,19 @@ AtaDevicePassThru (
   EFI_ATA_PASS_THRU_COMMAND_PACKET        *Packet;\r
 \r
   //\r
-  // Assemble packet\r
+  // Assemble packet. If it is non blocking mode, the Ata driver should keep each \r
+  // subtask and clean them when the event is signaled.\r
   //\r
-  Packet = &AtaDevice->Packet;\r
-  Packet->Asb = AtaDevice->Asb;\r
-  Packet->Acb = &AtaDevice->Acb;\r
-  Packet->Timeout = ATA_TIMEOUT;\r
+  if (TaskPacket != NULL) {\r
+    Packet = TaskPacket;\r
+    Packet->Asb = AllocateAlignedBuffer (AtaDevice, sizeof (*AtaDevice->Asb));\r
+    CopyMem (Packet->Asb, AtaDevice->Asb, sizeof (*AtaDevice->Asb));\r
+    Packet->Acb = AllocateCopyPool(sizeof (EFI_ATA_COMMAND_BLOCK), &AtaDevice->Acb);\r
+  } else {\r
+    Packet = &AtaDevice->Packet;\r
+    Packet->Asb = AtaDevice->Asb;\r
+    Packet->Acb = &AtaDevice->Acb;\r
+  }\r
 \r
   AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru;\r
 \r
@@ -104,7 +122,7 @@ AtaDevicePassThru (
                           AtaDevice->Port,\r
                           AtaDevice->PortMultiplierPort,\r
                           Packet,\r
-                          NULL\r
+                          Event\r
                           );\r
   //\r
   // Ensure ATA pass through caller and callee have the same\r
@@ -257,6 +275,8 @@ IdentifyAtaDevice (
     return EFI_UNSUPPORTED;\r
   }\r
 \r
+  DEBUG ((EFI_D_INFO, "AtaBus - Identify Device (%x %x)\n", (UINTN)AtaDevice->Port, (UINTN)AtaDevice->PortMultiplierPort));\r
+\r
   //\r
   // Check whether the WORD 88 (supported UltraDMA by drive) is valid\r
   //\r
@@ -319,7 +339,7 @@ IdentifyAtaDevice (
   //\r
   // Get ATA model name from identify data structure. \r
   //\r
-  PrintAtaModelName (AtaDevice); \r
+  PrintAtaModelName (AtaDevice);\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -354,7 +374,7 @@ DiscoverAtaDevice (
   //\r
   Acb = ZeroMem (&AtaDevice->Acb, sizeof (*Acb));\r
   Acb->AtaCommand = ATA_CMD_IDENTIFY_DRIVE;\r
-  Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4)); \r
+  Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));\r
 \r
   //\r
   // Prepare for ATA pass through packet.\r
@@ -363,11 +383,12 @@ DiscoverAtaDevice (
   Packet->InDataBuffer = AtaDevice->IdentifyData;\r
   Packet->InTransferLength = sizeof (*AtaDevice->IdentifyData);\r
   Packet->Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN;\r
-  Packet->Length = EFI_ATA_PASS_THRU_LENGTH_BYTES | EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;\r
+  Packet->Length   = EFI_ATA_PASS_THRU_LENGTH_BYTES | EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;\r
+  Packet->Timeout  = ATA_TIMEOUT;\r
 \r
   Retry = MAX_RETRY_TIMES;\r
   do {\r
-    Status = AtaDevicePassThru (AtaDevice);\r
+    Status = AtaDevicePassThru (AtaDevice, NULL, NULL);\r
     if (!EFI_ERROR (Status)) {\r
       //\r
       // The command is issued successfully\r
@@ -389,11 +410,20 @@ DiscoverAtaDevice (
   ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru\r
   interface of ATA pass through.\r
 \r
-  @param  AtaDevice         The ATA child device involved for the operation.\r
-  @param  Buffer            The pointer to the current transaction buffer.\r
-  @param  StartLba          The starting logical block address to be accessed.\r
-  @param  TransferLength    The block number or sector count of the transfer.\r
-  @param  IsWrite           Indicates whether it is a write operation.\r
+  @param[in, out]  AtaDevice       The ATA child device involved for the operation.\r
+  @param[in, out]  TaskPacket      Pointer to a Pass Thru Command Packet. Optional, \r
+                                   if it is NULL, blocking mode, and use the packet\r
+                                   in AtaDevice. If it is not NULL, non blocking mode,\r
+                                   and pass down this Packet.\r
+  @param[in, out]  Buffer          The pointer to the current transaction buffer.\r
+  @param[in]       StartLba        The starting logical block address to be accessed.\r
+  @param[in]       TransferLength  The block number or sector count of the transfer.\r
+  @param[in]       IsWrite         Indicates whether it is a write operation.\r
+  @param[in]       Event           If Event is NULL, then blocking I/O is performed.\r
+                                   If Event is not NULL and non-blocking I/O is\r
+                                   supported,then non-blocking I/O is performed,\r
+                                   and Event will be signaled when the write\r
+                                   request is completed.\r
 \r
   @retval EFI_SUCCESS       The data transfer is complete successfully.\r
   @return others            Some error occurs when transferring data. \r
@@ -401,11 +431,13 @@ DiscoverAtaDevice (
 **/\r
 EFI_STATUS\r
 TransferAtaDevice (\r
-  IN OUT ATA_DEVICE                 *AtaDevice,\r
-  IN OUT VOID                       *Buffer,\r
-  IN EFI_LBA                        StartLba,\r
-  IN UINT32                         TransferLength,\r
-  IN BOOLEAN                        IsWrite\r
+  IN OUT ATA_DEVICE                       *AtaDevice,\r
+  IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *TaskPacket, OPTIONAL\r
+  IN OUT VOID                             *Buffer,\r
+  IN EFI_LBA                              StartLba,\r
+  IN UINT32                               TransferLength,\r
+  IN BOOLEAN                              IsWrite, \r
+  IN EFI_EVENT                            Event OPTIONAL\r
   )\r
 {\r
   EFI_ATA_COMMAND_BLOCK             *Acb;\r
@@ -425,7 +457,7 @@ TransferAtaDevice (
   Acb->AtaSectorNumber = (UINT8) StartLba;\r
   Acb->AtaCylinderLow = (UINT8) RShiftU64 (StartLba, 8);\r
   Acb->AtaCylinderHigh = (UINT8) RShiftU64 (StartLba, 16);\r
-  Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4)); \r
+  Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));\r
   Acb->AtaSectorCount = (UINT8) TransferLength;\r
   if (AtaDevice->Lba48Bit) {\r
     Acb->AtaSectorNumberExp = (UINT8) RShiftU64 (StartLba, 24);\r
@@ -439,7 +471,12 @@ TransferAtaDevice (
   //\r
   // Prepare for ATA pass through packet.\r
   //\r
-  Packet = ZeroMem (&AtaDevice->Packet, sizeof (*Packet));\r
+  if (TaskPacket != NULL) {\r
+    Packet = ZeroMem (TaskPacket, sizeof (*Packet));\r
+  } else {\r
+    Packet = ZeroMem (&AtaDevice->Packet, sizeof (*Packet));\r
+  }\r
+\r
   if (IsWrite) {\r
     Packet->OutDataBuffer = Buffer;\r
     Packet->OutTransferLength = TransferLength;\r
@@ -447,10 +484,109 @@ TransferAtaDevice (
     Packet->InDataBuffer = Buffer;\r
     Packet->InTransferLength = TransferLength;\r
   }\r
+\r
   Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsWrite];\r
   Packet->Length = EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;\r
+  Packet->Timeout  = ATA_TIMEOUT;\r
+\r
+  return AtaDevicePassThru (AtaDevice, TaskPacket, Event);\r
+}\r
+\r
+/**\r
+  Free SubTask. \r
+\r
+  @param[in, out]  Task      Pointer to task to be freed.\r
+\r
+**/\r
+VOID\r
+EFIAPI \r
+FreeAtaSubTask (\r
+  IN ATA_BUS_ASYN_TASK  *Task\r
+  )\r
+{\r
+  if (Task->Packet.Asb != NULL) {\r
+    FreeAlignedBuffer (Task->Packet.Asb, sizeof (Task->Packet.Asb));\r
+  }\r
+  if (Task->Packet.Acb != NULL) {\r
+    FreePool (Task->Packet.Acb);\r
+  }\r
+\r
+  FreePool (Task);\r
+}\r
+\r
+/**\r
+  Call back funtion when the event is signaled.\r
+\r
+  @param[in]  Event     The Event this notify function registered to.\r
+  @param[in]  Context   Pointer to the context data registerd to the\r
+                        Event.\r
+\r
+**/\r
+VOID\r
+EFIAPI \r
+AtaNonBlockingCallBack (\r
+  IN EFI_EVENT                Event,\r
+  IN VOID                     *Context\r
+  )\r
+{\r
+  ATA_BUS_ASYN_TASK *Task;\r
+\r
+  Task = (ATA_BUS_ASYN_TASK *) Context;\r
+  gBS->CloseEvent (Event);\r
+\r
+  //\r
+  // Check the command status.\r
+  // If there is error during the sub task source allocation, the error status\r
+  // should be returned to the caller directly, so here the Task->Token may already\r
+  // be deleted by the caller and no need to update the status.\r
+  //\r
+  if ((!(*Task->IsError)) && (Task->Packet.Asb->AtaStatus & 0x01) == 0x01) {\r
+    Task->Token->TransactionStatus = EFI_DEVICE_ERROR;\r
+  }\r
+  DEBUG ((\r
+    DEBUG_INFO, \r
+    "NON-BLOCKING EVENT FINISHED!- STATUS = %r\n", \r
+    Task->Token->TransactionStatus\r
+    ));\r
+\r
+  //\r
+  // Reduce the SubEventCount, till it comes to zero.\r
+  //\r
+  (*Task->UnsignalledEventCount) --;\r
+  DEBUG ((DEBUG_INFO, "UnsignalledEventCount = %x\n", *Task->UnsignalledEventCount));\r
+\r
+  //\r
+  // Remove the SubTask from the Task list.\r
+  //\r
+  RemoveEntryList (&Task->TaskEntry);\r
+  if ((*Task->UnsignalledEventCount) == 0) {\r
+    //\r
+    // All Sub tasks are done, then signal the upper layyer event.\r
+    // Except there is error during the sub task source allocation.\r
+    //\r
+    if (!(*Task->IsError)) {\r
+      gBS->SignalEvent (Task->Token->Event);\r
+      DEBUG ((DEBUG_INFO, "Signal Up Level Event UnsignalledEventCount = %x!\n", *Task->UnsignalledEventCount));\r
+    }\r
+    \r
+    FreePool (Task->UnsignalledEventCount);\r
+    FreePool (Task->IsError);\r
+  }\r
 \r
-  return AtaDevicePassThru (AtaDevice); \r
+  DEBUG ((\r
+    DEBUG_INFO, \r
+    "PACKET INFO: Write=%s, Lenght=%x, LowCylinder=%x, HighCylinder=%x,SectionNumber=%x",\r
+    Task->Packet.OutDataBuffer != NULL ? L"YES" : L"NO",\r
+    Task->Packet.OutDataBuffer != NULL ? Task->Packet.OutTransferLength : Task->Packet.InTransferLength,\r
+    Task->Packet.Acb->AtaCylinderLow,\r
+    Task->Packet.Acb->AtaCylinderHigh,\r
+    Task->Packet.Acb->AtaSectorCount\r
+    ));\r
+\r
+  //\r
+  // Free the buffer of SubTask.\r
+  //\r
+  FreeAtaSubTask (Task);\r
 }\r
 \r
 /**\r
@@ -460,11 +596,12 @@ TransferAtaDevice (
   ATA device. It may separate the read/write request into several ATA pass through\r
   transactions.\r
 \r
-  @param  AtaDevice         The ATA child device involved for the operation.\r
-  @param  Buffer            The pointer to the current transaction buffer.\r
-  @param  StartLba          The starting logical block address to be accessed.\r
-  @param  NumberOfBlocks    The block number or sector count of the transfer.\r
-  @param  IsWrite           Indicates whether it is a write operation.\r
+  @param[in, out]  AtaDevice       The ATA child device involved for the operation.\r
+  @param[in, out]  Buffer          The pointer to the current transaction buffer.\r
+  @param[in]       StartLba        The starting logical block address to be accessed.\r
+  @param[in]       NumberOfBlocks  The block number or sector count of the transfer.\r
+  @param[in]       IsWrite         Indicates whether it is a write operation.\r
+  @param[in, out]  Token           A pointer to the token associated with the transaction.\r
 \r
   @retval EFI_SUCCESS       The data transfer is complete successfully.\r
   @return others            Some error occurs when transferring data. \r
@@ -476,36 +613,146 @@ AccessAtaDevice(
   IN OUT UINT8                      *Buffer,\r
   IN EFI_LBA                        StartLba,\r
   IN UINTN                          NumberOfBlocks,\r
-  IN BOOLEAN                        IsWrite\r
+  IN BOOLEAN                        IsWrite,\r
+  IN OUT EFI_BLOCK_IO2_TOKEN        *Token\r
   )\r
 {\r
   EFI_STATUS                        Status;\r
   UINTN                             MaxTransferBlockNumber;\r
   UINTN                             TransferBlockNumber;\r
   UINTN                             BlockSize;\r
\r
+  UINTN                             *EventCount;\r
+  UINTN                             TempCount;\r
+  ATA_BUS_ASYN_TASK                 *Task;\r
+  EFI_EVENT                         SubEvent;\r
+  UINTN                             Index;\r
+  BOOLEAN                           *IsError;\r
+  EFI_TPL                           OldTpl;\r
+\r
+  SubEvent  = NULL;\r
+  TempCount = 0;\r
+  Status    = EFI_SUCCESS;\r
+\r
+  EventCount = AllocateZeroPool (sizeof (UINTN));\r
+  if (EventCount == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  \r
+  IsError = AllocateZeroPool (sizeof (BOOLEAN));\r
+  if (IsError == NULL) {\r
+    goto EXIT;\r
+  }\r
+  *IsError = FALSE;\r
+\r
+  //\r
+  // Initial the return status for Non Blocking.\r
+  //\r
+  if (Token != NULL && Token->Event != NULL) {\r
+    Token->TransactionStatus = EFI_SUCCESS;\r
+  }\r
   //\r
   // Ensure AtaDevice->Lba48Bit is a valid boolean value \r
   //\r
   ASSERT ((UINTN) AtaDevice->Lba48Bit < 2);\r
   MaxTransferBlockNumber = mMaxTransferBlockNumber[AtaDevice->Lba48Bit];\r
-  BlockSize = AtaDevice->BlockMedia.BlockSize;\r
+  BlockSize              = AtaDevice->BlockMedia.BlockSize;\r
+\r
+  TempCount     = (NumberOfBlocks + MaxTransferBlockNumber - 1) / MaxTransferBlockNumber;\r
+  *EventCount   = TempCount;\r
+  Index         = 0;\r
+\r
   do {\r
     if (NumberOfBlocks > MaxTransferBlockNumber) {\r
       TransferBlockNumber = MaxTransferBlockNumber;\r
-      NumberOfBlocks -= MaxTransferBlockNumber;\r
+      NumberOfBlocks     -= MaxTransferBlockNumber;\r
     } else  {\r
       TransferBlockNumber = NumberOfBlocks;\r
       NumberOfBlocks  = 0;\r
     }\r
 \r
-    Status = TransferAtaDevice (AtaDevice, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite);\r
+    //\r
+    // Create sub event for the sub Ata task. Non-Blocking Mode.\r
+    //\r
+    if (Token != NULL && Token->Event != NULL) {\r
+      OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+      Task   = AllocateZeroPool (sizeof (ATA_BUS_ASYN_TASK));\r
+      if (Task == NULL) {\r
+        //\r
+        // If resource allocation fail, reduce the total sub event counts.\r
+        //\r
+        *EventCount              = (*EventCount) - (TempCount - Index);\r
+        *IsError                 = TRUE;\r
+        Token->TransactionStatus = EFI_OUT_OF_RESOURCES;\r
+        Status                   = EFI_OUT_OF_RESOURCES;\r
+\r
+        gBS->RestoreTPL (OldTpl);\r
+        goto EXIT;\r
+      }\r
+\r
+      Task->UnsignalledEventCount = EventCount;\r
+      Task->Token                 = Token;\r
+      Task->IsError               = IsError;\r
+\r
+      InsertTailList (&AtaDevice->AtaTaskList, &Task->TaskEntry);\r
+\r
+      Status = gBS->CreateEvent (\r
+                      EVT_NOTIFY_SIGNAL,\r
+                      TPL_NOTIFY,\r
+                      AtaNonBlockingCallBack,\r
+                      Task,\r
+                      &SubEvent\r
+                      );\r
+      //\r
+      // If resource allocation fail, the un-signalled event count should equal to\r
+      // the original one minus the unassigned subtasks number.\r
+      //\r
+      if (EFI_ERROR (Status)) {\r
+        *EventCount = (*EventCount) - (TempCount - Index);\r
+        *IsError    = TRUE;\r
+        gBS->RestoreTPL (OldTpl);\r
+        goto EXIT;\r
+      }\r
+      Index++;\r
+      gBS->RestoreTPL (OldTpl); \r
+\r
+      DEBUG ((EFI_D_INFO, "NON-BLOCKING SET EVENT START: WRITE = %d\n", IsWrite));\r
+      Status = TransferAtaDevice (AtaDevice, &Task->Packet, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite, SubEvent);\r
+      DEBUG ((\r
+        EFI_D_INFO,\r
+        "NON-BLOCKING SET EVENT END:StartLba=%x, TransferBlockNumbers=%x, Status=%r\n",\r
+        StartLba,\r
+        TransferBlockNumber,\r
+        Status\r
+        ));\r
+    }else {\r
+      //\r
+      // Blocking Mode.\r
+      //\r
+      DEBUG ((EFI_D_INFO, "BLOCKING BLOCK I/O START: WRITE = %d\n", IsWrite));\r
+      Status = TransferAtaDevice (AtaDevice, NULL, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite, NULL);\r
+      DEBUG ((\r
+        EFI_D_INFO,\r
+        "BLOCKING BLOCK I/O FINISHE - StartLba = %x; TransferBlockNumbers = %x, status = %r\n", \r
+        StartLba,\r
+        TransferBlockNumber,\r
+        Status\r
+        ));\r
+    }\r
+\r
     if (EFI_ERROR (Status)) {\r
-      return Status;\r
+      goto EXIT;\r
     }\r
+\r
     StartLba += TransferBlockNumber;\r
     Buffer   += TransferBlockNumber * BlockSize;\r
   } while (NumberOfBlocks > 0);\r
 \r
+EXIT:\r
+\r
+  if (*EventCount == 0) {\r
+    FreePool (EventCount);\r
+    FreePool (IsError);\r
+  }\r
+\r
   return Status;\r
 }\r
index 98e46e9d766a612f439bf5975f1b21c7d18b29b0..13b94c307fc0201bc5a4da66e062c1da6e6975ba 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Decode an El Torito formatted CD-ROM\r
 \r
-Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 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
@@ -20,15 +20,16 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
   Install child handles if the Handle supports El Torito format.\r
 \r
   @param[in]  This        Calling context.\r
-  @param[in]  Handle      Parent Handle\r
-  @param[in]  DiskIo      Parent DiskIo interface\r
-  @param[in]  BlockIo     Parent BlockIo interface\r
+  @param[in]  Handle      Parent Handle.\r
+  @param[in]  DiskIo      Parent DiskIo interface.\r
+  @param[in]  BlockIo     Parent BlockIo interface.\r
+  @param[in]  BlockIo2    Parent BlockIo2 interface.\r
   @param[in]  DevicePath  Parent Device Path\r
 \r
 \r
-  @retval EFI_SUCCESS         Child handle(s) was added\r
-  @retval EFI_MEDIA_CHANGED   Media changed Detected\r
-  @retval other               no child handle was added\r
+  @retval EFI_SUCCESS         Child handle(s) was added.\r
+  @retval EFI_MEDIA_CHANGED   Media changed Detected.\r
+  @retval other               no child handle was added.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -37,6 +38,7 @@ PartitionInstallElToritoChildHandles (
   IN  EFI_HANDLE                   Handle,\r
   IN  EFI_DISK_IO_PROTOCOL         *DiskIo,\r
   IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,\r
+  IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,\r
   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
   )\r
 {\r
@@ -59,6 +61,7 @@ PartitionInstallElToritoChildHandles (
 \r
   Found         = EFI_NOT_FOUND;\r
   Media         = BlockIo->Media;\r
+\r
   VolSpaceSize  = 0;\r
 \r
   //\r
@@ -256,6 +259,7 @@ PartitionInstallElToritoChildHandles (
                 Handle,\r
                 DiskIo,\r
                 BlockIo,\r
+                BlockIo2,\r
                 DevicePath,\r
                 (EFI_DEVICE_PATH_PROTOCOL *) &CdDev,\r
                 Catalog->Boot.Lba,\r
index 19eb6f12c2d102c3ae14475ea1a740ec182aed16..682e8b41b5a7e93679ca0c0b8202ed29219a5627 100644 (file)
@@ -2,7 +2,7 @@
   Decode a hard disk partitioned with the GPT scheme in the UEFI 2.0\r
   specification.\r
 \r
-Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 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
@@ -16,11 +16,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "Partition.h"\r
 \r
-\r
 /**\r
   Install child handles if the Handle supports GPT partition structure.\r
 \r
-  @param[in]  BlockIo     Parent BlockIo interface\r
+  @param[in]  BlockIo     Parent BlockIo interface.\r
   @param[in]  DiskIo      Disk Io protocol.\r
   @param[in]  Lba         The starting Lba of the Partition Table\r
   @param[out] PartHeader  Stores the partition table that is read\r
@@ -37,7 +36,6 @@ PartitionValidGptTable (
   OUT EFI_PARTITION_TABLE_HEADER  *PartHeader\r
   );\r
 \r
-\r
 /**\r
   Check if the CRC field in the Partition table header is valid\r
   for Partition entry array.\r
@@ -60,11 +58,11 @@ PartitionCheckGptEntryArrayCRC (
 \r
 /**\r
   Restore Partition Table to its alternate place\r
-  (Primary -> Backup or Backup -> Primary)\r
+  (Primary -> Backup or Backup -> Primary).\r
 \r
-  @param[in]  BlockIo     Parent BlockIo interface\r
+  @param[in]  BlockIo     Parent BlockIo interface.\r
   @param[in]  DiskIo      Disk Io Protocol.\r
-  @param[in]  PartHeader  Partition table header structure\r
+  @param[in]  PartHeader  Partition table header structure.\r
 \r
   @retval TRUE      Restoring succeeds\r
   @retval FALSE     Restoring failed\r
@@ -160,15 +158,16 @@ PartitionSetCrc (
 /**\r
   Install child handles if the Handle supports GPT partition structure.\r
 \r
-  @param[in]  This       - Calling context.\r
-  @param[in]  Handle     - Parent Handle\r
-  @param[in]  DiskIo     - Parent DiskIo interface\r
-  @param[in]  BlockIo    - Parent BlockIo interface\r
-  @param[in]  DevicePath - Parent Device Path\r
+  @param[in]  This       Calling context.\r
+  @param[in]  Handle     Parent Handle.\r
+  @param[in]  DiskIo     Parent DiskIo interface.\r
+  @param[in]  BlockIo    Parent BlockIo interface.\r
+  @param[in]  BlockIo2   Parent BlockIo2 interface.\r
+  @param[in]  DevicePath Parent Device Path.\r
 \r
-  @retval EFI_SUCCESS         Valid GPT disk\r
-  @retval EFI_MEDIA_CHANGED   Media changed Detected\r
-  @retval other               Not a valid GPT disk\r
+  @retval EFI_SUCCESS           Valid GPT disk.\r
+  @retval EFI_MEDIA_CHANGED     Media changed Detected.\r
+  @retval other                 Not a valid GPT disk.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -177,6 +176,7 @@ PartitionInstallGptChildHandles (
   IN  EFI_HANDLE                   Handle,\r
   IN  EFI_DISK_IO_PROTOCOL         *DiskIo,\r
   IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,\r
+  IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,\r
   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
   )\r
 {\r
@@ -191,6 +191,7 @@ PartitionInstallGptChildHandles (
   UINTN                       Index;\r
   EFI_STATUS                  GptValidStatus;\r
   HARDDRIVE_DEVICE_PATH       HdDev;\r
+  UINT32                      MediaId;\r
 \r
   ProtectiveMbr = NULL;\r
   PrimaryHeader = NULL;\r
@@ -200,6 +201,7 @@ PartitionInstallGptChildHandles (
 \r
   BlockSize     = BlockIo->Media->BlockSize;\r
   LastBlock     = BlockIo->Media->LastBlock;\r
+  MediaId       = BlockIo->Media->MediaId;\r
 \r
   DEBUG ((EFI_D_INFO, " BlockSize : %d \n", BlockSize));\r
   DEBUG ((EFI_D_INFO, " LastBlock : %lx \n", LastBlock));\r
@@ -219,15 +221,16 @@ PartitionInstallGptChildHandles (
   //\r
   Status = DiskIo->ReadDisk (\r
                      DiskIo,\r
-                     BlockIo->Media->MediaId,\r
+                     MediaId,\r
                      0,\r
-                     BlockIo->Media->BlockSize,\r
+                     BlockSize,\r
                      ProtectiveMbr\r
                      );\r
   if (EFI_ERROR (Status)) {\r
     GptValidStatus = Status;\r
     goto Done;\r
   }\r
+\r
   //\r
   // Verify that the Protective MBR is valid\r
   //\r
@@ -302,7 +305,7 @@ PartitionInstallGptChildHandles (
 \r
   Status = DiskIo->ReadDisk (\r
                      DiskIo,\r
-                     BlockIo->Media->MediaId,\r
+                     MediaId,\r
                      MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockSize),\r
                      PrimaryHeader->NumberOfPartitionEntries * (PrimaryHeader->SizeOfPartitionEntry),\r
                      PartEntry\r
@@ -369,17 +372,18 @@ PartitionInstallGptChildHandles (
     DEBUG ((EFI_D_INFO, " End : %lx\n", MultU64x32 (PartEntry[Index].EndingLBA, BlockSize)));\r
 \r
     Status = PartitionInstallChildHandle (\r
-              This,\r
-              Handle,\r
-              DiskIo,\r
-              BlockIo,\r
-              DevicePath,\r
-              (EFI_DEVICE_PATH_PROTOCOL *) &HdDev,\r
-              PartEntry[Index].StartingLBA,\r
-              PartEntry[Index].EndingLBA,\r
-              BlockSize,\r
-              CompareGuid(&PartEntry[Index].PartitionTypeGUID, &gEfiPartTypeSystemPartGuid)\r
-              );\r
+               This,\r
+               Handle,\r
+               DiskIo,\r
+               BlockIo,\r
+               BlockIo2,\r
+               DevicePath,\r
+               (EFI_DEVICE_PATH_PROTOCOL *) &HdDev,\r
+               PartEntry[Index].StartingLBA,\r
+               PartEntry[Index].EndingLBA,\r
+               BlockSize,\r
+               CompareGuid(&PartEntry[Index].PartitionTypeGUID, &gEfiPartTypeSystemPartGuid)\r
+               );\r
   }\r
 \r
   DEBUG ((EFI_D_INFO, "Prepare to Free Pool\n"));\r
@@ -404,11 +408,10 @@ Done:
   return GptValidStatus;\r
 }\r
 \r
-\r
 /**\r
   Install child handles if the Handle supports GPT partition structure.\r
 \r
-  @param[in]  BlockIo     Parent BlockIo interface\r
+  @param[in]  BlockIo     Parent BlockIo interface.\r
   @param[in]  DiskIo      Disk Io protocol.\r
   @param[in]  Lba         The starting Lba of the Partition Table\r
   @param[out] PartHeader  Stores the partition table that is read\r
@@ -428,9 +431,10 @@ PartitionValidGptTable (
   EFI_STATUS                  Status;\r
   UINT32                      BlockSize;\r
   EFI_PARTITION_TABLE_HEADER  *PartHdr;\r
+  UINT32                      MediaId;\r
 \r
   BlockSize = BlockIo->Media->BlockSize;\r
-\r
+  MediaId   = BlockIo->Media->MediaId;\r
   PartHdr   = AllocateZeroPool (BlockSize);\r
 \r
   if (PartHdr == NULL) {\r
@@ -442,7 +446,7 @@ PartitionValidGptTable (
   //\r
   Status = DiskIo->ReadDisk (\r
                      DiskIo,\r
-                     BlockIo->Media->MediaId,\r
+                     MediaId,\r
                      MultU64x32 (Lba, BlockSize),\r
                      BlockSize,\r
                      PartHdr\r
@@ -472,12 +476,12 @@ PartitionValidGptTable (
   return TRUE;\r
 }\r
 \r
-\r
 /**\r
   Check if the CRC field in the Partition table header is valid\r
   for Partition entry array.\r
 \r
   @param[in]  BlockIo     Parent BlockIo interface\r
+  @param[in]  BlockIo2    Parent BlockIo2 interface.\r
   @param[in]  DiskIo      Disk Io Protocol.\r
   @param[in]  PartHeader  Partition table header structure\r
 \r
@@ -535,11 +539,11 @@ PartitionCheckGptEntryArrayCRC (
 \r
 /**\r
   Restore Partition Table to its alternate place\r
-  (Primary -> Backup or Backup -> Primary)\r
+  (Primary -> Backup or Backup -> Primary).\r
 \r
-  @param[in]  BlockIo     Parent BlockIo interface\r
+  @param[in]  BlockIo     Parent BlockIo interface.\r
   @param[in]  DiskIo      Disk Io Protocol.\r
-  @param[in]  PartHeader  Partition table header structure\r
+  @param[in]  PartHeader  Partition table header structure.\r
 \r
   @retval TRUE      Restoring succeeds\r
   @retval FALSE     Restoring failed\r
@@ -557,11 +561,13 @@ PartitionRestoreGptTable (
   EFI_PARTITION_TABLE_HEADER  *PartHdr;\r
   EFI_LBA                     PEntryLBA;\r
   UINT8                       *Ptr;\r
+  UINT32                      MediaId;\r
 \r
   PartHdr   = NULL;\r
   Ptr       = NULL;\r
 \r
   BlockSize = BlockIo->Media->BlockSize;\r
+  MediaId   = BlockIo->Media->MediaId;\r
 \r
   PartHdr   = AllocateZeroPool (BlockSize);\r
 \r
@@ -583,8 +589,8 @@ PartitionRestoreGptTable (
 \r
   Status = DiskIo->WriteDisk (\r
                      DiskIo,\r
-                     BlockIo->Media->MediaId,\r
-                     MultU64x32 (PartHdr->MyLBA, BlockIo->Media->BlockSize),\r
+                     MediaId,\r
+                     MultU64x32 (PartHdr->MyLBA, (UINT32) BlockSize),\r
                      BlockSize,\r
                      PartHdr\r
                      );\r
@@ -601,8 +607,8 @@ PartitionRestoreGptTable (
 \r
   Status = DiskIo->ReadDisk (\r
                     DiskIo,\r
-                    BlockIo->Media->MediaId,\r
-                    MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),\r
+                    MediaId,\r
+                    MultU64x32(PartHeader->PartitionEntryLBA, (UINT32) BlockSize),\r
                     PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,\r
                     Ptr\r
                     );\r
@@ -612,8 +618,8 @@ PartitionRestoreGptTable (
 \r
   Status = DiskIo->WriteDisk (\r
                     DiskIo,\r
-                    BlockIo->Media->MediaId,\r
-                    MultU64x32(PEntryLBA, BlockIo->Media->BlockSize),\r
+                    MediaId,\r
+                    MultU64x32(PEntryLBA, (UINT32) BlockSize),\r
                     PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,\r
                     Ptr\r
                     );\r
index 8aef497ad38049579b5404b29567bbd563c83839..4c64663746cc07adc66840c1ab09a4dd779d7d15 100644 (file)
@@ -11,7 +11,7 @@
         always on the first sector of a media. The first sector also contains\r
         the legacy boot strap code.\r
 \r
-Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 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
@@ -101,11 +101,12 @@ PartitionValidMbr (
 /**\r
   Install child handles if the Handle supports MBR format.\r
 \r
-  @param  This              Calling context.\r
-  @param  Handle            Parent Handle.\r
-  @param  DiskIo            Parent DiskIo interface.\r
-  @param  BlockIo           Parent BlockIo interface.\r
-  @param  DevicePath        Parent Device Path.\r
+  @param[in]  This              Calling context.\r
+  @param[in]  Handle            Parent Handle.\r
+  @param[in]  DiskIo            Parent DiskIo interface.\r
+  @param[in]  BlockIo           Parent BlockIo interface.\r
+  @param[in]  BlockIo2          Parent BlockIo2 interface.\r
+  @param[in]  DevicePath        Parent Device Path.\r
    \r
   @retval EFI_SUCCESS       A child handle was added.\r
   @retval EFI_MEDIA_CHANGED Media change was detected.\r
@@ -118,6 +119,7 @@ PartitionInstallMbrChildHandles (
   IN  EFI_HANDLE                   Handle,\r
   IN  EFI_DISK_IO_PROTOCOL         *DiskIo,\r
   IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,\r
+  IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,\r
   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
   )\r
 {\r
@@ -131,26 +133,33 @@ PartitionInstallMbrChildHandles (
   UINT32                    PartitionNumber;\r
   EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode;\r
   EFI_DEVICE_PATH_PROTOCOL  *LastDevicePathNode;\r
+  UINT32                    BlockSize;\r
+  UINT32                    MediaId;\r
+  EFI_LBA                   LastBlock;\r
 \r
   Found           = EFI_NOT_FOUND;\r
 \r
-  Mbr             = AllocatePool (BlockIo->Media->BlockSize);\r
+  BlockSize = BlockIo->Media->BlockSize;\r
+  MediaId   = BlockIo->Media->MediaId;\r
+  LastBlock = BlockIo->Media->LastBlock;\r
+\r
+  Mbr = AllocatePool (BlockSize);\r
   if (Mbr == NULL) {\r
     return Found;\r
   }\r
 \r
   Status = DiskIo->ReadDisk (\r
                      DiskIo,\r
-                     BlockIo->Media->MediaId,\r
+                     MediaId,\r
                      0,\r
-                     BlockIo->Media->BlockSize,\r
+                     BlockSize,\r
                      Mbr\r
                      );\r
   if (EFI_ERROR (Status)) {\r
     Found = Status;\r
     goto Done;\r
   }\r
-  if (!PartitionValidMbr (Mbr, BlockIo->Media->LastBlock)) {\r
+  if (!PartitionValidMbr (Mbr, LastBlock)) {\r
     goto Done;\r
   }\r
   //\r
@@ -218,6 +227,7 @@ PartitionInstallMbrChildHandles (
                 Handle,\r
                 DiskIo,\r
                 BlockIo,\r
+                BlockIo2,\r
                 DevicePath,\r
                 (EFI_DEVICE_PATH_PROTOCOL *) &HdDev,\r
                 HdDev.PartitionStart,\r
@@ -241,9 +251,9 @@ PartitionInstallMbrChildHandles (
 \r
       Status = DiskIo->ReadDisk (\r
                          DiskIo,\r
-                         BlockIo->Media->MediaId,\r
-                         MultU64x32 (ExtMbrStartingLba, BlockIo->Media->BlockSize),\r
-                         BlockIo->Media->BlockSize,\r
+                         MediaId,\r
+                         MultU64x32 (ExtMbrStartingLba, BlockSize),\r
+                         BlockSize,\r
                          Mbr\r
                          );\r
       if (EFI_ERROR (Status)) {\r
@@ -274,17 +284,18 @@ PartitionInstallMbrChildHandles (
       *((UINT32 *) &HdDev.Signature[0]) = 0;\r
 \r
       Status = PartitionInstallChildHandle (\r
-                This,\r
-                Handle,\r
-                DiskIo,\r
-                BlockIo,\r
-                DevicePath,\r
-                (EFI_DEVICE_PATH_PROTOCOL *) &HdDev,\r
-                HdDev.PartitionStart - ParentHdDev.PartitionStart,\r
-                HdDev.PartitionStart - ParentHdDev.PartitionStart + HdDev.PartitionSize - 1,\r
-                MBR_SIZE,\r
-                (BOOLEAN) (Mbr->Partition[0].OSIndicator == EFI_PARTITION)\r
-                );\r
+                 This,\r
+                 Handle,\r
+                 DiskIo,\r
+                 BlockIo,\r
+                 BlockIo2,\r
+                 DevicePath,\r
+                 (EFI_DEVICE_PATH_PROTOCOL *) &HdDev,\r
+                 HdDev.PartitionStart - ParentHdDev.PartitionStart,\r
+                 HdDev.PartitionStart - ParentHdDev.PartitionStart + HdDev.PartitionSize - 1,\r
+                 MBR_SIZE,\r
+                 (BOOLEAN) (Mbr->Partition[0].OSIndicator == EFI_PARTITION)\r
+                 );\r
       if (!EFI_ERROR (Status)) {\r
         Found = EFI_SUCCESS;\r
       }\r
index 3596a3bfc1c6cdf59109a0f3a17ed179dc68db85..7d194daaeab6fbd74c04b496f8e6e48e1e667d26 100644 (file)
@@ -40,16 +40,15 @@ PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {
   NULL\r
 };\r
 \r
-\r
-\r
 /**\r
   Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
-  than contains a BlockIo and DiskIo protocol can be supported.\r
+  than contains a BlockIo and DiskIo protocol or a BlockIo2 protocol can be\r
+  supported.\r
 \r
-  @param  This                Protocol instance pointer.\r
-  @param  ControllerHandle    Handle of device to test\r
-  @param  RemainingDevicePath Optional parameter use to pick a specific child\r
-                              device to start.\r
+  @param[in]  This                Protocol instance pointer.\r
+  @param[in]  ControllerHandle    Handle of device to test.\r
+  @param[in]  RemainingDevicePath Optional parameter use to pick a specific child\r
+                                  device to start.\r
 \r
   @retval EFI_SUCCESS         This driver supports this device\r
   @retval EFI_ALREADY_STARTED This driver is already running on this device\r
@@ -86,7 +85,7 @@ PartitionDriverBindingSupported (
       if (Node->DevPath.Type != MEDIA_DEVICE_PATH ||\r
         Node->DevPath.SubType != MEDIA_HARDDRIVE_DP ||\r
         DevicePathNodeLength (&Node->DevPath) != sizeof (HARDDRIVE_DEVICE_PATH)) {\r
-      return EFI_UNSUPPORTED;\r
+        return EFI_UNSUPPORTED;\r
       }\r
     }\r
   }\r
@@ -105,7 +104,6 @@ PartitionDriverBindingSupported (
   if (Status == EFI_ALREADY_STARTED) {\r
     return EFI_SUCCESS;\r
   }\r
-\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -159,20 +157,39 @@ PartitionDriverBindingSupported (
                   ControllerHandle,\r
                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
                   );\r
-\r
-  return Status;\r
+ if (EFI_ERROR (Status)) {\r
+   return Status;\r
+ }\r
+  \r
+ Status = gBS->OpenProtocol (\r
+                 ControllerHandle,\r
+                 &gEfiBlockIo2ProtocolGuid,\r
+                 NULL,\r
+                 This->DriverBindingHandle,\r
+                 ControllerHandle,\r
+                 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                 );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // According to UEFI Spec 2.3.1, if a driver is written for a disk device, \r
+    // then the EFI_BLOCK_IO_PROTOCOL and EFI_BLOCK_IO2_PROTOCOAL must be implemented.\r
+    // Currently, SCSI disk driver only produce the EFI_BLOCK_IO_PROTOCOL, it will\r
+    // not be updated until the non blocking SCSI Pass Thru Protocol is provided.\r
+    // If there is no EFI_BLOCK_IO2_PROTOCOL, skip here.\r
+    //    \r
+  } \r
+  return EFI_SUCCESS;  \r
 }\r
 \r
-\r
 /**\r
-  Start this driver on ControllerHandle by opening a Block IO and Disk IO\r
-  protocol, reading Device Path, and creating a child handle with a\r
-  Disk IO and device path protocol.\r
+  Start this driver on ControllerHandle by opening a Block IO or a Block IO2\r
+  or both, and Disk IO protocol, reading Device Path, and creating a child\r
+  handle with a Disk IO and device path protocol.\r
 \r
-  @param  This                 Protocol instance pointer.\r
-  @param  ControllerHandle     Handle of device to bind driver to\r
-  @param  RemainingDevicePath  Optional parameter use to pick a specific child\r
-                               device to start.\r
+  @param[in]  This                 Protocol instance pointer.\r
+  @param[in]  ControllerHandle     Handle of device to bind driver to\r
+  @param[in]  RemainingDevicePath  Optional parameter use to pick a specific child\r
+                                   device to start.\r
 \r
   @retval EFI_SUCCESS          This driver is added to ControllerHandle\r
   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle\r
@@ -190,6 +207,7 @@ PartitionDriverBindingStart (
   EFI_STATUS                Status;\r
   EFI_STATUS                OpenStatus;\r
   EFI_BLOCK_IO_PROTOCOL     *BlockIo;\r
+  EFI_BLOCK_IO2_PROTOCOL    *BlockIo2;\r
   EFI_DISK_IO_PROTOCOL      *DiskIo;\r
   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;\r
   PARTITION_DETECT_ROUTINE  *Routine;\r
@@ -211,6 +229,10 @@ PartitionDriverBindingStart (
     }\r
   }\r
 \r
+  //\r
+  // Try to open BlockIO and BlockIO2. If BlockIO would be opened, continue,\r
+  // otherwise, return error.\r
+  //\r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
                   &gEfiBlockIoProtocolGuid,\r
@@ -222,8 +244,27 @@ PartitionDriverBindingStart (
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiBlockIo2ProtocolGuid,\r
+                  (VOID **) &BlockIo2,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // According to UEFI Spec 2.3.1, if a driver is written for a disk device, \r
+    // then the EFI_BLOCK_IO_PROTOCOL and EFI_BLOCK_IO2_PROTOCOAL must be implemented.\r
+    // Currently, SCSI disk driver only produce the EFI_BLOCK_IO_PROTOCOL, it will\r
+    // not be updated until the non blocking SCSI Pass Thru Protocol is provided.\r
+    // If there is no EFI_BLOCK_IO2_PROTOCOL, skip here.\r
+    //\r
+  }\r
+\r
   //\r
-  // Get the Device Path Protocol on ControllerHandle's handle\r
+  // Get the Device Path Protocol on ControllerHandle's handle.\r
   //\r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
@@ -276,6 +317,7 @@ PartitionDriverBindingStart (
                    ControllerHandle,\r
                    DiskIo,\r
                    BlockIo,\r
+                   BlockIo2,\r
                    ParentDevicePath\r
                    );\r
       if (!EFI_ERROR (Status) || Status == EFI_MEDIA_CHANGED || Status == EFI_NO_MEDIA) {\r
@@ -306,6 +348,15 @@ PartitionDriverBindingStart (
           This->DriverBindingHandle,\r
           ControllerHandle\r
           );\r
+    //\r
+    // Close Parent BlockIO2 if has.\r
+    //    \r
+    gBS->CloseProtocol (\r
+           ControllerHandle,\r
+           &gEfiBlockIo2ProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           ControllerHandle\r
+           );\r
 \r
     gBS->CloseProtocol (\r
           ControllerHandle,\r
@@ -320,7 +371,6 @@ Exit:
   return Status;\r
 }\r
 \r
-\r
 /**\r
   Stop this driver on ControllerHandle. Support stopping any child handles\r
   created by this driver.\r
@@ -347,10 +397,15 @@ PartitionDriverBindingStop (
   EFI_STATUS              Status;\r
   UINTN                   Index;\r
   EFI_BLOCK_IO_PROTOCOL   *BlockIo;\r
+  EFI_BLOCK_IO2_PROTOCOL  *BlockIo2;\r
   BOOLEAN                 AllChildrenStopped;\r
   PARTITION_PRIVATE_DATA  *Private;\r
   EFI_DISK_IO_PROTOCOL    *DiskIo;\r
 \r
+  BlockIo  = NULL;\r
+  BlockIo2 = NULL;\r
+  Private = NULL;\r
+\r
   if (NumberOfChildren == 0) {\r
     //\r
     // Close the bus driver\r
@@ -361,6 +416,15 @@ PartitionDriverBindingStop (
           This->DriverBindingHandle,\r
           ControllerHandle\r
           );\r
+    //\r
+    // Close Parent BlockIO2 if has.\r
+    //    \r
+    gBS->CloseProtocol (\r
+           ControllerHandle,\r
+           &gEfiBlockIo2ProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           ControllerHandle\r
+           );\r
 \r
     gBS->CloseProtocol (\r
           ControllerHandle,\r
@@ -368,60 +432,91 @@ PartitionDriverBindingStop (
           This->DriverBindingHandle,\r
           ControllerHandle\r
           );\r
-\r
     return EFI_SUCCESS;\r
   }\r
 \r
   AllChildrenStopped = TRUE;\r
   for (Index = 0; Index < NumberOfChildren; Index++) {\r
-    Status = gBS->OpenProtocol (\r
-                    ChildHandleBuffer[Index],\r
-                    &gEfiBlockIoProtocolGuid,\r
-                    (VOID **) &BlockIo,\r
-                    This->DriverBindingHandle,\r
-                    ControllerHandle,\r
-                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                    );\r
-    if (!EFI_ERROR (Status)) {\r
-\r
+    gBS->OpenProtocol (\r
+           ChildHandleBuffer[Index],\r
+           &gEfiBlockIoProtocolGuid,\r
+           (VOID **) &BlockIo,\r
+           This->DriverBindingHandle,\r
+           ControllerHandle,\r
+           EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+           );\r
+    //\r
+    // Try to locate BlockIo2.\r
+    //\r
+    gBS->OpenProtocol (\r
+           ChildHandleBuffer[Index],\r
+           &gEfiBlockIo2ProtocolGuid,\r
+           (VOID **) &BlockIo2,\r
+           This->DriverBindingHandle,\r
+           ControllerHandle,\r
+           EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+           ); \r
+\r
+    if (BlockIo != NULL) {\r
       Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);\r
+    } else if (BlockIo2 != NULL) {\r
+      Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (BlockIo2);\r
+    } else {\r
+      ASSERT (FALSE);\r
+    }\r
 \r
-      //\r
-      // All Software protocols have be freed from the handle so remove it.\r
-      //\r
+    Status = gBS->CloseProtocol (\r
+                    ControllerHandle,\r
+                    &gEfiDiskIoProtocolGuid,\r
+                    This->DriverBindingHandle,\r
+                    ChildHandleBuffer[Index]\r
+                    );\r
+    //\r
+    // All Software protocols have be freed from the handle so remove it.\r
+    // Remove the BlockIo Protocol if has.\r
+    // Remove the BlockIo2 Protocol if has.\r
+    //\r
+    if (BlockIo2 != NULL) {\r
       BlockIo->FlushBlocks (BlockIo);\r
-\r
-      Status = gBS->CloseProtocol (\r
-                      ControllerHandle,\r
-                      &gEfiDiskIoProtocolGuid,\r
-                      This->DriverBindingHandle,\r
-                      ChildHandleBuffer[Index]\r
-                      );\r
-\r
+      BlockIo2->FlushBlocksEx (BlockIo2, NULL);\r
       Status = gBS->UninstallMultipleProtocolInterfaces (\r
-                      ChildHandleBuffer[Index],\r
-                      &gEfiDevicePathProtocolGuid,\r
-                      Private->DevicePath,\r
-                      &gEfiBlockIoProtocolGuid,\r
-                      &Private->BlockIo,\r
-                      Private->EspGuid,\r
-                      NULL,\r
-                      NULL\r
-                      );\r
-      if (EFI_ERROR (Status)) {\r
-        gBS->OpenProtocol (\r
-              ControllerHandle,\r
-              &gEfiDiskIoProtocolGuid,\r
-              (VOID **) &DiskIo,\r
-              This->DriverBindingHandle,\r
-              ChildHandleBuffer[Index],\r
-              EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
-              );\r
-      } else {\r
-        FreePool (Private->DevicePath);\r
-        FreePool (Private);\r
-      }\r
+                       ChildHandleBuffer[Index],\r
+                       &gEfiDevicePathProtocolGuid,\r
+                       Private->DevicePath,\r
+                       &gEfiBlockIoProtocolGuid,\r
+                       &Private->BlockIo,\r
+                       &gEfiBlockIo2ProtocolGuid,\r
+                       &Private->BlockIo2,\r
+                       Private->EspGuid,\r
+                       NULL,\r
+                       NULL\r
+                       );\r
+    } else {\r
+      BlockIo->FlushBlocks (BlockIo);\r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                       ChildHandleBuffer[Index],\r
+                       &gEfiDevicePathProtocolGuid,\r
+                       Private->DevicePath,\r
+                       &gEfiBlockIoProtocolGuid,\r
+                       &Private->BlockIo,\r
+                       Private->EspGuid,\r
+                       NULL,\r
+                       NULL\r
+                       );\r
+    }\r
 \r
+    if (EFI_ERROR (Status)) {\r
+      gBS->OpenProtocol (\r
+             ControllerHandle,\r
+             &gEfiDiskIoProtocolGuid,\r
+             (VOID **) &DiskIo,\r
+             This->DriverBindingHandle,\r
+             ChildHandleBuffer[Index],\r
+             EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+             );\r
+    } else {\r
+      FreePool (Private->DevicePath);\r
+      FreePool (Private);\r
     }\r
 \r
     if (EFI_ERROR (Status)) {\r
@@ -551,11 +646,11 @@ PartitionReadBlocks (
   Write by using the Disk IO protocol on the parent device. Lba addresses\r
   must be converted to byte offsets.\r
 \r
-  @param  This       Protocol instance pointer.\r
-  @param  MediaId    Id of the media, changes every time the media is replaced.\r
-  @param  Lba        The starting Logical Block Address to read from\r
-  @param  BufferSize Size of Buffer, must be a multiple of device block size.\r
-  @param  Buffer     Buffer containing read data\r
+  @param[in]  This       Protocol instance pointer.\r
+  @param[in]  MediaId    Id of the media, changes every time the media is replaced.\r
+  @param[in]  Lba        The starting Logical Block Address to read from\r
+  @param[in]  BufferSize Size of Buffer, must be a multiple of device block size.\r
+  @param[in]  Buffer     Buffer containing data to be written to device.\r
 \r
   @retval EFI_SUCCESS           The data was written correctly to the device.\r
   @retval EFI_WRITE_PROTECTED   The device can not be written to.\r
@@ -574,7 +669,7 @@ PartitionWriteBlocks (
   IN UINT32                 MediaId,\r
   IN EFI_LBA                Lba,\r
   IN UINTN                  BufferSize,\r
-  OUT VOID                  *Buffer\r
+  IN VOID                  *Buffer\r
   )\r
 {\r
   PARTITION_PRIVATE_DATA  *Private;\r
@@ -622,25 +717,261 @@ PartitionFlushBlocks (
   return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);\r
 }\r
 \r
+/**\r
+  Reset the Block Device throught Block I/O2 protocol.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  ExtendedVerification Driver may perform diagnostics on reset.\r
+\r
+  @retval EFI_SUCCESS          The device was reset.\r
+  @retval EFI_DEVICE_ERROR     The device is not functioning properly and could\r
+                               not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PartitionResetEx (\r
+  IN EFI_BLOCK_IO2_PROTOCOL *This,\r
+  IN BOOLEAN                ExtendedVerification\r
+  )\r
+{\r
+  PARTITION_PRIVATE_DATA  *Private;\r
+\r
+  Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);\r
+\r
+  return Private->ParentBlockIo2->Reset (\r
+                                    Private->ParentBlockIo2,\r
+                                    ExtendedVerification\r
+                                    );\r
+}\r
+\r
+/**\r
+  Read BufferSize bytes from Lba into Buffer.\r
+  \r
+  This function reads the requested number of blocks from the device. All the\r
+  blocks are read, or an error is returned.\r
+  If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and\r
+  non-blocking I/O is being used, the Event associated with this request will\r
+  not be signaled.\r
+\r
+  @param[in]       This       Indicates a pointer to the calling context.\r
+  @param[in]       MediaId    Id of the media, changes every time the media is \r
+                              replaced.\r
+  @param[in]       Lba        The starting Logical Block Address to read from.\r
+  @param[in, out]  Token           A pointer to the token associated with the transaction.\r
+  @param[in]       BufferSize Size of Buffer, must be a multiple of device block size.  \r
+  @param[out]      Buffer     A pointer to the destination buffer for the data. The \r
+                              caller is responsible for either having implicit or \r
+                              explicit ownership of the buffer.\r
+\r
+  @retval EFI_SUCCESS           The read request was queued if Token->Event is\r
+                                not NULL.The data was read correctly from the\r
+                                device if the Token->Event is NULL.\r
+  @retval EFI_DEVICE_ERROR      The device reported an error while performing\r
+                                the read.\r
+  @retval EFI_NO_MEDIA          There is no media in the device.\r
+  @retval EFI_MEDIA_CHANGED     The MediaId is not for the current media.\r
+  @retval EFI_BAD_BUFFER_SIZE   The BufferSize parameter is not a multiple of the\r
+                                intrinsic block size of the device.\r
+  @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
+                                or the buffer is not on proper alignment.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack\r
+                                of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PartitionReadBlocksEx (\r
+  IN     EFI_BLOCK_IO2_PROTOCOL *This,\r
+  IN     UINT32                 MediaId,\r
+  IN     EFI_LBA                Lba,\r
+  IN OUT EFI_BLOCK_IO2_TOKEN    *Token,\r
+  IN     UINTN                  BufferSize,\r
+  OUT    VOID                   *Buffer\r
+  )\r
+{\r
+  PARTITION_PRIVATE_DATA  *Private;\r
+  UINT64                  Offset;\r
+  UINT32                  UnderRun;\r
+\r
+  if (Token == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);\r
+  if (BufferSize % Private->BlockSize != 0) {\r
+    return EFI_BAD_BUFFER_SIZE;\r
+  }\r
+\r
+  Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
+  if (Offset + BufferSize > Private->End) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Since the BlockIO2 call Parent BlockIO2 directly, so here the offset must\r
+  // be multiple of BlockSize. If the Spec will be updated the DiskIO to support\r
+  // BlockIO2, this limitation will be removed and call DiskIO here.\r
+  //\r
+  Lba = DivU64x32Remainder (Offset, Private->BlockSize, &UnderRun);\r
+  if (UnderRun != 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Because some partitions have different block size from their parent\r
+  // device, in that case the Block I/O2 couldn't be called.\r
+  //\r
+  if (Private->BlockSize != Private->ParentBlockIo->Media->BlockSize) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return Private->ParentBlockIo2->ReadBlocksEx (Private->ParentBlockIo2, MediaId, Lba, Token, BufferSize, Buffer);\r
+}\r
+\r
+/**\r
+  Write BufferSize bytes from Lba into Buffer.\r
+\r
+  This function writes the requested number of blocks to the device. All blocks\r
+  are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,\r
+  EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is\r
+  being used, the Event associated with this request will not be signaled.\r
+\r
+  @param[in]       This       Indicates a pointer to the calling context.\r
+  @param[in]       MediaId    The media ID that the write request is for.\r
+  @param[in]       Lba        The starting logical block address to be written. The\r
+                              caller is responsible for writing to only legitimate\r
+                              locations.\r
+  @param[in, out]  Token      A pointer to the token associated with the transaction.\r
+  @param[in]       BufferSize Size of Buffer, must be a multiple of device block size.\r
+  @param[in]       Buffer     A pointer to the source buffer for the data.\r
+\r
+  @retval EFI_SUCCESS           The write request was queued if Event is not NULL.\r
+                                The data was written correctly to the device if\r
+                                the Event is NULL.\r
+  @retval EFI_WRITE_PROTECTED   The device can not be written to.\r
+  @retval EFI_NO_MEDIA          There is no media in the device.\r
+  @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.\r
+  @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.\r
+  @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.\r
+  @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
+                                or the buffer is not on proper alignment.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack\r
+                                of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PartitionWriteBlocksEx (\r
+  IN     EFI_BLOCK_IO2_PROTOCOL *This,\r
+  IN     UINT32                 MediaId,\r
+  IN     EFI_LBA                Lba,\r
+  IN OUT EFI_BLOCK_IO2_TOKEN    *Token,\r
+  IN     UINTN                  BufferSize,\r
+  IN     VOID                   *Buffer\r
+  )\r
+{\r
+  PARTITION_PRIVATE_DATA  *Private;\r
+  UINT64                  Offset;\r
+  UINT32                  UnderRun;\r
+\r
+  if (Token == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);\r
+  if (BufferSize % Private->BlockSize != 0) {\r
+    return EFI_BAD_BUFFER_SIZE;\r
+  }\r
+\r
+  Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;\r
+  if (Offset + BufferSize > Private->End) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Since the BlockIO2 call Parent BlockIO2 directly, so here the offset must\r
+  // be multiple of BlockSize. If the Spec will be updated the DiskIO to support\r
+  // BlockIO2, this limitation will be removed and call DiskIO here.\r
+  //\r
+  Lba = DivU64x32Remainder (Offset, Private->BlockSize, &UnderRun);\r
+  if (UnderRun != 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Because some kinds of partition have different block size from their parent,\r
+  // in that case it couldn't call parent Block I/O2. \r
+  //\r
+  if (Private->BlockSize != Private->ParentBlockIo->Media->BlockSize) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return Private->ParentBlockIo2->WriteBlocksEx (Private->ParentBlockIo2, MediaId, Lba, Token, BufferSize, Buffer);\r
+}\r
+\r
+/**\r
+  Flush the Block Device.\r
\r
+  If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED\r
+  is returned and non-blocking I/O is being used, the Event associated with\r
+  this request will not be signaled.  \r
+\r
+  @param[in]      This     Indicates a pointer to the calling context.\r
+  @param[in,out]  Token    A pointer to the token associated with the transaction\r
+\r
+  @retval EFI_SUCCESS          The flush request was queued if Event is not NULL.\r
+                               All outstanding data was written correctly to the\r
+                               device if the Event is NULL.\r
+  @retval EFI_DEVICE_ERROR     The device reported an error while writting back\r
+                               the data.\r
+  @retval EFI_WRITE_PROTECTED  The device cannot be written to.\r
+  @retval EFI_NO_MEDIA         There is no media in the device.\r
+  @retval EFI_MEDIA_CHANGED    The MediaId is not for the current media.\r
+  @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
+                               of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PartitionFlushBlocksEx (\r
+  IN     EFI_BLOCK_IO2_PROTOCOL *This,\r
+  IN OUT EFI_BLOCK_IO2_TOKEN    *Token\r
+  )\r
+{\r
+  PARTITION_PRIVATE_DATA  *Private;\r
+\r
+  Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);\r
+\r
+  //\r
+  // Because some kinds of partition have different block size from their parent,\r
+  // in that case it couldn't call parent Block I/O2. \r
+  //\r
+  if (Private->BlockSize != Private->ParentBlockIo->Media->BlockSize) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return Private->ParentBlockIo2->FlushBlocksEx (Private->ParentBlockIo2, Token);\r
+}\r
 \r
 \r
 /**\r
   Create a child handle for a logical block device that represents the\r
   bytes Start to End of the Parent Block IO device.\r
 \r
-  @param[in]  This              Protocol instance pointer\r
-  @param[in]  ParentHandle      Parent Handle for new child\r
-  @param[in]  ParentDiskIo      Parent DiskIo interface\r
-  @param[in]  ParentBlockIo     Parent BlockIo interface\r
-  @param[in]  ParentDevicePath  Parent Device Path\r
-  @param[in]  DevicePathNode    Child Device Path node\r
-  @param[in]  Start             Start Block\r
-  @param[in]  End               End Block\r
-  @param[in]  BlockSize         Child block size\r
-  @param[in]  InstallEspGuid    Flag to install EFI System Partition GUID on handle\r
-\r
-  @retval EFI_SUCCESS       A child handle was added\r
-  @retval other             A child handle was not added\r
+  @param[in]  This              Protocol instance pointer.\r
+  @param[in]  ParentHandle      Parent Handle for new child.\r
+  @param[in]  ParentDiskIo      Parent DiskIo interface.\r
+  @param[in]  ParentBlockIo     Parent BlockIo interface.\r
+  @param[in]  ParentBlockIo2    Parent BlockIo2 interface.\r
+  @param[in]  ParentDevicePath  Parent Device Path.\r
+  @param[in]  DevicePathNode    Child Device Path node.\r
+  @param[in]  Start             Start Block.\r
+  @param[in]  End               End Block.\r
+  @param[in]  BlockSize         Child block size.\r
+  @param[in]  InstallEspGuid    Flag to install EFI System Partition GUID on handle.\r
+\r
+  @retval EFI_SUCCESS       A child handle was added.\r
+  @retval other             A child handle was not added.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -649,6 +980,7 @@ PartitionInstallChildHandle (
   IN  EFI_HANDLE                   ParentHandle,\r
   IN  EFI_DISK_IO_PROTOCOL         *ParentDiskIo,\r
   IN  EFI_BLOCK_IO_PROTOCOL        *ParentBlockIo,\r
+  IN  EFI_BLOCK_IO2_PROTOCOL       *ParentBlockIo2,\r
   IN  EFI_DEVICE_PATH_PROTOCOL     *ParentDevicePath,\r
   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,\r
   IN  EFI_LBA                      Start,\r
@@ -660,6 +992,7 @@ PartitionInstallChildHandle (
   EFI_STATUS              Status;\r
   PARTITION_PRIVATE_DATA  *Private;\r
 \r
+  Status  = EFI_SUCCESS;\r
   Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));\r
   if (Private == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -672,28 +1005,51 @@ PartitionInstallChildHandle (
 \r
   Private->BlockSize        = BlockSize;\r
   Private->ParentBlockIo    = ParentBlockIo;\r
+  Private->ParentBlockIo2   = ParentBlockIo2;\r
   Private->DiskIo           = ParentDiskIo;\r
 \r
-  Private->BlockIo.Revision = ParentBlockIo->Revision;\r
+  if (Private->ParentBlockIo != NULL) {\r
+    Private->BlockIo.Revision = ParentBlockIo->Revision;\r
 \r
-  Private->BlockIo.Media    = &Private->Media;\r
-  CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));\r
-  Private->Media.LogicalPartition = TRUE;\r
+    Private->BlockIo.Media    = &Private->Media;\r
+    CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));\r
+\r
+\r
+    Private->BlockIo.Reset        = PartitionReset;\r
+    Private->BlockIo.ReadBlocks   = PartitionReadBlocks;\r
+    Private->BlockIo.WriteBlocks  = PartitionWriteBlocks;\r
+    Private->BlockIo.FlushBlocks  = PartitionFlushBlocks;\r
+  }\r
+\r
+  if (Private->ParentBlockIo2 != NULL) {\r
+    Private->BlockIo2.Media    = &Private->Media2;\r
+    CopyMem (Private->BlockIo2.Media, ParentBlockIo2->Media, sizeof (EFI_BLOCK_IO_MEDIA));\r
+\r
+    Private->BlockIo2.Reset          = PartitionResetEx;\r
+    Private->BlockIo2.ReadBlocksEx   = PartitionReadBlocksEx;\r
+    Private->BlockIo2.WriteBlocksEx  = PartitionWriteBlocksEx;\r
+    Private->BlockIo2.FlushBlocksEx  = PartitionFlushBlocksEx; \r
+  }\r
 \r
-  //\r
-  // Logical BlockIo instance doesn't have IoAlign restriction because it implements block io operation based on DiskIo\r
-  //\r
   Private->Media.IoAlign   = 0;\r
+  Private->Media.LogicalPartition = TRUE;\r
   Private->Media.LastBlock = DivU64x32 (\r
                                MultU64x32 (\r
                                  End - Start + 1,\r
-                                 ParentBlockIo->Media->BlockSize\r
+                                 (ParentBlockIo != NULL) ? ParentBlockIo->Media->BlockSize : ParentBlockIo2->Media->BlockSize\r
                                  ),\r
-                               BlockSize\r
+                                BlockSize\r
                                ) - 1;\r
 \r
   Private->Media.BlockSize = (UINT32) BlockSize;\r
 \r
+  //\r
+  // For BlockIO2, it should keep the same alignment with the parent BlockIO2's.\r
+  //\r
+  Private->Media2.LogicalPartition = TRUE;\r
+  Private->Media2.LastBlock = Private->Media.LastBlock;\r
+  Private->Media2.BlockSize = (UINT32) BlockSize;\r
+\r
   //\r
   // Per UEFI Spec, LowestAlignedLba and LogicalBlocksPerPhysicalBlock must be 0\r
   //  for logical partitions.\r
@@ -703,12 +1059,7 @@ PartitionInstallChildHandle (
     Private->BlockIo.Media->LogicalBlocksPerPhysicalBlock = 0;\r
   }\r
 \r
-  Private->BlockIo.Reset        = PartitionReset;\r
-  Private->BlockIo.ReadBlocks   = PartitionReadBlocks;\r
-  Private->BlockIo.WriteBlocks  = PartitionWriteBlocks;\r
-  Private->BlockIo.FlushBlocks  = PartitionFlushBlocks;\r
-\r
-  Private->DevicePath           = AppendDevicePathNode (ParentDevicePath, DevicePathNode);\r
+  Private->DevicePath     = AppendDevicePathNode (ParentDevicePath, DevicePathNode);\r
 \r
   if (Private->DevicePath == NULL) {\r
     FreePool (Private);\r
@@ -723,20 +1074,61 @@ PartitionInstallChildHandle (
     //\r
     Private->EspGuid = NULL;\r
   }\r
+\r
   //\r
-  // Create the new handle\r
+  // Create the new handle. \r
+  // BlockIO2 will be installed on the condition that the blocksize of parent BlockIO \r
+  // is same with the child BlockIO's. Instead of calling the DiskIO, the child BlockIO2 \r
+  // directly call the parent BlockIO and doesn't handle the different block size issue.\r
+  // If SPEC will update the DiskIO to support the Non-Blocking model, the BlockIO2 will call\r
+  // DiskIO to handle the blocksize unequal issue and the limitation will be remove from\r
+  // here.\r
   //\r
   Private->Handle = NULL;\r
-  Status = gBS->InstallMultipleProtocolInterfaces (\r
-                  &Private->Handle,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  Private->DevicePath,\r
-                  &gEfiBlockIoProtocolGuid,\r
-                  &Private->BlockIo,\r
-                  Private->EspGuid,\r
-                  NULL,\r
-                  NULL\r
-                  );\r
+  if ((Private->ParentBlockIo != NULL) &&\r
+      (Private->ParentBlockIo2 != NULL) &&\r
+      (Private->ParentBlockIo2->Media->BlockSize == BlockSize)\r
+     ) {\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                    &Private->Handle,\r
+                    &gEfiDevicePathProtocolGuid,\r
+                    Private->DevicePath,\r
+                    &gEfiBlockIoProtocolGuid,\r
+                    &Private->BlockIo,\r
+                    &gEfiBlockIo2ProtocolGuid,\r
+                    &Private->BlockIo2,\r
+                    Private->EspGuid,\r
+                    NULL,\r
+                    NULL\r
+                    );\r
+  } else {\r
+    if (Private->ParentBlockIo != NULL) {\r
+      Status = gBS->InstallMultipleProtocolInterfaces (\r
+                      &Private->Handle,\r
+                      &gEfiDevicePathProtocolGuid,\r
+                      Private->DevicePath,\r
+                      &gEfiBlockIoProtocolGuid,\r
+                      &Private->BlockIo,\r
+                      Private->EspGuid,\r
+                      NULL,\r
+                      NULL\r
+                      );\r
+    }\r
+    if (Private->ParentBlockIo2 != NULL && \r
+        Private->ParentBlockIo2->Media->BlockSize == BlockSize\r
+       ) {\r
+      Status = gBS->InstallMultipleProtocolInterfaces (\r
+                      &Private->Handle,\r
+                      &gEfiDevicePathProtocolGuid,\r
+                      Private->DevicePath,\r
+                      &gEfiBlockIo2ProtocolGuid,\r
+                      &Private->BlockIo2,\r
+                      Private->EspGuid,\r
+                      NULL,\r
+                      NULL\r
+                      );\r
+    }\r
+  }\r
 \r
   if (!EFI_ERROR (Status)) {\r
     //\r
index 9fca9f360ee6ec7a03cbdf013137b99b261cbfe1..7a4ca8a3192f85200040acb89306c9c15a9e24db 100644 (file)
@@ -4,7 +4,7 @@
   of the raw block devices media. Currently "El Torito CD-ROM", Legacy \r
   MBR, and GPT partition schemes are supported.\r
 \r
-Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 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
@@ -20,6 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include <Uefi.h>\r
 #include <Protocol/BlockIo.h>\r
+#include <Protocol/BlockIo2.h>\r
 #include <Guid/Gpt.h>\r
 #include <Protocol/ComponentName.h>\r
 #include <Protocol/DevicePath.h>\r
@@ -48,10 +49,13 @@ typedef struct {
   EFI_HANDLE                Handle;\r
   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
   EFI_BLOCK_IO_PROTOCOL     BlockIo;\r
+  EFI_BLOCK_IO2_PROTOCOL    BlockIo2;\r
   EFI_BLOCK_IO_MEDIA        Media;\r
+  EFI_BLOCK_IO_MEDIA        Media2;//For BlockIO2\r
 \r
   EFI_DISK_IO_PROTOCOL      *DiskIo;\r
   EFI_BLOCK_IO_PROTOCOL     *ParentBlockIo;\r
+  EFI_BLOCK_IO2_PROTOCOL    *ParentBlockIo2;\r
   UINT64                    Start;\r
   UINT64                    End;\r
   UINT32                    BlockSize;\r
@@ -61,6 +65,7 @@ typedef struct {
 } PARTITION_PRIVATE_DATA;\r
 \r
 #define PARTITION_DEVICE_FROM_BLOCK_IO_THIS(a)  CR (a, PARTITION_PRIVATE_DATA, BlockIo, PARTITION_PRIVATE_DATA_SIGNATURE)\r
+#define PARTITION_DEVICE_FROM_BLOCK_IO2_THIS(a) CR (a, PARTITION_PRIVATE_DATA, BlockIo2, PARTITION_PRIVATE_DATA_SIGNATURE)\r
 \r
 //\r
 // Global Variables\r
@@ -300,19 +305,20 @@ PartitionComponentNameGetControllerName (
   Create a child handle for a logical block device that represents the\r
   bytes Start to End of the Parent Block IO device.\r
 \r
-  @param[in]  This              Protocol instance pointer\r
-  @param[in]  ParentHandle      Parent Handle for new child\r
-  @param[in]  ParentDiskIo      Parent DiskIo interface\r
-  @param[in]  ParentBlockIo     Parent BlockIo interface\r
-  @param[in]  ParentDevicePath  Parent Device Path\r
-  @param[in]  DevicePathNode    Child Device Path node\r
-  @param[in]  Start             Start Block\r
-  @param[in]  End               End Block\r
-  @param[in]  BlockSize         Child block size\r
-  @param[in]  InstallEspGuid    Flag to install EFI System Partition GUID on handle\r
+  @param[in]  This              Protocol instance pointer.\r
+  @param[in]  ParentHandle      Parent Handle for new child.\r
+  @param[in]  ParentDiskIo      Parent DiskIo interface.\r
+  @param[in]  ParentBlockIo     Parent BlockIo interface.\r
+  @param[in]  ParentBlockIo2    Parent BlockIo2 interface.\r
+  @param[in]  ParentDevicePath  Parent Device Path.\r
+  @param[in]  DevicePathNode    Child Device Path node.\r
+  @param[in]  Start             Start Block.\r
+  @param[in]  End               End Block.\r
+  @param[in]  BlockSize         Child block size.\r
+  @param[in]  InstallEspGuid    Flag to install EFI System Partition GUID on handle.\r
 \r
-  @retval EFI_SUCCESS       A child handle was added\r
-  @retval other             A child handle was not added\r
+  @retval EFI_SUCCESS       A child handle was added.\r
+  @retval other             A child handle was not added.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -321,6 +327,7 @@ PartitionInstallChildHandle (
   IN  EFI_HANDLE                   ParentHandle,\r
   IN  EFI_DISK_IO_PROTOCOL         *ParentDiskIo,\r
   IN  EFI_BLOCK_IO_PROTOCOL        *ParentBlockIo,\r
+  IN  EFI_BLOCK_IO2_PROTOCOL       *ParentBlockIo2,\r
   IN  EFI_DEVICE_PATH_PROTOCOL     *ParentDevicePath,\r
   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode,\r
   IN  EFI_LBA                      Start,\r
@@ -332,15 +339,17 @@ PartitionInstallChildHandle (
 /**\r
   Install child handles if the Handle supports GPT partition structure.\r
 \r
-  @param[in]  This       - Calling context.\r
-  @param[in]  Handle     - Parent Handle\r
-  @param[in]  DiskIo     - Parent DiskIo interface\r
-  @param[in]  BlockIo    - Parent BlockIo interface\r
-  @param[in]  DevicePath - Parent Device Path\r
+  @param[in]  This       Calling context.\r
+  @param[in]  Handle     Parent Handle.\r
+  @param[in]  DiskIo     Parent DiskIo interface.\r
+  @param[in]  BlockIo    Parent BlockIo interface.\r
+  @param[in]  BlockIo2   Parent BlockIo2 interface.\r
+  @param[in]  DevicePath Parent Device Path.\r
 \r
-  @retval EFI_SUCCESS         Valid GPT disk\r
-  @retval EFI_MEDIA_CHANGED   Media changed Detected\r
-  @retval other               Not a valid GPT disk\r
+  @retval EFI_SUCCESS           Valid GPT disk.\r
+  @retval EFI_MEDIA_CHANGED     Media changed Detected.\r
+  @retval EFI_INVALID_PARAMETER If both BlockIo and BlockIo2 are NULL;\r
+  @retval other                 Not a valid GPT disk.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -349,6 +358,7 @@ PartitionInstallGptChildHandles (
   IN  EFI_HANDLE                   Handle,\r
   IN  EFI_DISK_IO_PROTOCOL         *DiskIo,\r
   IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,\r
+  IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,\r
   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
   );\r
 \r
@@ -356,15 +366,16 @@ PartitionInstallGptChildHandles (
   Install child handles if the Handle supports El Torito format.\r
 \r
   @param[in]  This        Calling context.\r
-  @param[in]  Handle      Parent Handle\r
-  @param[in]  DiskIo      Parent DiskIo interface\r
-  @param[in]  BlockIo     Parent BlockIo interface\r
+  @param[in]  Handle      Parent Handle.\r
+  @param[in]  DiskIo      Parent DiskIo interface.\r
+  @param[in]  BlockIo     Parent BlockIo interface.\r
+  @param[in]  BlockIo2    Parent BlockIo2 interface.\r
   @param[in]  DevicePath  Parent Device Path\r
 \r
 \r
-  @retval EFI_SUCCESS         Child handle(s) was added\r
-  @retval EFI_MEDIA_CHANGED   Media changed Detected\r
-  @retval other               no child handle was added\r
+  @retval EFI_SUCCESS         Child handle(s) was added.\r
+  @retval EFI_MEDIA_CHANGED   Media changed Detected.\r
+  @retval other               no child handle was added.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -373,17 +384,19 @@ PartitionInstallElToritoChildHandles (
   IN  EFI_HANDLE                   Handle,\r
   IN  EFI_DISK_IO_PROTOCOL         *DiskIo,\r
   IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,\r
+  IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,\r
   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
   );\r
 \r
 /**\r
   Install child handles if the Handle supports MBR format.\r
 \r
-  @param  This              Calling context.\r
-  @param  Handle            Parent Handle.\r
-  @param  DiskIo            Parent DiskIo interface.\r
-  @param  BlockIo           Parent BlockIo interface.\r
-  @param  DevicePath        Parent Device Path.\r
+  @param[in]  This              Calling context.\r
+  @param[in]  Handle            Parent Handle.\r
+  @param[in]  DiskIo            Parent DiskIo interface.\r
+  @param[in]  BlockIo           Parent BlockIo interface.\r
+  @param[in]  BlockIo2          Parent BlockIo2 interface.\r
+  @param[in]  DevicePath        Parent Device Path.\r
    \r
   @retval EFI_SUCCESS       A child handle was added.\r
   @retval EFI_MEDIA_CHANGED Media change was detected.\r
@@ -396,6 +409,7 @@ PartitionInstallMbrChildHandles (
   IN  EFI_HANDLE                   Handle,\r
   IN  EFI_DISK_IO_PROTOCOL         *DiskIo,\r
   IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,\r
+  IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,\r
   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
   );\r
 \r
@@ -406,6 +420,7 @@ EFI_STATUS
   IN  EFI_HANDLE                   Handle,\r
   IN  EFI_DISK_IO_PROTOCOL         *DiskIo,\r
   IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,\r
+  IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,\r
   IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
   );\r
 \r
index 45a0e0d73b8cc379355f55b3b06c39b5322fa9e1..cf5090fb7ce08bebd4be67b58b26e313b6cf7141 100644 (file)
@@ -7,7 +7,7 @@
 #  The partition of physical BlockIo device supported is one of legacy MBR, GPT,\r
 #  and "El Torito" partitions.\r
 #  \r
-#  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2006 - 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
@@ -70,5 +70,6 @@
   gEfiDevicePathProtocolGuid                    ## BY_START\r
   gEfiDiskIoProtocolGuid                        ## BY_START\r
   gEfiBlockIoProtocolGuid                       ## TO_START\r
+  gEfiBlockIo2ProtocolGuid                      ## TO_START\r
   gEfiDevicePathProtocolGuid                    ## TO_START\r
   gEfiDiskIoProtocolGuid                        ## TO_START\r
index c6c6e67a132fb79ccfab9628ab10c720f9b18a39..231fd1af9569e8295fef5654193bff0cd14adfb1 100644 (file)
   ## Include/Protocol/BlockIo.h\r
   gEfiBlockIoProtocolGuid        = { 0x964E5B21, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}\r
 \r
+  ## Include/Protocol/BlockIo2.h\r
+  gEfiBlockIo2ProtocolGuid       = { 0xa77b2472, 0xe282, 0x4e9f, {0xa2, 0x45, 0xc2, 0xc0, 0xe2, 0x7b, 0xbc, 0xc1 }}\r
+\r
   ## Include/Protocol/UnicodeCollation.h\r
   gEfiUnicodeCollationProtocolGuid = { 0x1D85CD7F, 0xF43D, 0x11D2, { 0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}\r
 \r