]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/AtapiPassThruDxe/AtapiPassThru.c
1. Set the Target array to zero before fill the target id.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / AtapiPassThruDxe / AtapiPassThru.c
index f14d9e34820fe3a3eb3e04be88f25924b9ac6d3b..b6dceeb83a91d8890cf4ed5bf63cac2abb947402 100644 (file)
 \r
 #include "AtapiPassThru.h"\r
 \r
-///\r
-/// IDE registers' fixed address\r
-///\r
-static IDE_BASE_REGISTERS   gAtapiIoPortRegisters[2] = {\r
-  { 0x1f0, { 0x1f1 }, 0x1f2, 0x1f3, 0x1f4, 0x1f5, 0x1f6, { 0x1f7 }, { 0x3f6 }, 0x3f7, 0 },\r
-  { 0x170, { 0x171 }, 0x172, 0x173, 0x174, 0x175, 0x176, { 0x177 }, { 0x376 }, 0x377, 0 } \r
-};\r
 \r
 static SCSI_COMMAND_SET     gEndTable = { 0xff, (DATA_DIRECTION) 0xff };\r
 \r
@@ -97,6 +90,7 @@ AtapiScsiPassThruDriverBindingSupported (
   EFI_PCI_IO_PROTOCOL *PciIo;\r
   PCI_TYPE00          Pci;\r
 \r
+\r
   //\r
   // Open the IO Abstraction(s) needed to perform the supported test\r
   //\r
@@ -125,11 +119,11 @@ AtapiScsiPassThruDriverBindingSupported (
                         );\r
   if (EFI_ERROR (Status)) {\r
     gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiPciIoProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
+           Controller,\r
+           &gEfiPciIoProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
@@ -139,11 +133,11 @@ AtapiScsiPassThruDriverBindingSupported (
   }\r
 \r
   gBS->CloseProtocol (\r
-        Controller,\r
-        &gEfiPciIoProtocolGuid,\r
-        This->DriverBindingHandle,\r
-        Controller\r
-        );\r
+         Controller,\r
+         &gEfiPciIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
 \r
   return Status;\r
 }\r
@@ -169,7 +163,9 @@ AtapiScsiPassThruDriverBindingStart (
   )\r
 {\r
   EFI_STATUS          Status;\r
+  EFI_STATUS          DisableStatus;\r
   EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT64              Supports;\r
 \r
   PciIo = NULL;\r
   Status = gBS->OpenProtocol (\r
@@ -186,10 +182,21 @@ AtapiScsiPassThruDriverBindingStart (
 \r
   Status = PciIo->Attributes (\r
                     PciIo,\r
-                    EfiPciIoAttributeOperationEnable,\r
-                    EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE,\r
-                    NULL\r
+                    EfiPciIoAttributeOperationSupported,\r
+                    0,\r
+                    &Supports\r
                     );\r
+  if (!EFI_ERROR (Status)) {\r
+    Supports &= (EFI_PCI_DEVICE_ENABLE               |\r
+                 EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO |\r
+                 EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO);\r
+    Status = PciIo->Attributes (\r
+                      PciIo,\r
+                      EfiPciIoAttributeOperationEnable,\r
+                      Supports,\r
+                      NULL\r
+                      );\r
+  }\r
   if (EFI_ERROR (Status)) {\r
     goto Done;\r
   }\r
@@ -202,20 +209,31 @@ AtapiScsiPassThruDriverBindingStart (
 Done:\r
   if (EFI_ERROR (Status)) {\r
     if (PciIo) {\r
-      PciIo->Attributes (\r
-              PciIo,\r
-              EfiPciIoAttributeOperationDisable,\r
-              EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE,\r
-              NULL\r
-              );\r
+      DisableStatus = PciIo->Attributes (\r
+                               PciIo,\r
+                               EfiPciIoAttributeOperationSupported,\r
+                               0,\r
+                               &Supports\r
+                               );\r
+      if (!EFI_ERROR (DisableStatus)) {\r
+        Supports &= (EFI_PCI_DEVICE_ENABLE               |\r
+                     EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO |\r
+                     EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO);\r
+        DisableStatus = PciIo->Attributes (\r
+                                 PciIo,\r
+                                 EfiPciIoAttributeOperationDisable,\r
+                                 Supports,\r
+                                 NULL\r
+                                 );\r
+      }\r
     }\r
 \r
     gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiPciIoProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
+           Controller,\r
+           &gEfiPciIoProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
   }\r
 \r
   return Status;\r
@@ -246,6 +264,7 @@ AtapiScsiPassThruDriverBindingStop (
   EFI_STATUS                  Status;\r
   EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru;\r
   ATAPI_SCSI_PASS_THRU_DEV    *AtapiScsiPrivate;\r
+  UINT64                      Supports;\r
 \r
   Status = gBS->OpenProtocol (\r
                   Controller,\r
@@ -272,19 +291,30 @@ AtapiScsiPassThruDriverBindingStop (
   //\r
   // Release Pci Io protocol on the controller handle.\r
   //\r
-  AtapiScsiPrivate->PciIo->Attributes (\r
-                            AtapiScsiPrivate->PciIo,\r
-                            EfiPciIoAttributeOperationDisable,\r
-                            EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE,\r
-                            NULL\r
-                            );\r
+  Status = AtapiScsiPrivate->PciIo->Attributes (\r
+                                      AtapiScsiPrivate->PciIo,\r
+                                      EfiPciIoAttributeOperationSupported,\r
+                                      0,\r
+                                      &Supports\r
+                                      );\r
+  if (!EFI_ERROR (Status)) {\r
+    Supports &= (EFI_PCI_DEVICE_ENABLE               |\r
+                 EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO |\r
+                 EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO);\r
+    Status = AtapiScsiPrivate->PciIo->Attributes (\r
+                                        AtapiScsiPrivate->PciIo,\r
+                                        EfiPciIoAttributeOperationDisable,\r
+                                        Supports,\r
+                                        NULL\r
+                                        );\r
+  }\r
 \r
   gBS->CloseProtocol (\r
-        Controller,\r
-        &gEfiPciIoProtocolGuid,\r
-        This->DriverBindingHandle,\r
-        Controller\r
-        );\r
+         Controller,\r
+         &gEfiPciIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
 \r
   gBS->FreePool (AtapiScsiPrivate);\r
 \r
@@ -313,20 +343,36 @@ RegisterAtapiScsiPassThru (
 {\r
   EFI_STATUS                Status;\r
   ATAPI_SCSI_PASS_THRU_DEV  *AtapiScsiPrivate;\r
-  UINT64                    Attributes;\r
+  UINT64                    Supports;\r
+  IDE_REGISTERS_BASE_ADDR   IdeRegsBaseAddr[ATAPI_MAX_CHANNEL];\r
 \r
   AtapiScsiPrivate = AllocateZeroPool (sizeof (ATAPI_SCSI_PASS_THRU_DEV));\r
   if (AtapiScsiPrivate == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  Attributes = EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE;\r
   CopyMem (AtapiScsiPrivate->ChannelName, gAtapiChannelString, sizeof (gAtapiChannelString));\r
 \r
   //\r
   // Enable channel\r
   //\r
-  PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSet, Attributes, NULL);\r
+  Status = PciIo->Attributes (\r
+                    PciIo,\r
+                    EfiPciIoAttributeOperationSupported,\r
+                    0,\r
+                    &Supports\r
+                    );\r
+  if (!EFI_ERROR (Status)) {\r
+    Supports &= (EFI_PCI_DEVICE_ENABLE               |\r
+                 EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO |\r
+                 EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO);\r
+    Status = PciIo->Attributes (\r
+                      PciIo,\r
+                      EfiPciIoAttributeOperationEnable,\r
+                      Supports,\r
+                      NULL\r
+                      );\r
+  }\r
 \r
   AtapiScsiPrivate->Signature = ATAPI_SCSI_PASS_THRU_DEV_SIGNATURE;\r
   AtapiScsiPrivate->Handle    = Controller;\r
@@ -334,10 +380,19 @@ RegisterAtapiScsiPassThru (
   //\r
   // will reset the IoPort inside each API function.\r
   //\r
-  AtapiScsiPrivate->IoPort  = gAtapiIoPortRegisters;\r
+  AtapiScsiPrivate->IoPort  = NULL;\r
   AtapiScsiPrivate->PciIo   = PciIo;\r
 \r
   //\r
+  // Obtain IDE IO port registers' base addresses\r
+  //\r
+  Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  InitAtapiIoPortRegisters(AtapiScsiPrivate, IdeRegsBaseAddr);\r
+\r
   // initialize SCSI Pass Thru Protocol interface\r
   //\r
   AtapiScsiPrivate->ScsiPassThru.Mode             = &AtapiScsiPrivate->ScsiPassThruMode;\r
@@ -364,9 +419,9 @@ RegisterAtapiScsiPassThru (
   AtapiScsiPrivate->ScsiPassThruMode.IoAlign = 0;\r
 \r
   //\r
-  // Initialize the LatestTargetId to 0xFFFFFFFF (for the GetNextDevice() call).\r
+  // Initialize the LatestTargetId.\r
   //\r
-  AtapiScsiPrivate->LatestTargetId  = 0xFFFFFFFF;\r
+  AtapiScsiPrivate->LatestTargetId  = 4;\r
   AtapiScsiPrivate->LatestLun       = 0;\r
 \r
   Status = gBS->InstallProtocolInterface (\r
@@ -411,15 +466,15 @@ AtapiScsiPassThruFunction (
   IN EFI_EVENT                                          Event OPTIONAL\r
   )\r
 {\r
-  ATAPI_SCSI_PASS_THRU_DEV  *AtapiScsiPrivate;\r
-  EFI_STATUS                Status;\r
+  ATAPI_SCSI_PASS_THRU_DEV               *AtapiScsiPrivate;\r
+  EFI_STATUS                             Status;\r
 \r
   AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This);\r
 \r
   //\r
   // Target is not allowed beyond MAX_TARGET_ID\r
   //\r
-  if (Target > MAX_TARGET_ID) {\r
+  if ((Target > MAX_TARGET_ID) || (Lun != 0)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   \r
@@ -442,13 +497,15 @@ AtapiScsiPassThruFunction (
   \r
   //\r
   // According to Target ID, reset the Atapi I/O Register mapping\r
-  // (Target Id in [0,1] area, using gAtapiIoPortRegisters[0],\r
-  //  Target Id in [2,3] area, using gAtapiIoPortRegisters[1]\r
+  // (Target Id in [0,1] area, using AtapiIoPortRegisters[0],\r
+  //  Target Id in [2,3] area, using AtapiIoPortRegisters[1]\r
   //\r
   if ((Target / 2) == 0) {\r
-    AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[0];\r
+    Target = Target % 2;\r
+    AtapiScsiPrivate->IoPort = &AtapiScsiPrivate->AtapiIoPortRegisters[0];\r
   } else {\r
-    AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[1];\r
+    Target = Target % 2;\r
+    AtapiScsiPrivate->IoPort = &AtapiScsiPrivate->AtapiIoPortRegisters[1];\r
   }\r
   \r
   //\r
@@ -572,6 +629,7 @@ AtapiScsiPassThruBuildDevicePath (
 {\r
   EFI_DEV_PATH              *Node;\r
 \r
+\r
   //\r
   // Validate parameters passed in.\r
   //\r
@@ -691,8 +749,10 @@ AtapiScsiPassThruResetChannel (
   UINT8                     DeviceControlValue;\r
   ATAPI_SCSI_PASS_THRU_DEV  *AtapiScsiPrivate;\r
   UINT8                     Index;\r
+  BOOLEAN                   ResetFlag;\r
 \r
   AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This);\r
+  ResetFlag = FALSE;\r
 \r
   //\r
   // Reset both Primary channel and Secondary channel.\r
@@ -702,7 +762,7 @@ AtapiScsiPassThruResetChannel (
     //\r
     // Reset\r
     //\r
-    AtapiScsiPrivate->IoPort  = &gAtapiIoPortRegisters[Index];\r
+    AtapiScsiPrivate->IoPort  = &AtapiScsiPrivate->AtapiIoPortRegisters[Index];\r
 \r
     DeviceControlValue        = 0;\r
     //\r
@@ -735,12 +795,16 @@ AtapiScsiPassThruResetChannel (
     //\r
     // slave device needs at most 31s to clear BSY\r
     //\r
-    if (StatusWaitForBSYClear (AtapiScsiPrivate, 31000) == EFI_TIMEOUT) {\r
-      return EFI_DEVICE_ERROR;\r
+    if (StatusWaitForBSYClear (AtapiScsiPrivate, 31000000) != EFI_TIMEOUT) {\r
+      ResetFlag = TRUE;\r
     }\r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  if (ResetFlag) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  \r
+  return EFI_TIMEOUT;\r
 }\r
 \r
 /**\r
@@ -776,7 +840,7 @@ AtapiScsiPassThruResetTarget (
 \r
   AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This);\r
 \r
-  if (Target > MAX_TARGET_ID) {\r
+  if ((Target > MAX_TARGET_ID) || (Lun != 0)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   //\r
@@ -788,13 +852,13 @@ AtapiScsiPassThruResetTarget (
   \r
   //\r
   // According to Target ID, reset the Atapi I/O Register mapping\r
-  // (Target Id in [0,1] area, using gAtapiIoPortRegisters[0],\r
-  //  Target Id in [2,3] area, using gAtapiIoPortRegisters[1]\r
+  // (Target Id in [0,1] area, using AtapiIoPortRegisters[0],\r
+  //  Target Id in [2,3] area, using AtapiIoPortRegisters[1]\r
   //\r
   if ((Target / 2) == 0) {\r
-    AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[0];\r
+    AtapiScsiPrivate->IoPort = &AtapiScsiPrivate->AtapiIoPortRegisters[0];\r
   } else {\r
-    AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[1];\r
+    AtapiScsiPrivate->IoPort = &AtapiScsiPrivate->AtapiIoPortRegisters[1];\r
   }\r
   \r
   //\r
@@ -813,8 +877,8 @@ AtapiScsiPassThruResetTarget (
   // when reset is complete.\r
   // slave device needs at most 31s to clear BSY\r
   //\r
-  if (EFI_ERROR (StatusWaitForBSYClear (AtapiScsiPrivate, 31000))) {\r
-    return EFI_DEVICE_ERROR;\r
+  if (EFI_ERROR (StatusWaitForBSYClear (AtapiScsiPrivate, 31000000))) {\r
+    return EFI_TIMEOUT;\r
   }\r
   \r
   //\r
@@ -825,25 +889,159 @@ AtapiScsiPassThruResetTarget (
   return EFI_SUCCESS;\r
 }\r
 \r
+EFI_STATUS\r
+GetIdeRegistersBaseAddr (\r
+  IN  EFI_PCI_IO_PROTOCOL         *PciIo,\r
+  OUT IDE_REGISTERS_BASE_ADDR     *IdeRegsBaseAddr\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode,\r
+  use fixed addresses. In Native-PCI mode, get base addresses from BARs in\r
+  the PCI IDE controller's Configuration Space.\r
+\r
+Arguments:\r
+  PciIo             - Pointer to the EFI_PCI_IO_PROTOCOL instance\r
+  IdeRegsBaseAddr   - Pointer to IDE_REGISTERS_BASE_ADDR to \r
+                      receive IDE IO port registers' base addresses\r
+                      \r
+Returns:\r
+\r
+  EFI_STATUS\r
     \r
-/**\r
-  Checks the parameters in the SCSI Request Packet to make sure\r
-  they are valid for a SCSI Pass Thru request.\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  PCI_TYPE00  PciData;\r
 \r
-  @todo function comment is missing 'Routine Description:'\r
-  @todo function comment is missing 'Arguments:'\r
-  @todo function comment is missing 'Returns:'\r
-  @todo    Packet - add argument and description to function comment\r
-  @todo    EFI_INVALID_PARAMETER - add return value to function comment\r
-  @todo    EFI_INVALID_PARAMETER - add return value to function comment\r
-  @todo    EFI_INVALID_PARAMETER - add return value to function comment\r
-  @todo    EFI_UNSUPPORTED - add return value to function comment\r
-  @todo    EFI_SUCCESS - add return value to function comment\r
-**/\r
+  Status = PciIo->Pci.Read (\r
+                        PciIo,\r
+                        EfiPciIoWidthUint8,\r
+                        0,\r
+                        sizeof (PciData),\r
+                        &PciData\r
+                        );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if ((PciData.Hdr.ClassCode[0] & IDE_PRIMARY_OPERATING_MODE) == 0) {\r
+    IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr  = 0x1f0;\r
+    IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr  = 0x3f6;\r
+  } else {\r
+    //\r
+    // The BARs should be of IO type\r
+    //\r
+    if ((PciData.Device.Bar[0] & BIT0) == 0 || \r
+        (PciData.Device.Bar[1] & BIT0) == 0) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr  =\r
+    (UINT16) (PciData.Device.Bar[0] & 0x0000fff8);\r
+    IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr  =\r
+    (UINT16) ((PciData.Device.Bar[1] & 0x0000fffc) + 2);\r
+  }\r
+\r
+  if ((PciData.Hdr.ClassCode[0] & IDE_SECONDARY_OPERATING_MODE) == 0) {\r
+    IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr  = 0x170;\r
+    IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr  = 0x376;\r
+  } else {\r
+    //\r
+    // The BARs should be of IO type\r
+    //\r
+    if ((PciData.Device.Bar[2] & BIT0) == 0 ||\r
+        (PciData.Device.Bar[3] & BIT0) == 0) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr  =\r
+    (UINT16) (PciData.Device.Bar[2] & 0x0000fff8);\r
+    IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr  =\r
+    (UINT16) ((PciData.Device.Bar[3] & 0x0000fffc) + 2);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+InitAtapiIoPortRegisters (\r
+  IN  ATAPI_SCSI_PASS_THRU_DEV     *AtapiScsiPrivate,\r
+  IN  IDE_REGISTERS_BASE_ADDR      *IdeRegsBaseAddr\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initialize each Channel's Base Address of CommandBlock and ControlBlock.\r
+\r
+Arguments:\r
+    \r
+  AtapiScsiPrivate            - The pointer of ATAPI_SCSI_PASS_THRU_DEV\r
+  IdeRegsBaseAddr             - The pointer of IDE_REGISTERS_BASE_ADDR\r
+  \r
+Returns:\r
+  \r
+  None\r
+\r
+--*/  \r
+{\r
+  \r
+  UINT8               IdeChannel;\r
+  UINT16              CommandBlockBaseAddr;\r
+  UINT16              ControlBlockBaseAddr;\r
+  IDE_BASE_REGISTERS  *RegisterPointer;\r
+\r
+  \r
+  for (IdeChannel = 0; IdeChannel < ATAPI_MAX_CHANNEL; IdeChannel++) {\r
+\r
+    RegisterPointer =  &AtapiScsiPrivate->AtapiIoPortRegisters[IdeChannel];\r
+\r
+    //\r
+    // Initialize IDE IO port addresses, including Command Block registers\r
+    // and Control Block registers\r
+    //\r
+    CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr;\r
+    ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr;\r
+  \r
+    RegisterPointer->Data = CommandBlockBaseAddr;\r
+    (*(UINT16 *) &RegisterPointer->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);\r
+    RegisterPointer->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);\r
+    RegisterPointer->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);\r
+    RegisterPointer->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);\r
+    RegisterPointer->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);\r
+    RegisterPointer->Head = (UINT16) (CommandBlockBaseAddr + 0x06);\r
+    (*(UINT16 *) &RegisterPointer->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);\r
+  \r
+    (*(UINT16 *) &RegisterPointer->Alt) = ControlBlockBaseAddr;\r
+    RegisterPointer->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);\r
+  }\r
+\r
+}\r
+\r
+    \r
 EFI_STATUS\r
 CheckSCSIRequestPacket (\r
   EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET      *Packet\r
   )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Checks the parameters in the SCSI Request Packet to make sure\r
+  they are valid for a SCSI Pass Thru request.\r
+\r
+Arguments:\r
+\r
+  Packet         -  The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET   \r
+\r
+Returns:\r
+\r
+  EFI_STATUS\r
+\r
+--*/\r
 {\r
   if (Packet == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -971,11 +1169,23 @@ SubmitBlockingIoCommand (
     Packet->SenseDataLength = 0;\r
     return PacketCommandStatus;\r
   }\r
+  \r
+  //\r
+  // Check if SenseData meets the alignment requirement.\r
+  //\r
+  if ((AtapiScsiPrivate->ScsiPassThru.Mode->IoAlign != 0)     \\r
+    && (AtapiScsiPrivate->ScsiPassThru.Mode->IoAlign != 1)) {\r
+    if (((UINTN)Packet->SenseData % AtapiScsiPrivate->ScsiPassThru.Mode->IoAlign) != 0) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+\r
+  \r
   //\r
   // Return SenseData if PacketCommandStatus matches\r
   // the following return codes.\r
   //\r
-  if ((PacketCommandStatus == EFI_WARN_BUFFER_TOO_SMALL) ||\r
+  if ((PacketCommandStatus ==  EFI_BAD_BUFFER_SIZE) ||\r
       (PacketCommandStatus == EFI_DEVICE_ERROR) ||\r
       (PacketCommandStatus == EFI_TIMEOUT)) {\r
     \r
@@ -1096,18 +1306,25 @@ AtapiPacketCommand (
   EFI_STATUS  Status;\r
 \r
   //\r
-  // Set all the command parameters by fill related registers.\r
-  // Before write to all the following registers, BSY and DRQ must be 0.\r
+  // Check if the buffer meets the alignment requirement.\r
   //\r
-  Status = StatusDRQClear (AtapiScsiPrivate, TimeoutInMicroSeconds);\r
-  if (EFI_ERROR (Status)) {\r
-    if (Status == EFI_ABORTED) {\r
-      Status = EFI_DEVICE_ERROR;\r
+  if ((AtapiScsiPrivate->ScsiPassThru.Mode->IoAlign != 0)     \\r
+    && (AtapiScsiPrivate->ScsiPassThru.Mode->IoAlign != 1)) {\r
+    if (((UINTN)Buffer % AtapiScsiPrivate->ScsiPassThru.Mode->IoAlign) != 0) {\r
+      return EFI_INVALID_PARAMETER;\r
     }\r
+  }\r
 \r
-    *ByteCount = 0;\r
-    return Status;\r
+  //\r
+  // Set all the command parameters by fill related registers.\r
+  // Before write to all the following registers, BSY must be 0.\r
+  //\r
+  Status = StatusWaitForBSYClear (AtapiScsiPrivate, TimeoutInMicroSeconds);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
   }\r
+\r
+\r
   //\r
   // Select device via Device/Head Register.\r
   // "Target = 0" indicates device 0; "Target = 1" indicates device 1\r
@@ -1118,6 +1335,20 @@ AtapiPacketCommand (
     (UINT8) ((Target << 4) | DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000)\r
     );\r
 \r
+  //\r
+  // Set all the command parameters by fill related registers.\r
+  // Before write to all the following registers, BSY DRQ must be 0.\r
+  //\r
+   Status =  StatusDRQClear(AtapiScsiPrivate,  TimeoutInMicroSeconds);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    if (Status == EFI_ABORTED) {\r
+      Status = EFI_DEVICE_ERROR;\r
+    }\r
+    *ByteCount = 0;\r
+    return Status;\r
+  }\r
+\r
   //\r
   // No OVL; No DMA (by setting feature register)\r
   //\r
@@ -1282,7 +1513,7 @@ AtapiPassThruPioReadWriteData (
       // ActualWordCount > 0\r
       //\r
       if (ActualWordCount < RequiredWordCount) {\r
-        return EFI_WARN_BUFFER_TOO_SMALL;\r
+        return EFI_BAD_BUFFER_SIZE;\r
       }\r
     }\r
     //\r