]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c
In IdeBus driver block I/O read/write interface, it will always try to use UDMA mode...
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / IdeBus / Dxe / ide.c
index 5a65995c26aad90c526322ece951f3696cc95754..4b4a8ef0a355cfe798d31b2dfba5eba993bd3f28 100644 (file)
 \r
 #include "idebus.h"\r
 \r
-BOOLEAN SlaveDeviceExist  = FALSE;\r
-BOOLEAN MasterDeviceExist = FALSE;\r
+BOOLEAN ChannelDeviceDetected = FALSE;\r
+BOOLEAN SlaveDeviceExist      = FALSE;\r
+UINT8   SlaveDeviceType       = INVALID_DEVICE_TYPE;\r
+BOOLEAN MasterDeviceExist     = FALSE;\r
+UINT8   MasterDeviceType      = INVALID_DEVICE_TYPE;\r
 \r
 /**\r
   TODO: Add function description\r
@@ -225,70 +228,6 @@ IDEWritePortWMultiple (
   gBS->FreePool (WorkingBuffer);\r
 }\r
 \r
-/**\r
-  TODO: Add function description\r
-\r
-  @param  IdeDev TODO: add argument description\r
-\r
-  TODO: add return values\r
-\r
-**/\r
-BOOLEAN\r
-BadIdeDeviceCheck (\r
-  IN IDE_BLK_IO_DEV *IdeDev\r
-  )\r
-{\r
-  //\r
-  //  check whether all registers return 0xff,\r
-  //  if so, deem the channel is disabled.\r
-  //\r
-#ifdef EFI_DEBUG\r
-\r
-  if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Data) != 0xff) {\r
-    return FALSE;\r
-  }\r
-\r
-  if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature) != 0xff) {\r
-    return FALSE;\r
-  }\r
-\r
-  if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount) != 0xff) {\r
-    return FALSE;\r
-  }\r
-\r
-  if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber) != 0xff) {\r
-    return FALSE;\r
-  }\r
-\r
-  if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb) != 0xff) {\r
-    return FALSE;\r
-  }\r
-\r
-  if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb) != 0xff) {\r
-    return FALSE;\r
-  }\r
-\r
-  if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Head) != 0xff) {\r
-    return FALSE;\r
-  }\r
-\r
-  if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command) != 0xff) {\r
-    return FALSE;\r
-  }\r
-\r
-  if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus) != 0xff) {\r
-    return FALSE;\r
-  }\r
-\r
-  return TRUE;\r
-\r
-#else\r
-\r
-  return FALSE;\r
-\r
-#endif\r
-}\r
-\r
 //\r
 // GetIdeRegistersBaseAddr\r
 //\r
@@ -464,57 +403,6 @@ ReassignIdeResources (
   return EFI_SUCCESS;\r
 }\r
 \r
-/**\r
-  Read SATA registers to detect SATA disks\r
-\r
-  @param  IdeDev The BLK_IO private data which specifies the IDE device\r
-\r
-**/\r
-EFI_STATUS\r
-CheckPowerMode (\r
-  IDE_BLK_IO_DEV    *IdeDev\r
-  )\r
-// TODO:    EFI_NOT_FOUND - add return value to function comment\r
-// TODO:    EFI_SUCCESS - add return value to function comment\r
-// TODO:    EFI_NOT_FOUND - add return value to function comment\r
-{\r
-  UINT8       ErrorRegister;\r
-  EFI_STATUS  Status;\r
-\r
-  IDEWritePortB (\r
-    IdeDev->PciIo,\r
-    IdeDev->IoPort->Head,\r
-    (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
-    );\r
-\r
-  //\r
-  // Wait 31 seconds for BSY clear. BSY should be in clear state if there exists\r
-  // a device (initial state). Normally, BSY is also in clear state if there is\r
-  // no device\r
-  //\r
-  Status = WaitForBSYClear (IdeDev, 31000);\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  //\r
-  // select device, read error register\r
-  //\r
-  IDEWritePortB (\r
-    IdeDev->PciIo,\r
-    IdeDev->IoPort->Head,\r
-    (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
-    );\r
-  Status        = DRDYReady (IdeDev, 200);\r
-\r
-  ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
-  if ((ErrorRegister == 0x01) || (ErrorRegister == 0x81)) {\r
-    return EFI_SUCCESS;\r
-  } else {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-}\r
-\r
 //\r
 // DiscoverIdeDevice\r
 //\r
@@ -533,44 +421,67 @@ DiscoverIdeDevice (
 // TODO:    EFI_SUCCESS - add return value to function comment\r
 {\r
   EFI_STATUS  Status;\r
-  BOOLEAN     SataFlag;\r
-\r
-  SataFlag = FALSE;\r
-  //\r
-  // This extra detection is for SATA disks\r
-  //\r
-  Status = CheckPowerMode (IdeDev);\r
-  if (Status == EFI_SUCCESS) {\r
-    SataFlag = TRUE;\r
-  }\r
 \r
   //\r
   // If a channel has not been checked, check it now. Then set it to "checked" state\r
   // After this step, all devices in this channel have been checked.\r
   //\r
-  Status = DetectIDEController (IdeDev);\r
-\r
-  if ((EFI_ERROR (Status)) && !SataFlag) {\r
-    return EFI_NOT_FOUND;\r
+  if (ChannelDeviceDetected == FALSE) {\r
+    Status = DetectIDEController (IdeDev);\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
   }\r
 \r
+  Status = EFI_NOT_FOUND;\r
+\r
   //\r
-  // Device exists. test if it is an ATA device\r
+  // Device exists. test if it is an ATA device.\r
+  // Prefer the result from DetectIDEController,\r
+  // if failed, try another device type to handle\r
+  // devices that not follow the spec.\r
   //\r
-  Status = ATAIdentify (IdeDev);\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // if not ATA device, test if it is an ATAPI device\r
-    //\r
-    Status = ATAPIIdentify (IdeDev);\r
-    if (EFI_ERROR (Status)) {\r
-      //\r
-      // if not ATAPI device either, return error.\r
-      //\r
-      return EFI_NOT_FOUND;\r
+  if ((IdeDev->Device == IdeMaster) && (MasterDeviceExist)) {\r
+    if (MasterDeviceType == ATA_DEVICE_TYPE) {\r
+      Status = ATAIdentify (IdeDev);\r
+      if (EFI_ERROR (Status)) {\r
+        Status = ATAPIIdentify (IdeDev);\r
+        if (!EFI_ERROR (Status)) {\r
+          MasterDeviceType = ATAPI_DEVICE_TYPE;\r
+        }\r
+      }\r
+    } else {\r
+      Status = ATAPIIdentify (IdeDev);\r
+      if (EFI_ERROR (Status)) {\r
+        Status = ATAIdentify (IdeDev);\r
+        if (!EFI_ERROR (Status)) {\r
+          MasterDeviceType = ATA_DEVICE_TYPE;\r
+        }\r
+      }\r
     }\r
   }\r
-\r
+  if ((IdeDev->Device == IdeSlave) && (SlaveDeviceExist)) {\r
+    if (SlaveDeviceType == ATA_DEVICE_TYPE) {\r
+      Status = ATAIdentify (IdeDev);\r
+      if (EFI_ERROR (Status)) {\r
+        Status = ATAPIIdentify (IdeDev);\r
+        if (!EFI_ERROR (Status)) {\r
+          SlaveDeviceType = ATAPI_DEVICE_TYPE;\r
+        }\r
+      }\r
+    } else {\r
+      Status = ATAPIIdentify (IdeDev);\r
+      if (EFI_ERROR (Status)) {\r
+        Status = ATAIdentify (IdeDev);\r
+        if (!EFI_ERROR (Status)) {\r
+          SlaveDeviceType = ATA_DEVICE_TYPE;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
   //\r
   // Init Block I/O interface\r
   //\r
@@ -595,6 +506,26 @@ DiscoverIdeDevice (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  This interface is used to initialize all state data related to the detection of one\r
+  channel.\r
+\r
+  @retval EFI_SUCCESS Completed Successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeIDEChannelData (\r
+  VOID\r
+  )\r
+{\r
+  ChannelDeviceDetected = FALSE;\r
+  MasterDeviceExist = FALSE;\r
+  MasterDeviceType  = 0xff;\r
+  SlaveDeviceExist  = FALSE;\r
+  SlaveDeviceType   = 0xff;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   This function is called by DiscoverIdeDevice(). It is used for detect\r
   whether the IDE device exists in the specified Channel as the specified\r
@@ -633,31 +564,12 @@ DetectIDEController (
   )\r
 {\r
   EFI_STATUS  Status;\r
-  UINT8       ErrorReg;\r
-  UINT8       StatusReg;\r
+  UINT8       SectorCountReg;\r
+  UINT8       LBALowReg;\r
+  UINT8       LBAMidReg;\r
+  UINT8       LBAHighReg;\r
   UINT8       InitStatusReg;\r
-  EFI_STATUS  DeviceStatus;\r
-\r
-  //\r
-  // Slave device has been detected with master device.\r
-  //\r
-  if ((IdeDev->Device) == 1) {\r
-    if (SlaveDeviceExist) {\r
-      //\r
-      // If master not exists but slave exists, slave have to wait a while\r
-      //\r
-      if (!MasterDeviceExist) {\r
-        //\r
-        // if single slave can't be detected, add delay 4s here.\r
-        //\r
-        gBS->Stall (4000000);\r
-      }\r
-\r
-      return EFI_SUCCESS;\r
-    } else {\r
-      return EFI_NOT_FOUND;\r
-    }\r
-  }\r
+  UINT8       StatusReg;\r
 \r
   //\r
   // Select slave device\r
@@ -675,7 +587,7 @@ DetectIDEController (
   InitStatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
 \r
   //\r
-  // Select master back\r
+  // Select Master back\r
   //\r
   IDEWritePortB (\r
     IdeDev->PciIo,\r
@@ -683,6 +595,7 @@ DetectIDEController (
     (UINT8) ((0 << 4) | 0xe0)\r
     );\r
   gBS->Stall (100);\r
+\r
   //\r
   // Send ATA Device Execut Diagnostic command.\r
   // This command should work no matter DRDY is ready or not\r
@@ -690,88 +603,124 @@ DetectIDEController (
   IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0x90);\r
 \r
   Status    = WaitForBSYClear (IdeDev, 3500);\r
-\r
-  ErrorReg  = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
-\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG((EFI_D_ERROR, "New detecting method: Send Execute Diagnostic Command: WaitForBSYClear: Status: %d\n", Status));\r
+    return Status;\r
+  }\r
   //\r
-  // Master Error register is 0x01. D0 passed, D1 passed or not present.\r
-  // Master Error register is 0x81. D0 passed, D1 failed. Return.\r
-  // Master Error register is other value. D0 failed, D1 passed or not present..\r
+  // Read device signature\r
   //\r
-  if (ErrorReg == 0x01) {\r
-    MasterDeviceExist = TRUE;\r
-    DeviceStatus      = EFI_SUCCESS;\r
-  } else if (ErrorReg == 0x81) {\r
-\r
+  //\r
+  // Select Master\r
+  //\r
+  IDEWritePortB (\r
+    IdeDev->PciIo,\r
+    IdeDev->IoPort->Head,\r
+    (UINT8) ((0 << 4) | 0xe0)\r
+    );\r
+  gBS->Stall (100);\r
+  SectorCountReg = IDEReadPortB (\r
+                     IdeDev->PciIo,\r
+                     IdeDev->IoPort->SectorCount\r
+                     );\r
+  LBALowReg      = IDEReadPortB (\r
+                     IdeDev->PciIo,\r
+                     IdeDev->IoPort->SectorNumber\r
+                     );\r
+  LBAMidReg      = IDEReadPortB (\r
+                     IdeDev->PciIo,\r
+                     IdeDev->IoPort->CylinderLsb\r
+                     );\r
+  LBAHighReg     = IDEReadPortB (\r
+                     IdeDev->PciIo,\r
+                     IdeDev->IoPort->CylinderMsb\r
+                     );\r
+  if ((SectorCountReg == 0x1) &&\r
+      (LBALowReg      == 0x1) &&\r
+      (LBAMidReg      == 0x0) &&\r
+      (LBAHighReg     == 0x0)) {\r
     MasterDeviceExist = TRUE;\r
-    DeviceStatus      = EFI_SUCCESS;\r
-    SlaveDeviceExist  = FALSE;\r
-\r
-    return DeviceStatus;\r
+    MasterDeviceType  = ATA_DEVICE_TYPE;\r
   } else {\r
-    MasterDeviceExist = FALSE;\r
-    DeviceStatus      = EFI_NOT_FOUND;\r
+    if ((LBAMidReg      == 0x14) &&\r
+        (LBAHighReg     == 0xeb)) {\r
+      MasterDeviceExist = TRUE;\r
+      MasterDeviceType  = ATAPI_DEVICE_TYPE;\r
+    }\r
   }\r
 \r
   //\r
-  // Master Error register is not 0x81, Go on check Slave\r
-  //\r
-\r
-  //\r
-  // Stall 20ms to wait for slave device ready if master device not exists\r
+  // For some Hard Drive, it takes some time to get\r
+  // the right signature when operating in single slave mode.\r
+  // We stall 20ms to work around this.\r
   //\r
   if (!MasterDeviceExist) {\r
     gBS->Stall (20000);\r
   }\r
 \r
   //\r
-  // select slave\r
+  // Select Slave\r
   //\r
   IDEWritePortB (\r
     IdeDev->PciIo,\r
     IdeDev->IoPort->Head,\r
     (UINT8) ((1 << 4) | 0xe0)\r
     );\r
-\r
-  gBS->Stall (300);\r
-  ErrorReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
-\r
-  //\r
-  // Slave Error register is not 0x01, D1 failed. Return.\r
-  //\r
-  if (ErrorReg != 0x01) {\r
-    SlaveDeviceExist = FALSE;\r
-    return DeviceStatus;\r
+  gBS->Stall (100);\r
+  SectorCountReg = IDEReadPortB (\r
+                     IdeDev->PciIo,\r
+                     IdeDev->IoPort->SectorCount\r
+                     );\r
+  LBALowReg  = IDEReadPortB (\r
+                 IdeDev->PciIo,\r
+                 IdeDev->IoPort->SectorNumber\r
+                 );\r
+  LBAMidReg  = IDEReadPortB (\r
+                 IdeDev->PciIo,\r
+                 IdeDev->IoPort->CylinderLsb\r
+                 );\r
+  LBAHighReg = IDEReadPortB (\r
+                 IdeDev->PciIo,\r
+                 IdeDev->IoPort->CylinderMsb\r
+                 );\r
+  StatusReg  = IDEReadPortB (\r
+                 IdeDev->PciIo,\r
+                 IdeDev->IoPort->Reg.Status\r
+                 );\r
+  if ((SectorCountReg == 0x1) &&\r
+      (LBALowReg      == 0x1) &&\r
+      (LBAMidReg      == 0x0) &&\r
+      (LBAHighReg     == 0x0)) {\r
+    SlaveDeviceExist = TRUE;\r
+    SlaveDeviceType  = ATA_DEVICE_TYPE;\r
+  } else {\r
+    if ((LBAMidReg     == 0x14) &&\r
+        (LBAHighReg    == 0xeb)) {\r
+      SlaveDeviceExist = TRUE;\r
+      SlaveDeviceType  = ATAPI_DEVICE_TYPE;\r
+    }\r
   }\r
 \r
-  StatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
-\r
   //\r
-  // Most ATAPI devices don't set DRDY bit, so test with a slow but accurate\r
-  //   "ATAPI TEST UNIT READY" command\r
+  // When single master is plugged, slave device\r
+  // will be wrongly detected. Here's the workaround\r
+  // for ATA devices by detecting DRY bit in status\r
+  // register.\r
+  // NOTE: This workaround doesn't apply to ATAPI.\r
   //\r
-  if (((StatusReg & DRDY) == 0) && ((InitStatusReg & DRDY) == 0)) {\r
-    Status = AtapiTestUnitReady (IdeDev);\r
-\r
-    //\r
-    // Still fail, Slave doesn't exist.\r
-    //\r
-    if (EFI_ERROR (Status)) {\r
-      SlaveDeviceExist = FALSE;\r
-      return DeviceStatus;\r
-    }\r
+  if (MasterDeviceExist && SlaveDeviceExist &&\r
+      (StatusReg & DRDY) == 0               &&\r
+      (InitStatusReg & DRDY) == 0           &&\r
+      MasterDeviceType == SlaveDeviceType   &&\r
+      SlaveDeviceType != ATAPI_DEVICE_TYPE) {\r
+    SlaveDeviceExist = FALSE;\r
   }\r
 \r
   //\r
-  // Error reg is 0x01 and DRDY is ready,\r
-  //  or ATAPI test unit ready success,\r
-  //  or  init Slave status DRDY is ready\r
-  // Slave exists.\r
+  // Indicate this channel has been detected\r
   //\r
-  SlaveDeviceExist = TRUE;\r
-\r
-  return DeviceStatus;\r
-\r
+  ChannelDeviceDetected = TRUE;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -1251,7 +1200,7 @@ DRDYReady (
       }\r
     }\r
 \r
-    gBS->Stall (15);\r
+    gBS->Stall (30);\r
 \r
     Delay--;\r
   } while (Delay);\r
@@ -1432,6 +1381,11 @@ ReleaseIdeResources (
     gBS->FreePool (IdeBlkIoDevice->DevicePath);\r
   }\r
 \r
+  if (IdeBlkIoDevice->ExitBootServiceEvent != NULL) {\r
+    gBS->CloseEvent (IdeBlkIoDevice->ExitBootServiceEvent);\r
+    IdeBlkIoDevice->ExitBootServiceEvent = NULL;\r
+  }\r
+\r
   gBS->FreePool (IdeBlkIoDevice);\r
   IdeBlkIoDevice = NULL;\r
 \r
@@ -1553,8 +1507,14 @@ AtaNonDataCommandIn (
 \r
   //\r
   // Wait for command completion\r
+  // For ATA_SMART_CMD, we may need more timeout to let device\r
+  // adjust internal states.\r
   //\r
-  Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
+  if (AtaCommand == ATA_SMART_CMD) {\r
+    Status = WaitForBSYClear (IdeDev, ATASMARTTIMEOUT);\r
+  } else {\r
+    Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
+  }\r
   if (EFI_ERROR (Status)) {\r
     return EFI_DEVICE_ERROR;\r
   }\r
@@ -1716,12 +1676,11 @@ SetDriveParameters (
   //\r
   // Send Init drive parameters\r
   //\r
-  Status = AtaPioDataIn (\r
+  Status = AtaNonDataCommandIn (\r
             IdeDev,\r
-            NULL,\r
-            0,\r
             INIT_DRIVE_PARAM_CMD,\r
             (UINT8) (DeviceSelect + DriveParameters->Heads),\r
+            0,\r
             DriveParameters->Sector,\r
             0,\r
             0,\r
@@ -1731,18 +1690,16 @@ SetDriveParameters (
   //\r
   // Send Set Multiple parameters\r
   //\r
-  Status = AtaPioDataIn (\r
+  Status = AtaNonDataCommandIn (\r
             IdeDev,\r
-            NULL,\r
-            0,\r
             SET_MULTIPLE_MODE_CMD,\r
             DeviceSelect,\r
+            0,\r
             DriveParameters->MultipleSector,\r
             0,\r
             0,\r
             0\r
             );\r
-\r
   return Status;\r
 }\r
 \r
@@ -1769,3 +1726,99 @@ EnableInterrupt (
 \r
   return EFI_SUCCESS;\r
 }\r
+\r
+/**\r
+  Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.\r
+\r
+  @param[in]  Event   Pointer to this event\r
+  @param[in]  Context Event hanlder private data\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ClearInterrupt (\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+  UINT64          IoPortForBmis;\r
+  UINT8           RegisterValue;\r
+  IDE_BLK_IO_DEV  *IdeDev;\r
+\r
+  //\r
+  // Get our context\r
+  //\r
+  IdeDev = (IDE_BLK_IO_DEV *) Context;\r
+\r
+  //\r
+  // Obtain IDE IO port registers' base addresses\r
+  //\r
+  Status = ReassignIdeResources (IdeDev);\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Check whether interrupt is pending\r
+  //\r
+\r
+  //\r
+  // Reset IDE device to force it de-assert interrupt pin\r
+  // Note: this will reset all devices on this IDE channel\r
+  //\r
+  AtaSoftReset (IdeDev);\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Get base address of IDE Bus Master Status Regsiter\r
+  //\r
+  if (IdePrimary == IdeDev->Channel) {\r
+    IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;\r
+  } else {\r
+    if (IdeSecondary == IdeDev->Channel) {\r
+      IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;\r
+    } else {\r
+      return;\r
+    }\r
+  }\r
+  //\r
+  // Read BMIS register and clear ERROR and INTR bit\r
+  //\r
+  IdeDev->PciIo->Io.Read (\r
+                      IdeDev->PciIo,\r
+                      EfiPciIoWidthUint8,\r
+                      EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                      IoPortForBmis,\r
+                      1,\r
+                      &RegisterValue\r
+                      );\r
+\r
+  RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
+\r
+  IdeDev->PciIo->Io.Write (\r
+                      IdeDev->PciIo,\r
+                      EfiPciIoWidthUint8,\r
+                      EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                      IoPortForBmis,\r
+                      1,\r
+                      &RegisterValue\r
+                      );\r
+\r
+  //\r
+  // Select the other device on this channel to ensure this device to release the interrupt pin\r
+  //\r
+  if (IdeDev->Device == 0) {\r
+    RegisterValue = (1 << 4) | 0xe0;\r
+  } else {\r
+    RegisterValue = (0 << 4) | 0xe0;\r
+  }\r
+  IDEWritePortB (\r
+    IdeDev->PciIo,\r
+    IdeDev->IoPort->Head,\r
+    RegisterValue\r
+    );\r
+\r
+}\r