[uniata]
[reactos.git] / reactos / drivers / storage / ide / uniata / id_ata.cpp
index d362a76..122431b 100644 (file)
@@ -1,6 +1,6 @@
 /*++
 
-Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2002-2014 Alexandr A. Telyatnikov (Alter)
 
 Module Name:
     id_ata.cpp
@@ -37,8 +37,8 @@ Revision History:
     Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by
          Søren Schmidt, Copyright (c) 1998-2007
 
-    All parts of code are greatly changed/updated by
-         Alter, Copyright (c) 2002-2007:
+    All parts of code are significantly changed/updated by
+         Alter, Copyright (c) 2002-2014:
 
     1. Internal command queueing/reordering
     2. Drive identification
@@ -47,7 +47,7 @@ Revision History:
     5. W2k support (binary compatibility)
     6. HDD hot swap under NT4
     7. XP support (binary compatibility)
-    8. Serial ATA (SATA/SATA2) support
+    8. Serial ATA (SATA/SATA2/SATA3) support
     9. NT 3.51 support (binary compatibility)
 
     etc. (See todo.txt)
@@ -121,6 +121,14 @@ AtapiHwInitialize__(
     IN ULONG lChannel
     );
 
+VOID
+NTAPI
+UniataUserDeviceReset(
+    PHW_DEVICE_EXTENSION deviceExtension,
+    PHW_LU_EXTENSION LunExt,
+    ULONG lChannel
+    );
+
 #define RESET_COMPLETE_CURRENT  0x00
 #define RESET_COMPLETE_ALL      0x01
 #define RESET_COMPLETE_NONE     0x02
@@ -482,6 +490,7 @@ AtapiSuckPort2(
     UCHAR statusByte;
     ULONG i;
 
+    // Assume, proper drive is already seleted
     WaitOnBusyLong(chan);
     for (i = 0; i < 0x10000; i++) {
 
@@ -716,8 +725,23 @@ AtapiSoftReset(
         }
     } else {
         AtapiStallExecution(500);
+        GetBaseStatus(chan, statusByte2);
         AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
 
+        // Do not wait for BUSY assertion if it was initially set, jump to
+        // BUSY release wait loop
+        if(!(statusByte2 & IDE_STATUS_BUSY)) {
+            // Wait for BUSY assertion, in some cases delay may occure
+            // 100ms should be enough
+            i = 10*1000;
+            while (!(AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
+                   i--)
+            {
+                AtapiStallExecution(10);
+            }
+        }
+
+        i = 30 * 1000;
         // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
         // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
         // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
@@ -1066,6 +1090,24 @@ AtaUmode(PIDENTIFY_DATA2 ident)
     return IOMODE_NOT_SPECIFIED;
 } // end AtaUmode()
 
+LONG
+NTAPI
+AtaSAmode(PIDENTIFY_DATA2 ident) {
+    if(!ident->SataCapabilities || 
+       ident->SataCapabilities == 0xffff) {
+        return IOMODE_NOT_SPECIFIED;
+    }
+    if(ident->SataCapabilities & ATA_SATA_GEN3) {
+        return ATA_SA600;
+    } else
+    if(ident->SataCapabilities & ATA_SATA_GEN2) {
+        return ATA_SA300;
+    } else
+    if(ident->SataCapabilities & ATA_SATA_GEN1) {
+        return ATA_SA150;
+    }
+    return IOMODE_NOT_SPECIFIED;
+} // end AtaSAmode()
 
 #ifndef UNIATA_CORE
 
@@ -1244,6 +1286,42 @@ UniataDumpATARegs(
 } // end UniataDumpATARegs()
 #endif
 
+VOID
+NTAPI
+UniataSnapAtaRegs(
+    IN PHW_CHANNEL chan,
+    IN ULONG DeviceNumber,
+ IN OUT PIDEREGS_EX regs
+    )
+{
+    if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
+        // AHCI
+        UniataAhciSnapAtaRegs(chan, DeviceNumber, regs);
+    } else {
+        // SATA/PATA, assume drive is selected
+        ULONG                j;
+        UCHAR                statusByteAlt;
+
+        if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) {
+            for(j=IDX_IO1_i_Error; j<=IDX_IO1_i_Status; j++) {
+                statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
+                ((PUCHAR)regs)[j-1] = statusByteAlt;
+            }
+            regs->bOpFlags = 0;
+        } else {
+            regs->bDriveHeadReg    = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect);
+            for(j=IDX_IO1_i_Error; j<IDX_IO1_i_DriveSelect; j++) {
+                statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
+                ((PUCHAR)regs)[j-1] = statusByteAlt;
+                statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
+                ((PUCHAR)regs)[j+8-1] = statusByteAlt;
+            }
+            regs->bCommandReg      = AtapiReadPort1(chan, IDX_IO1_i_Status);
+        }
+    }
+    return;
+} // end UniataSnapAtaRegs()
+
 /*++
 
 Routine Description:
@@ -1276,7 +1354,7 @@ IssueIdentify(
     ULONG                waitCount = 50000;
     ULONG                j;
     UCHAR                statusByte;
-    UCHAR                statusByte2;
+    //UCHAR                statusByte2;
     UCHAR                signatureLow,
                          signatureHigh;
     BOOLEAN              atapiDev = FALSE;
@@ -1315,7 +1393,7 @@ IssueIdentify(
         AtapiStallExecution(10);
         statusByte = WaitOnBusyLong(chan);
         // Check that the status register makes sense.
-        GetBaseStatus(chan, statusByte2);
+        GetBaseStatus(chan, statusByte);
     }
 
     if (Command == IDE_COMMAND_IDENTIFY) {
@@ -1357,11 +1435,11 @@ IssueIdentify(
                     }
 
                 } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
-                GetBaseStatus(chan, statusByte2);
+                GetBaseStatus(chan, statusByte);
 
                 SelectDrive(chan, DeviceNumber);
             } else {
-                GetBaseStatus(chan, statusByte2);
+                GetBaseStatus(chan, statusByte);
             }
             // Another check for signature, to deal with one model Atapi that doesn't assert signature after
             // a soft reset.
@@ -1465,7 +1543,7 @@ IssueIdentify(
                     break;
                 }
             }
-            // Device didn't respond correctly. It will be given one more chances.
+            // Device didn't respond correctly. It will be given one more chance.
             KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
                         statusByte, AtapiReadPort1(chan, IDX_IO1_i_Error)));
             GetBaseStatus(chan, statusByte);
@@ -1516,33 +1594,13 @@ IssueIdentify(
         if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
 
             KdPrint2((PRINT_PREFIX "  use 16bit IO\n"));
-#if 0
-            USHORT w;
-            ULONG i;
+
             // ATI/SII chipsets with memory-mapped IO hangs when
             // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
-            // Unfortunately, I don't know yet how to workaround it except the way you see below.
-            KdPrint2((PRINT_PREFIX 
-                       "  IO_%#x (%#x), %s:\n",
-                       IDX_IO1_i_Data,
-                       chan->RegTranslation[IDX_IO1_i_Data].Addr,
-                       chan->RegTranslation[IDX_IO1_i_Data].MemIo ? "Mem" : "IO"));
-            for(i=0; i<256; i++) {
-    /*
-                KdPrint2((PRINT_PREFIX 
-                           "  IO_%#x (%#x):\n",
-                           IDX_IO1_i_Data,
-                           chan->RegTranslation[IDX_IO1_i_Data].Addr));
-    */
-                w = AtapiReadPort2(chan, IDX_IO1_i_Data);
-                KdPrint2((PRINT_PREFIX 
-                           "    %x\n", w));
-                AtapiStallExecution(1);
-                ((PUSHORT)&deviceExtension->FullIdentifyData)[i] = w;
-            }
-#else
+            // Unfortunately, I don't know yet how to workaround it except
+            // spacifying manual delay in the way you see below.
             ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
-#endif
+
             // Work around for some IDE and one model Atapi that will present more than
             // 256 bytes for the Identify data.
             KdPrint2((PRINT_PREFIX "IssueIdentify: suck data port\n", statusByte));
@@ -1574,13 +1632,28 @@ IssueIdentify(
     KdPrint2((PRINT_PREFIX "SWDMA: %x\n", deviceExtension->FullIdentifyData.SingleWordDMAActive));
     KdPrint2((PRINT_PREFIX "MWDMA: %x\n", deviceExtension->FullIdentifyData.MultiWordDMAActive));
     if(deviceExtension->FullIdentifyData.UdmaModesValid) {
-        KdPrint2((PRINT_PREFIX "UDMA:  %x\n", deviceExtension->FullIdentifyData.UltraDMAActive));
+        KdPrint2((PRINT_PREFIX "UDMA:  %x/%x\n", deviceExtension->FullIdentifyData.UltraDMAActive, deviceExtension->FullIdentifyData.UltraDMASupport));
     }
     KdPrint2((PRINT_PREFIX "SATA:  %x\n", deviceExtension->FullIdentifyData.SataEnable));
     KdPrint2((PRINT_PREFIX "SATA support: %x, CAPs %#x\n",
         deviceExtension->FullIdentifyData.SataSupport,
         deviceExtension->FullIdentifyData.SataCapabilities));
 
+    LunExt->LimitedTransferMode =
+    LunExt->OrigTransferMode =
+        (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData), IDENT_MODE_MAX);
+    LunExt->TransferMode =
+        (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData), IDENT_MODE_ACTIVE);
+
+    KdPrint2((PRINT_PREFIX "OrigTransferMode: %x, Active: %x\n", LunExt->OrigTransferMode, LunExt->TransferMode));
+    KdPrint2((PRINT_PREFIX "Accoustic %d, cur %d\n",
+        deviceExtension->FullIdentifyData.VendorAcoustic,
+        deviceExtension->FullIdentifyData.CurrentAcoustic
+        ));
+    KdPrint2((PRINT_PREFIX "AdvPowerMode %d, cur %d\n",
+        deviceExtension->FullIdentifyData.CfAdvPowerMode
+        ));
+
     // Check out a few capabilities / limitations of the device.
     if (deviceExtension->FullIdentifyData.RemovableStatus & 1) {
         // Determine if this drive supports the MSN functions.
@@ -1809,7 +1882,6 @@ IssueIdentify(
                 }
             }
         }
-        KdPrint2((PRINT_PREFIX "final LunExt->opt_GeomType=%x\n", LunExt->opt_GeomType));
 
         if(LunExt->opt_GeomType == GEOM_STD) {
             deviceExtension->FullIdentifyData.CurrentSectorsPerTrack =
@@ -1993,6 +2065,7 @@ UniataForgetDevice(
     PHW_LU_EXTENSION   LunExt
     )
 {
+    // keep only DFLAGS_HIDDEN flag
     LunExt->DeviceFlags &= DFLAGS_HIDDEN;
     LunExt->AtapiReadyWaitDelay = 0;
 } // end UniataForgetDevice()
@@ -2002,6 +2075,7 @@ UniataForgetDevice(
 
 Routine Description:
     Reset IDE controller and/or Atapi device.
+    ->HwResetBus
 
 Arguments:
     HwDeviceExtension - HBA miniport driver's adapter data storage
@@ -2022,7 +2096,6 @@ AtapiResetController(
     return AtapiResetController__(HwDeviceExtension, PathId, RESET_COMPLETE_ALL);
 } // end AtapiResetController()
 
-
 BOOLEAN
 NTAPI
 AtapiResetController__(
@@ -2156,14 +2229,21 @@ AtapiResetController__(
         InterlockedExchange(&(chan->CheckIntr),
                                       CHECK_INTR_IDLE);
         
+        for (i = 0; i < MaxLuns; i++) {
+            chan->lun[i]->PowerState = 0;
+        }
         // Reset controller
         if(ChipFlags & UNIATA_AHCI) {
             KdPrint2((PRINT_PREFIX "  AHCI path\n"));
-#if DBG
-            UniataDumpAhciPortRegs(chan);
+            if(UniataAhciChanImplemented(deviceExtension, j)) {
+#ifdef _DEBUG
+                UniataDumpAhciPortRegs(chan);
 #endif
-            AtapiDisableInterrupts(deviceExtension, j);
-            UniataAhciReset(HwDeviceExtension, j);
+                AtapiDisableInterrupts(deviceExtension, j);
+                UniataAhciReset(HwDeviceExtension, j);
+            } else {
+                KdPrint2((PRINT_PREFIX "  skip not implemented\n"));
+            }
         } else {
             KdPrint2((PRINT_PREFIX "  ATA path, chan %#x\n", chan));
             KdPrint2((PRINT_PREFIX "  disable intr (0)\n"));
@@ -2811,6 +2891,7 @@ Routine Description:
 
 Arguments:
     HwDeviceExtension - HBA miniport driver's adapter data storage
+    ->HwInitialize
 
 Return Value:
     TRUE - if initialization successful.
@@ -2832,6 +2913,11 @@ AtapiHwInitialize(
     if(WinVer_WDM_Model) {
         AtapiResetController__(HwDeviceExtension, CHAN_NOT_SPECIFIED, RESET_COMPLETE_ALL);
     }
+    if(deviceExtension->MasterDev) {
+        KdPrint2((PRINT_PREFIX "  mark chan %d of master controller [%x] as inited\n",
+            deviceExtension->Channel, deviceExtension->DevIndex));
+        BMList[deviceExtension->DevIndex].ChanInitOk |= 0x01 << deviceExtension->Channel;
+    }
 
     /* do extra chipset specific setups */
     AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
@@ -2862,6 +2948,11 @@ AtapiHwInitialize__(
 //    ULONG tmp32;
     ULONG PreferedMode = 0xffffffff;
 
+    if((deviceExtension->HwFlags & UNIATA_AHCI) &&
+       !UniataAhciChanImplemented(deviceExtension, lChannel)) {
+        return;
+    }
+
     AtapiChipInit(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel);
     FindDevices(deviceExtension, 0, lChannel);
 
@@ -2966,15 +3057,71 @@ AtapiHwInitialize__(
                     KdPrint2((PRINT_PREFIX "  Disable Write Cache\n"));
                     statusByte = AtaCommand(deviceExtension, i, lChannel,
                                         IDE_COMMAND_SET_FEATURES, 0, 0, 0,
-                                        0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
+                                        0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY);
                     LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
                 }
+
+                if(LunExt->IdentifyData.FeaturesSupport.PowerMngt ||
+                   LunExt->IdentifyData.FeaturesSupport.APM) {
+
+                    if(LunExt->opt_AdvPowerMode) {
+                        KdPrint2((PRINT_PREFIX "  Try Enable Adv. Power Mgmt\n"));
+                        // setup APM
+                        statusByte = AtaCommand(deviceExtension, i, lChannel,
+                                            IDE_COMMAND_SET_FEATURES, 0, 0, 0,
+                                            LunExt->opt_AdvPowerMode, ATA_C_F_ENAB_APM, ATA_WAIT_BASE_READY);
+                        // Check for errors.
+                        if (statusByte & IDE_STATUS_ERROR) {
+                            KdPrint2((PRINT_PREFIX 
+                                        "AtapiHwInitialize: Enable APM on Device %d failed\n",
+                                        i));
+                        }
+                    } else {
+                        KdPrint2((PRINT_PREFIX "  Disable Adv. Power Mgmt\n"));
+                        statusByte = AtaCommand(deviceExtension, i, lChannel,
+                                            IDE_COMMAND_SET_FEATURES, 0, 0, 0,
+                                            0, ATA_C_F_DIS_APM, ATA_WAIT_BASE_READY);
+                    }
+                }
+                if(LunExt->IdentifyData.FeaturesSupport.AutoAcoustic) {
+                    if(LunExt->opt_AcousticMode) {
+                        KdPrint2((PRINT_PREFIX "  Try Enable Acoustic Mgmt\n"));
+                        // setup acoustic mgmt
+                        statusByte = AtaCommand(deviceExtension, i, lChannel,
+                                            IDE_COMMAND_SET_FEATURES, 0, 0, 0,
+                                            LunExt->opt_AcousticMode, ATA_C_F_ENAB_ACOUSTIC, ATA_WAIT_BASE_READY);
+                        // Check for errors.
+                        if (statusByte & IDE_STATUS_ERROR) {
+                            KdPrint2((PRINT_PREFIX 
+                                        "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n",
+                                        i));
+                        }
+                    } else {
+                        KdPrint2((PRINT_PREFIX "  Disable Acoustic Mgmt\n"));
+                        statusByte = AtaCommand(deviceExtension, i, lChannel,
+                                            IDE_COMMAND_SET_FEATURES, 0, 0, 0,
+                                            0, ATA_C_F_DIS_ACOUSTIC, ATA_WAIT_BASE_READY);
+                    }
+                }
+                if(LunExt->IdentifyData.FeaturesSupport.Standby) {
+                    KdPrint2((PRINT_PREFIX "  Try init standby timer: %d\n"));
+                    // setup standby timer
+                    statusByte = AtaCommand(deviceExtension, i, lChannel,
+                                        IDE_COMMAND_IDLE, 0, 0, 0,
+                                        LunExt->opt_StandbyTimer, 0, ATA_WAIT_BASE_READY);
+                    // Check for errors.
+                    if (statusByte & IDE_STATUS_ERROR) {
+                        KdPrint2((PRINT_PREFIX 
+                                    "AtapiHwInitialize: standby timer on Device %d failed\n",
+                                    i));
+                    }
+                }
             }
 
         } else if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)){
 
             ULONG j;
-            BOOLEAN isSanyo = FALSE;
+            //BOOLEAN isSanyo = FALSE;
             CCHAR vendorId[26];
 
             KdPrint2((PRINT_PREFIX "AtapiHwInitialize: ATAPI/Changer branch\n"));
@@ -2995,13 +3142,13 @@ AtapiHwInitialize__(
                     // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
                     LunExt->DeviceFlags |= (DFLAGS_CHANGER_INITED | DFLAGS_SANYO_ATAPI_CHANGER);
                     LunExt->DiscsPresent = 3;
-                    isSanyo = TRUE;
+                    //isSanyo = TRUE;
                 }
             }
         }
 
         PreferedMode = LunExt->opt_MaxTransferMode;
-        if(PreferedMode == 0xffffffff) {
+        if((PreferedMode == 0xffffffff) || (PreferedMode > chan->MaxTransferMode)) {
             KdPrint2((PRINT_PREFIX "MaxTransferMode (overriden): %#x\n", chan->MaxTransferMode));
             PreferedMode = chan->MaxTransferMode;
         }
@@ -3012,14 +3159,12 @@ AtapiHwInitialize__(
         }
 
         KdPrint2((PRINT_PREFIX "  try mode %#x\n", PreferedMode));
-        LunExt->OrigTransferMode =
         LunExt->LimitedTransferMode =
         LunExt->TransferMode =
             (CHAR)PreferedMode;
 
         AtapiDmaInit__(deviceExtension, LunExt);
 
-        LunExt->OrigTransferMode =
         LunExt->LimitedTransferMode =
             LunExt->TransferMode;
         KdPrint2((PRINT_PREFIX "Using %#x mode\n", LunExt->TransferMode));
@@ -3468,7 +3613,10 @@ AtapiInterrupt(
         if(!hIS) {
             return FALSE;
         }
-        checked = ~hIS; // assume all non-interrupted ports to be already checked
+        // assume all non-interrupted ports to be already checked
+        checked = ~hIS;
+        // assume all not implemented ports to be already checked
+        checked |= ~deviceExtension->AHCI_PI;
     } else {
         checked = 0; // assume all ports are not checked
     }
@@ -3631,7 +3779,11 @@ AtapiInterrupt2(
         if(!hIS) {
             return FALSE;
         }
-        checked = ~hIS; // assume all non-interrupted ports to be already checked
+        // assume all non-interrupted ports to be already checked
+        checked = ~hIS; 
+        // assume all not implemented ports to be already checked
+        checked |= ~deviceExtension->AHCI_PI;
+
     } else {
         checked = 0; // assume all ports are not checked
     }
@@ -3814,6 +3966,12 @@ AtapiEnableInterrupts(
         KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c));
         return;
     }
+    if((deviceExtension->HwFlags & UNIATA_AHCI) &&
+       !UniataAhciChanImplemented(deviceExtension, c)) {
+        KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c));
+        return;
+    }
+
     chan = &(deviceExtension->chan[c]);
     KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: %d\n",c, chan->DisableIntr));
     if(!InterlockedDecrement(&chan->DisableIntr)) {
@@ -3947,6 +4105,11 @@ AtapiCheckInterrupt__(
 
     if((ChipFlags & UNIATA_AHCI) &&
         UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
+
+        if(!UniataAhciChanImplemented(deviceExtension, lChannel)) {
+            return OurInterrupt;
+        }
+
         OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED);
         if((OurInterrupt == INTERRUPT_REASON_UNEXPECTED) &&
            (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
@@ -4019,23 +4182,41 @@ AtapiCheckInterrupt__(
                 return INTERRUPT_REASON_IGNORE;
             }
             break;
-        case PRMIO:
-            status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x0040);
-            if(ChipFlags & PRSATA) {
-                pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x006c);
-                AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x006c, pr_status & 0x000000ff);
+        case PRMIO: {
+            ULONG stat_reg = (ChipFlags & PRG2) ? 0x60 : 0x6c;
+            status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x40);
+            AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x40, status);
+
+            if(status & (1 << (Channel+1))) {
+                // our
+            } else {
+                KdPrint2((PRINT_PREFIX "  Promise mio unexpected\n"));
+                return INTERRUPT_REASON_IGNORE;
             }
+
+            if(!(ChipFlags & UNIATA_SATA))
+                break;
+
+            pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),stat_reg);
+            AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),stat_reg, (pr_status & (0x11 << Channel)));
             if(pr_status & (0x11 << Channel)) {
                 // TODO: reset channel
                 KdPrint2((PRINT_PREFIX "  Promise mio unexpected + reset req\n"));
-                return INTERRUPT_REASON_IGNORE;
+                UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, 0);
             }
             if(!(status & (0x01 << Channel))) {
-                KdPrint2((PRINT_PREFIX "  Promise mio unexpected\n"));
+                // Connect event
+                KdPrint2((PRINT_PREFIX "  Promise mio unexpected attach\n"));
+                UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, 0);
+            }
+            if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
+                OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
+            } else {
                 return INTERRUPT_REASON_IGNORE;
             }
+
             AtapiWritePort4(chan, IDX_BM_DeviceSpecific0, 0x00000001);
-            break;
+            break; }
         }
         break; }
     case ATA_NVIDIA_ID: {
@@ -4336,7 +4517,7 @@ skip_dma_stat_check:
             KdPrint2((PRINT_PREFIX "  OurInterrupt = %d\n", OurInterrupt));
             return OurInterrupt;
         }
-        interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
+        interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
         KdPrint3((PRINT_PREFIX "AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason));
         return OurInterrupt;
     }
@@ -4370,7 +4551,9 @@ AtapiInterrupt__(
 
     BOOLEAN atapiDev = FALSE;
 
+#ifdef DBG
     UCHAR Channel;
+#endif //DBG
     UCHAR lChannel;
     UCHAR DeviceNumber;
     BOOLEAN DmaTransfer = FALSE;
@@ -4386,6 +4569,7 @@ AtapiInterrupt__(
 //    BOOLEAN RestoreUseDpc = FALSE;
     BOOLEAN DataOverrun = FALSE;
     BOOLEAN NoStartIo = TRUE;
+    BOOLEAN NoRetry = FALSE;
 
     KdPrint2((PRINT_PREFIX "AtapiInterrupt:\n"));
     if(InDpc) {
@@ -4401,9 +4585,12 @@ AtapiInterrupt__(
     PHW_LU_EXTENSION LunExt;
 
     lChannel = c;
+
+#ifdef DBG
     Channel = (UCHAR)(deviceExtension->Channel + lChannel);
 
     KdPrint2((PRINT_PREFIX "  cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension->DevIndex, Channel, KeGetCurrentIrql(), c));
+#endif //DBG
 
     if((chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
        (AtaReq && (AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) ||
@@ -4595,21 +4782,28 @@ ServiceInterrupt:
         statusByte = (UCHAR)(AtaReq->ahci.in_status & IDE_STATUS_MASK);
 
         if(chan->AhciLastIS & ~(ATA_AHCI_P_IX_DHR | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_SDB)) {
-            KdPrint3((PRINT_PREFIX "Err intr (%#x)\n", chan->AhciLastIS & ~(ATA_AHCI_P_IX_DHR | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_SDB)));
+            KdPrint3((PRINT_PREFIX "Err intr (%#x), SE (%#x)\n",
+                chan->AhciLastIS & ~(ATA_AHCI_P_IX_DHR | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_SDB),
+                chan->AhciLastSError));
             if(chan->AhciLastIS & ~ATA_AHCI_P_IX_OF) {
                 //KdPrint3((PRINT_PREFIX "Err mask (%#x)\n", chan->AhciLastIS & ~ATA_AHCI_P_IX_OF));
                 // We have some other error except Overflow
                 // Just signal ERROR, operation will be aborted in ERROR branch.
                 statusByte |= IDE_STATUS_ERROR;
+                AtaReq->ahci.in_serror = chan->AhciLastSError;
+                if(chan->AhciLastSError & (ATA_SE_HANDSHAKE_ERR | ATA_SE_LINKSEQ_ERR | ATA_SE_TRANSPORT_ERR | ATA_SE_UNKNOWN_FIS)) {
+                    KdPrint2((PRINT_PREFIX "Unrecoverable\n"));
+                    NoRetry = TRUE;
+                }
             } else {
                 // We have only Overflow. Abort operation and continue
-#if DBG
+#ifdef _DEBUG
                 UniataDumpAhciPortRegs(chan);
 #endif
                 if(!UniataAhciAbortOperation(chan)) {
                     KdPrint2((PRINT_PREFIX "need UniataAhciReset\n"));
                 }
-#if DBG
+#ifdef _DEBUG
                 UniataDumpAhciPortRegs(chan);
 #endif
                 UniataAhciWaitCommandReady(chan, 10);
@@ -4691,7 +4885,7 @@ try_dpc_wait:
         if(deviceExtension->HwFlags & UNIATA_AHCI) {
             KdPrint3((PRINT_PREFIX "  AHCI branch (ATAPI)\n"));
         } else {
-            interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
+            interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
             KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
         }
 
@@ -4780,7 +4974,7 @@ try_dpc_wait:
         if(deviceExtension->HwFlags & UNIATA_AHCI) {
             error = AtaReq->ahci.in_error;
             // wait ready
-#if DBG
+#ifdef _DEBUG
             UniataDumpAhciPortRegs(chan);
 #endif
             if(!UniataAhciAbortOperation(chan)) {
@@ -4788,11 +4982,18 @@ try_dpc_wait:
             }
             // clear interrupts again
             UniataAhciWaitCommandReady(chan, 10);
-#if DBG
+#ifdef _DEBUG
             UniataDumpAhciPortRegs(chan);
 #endif
             UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED);
-#if DBG
+            if(NoRetry) {
+                AtaReq->retry += MAX_RETRIES;
+                if(!error && (statusByte & IDE_STATUS_ERROR)) {
+                    KdPrint2((PRINT_PREFIX "AtapiInterrupt: force error status\n"));
+                    error |= IDE_STATUS_ERROR;
+                }
+            }
+#ifdef _DEBUG
             UniataDumpAhciPortRegs(chan);
 #endif
         } else {
@@ -4812,7 +5013,9 @@ try_dpc_wait:
             KdPrint2((PRINT_PREFIX "  Bad Lba unknown\n"));
         }
 
-
+        if(deviceExtension->HwFlags & UNIATA_AHCI) {
+            KdPrint2((PRINT_PREFIX "  no wait ready after error\n"));
+        } else
         if(!atapiDev) {
             KdPrint2((PRINT_PREFIX "  wait 100 ready after IDE error\n"));
             AtapiStallExecution(100);
@@ -4844,11 +5047,14 @@ continue_err:
 #endif //IO_STATISTICS
                 if(DmaTransfer /*&&
                    (error & IDE_ERROR_ICRC)*/) {
+                    KdPrint2((PRINT_PREFIX "Errors in DMA mode\n"));
                     if(AtaReq->retry < MAX_RETRIES) {
 //fallback_pio:
-                        AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
-                        AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
+                        if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
+                            AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
+                            AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
 //                        LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
+                        }
                         AtaReq->ReqState = REQ_STATE_QUEUED;
                         goto reenqueue_req;
                     }
@@ -4860,7 +5066,7 @@ continue_err:
                 }
             }
         } else {
-            interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
+            interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
             KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason));
 
             if(DmaTransfer && (chan->lun[DeviceNumber]->TransferMode > ATA_UDMA2) &&
@@ -4899,27 +5105,27 @@ continue_err:
         KdPrint2((PRINT_PREFIX "Some higher mode doesn't work right :((\n"));
         KdPrint2((PRINT_PREFIX "Recovery stats[%d]: %d vs %d\n",
               AtaReq->retry,
-              chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry],
-              chan->lun[DeviceNumber]->BlockIoCount
+              LunExt->RecoverCount[AtaReq->retry],
+              LunExt->BlockIoCount
               ));
-        chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry]++;
-        if(chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->BlockIoCount/3 ||
+        LunExt->RecoverCount[AtaReq->retry]++;
+        if(LunExt->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->BlockIoCount/3 ||
            (deviceExtension->HwFlags & UNIATA_NO80CHK)
            ) {
 #else
         if(deviceExtension->HwFlags & UNIATA_NO80CHK) {
 #endif //IO_STATISTICS
-            KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", deviceExtension->lun[DeviceNumber].TransferMode));
-            deviceExtension->lun[DeviceNumber].LimitedTransferMode =
-                deviceExtension->lun[DeviceNumber].TransferMode;
+            KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", LunExt->TransferMode));
+            LunExt->LimitedTransferMode =
+                LunExt->TransferMode;
         }
     }
 #ifdef IO_STATISTICS
     if(AtaReq->bcount) {
         // we need stats for Read/Write operations
-        chan->lun[DeviceNumber]->BlockIoCount++;
+        LunExt->BlockIoCount++;
     }
-    chan->lun[DeviceNumber]->IoCount++;
+    LunExt->IoCount++;
 #endif //IO_STATISTICS
 
 continue_PIO:
@@ -4930,7 +5136,7 @@ continue_PIO:
         KdPrint2((PRINT_PREFIX "AtapiInterrupt: ATAPI branch\n"));
         // ATAPI branch
 
-        interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
+        interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
         KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
         if(DmaTransfer) {
             wordsThisInterrupt = DEV_BSIZE/2*512;
@@ -4957,10 +5163,10 @@ continue_PIO:
 
             if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
 
-                interruptReason =  0x2;
+                interruptReason = ATAPI_IR_IO_toHost;
 
             } else if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
-                interruptReason = 0x0;
+                interruptReason = ATAPI_IR_IO_toDev;
 
             } else {
                 status = SRB_STATUS_ERROR;
@@ -5008,13 +5214,13 @@ IntrPrepareResetController:
                     goto ReturnEnableIntr;
 
                 } else {
-                    interruptReason = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ? 0x2 : 0x0;
+                    interruptReason = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ? ATAPI_IR_IO_toHost : ATAPI_IR_IO_toDev;
                 }
 
             } else {
                 // Command complete - verify, write, or the SMART enable/disable.
                 // Also get_media_status
-                interruptReason = 0x3;
+                interruptReason = ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd;
             }
         }
     }
@@ -5033,19 +5239,20 @@ IntrPrepareResetController:
         } else {
             AtaReq->WordsLeft -= AtaReq->WordsTransfered;
         }
-        if(AtaReq->WordsLeft) {
-            status = SRB_STATUS_DATA_OVERRUN;
-        } else {
-            status = SRB_STATUS_SUCCESS;
-        }
+        //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
+        //    status = SRB_STATUS_DATA_OVERRUN;
+        //}
+        status = SRB_STATUS_SUCCESS;
         chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
         goto CompleteRequest;
     } else
-    if (interruptReason == 0x1 && (statusByte & IDE_STATUS_DRQ)) {
+    if (interruptReason == ATAPI_IR_COD_Cmd && (statusByte & IDE_STATUS_DRQ)) {
         // Write the packet.
         KdPrint3((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n"));
         // Send CDB to device.
-        WriteBuffer(chan, (PUSHORT)srb->Cdb, 6, 0);
+        WriteBuffer(chan, (PUSHORT)srb->Cdb, 
+                          LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
+                          0);
         AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
 
         if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
@@ -5055,7 +5262,7 @@ IntrPrepareResetController:
 
         goto ReturnEnableIntr;
 
-    } else if (interruptReason == 0x0 && (statusByte & IDE_STATUS_DRQ)) {
+    } else if (interruptReason == ATAPI_IR_IO_toDev && (statusByte & IDE_STATUS_DRQ)) {
 
         // Write the data.
         if (atapiDev) {
@@ -5106,11 +5313,13 @@ IntrPrepareResetController:
                           "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount));
                 if(AtaReq->WordsLeft > wordCount) {
                     AtaReq->WordsLeft -= wordCount;
+                    AtaReq->WordsTransfered += wordCount;
                     AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
                     goto ReturnEnableIntr;
                 }
                 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
             }
+            AtaReq->WordsTransfered = AtaReq->WordsLeft;
             AtaReq->WordsLeft = 0;
             status = SRB_STATUS_SUCCESS;
             chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
@@ -5152,6 +5361,7 @@ IntrPrepareResetController:
         // Advance data buffer pointer and bytes left.
         AtaReq->DataBuffer += wordCount;
         AtaReq->WordsLeft -= wordCount;
+        AtaReq->WordsTransfered += wordCount;
 
         if (atapiDev) {
             AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
@@ -5159,7 +5369,7 @@ IntrPrepareResetController:
 
         goto ReturnEnableIntr;
 
-    } else if (interruptReason == 0x2 && (statusByte & IDE_STATUS_DRQ)) {
+    } else if (interruptReason == ATAPI_IR_IO_toHost && (statusByte & IDE_STATUS_DRQ)) {
 
 
         if (atapiDev) {
@@ -5205,12 +5415,14 @@ IntrPrepareResetController:
                           "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount));
                 if(AtaReq->WordsLeft > wordCount) {
                     AtaReq->WordsLeft -= wordCount;
+                    AtaReq->WordsTransfered += wordCount;
                     AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
                     goto ReturnEnableIntr;
                 }
                 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
             }
             //ASSERT(AtaReq->WordsLeft == wordCount);
+            AtaReq->WordsTransfered = AtaReq->WordsLeft;
             AtaReq->WordsLeft = 0;
             status = SRB_STATUS_SUCCESS;
             chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
@@ -5281,6 +5493,7 @@ IntrPrepareResetController:
         // Advance data buffer pointer and bytes left.
         AtaReq->DataBuffer += wordCount;
         AtaReq->WordsLeft -= wordCount;
+        AtaReq->WordsTransfered += wordCount;
 
         // Check for read command complete.
         if (AtaReq->WordsLeft == 0) {
@@ -5352,19 +5565,29 @@ IntrPrepareResetController:
 
         goto ReturnEnableIntr;
 
-    } else if (interruptReason == 0x3  && !(statusByte & IDE_STATUS_DRQ)) {
+    } else if (interruptReason == (ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd) && !(statusByte & IDE_STATUS_DRQ)) {
 
         KdPrint2((PRINT_PREFIX "AtapiInterrupt: interruptReason = CompleteRequest\n"));
-        // Command complete.
+        // Command complete. We exactly know this because os IReason.
+
         if(DmaTransfer) {
             KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
+            AtaReq->WordsTransfered += AtaReq->WordsLeft;
             AtaReq->WordsLeft = 0;
-        }
-        if (AtaReq->WordsLeft) {
-            status = SRB_STATUS_DATA_OVERRUN;
         } else {
-            status = SRB_STATUS_SUCCESS;
+            KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was PIO\n"));
+
+            wordCount = AtaReq->WordsLeft;
+            // Advance data buffer pointer and bytes left.
+            AtaReq->DataBuffer += wordCount;
+            AtaReq->WordsLeft -= wordCount;
+            AtaReq->WordsTransfered += wordCount;
         }
+        //if (AtaReq->WordsLeft) {
+        //    status = SRB_STATUS_DATA_OVERRUN;
+        //} else {
+            status = SRB_STATUS_SUCCESS;
+        //}
 
 #ifdef UNIATA_DUMP_ATAPI
         if(srb &&
@@ -5419,6 +5642,12 @@ CompleteRequest:
 
         KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, srbstatus %x\n", status));
         // Check and see if we are processing our secret (mechanism status/request sense) srb
+
+        if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
+            KdPrint2((PRINT_PREFIX "WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq->WordsLeft));
+            status = SRB_STATUS_DATA_OVERRUN;
+        }
+
         if (AtaReq->OriginalSrb) {
 
             ULONG srbStatus;
@@ -5493,7 +5722,8 @@ CompleteRequest:
                                                               AtaReq->OriginalSrb);
                     } else {
 
-                        // last request was illegal.  No point trying again
+                        // last request was illegal.  No point trying again.
+                        // Do-nothing call ?
                         AtapiHwInitializeChanger (HwDeviceExtension,
                                                   srb,
                                                   (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
@@ -5536,6 +5766,7 @@ CompleteRequest:
 
             if (AtaReq->OriginalSrb) {
                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
+                // Do-nothing call ?
                 AtapiHwInitializeChanger (HwDeviceExtension,
                                           srb,
                                           (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
@@ -5691,10 +5922,10 @@ PIO_wait_DRQ:
                 }
             }
             if(status == SRB_STATUS_SUCCESS) {
-                if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
-                    // This should be set in UniataAhciEndTransaction() for AHCI
-                    AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
-                }
+                //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) {
+                //    // This should be set in UniataAhciEndTransaction() for AHCI
+                //    AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
+                //}
                 if(!atapiDev &&
                    AtaReq->WordsTransfered*2 < AtaReq->TransferLength) {
                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
@@ -5743,31 +5974,35 @@ IntrCompleteReq:
             } else {
 
                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: IOCTL completion\n"));
-                PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
 
                 if (status != SRB_STATUS_SUCCESS) {
                     error = AtapiReadPort1(chan, IDX_IO1_i_Error);
                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: error %#x\n", error));
                 }
 
-                // Build the SMART status block depending upon the completion status.
-                cmdOutParameters->cBufferSize = wordCount;
-                cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0;
-                cmdOutParameters->DriverStatus.bIDEError = error;
+                if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
 
-                // If the sub-command is return smart status, jam the value from cylinder low and high, into the
-                // data buffer.
-                if (chan->SmartCommand == RETURN_SMART_STATUS) {
-                    cmdOutParameters->bBuffer[0] = RETURN_SMART_STATUS;
-                    cmdOutParameters->bBuffer[1] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason);
-                    cmdOutParameters->bBuffer[2] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Unused1);
-                    cmdOutParameters->bBuffer[3] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
-                    cmdOutParameters->bBuffer[4] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh);
-                    cmdOutParameters->bBuffer[5] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_DriveSelect);
-                    cmdOutParameters->bBuffer[6] = SMART_CMD;
-                    cmdOutParameters->cBufferSize = 8;
-                }
+                    PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
+                    // Build the SMART status block depending upon the completion status.
+                    cmdOutParameters->cBufferSize = wordCount;
+                    cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0;
+                    cmdOutParameters->DriverStatus.bIDEError = error;
+
+                    // If the sub-command is return smart status, jam the value from cylinder low and high, into the
+                    // data buffer.
+                    if (chan->SmartCommand == RETURN_SMART_STATUS) {
+                        PIDEREGS_EX regs = (PIDEREGS_EX)&(cmdOutParameters->bBuffer);
+
+                        regs->bOpFlags = 0;
+                        UniataSnapAtaRegs(chan, 0, regs);
+
+                        regs->bCommandReg = SMART_CMD;
+                        regs->bFeaturesReg = RETURN_SMART_STATUS;
 
+                        cmdOutParameters->cBufferSize = 8;
+                    }
+                    chan->SmartCommand = 0; // cleanup after execution
+                }
                 // Indicate command complete.
                 goto IntrCompleteReq;
             }
@@ -5929,19 +6164,20 @@ ULONG
 NTAPI
 IdeSendSmartCommand(
     IN PVOID HwDeviceExtension,
-    IN PSCSI_REQUEST_BLOCK Srb
+    IN PSCSI_REQUEST_BLOCK Srb,
+    IN ULONG targetId // assume it is always valid
     )
 {
     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
-    ULONG                c               = GET_CHANNEL(Srb);
-    PHW_CHANNEL          chan            = &(deviceExtension->chan[c]);
+    ULONG                c               ; // = GET_CHANNEL(Srb); may be invalid
+    PHW_CHANNEL          chan            ; // = &(deviceExtension->chan[c]);
     PATA_REQ             AtaReq          = (PATA_REQ)(Srb->SrbExtension);
     PSENDCMDOUTPARAMS    cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
     SENDCMDINPARAMS      cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
     PIDEREGS             regs            = &cmdInParameters.irDriveRegs;
 //    ULONG                i;
-    UCHAR                statusByte,targetId;
-
+    UCHAR                statusByte;
+    ULONG DeviceNumber;
 
     if (regs->bCommandReg != SMART_CMD) {
         KdPrint2((PRINT_PREFIX 
@@ -5949,14 +6185,11 @@ IdeSendSmartCommand(
         return SRB_STATUS_INVALID_REQUEST;
     }
 
-    targetId = cmdInParameters.bDriveNumber;
-
-    //TODO optimize this check
-    if ((!(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_DEVICE_PRESENT)) ||
-         (deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
+    c = targetId / deviceExtension->NumberLuns;
+    DeviceNumber = targetId % deviceExtension->NumberLuns;
+    KdPrint2((PRINT_PREFIX "  c %d, dev %d\n", c, DeviceNumber));
 
-        return SRB_STATUS_SELECTION_TIMEOUT;
-    }
+    chan = &(deviceExtension->chan[c]);
 
     chan->SmartCommand = regs->bFeaturesReg;
 
@@ -5964,6 +6197,14 @@ IdeSendSmartCommand(
     switch(regs->bFeaturesReg) {
     case READ_ATTRIBUTES:
     case READ_THRESHOLDS:
+    case READ_LOG_SECTOR:
+    case WRITE_LOG_SECTOR:
+
+        if(Srb->DataTransferLength < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1) {
+            KdPrint2((PRINT_PREFIX 
+                        "IdeSendSmartCommand: wrong buffer size\n"));
+            return SRB_STATUS_DATA_OVERRUN;
+        }
 
         statusByte = WaitOnBusy(chan);
 
@@ -5980,7 +6221,7 @@ IdeSendSmartCommand(
         AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
         AtaReq->WordsLeft = READ_ATTRIBUTE_BUFFER_SIZE / 2;
 
-        statusByte = AtaCommand(deviceExtension, targetId & 0x1, c,
+        statusByte = AtaCommand(deviceExtension, DeviceNumber, c,
                    regs->bCommandReg,
                    (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
                    0,
@@ -6001,6 +6242,7 @@ IdeSendSmartCommand(
     case ENABLE_DISABLE_AUTOSAVE:
     case EXECUTE_OFFLINE_DIAGS:
     case SAVE_ATTRIBUTE_VALUES:
+    case AUTO_OFFLINE:
 
         statusByte = WaitOnBusy(chan);
 
@@ -6017,7 +6259,7 @@ IdeSendSmartCommand(
         AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
         AtaReq->WordsLeft = 0;
 
-        statusByte = AtaCommand(deviceExtension, targetId & 0x1, c,
+        statusByte = AtaCommand(deviceExtension, DeviceNumber, c,
                    regs->bCommandReg,
                    (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
                    0,
@@ -6028,6 +6270,7 @@ IdeSendSmartCommand(
 
         if(!(statusByte & IDE_STATUS_ERROR)) {
             // Wait for interrupt.
+            UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
             return SRB_STATUS_PENDING;
         }
         return SRB_STATUS_ERROR;
@@ -6573,9 +6816,8 @@ AtapiSendCommand(
     PHW_LU_EXTENSION     LunExt;
     //ULONG                ldev = GET_LDEV(Srb);
     ULONG                DeviceNumber = GET_CDEV(Srb);
-    ULONG i;
     ULONG flags;
-    UCHAR statusByte,byteCountLow,byteCountHigh;
+    UCHAR statusByte,statusByte0,byteCountLow,byteCountHigh;
     BOOLEAN use_dma = FALSE;
     BOOLEAN dma_reinited = FALSE;
     BOOLEAN retried = FALSE;
@@ -6667,6 +6909,7 @@ AtapiSendCommand(
 
     if(CmdAction == CMD_ACTION_PREPARE) {
         KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb->Cdb)));
+
         switch (Srb->Cdb[0]) {
         case SCSIOP_RECEIVE:
         case SCSIOP_SEND:
@@ -6719,9 +6962,27 @@ AtapiSendCommand(
             KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
             return srbStatus;
         } else {
+
+            // failed!  Get the sense key and maybe try again
+            AtaReq->Srb = BuildRequestSenseSrb (  HwDeviceExtension,
+                                                  AtaReq->OriginalSrb);
+
+            srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL);
+
+            KdPrint3((PRINT_PREFIX "AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt));
+
+            if (srbStatus == SRB_STATUS_PENDING) {
+                KdPrint2((PRINT_PREFIX "AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n"));
+                return srbStatus;
+            }
+
+            // failed again ? should not get here
+
             AtaReq->Srb = AtaReq->OriginalSrb;
             AtaReq->OriginalSrb = NULL;
+
             KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiHwInitializeChanger()\n"));
+            // Do-nothing call ?
             AtapiHwInitializeChanger (HwDeviceExtension, Srb,
                                       (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
             // fall out
@@ -6733,6 +6994,13 @@ AtapiSendCommand(
        (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
 
         KdPrint2((PRINT_PREFIX "AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb->Cdb[0], &(Srb->Cdb)));
+
+        if(!LunExt->IdentifyData.AtapiCmdSize &&
+            (Srb->CdbLength > 12)) {
+            KdPrint2((PRINT_PREFIX "Cdb16 not supported\n"));
+            return SRB_STATUS_INVALID_REQUEST;
+        }
+
         // Set data buffer pointer and words left.
         AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
         AtaReq->WordsLeft = Srb->DataTransferLength / 2;
@@ -6787,12 +7055,16 @@ GetLba2:
         }
 
         // check if DMA read/write
-        if(deviceExtension->HwFlags & UNIATA_SATA) {
-            // DEBUG !!!! for TEST ONLY
+        if(deviceExtension->HwFlags & UNIATA_AHCI) {
             KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (ahci)\n"));
             use_dma = TRUE;
             goto setup_dma;
         } else
+/*        if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) {
+            KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n"));
+            use_dma = TRUE;
+            goto setup_dma;
+        } else*/
         if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
             KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
         } else
@@ -7069,6 +7341,8 @@ retry:
         // Try to drain the data that one preliminary device thinks that it has
         // to transfer. Hopefully this random assertion of DRQ will not be present
         // in production devices.
+        statusByte = AtapiSuckPort2(chan);
+/*
         for (i = 0; i < 0x10000; i++) {
             GetStatus(chan, statusByte);
             if(statusByte & IDE_STATUS_DRQ) {
@@ -7077,8 +7351,8 @@ retry:
                 break;
             }
         }
-
-        if (i == 0x10000) {
+*/
+        if (statusByte & IDE_STATUS_DRQ) {
 make_reset:
             KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte));
 
@@ -7200,6 +7474,8 @@ make_reset:
     if(g_opt_AtapiSendDisableIntr) {
         AtapiDisableInterrupts(deviceExtension, lChannel);
     }
+    // remember status. Later we may check if error appeared after cmd packet 
+    statusByte0 = statusByte;
 
     // Write ATAPI packet command.
     AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
@@ -7241,9 +7517,41 @@ make_reset:
 
     WriteBuffer(chan,
                 (PUSHORT)Srb->Cdb,
-                6,
+                LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
                 0);
 
+    GetStatus(chan, statusByte);
+    KdPrint3((PRINT_PREFIX "AtapiSendCommand: cmd status (%#x)\n", statusByte));
+
+    // When we operate in DMA mode, we should not start transfer when there is an error on entry
+    // Interrupt may never come in such case.
+    if(statusByte & IDE_STATUS_ERROR) {
+        UCHAR interruptReason;
+
+        GetBaseStatus(chan, statusByte);
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on cmd: (%#x)\n", statusByte));
+
+        interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x\n", interruptReason));
+
+        // TODO:  we should check interruptReason and decide what to do now
+
+        // Read the error reg. to clear it and fail this request.
+        AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
+        return MapError(deviceExtension, Srb);
+    }
+/*    if(statusByte & IDE_STATUS_DSC) {
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: DSC on cmd: (%#x)\n", statusByte));
+        // Read the error reg. to clear it and fail this request.
+        statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte));
+        if(statusByte >> 4) {
+            GetBaseStatus(chan, statusByte);
+            AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
+            return MapError(deviceExtension, Srb);
+        }
+    }
+*/
     if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
         AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
     }
@@ -7301,13 +7609,15 @@ IdeSendCommand(
     SetCheckPoint(4);
 
     UCHAR statusByte,errorByte;
-    ULONG status;
+    ULONG status = SRB_STATUS_INVALID_REQUEST;
     ULONG i;
     ULONGLONG lba;
     PMODE_PARAMETER_HEADER   modeData;
     //ULONG ldev;
     ULONG DeviceNumber;
     PATA_REQ AtaReq;
+    UCHAR command;
+
     SetCheckPoint(5);
     //ULONG __ebp__ = 0;
 
@@ -7450,7 +7760,7 @@ default_no_prep:
 
             // Fill in vendor identification fields.
             for (i = 0; i < 24; i += 2) {
-                MOV_DW_SWP(inquiryData->VendorId[i], ((PUCHAR)identifyData->ModelNumber)[i]);
+                MOV_DW_SWP(inquiryData->DeviceIdentificationString[i], ((PUCHAR)identifyData->ModelNumber)[i]);
             }
 /*
             // Initialize unused portion of product id.
@@ -7469,21 +7779,61 @@ default_no_prep:
 
         break;
 
+    case SCSIOP_REPORT_LUNS: {
+
+        ULONG alen;
+        PREPORT_LUNS_INFO_HDR LunInfo;
+        
+        KdPrint2((PRINT_PREFIX 
+                   "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
+                   Srb->PathId, Srb->Lun, Srb->TargetId));
+
+        MOV_DD_SWP(alen, cdb->REPORT_LUNS.AllocationLength);
+
+        if(alen < 16) {
+            goto invalid_cdb;
+        }
+        alen = 8;
+
+        LunInfo = (PREPORT_LUNS_INFO_HDR)(Srb->DataBuffer);
+        RtlZeroMemory(LunInfo, 16);
+
+        MOV_DD_SWP( LunInfo->ListLength, alen );
+        Srb->DataTransferLength = 16;
+        status = SRB_STATUS_SUCCESS;
+
+        break; }
+
     case SCSIOP_MODE_SENSE:
 
         KdPrint2((PRINT_PREFIX 
                    "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
                    Srb->PathId, Srb->Lun, Srb->TargetId));
-        // This is used to determine if the media is write-protected.
-        // Since IDE does not support mode sense then we will modify just the portion we need
-        // so the higher level driver can determine if media is protected.
+        
+        if(cdb->MODE_SENSE.PageCode == MODE_PAGE_POWER_CONDITION) {
+            PMODE_POWER_CONDITION_PAGE modeData;
+
+            KdPrint2((PRINT_PREFIX "MODE_PAGE_POWER_CONDITION\n"));
+            modeData = (PMODE_POWER_CONDITION_PAGE)(Srb->DataBuffer);
+            if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_POWER_CONDITION_PAGE)) {
+                status = SRB_STATUS_DATA_OVERRUN;
+            } else {
+                RtlZeroMemory(modeData, sizeof(MODE_POWER_CONDITION_PAGE));
+                modeData->PageCode = MODE_PAGE_POWER_CONDITION;
+                modeData->PageLength = sizeof(MODE_PAGE_POWER_CONDITION)-sizeof(MODE_PARAMETER_HEADER);
+                modeData->Byte3.Fields.Idle = LunExt->PowerState <= StartStop_Power_Idle;
+                modeData->Byte3.Fields.Standby = LunExt->PowerState == StartStop_Power_Standby;
+                Srb->DataTransferLength = sizeof(MODE_POWER_CONDITION_PAGE);
+                status = SRB_STATUS_SUCCESS;
+            }
+        } else
         if(cdb->MODE_SENSE.PageCode == MODE_PAGE_CACHING) {
             PMODE_CACHING_PAGE modeData;
 
             KdPrint2((PRINT_PREFIX "MODE_PAGE_CACHING\n"));
-            modeData = (PMODE_CACHING_PAGE)Srb->DataBuffer;
+            modeData = (PMODE_CACHING_PAGE)(Srb->DataBuffer);
             if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_CACHING_PAGE)) {
-                status = STATUS_BUFFER_TOO_SMALL;
+                status = SRB_STATUS_DATA_OVERRUN;
             } else {
                 RtlZeroMemory(modeData, sizeof(MODE_CACHING_PAGE));
                 modeData->PageCode = MODE_PAGE_CACHING;
@@ -7496,6 +7846,10 @@ default_no_prep:
         } else
         if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
 
+            // This is used to determine if the media is write-protected.
+            // Since IDE does not support mode sense then we will modify just the portion we need
+            // so the higher level driver can determine if media is protected.
+
             //SelectDrive(chan, DeviceNumber);
             //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
             //statusByte = WaitOnBusy(chan);
@@ -7685,21 +8039,98 @@ default_no_prep:
     case SCSIOP_START_STOP_UNIT:
 
         KdPrint2((PRINT_PREFIX 
-                   "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
-                   Srb->PathId, Srb->Lun, Srb->TargetId));
+                   "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
+                   cdb->START_STOP.Immediate, Srb->PathId, Srb->Lun, Srb->TargetId));
         //Determine what type of operation we should perform
-        cdb = (PCDB)Srb->Cdb;
 
-        if (cdb->START_STOP.LoadEject == 1){
+        command = 0;
 
-            statusByte = WaitOnBaseBusy(chan);
+        if(cdb->START_STOP.FL ||
+           cdb->START_STOP.FormatLayerNumber ||
+           cdb->START_STOP.Reserved2 ||
+           cdb->START_STOP.Reserved2_2 ||
+           cdb->START_STOP.Reserved3 ||
+           FALSE) {
+            goto invalid_cdb;
+        }
+
+        if (cdb->START_STOP.PowerConditions) {
+            KdPrint2((PRINT_PREFIX "START_STOP Power %d\n", cdb->START_STOP.PowerConditions));
+            switch(cdb->START_STOP.PowerConditions) {
+            case StartStop_Power_Idle:
+                command = IDE_COMMAND_IDLE_IMMED;
+                break;
+            case StartStop_Power_Standby:
+                command = IDE_COMMAND_STANDBY_IMMED;
+                break;
+            case StartStop_Power_Sleep:
+                // TODO: we should save power state in order to know
+                // that RESET sould be issued to revert device into
+                // operable state
+
+                command = IDE_COMMAND_SLEEP;
+                break;
+            default:
+                goto invalid_cdb;
+            }
+            LunExt->PowerState = cdb->START_STOP.PowerConditions;
+        } else
+        if (cdb->START_STOP.LoadEject == 1) {
+            KdPrint2((PRINT_PREFIX "START_STOP eject\n"));
             // Eject media,
             // first select device 0 or 1.
             //SelectDrive(chan, DeviceNumber);
             //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
-            statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_MEDIA_EJECT, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
+            command = IDE_COMMAND_MEDIA_EJECT;
+        } else
+        if (cdb->START_STOP.Start == 0) {
+            KdPrint2((PRINT_PREFIX "START_STOP standby\n"));
+            command = IDE_COMMAND_STANDBY_IMMED;
+        } else {
+            // TODO: we may need to perform hard reset (after sleep) or
+            // issue IDE_COMMAND_IDLE_IMMED in order to activate device
+            KdPrint2((PRINT_PREFIX "START_STOP activate\n"));
+
+            if(LunExt->PowerState == StartStop_Power_Sleep) {
+                UniataUserDeviceReset(deviceExtension, LunExt, lChannel);
+                status = SRB_STATUS_SUCCESS;
+                break;
+            } else
+            if(LunExt->PowerState > StartStop_Power_Idle) {
+                KdPrint2((PRINT_PREFIX "  issue IDLE\n"));
+                command = IDE_COMMAND_IDLE_IMMED;
+            } else {
+                KdPrint2((PRINT_PREFIX "  do nothing\n"));
+                status = SRB_STATUS_SUCCESS;
+                break;
+            }
+        }
+        if(command) {
+            statusByte = WaitOnBaseBusy(chan);
+            statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, command, 0, 0, 0, 0, 0, 
+                cdb->START_STOP.Immediate ? ATA_IMMEDIATE : ATA_WAIT_READY);
+            status = (statusByte & IDE_STATUS_ERROR) ? SRB_STATUS_ERROR : SRB_STATUS_SUCCESS;
+            //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
+
+        } else {
+invalid_cdb:
+            KdPrint2((PRINT_PREFIX "START_STOP invalid\n"));
+            if (Srb->SenseInfoBuffer) {
+
+                PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
+
+                senseBuffer->ErrorCode = 0x70;
+                senseBuffer->Valid     = 1;
+                senseBuffer->AdditionalSenseLength = 0xb;
+                senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST;
+                senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_CDB;
+                senseBuffer->AdditionalSenseCodeQualifier = 0;
+
+                Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID;
+                Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
+            }
+            status = SRB_STATUS_ERROR;
         }
-        status = SRB_STATUS_SUCCESS;
         break;
 
     case SCSIOP_MEDIUM_REMOVAL:
@@ -7761,25 +8192,59 @@ default_no_prep:
         
         regs = (PIDEREGS_EX) &(Srb->Cdb[2]);
 
-        lChannel = Srb->TargetId >> 1;
-
-        regs->bDriveHeadReg &= 0x0f;
-        regs->bDriveHeadReg |= (UCHAR) (((Srb->TargetId & 0x1) << 4) | 0xA0);
+        if(chan->DeviceExtension->HwFlags & UNIATA_SATA) {
+            //lChannel = Srb->TargetId >> 1;
+        } else {
+            DeviceNumber = max(DeviceNumber, 1);
+            regs->bDriveHeadReg &= 0x0f;
+            regs->bDriveHeadReg |= (UCHAR) (((DeviceNumber & 0x1) << 4) | 0xA0);
+        }
 
         if((regs->bOpFlags & 1) == 0) {      // execute ATA command
 
             KdPrint2((PRINT_PREFIX 
-                       "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
+                       "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
                        Srb->PathId, Srb->Lun, Srb->TargetId));
 
+            if((regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) == UNIATA_SPTI_EX_SPEC_TO) {
+                to_lim = Srb->TimeOutValue;
+            } else {
+                if(Srb->TimeOutValue <= 2) {
+                    to_lim = Srb->TimeOutValue*900;
+                } else {
+                    to_lim = (Srb->TimeOutValue*999) - 500;
+                }
+            }
 
             AtapiDisableInterrupts(deviceExtension, lChannel);
 
+            if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
+                // AHCI
+                statusByte = UniataAhciSendPIOCommandDirect(
+                        deviceExtension,
+                        lChannel,
+                        DeviceNumber,
+                        Srb,
+                        regs,
+                        ATA_WAIT_INTR,
+                        to_lim
+                        );
+                if(statusByte == IDE_STATUS_WRONG) {
+                    goto passthrough_err;
+                }
+                if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
+                    UniataAhciAbortOperation(chan);
+                    goto passthrough_err;
+                }
+                goto passthrough_done;
+            }
+
+            // SATA/PATA
             if((AtaCommandFlags[regs->bCommandReg] & ATA_CMD_FLAG_DMA) || (regs->bOpFlags & UNIATA_SPTI_EX_USE_DMA)) {
-                if((chan->lun[Srb->TargetId & 0x1]->LimitedTransferMode >= ATA_DMA)) {
+                if((chan->lun[DeviceNumber]->LimitedTransferMode >= ATA_DMA)) {
                     use_dma = TRUE;
                     // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
-                    if(!AtapiDmaSetup(HwDeviceExtension, Srb->TargetId & 0x1, lChannel, Srb,
+                    if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
                                   (PUCHAR)(Srb->DataBuffer),
                                   ((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1)))) {
                         use_dma = FALSE;
@@ -7787,7 +8252,7 @@ default_no_prep:
                 }
             }
 
-            AtapiWritePort1(chan, IDX_IO1_o_DriveSelect,  regs->bDriveHeadReg);
+            AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, regs->bDriveHeadReg);
             AtapiStallExecution(10);
 
             if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) {      // execute ATA command
@@ -7815,20 +8280,11 @@ default_no_prep:
                 if(statusByte & IDE_STATUS_ERROR) {
                     goto passthrough_err;
                 }
-                AtapiDmaStart(HwDeviceExtension, (Srb->TargetId & 0x1), lChannel, Srb);
+                AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
             }
 
             ScsiPortStallExecution(1);                  // wait for busy to be set
 
-            if(regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) {
-                to_lim = Srb->TimeOutValue;
-            } else {
-                if(Srb->TimeOutValue <= 2) {
-                    to_lim = Srb->TimeOutValue*900;
-                } else {
-                    to_lim = (Srb->TimeOutValue*999) - 500;
-                }
-            }
             for(i=0; i<to_lim;i+=2) {      // 2 msec from WaitOnBaseBusy()
                 statusByte = WaitOnBaseBusy(chan);      // wait for busy to be clear, up to 2 msec
                 GetBaseStatus(chan, statusByte);
@@ -7849,7 +8305,7 @@ default_no_prep:
             if(use_dma) {
                 AtapiCheckInterrupt__(deviceExtension, (UCHAR)lChannel);
             }
-            AtapiDmaDone(deviceExtension, (Srb->TargetId & 0x1), lChannel, NULL);
+            AtapiDmaDone(deviceExtension, DeviceNumber, lChannel, NULL);
             GetBaseStatus(chan, statusByte);
 
             if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
@@ -7889,34 +8345,33 @@ passthrough_err:
                 }
                 status = SRB_STATUS_SUCCESS;
             }
-
+passthrough_done:;
             AtapiEnableInterrupts(deviceExtension, lChannel);
 
         } else { // read task register
 
+            BOOLEAN use48;
             regs = (PIDEREGS_EX) Srb->DataBuffer;
 
-            regs->bDriveHeadReg    = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect);
+            KdPrint2((PRINT_PREFIX 
+                       "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
+                       Srb->PathId, Srb->Lun, Srb->TargetId));
 
-            if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) {      // execute ATA command
-                regs->bFeaturesReg     = AtapiReadPort1(chan, IDX_IO1_i_Error);
-                regs->bSectorCountReg  = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
-                regs->bSectorNumberReg = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
-                regs->bCylLowReg       = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
-                regs->bCylHighReg      = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
+            if((Srb->DataTransferLength >= sizeof(IDEREGS_EX)) &&
+               (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND)) {
+                use48 = TRUE;
+            } else
+            if(Srb->DataTransferLength >= sizeof(IDEREGS)) {
+                use48 = FALSE;
             } else {
-                regs->bFeaturesReg     = AtapiReadPort1(chan, IDX_IO1_i_Error);
-                regs->bFeaturesRegH    = AtapiReadPort1(chan, IDX_IO1_i_Error);
-                regs->bSectorCountReg  = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
-                regs->bSectorCountRegH = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
-                regs->bSectorNumberReg = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
-                regs->bSectorNumberRegH= AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
-                regs->bCylLowReg       = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
-                regs->bCylLowRegH      = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
-                regs->bCylHighReg      = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
-                regs->bCylHighRegH     = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
+                KdPrint2((PRINT_PREFIX " buffer too small \n"));
+                status = SRB_STATUS_DATA_OVERRUN;
+                break;
             }
-            regs->bCommandReg      = AtapiReadPort1(chan, IDX_IO1_i_Status);
+            RtlZeroMemory(regs, use48 ? sizeof(IDEREGS_EX) : sizeof(IDEREGS));
+            regs->bOpFlags = use48 ? ATA_FLAGS_48BIT_COMMAND : 0;
+            UniataSnapAtaRegs(chan, 0, regs);
+
             status = SRB_STATUS_SUCCESS;
         }
         break;
@@ -8091,23 +8546,24 @@ NTAPI
 UniataUserDeviceReset(
     PHW_DEVICE_EXTENSION deviceExtension,
     PHW_LU_EXTENSION LunExt,
-    ULONG PathId
+    ULONG lChannel
     )
 {
     ULONG i;
-    AtapiDisableInterrupts(deviceExtension, PathId);
-    if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
+    AtapiDisableInterrupts(deviceExtension, lChannel);
+    if ((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
+        (LunExt->PowerState != StartStop_Power_Sleep)) {
         KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset ATAPI\n"));
-        AtapiSoftReset(&(deviceExtension->chan[PathId]), LunExt->Lun);
+        AtapiSoftReset(&(deviceExtension->chan[lChannel]), LunExt->Lun);
     } else {
         KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
-        AtapiResetController__(deviceExtension, PathId, RESET_COMPLETE_NONE);
+        AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_NONE);
         for(i=0; i<deviceExtension->NumberLuns; i++) {
-            deviceExtension->chan[PathId].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
+            deviceExtension->chan[lChannel].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
         }
     }
     LunExt->DeviceFlags |= DFLAGS_REINIT_DMA;  // force PIO/DMA reinit
-    AtapiEnableInterrupts(deviceExtension, PathId);
+    AtapiEnableInterrupts(deviceExtension, lChannel);
     return;
 } // end UniataUserDeviceReset()
 
@@ -8153,6 +8609,7 @@ Routine Description:
 
     This routine is called from the SCSI port driver synchronized
     with the kernel to start an IO request.
+    ->HwStartIo
 
 Arguments:
 
@@ -8216,13 +8673,14 @@ AtapiStartIo__(
         UniAtaClearAtaReq(Srb->SrbExtension);
     }
 
-    do {
+    do { // fetch all queued commands for the channel (if valid)
 
         lChannel = GET_CHANNEL(Srb);
         //ldev = GET_LDEV(Srb);
         chan = NULL;
         LunExt = NULL;
         DeviceNumber = GET_CDEV(Srb);
+        commPort = FALSE;
 
         //ASSERT(deviceExtension);
         //ASSERT(chan);
@@ -8242,6 +8700,14 @@ AtapiStartIo__(
                        "AtapiStartIo: Communication port\n"));
             if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
 
+                if(Srb->DataTransferLength < sizeof(PINQUIRYDATA)) {
+                    KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", Srb->DataTransferLength,
+                        sizeof(PINQUIRYDATA) ));
+wrong_buffer_size:
+                    status = SRB_STATUS_DATA_OVERRUN;
+                    goto complete_req;
+                }
+
                 PINQUIRYDATA    inquiryData  = (PINQUIRYDATA)(Srb->DataBuffer);
 
                 KdPrint2((PRINT_PREFIX 
@@ -8261,22 +8727,26 @@ AtapiStartIo__(
             /* Pass IOCTL request down */
         } else
         if(lChannel >= deviceExtension->NumberChannels ||
-           Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns ||
-           Srb->Lun) {
+            Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns ||
+            Srb->Lun) {
 
-           if(lChannel >= deviceExtension->NumberChannels) {
-               chan = NULL;
-           }
+            if(lChannel >= deviceExtension->NumberChannels) {
+                chan = NULL;
+            }
 
 reject_srb:
             //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
-                KdPrint3((PRINT_PREFIX 
+            KdPrint3((PRINT_PREFIX 
                            "AtapiStartIo: SRB rejected\n"));
-                // Indicate no device found at this address.
-                KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
-                status = SRB_STATUS_SELECTION_TIMEOUT;
-                goto complete_req;
+            // Indicate no device found at this address.
+            KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
+            status = SRB_STATUS_SELECTION_TIMEOUT;
+            goto complete_req;
             //}
+        } else
+        if((deviceExtension->HwFlags & UNIATA_AHCI) &&
+           !UniataAhciChanImplemented(deviceExtension, lChannel)) {
+            chan = NULL;
         }
 
         if(!commPort) {
@@ -8385,6 +8855,7 @@ reject_srb:
                 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
 
             } else {
+
                 // Send command to device.
                 KdPrint2((PRINT_PREFIX "Send to device %x\n", Srb->Cdb[0]));
                 if(TopLevel) {
@@ -8424,7 +8895,8 @@ reject_srb:
 #endif //NAVO_TEST
 
                 if(atapiDev &&
-                   (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) {
+                   (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)/* &&
+                   (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
                     KdPrint3((PRINT_PREFIX "Try ATAPI send %x\n", Srb->Cdb[0]));
                     status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
                 } else {
@@ -8619,44 +9091,122 @@ do_bus_reset:
 
             if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
 
+                ULONG targetId = (ULONG)(-1);
+
+                if(len < sizeof(SRB_IO_CONTROL)) {
+                    goto wrong_buffer_size;
+                }
+
+                // extract bogus bus address
                 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
                 case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
-
                     PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
-                    UCHAR deviceNumber;
 
-                    KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
+                    if(len < sizeof(SRB_IO_CONTROL)+sizeof(GETVERSIONINPARAMS)) {
+                        goto wrong_buffer_size;
+                    }
 
-                    // Version and revision per SMART 1.03
+                    targetId = versionParameters->bIDEDeviceMap;
+                    KdPrint2((PRINT_PREFIX "targetId (smart ver) %d\n", targetId));
+                    break; }
+                case IOCTL_SCSI_MINIPORT_IDENTIFY:
+                case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
+                case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
+                case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
+                case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
+                case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
+                case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
+                case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
+                case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
+                case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE:
+                case IOCTL_SCSI_MINIPORT_READ_SMART_LOG:
+                case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG:
+                    {
+                    PSENDCMDINPARAMS   cmdInParameters = (PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
+
+                    if(len < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDINPARAMS) - 1) {
+                        goto wrong_buffer_size;
+                    }
 
-                    versionParameters->bVersion = 1;
-                    versionParameters->bRevision = 1;
-                    versionParameters->bReserved = 0;
+                    targetId = cmdInParameters->bDriveNumber;
+                    KdPrint2((PRINT_PREFIX "targetId (smart/ident) %d\n", targetId));
+                    break; }
+                default:
+invalid_request:
+                    KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
+                                ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
+                    status = SRB_STATUS_INVALID_REQUEST;
+                    goto complete_req;
+                } // end switch()
 
-                    // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
-                    versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD);
+                // adjust (if necessary) bus address
+                if(targetId != (ULONG)(-1)) {
 
                     // This is done because of how the IOCTL_SCSI_MINIPORT
                     // determines 'targetid's'. Disk.sys places the real target id value
                     // in the DeviceMap field. Once we do some parameter checking, the value passed
                     // back to the application will be determined.
 
-                    deviceNumber = versionParameters->bIDEDeviceMap;
-
+                    if (deviceExtension->NumberChannels == 1) {
+                        // do this for legacy controllers and legacy callers
+                        KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call\n"));
+                        DeviceNumber = (targetId & 0x01);
+                        lChannel = 0;
+                    } else
                     if(commPort) {
+                        // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
+                        // due to DISK.SYS design bug, we have invalid SCSI address in SRB
+                        KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call (2)\n"));
+                        if(deviceExtension->HwFlags & UNIATA_AHCI) {
+                            lChannel = (UCHAR)targetId / 2;
+                            DeviceNumber = 0;
+                        } else {
+                            lChannel = (UCHAR)(targetId / 2);
+                            DeviceNumber = targetId & 0x01;
+                        }
+                    } else {
+                        // otherwise assume lChannel and DeviceNumber from Srb are ok
+                    }
+                    if(lChannel >= deviceExtension->NumberChannels ||
+                        DeviceNumber >= deviceExtension->NumberLuns) {
                         KdPrint2((PRINT_PREFIX 
-                                   "AtapiStartIo: SCSIDISK IOCTL for commPort -> EXECUTE_SCSI rejected (2)\n"));
+                                   "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
+                                       targetId));
                         // Indicate no device found at this address.
-                        KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
-                        status = SRB_STATUS_SELECTION_TIMEOUT;
-                        break;
+                        goto reject_srb;
                     }
-                    
-                    if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT) ||
-                        atapiDev) {
+                    targetId = lChannel*deviceExtension->NumberLuns+DeviceNumber;
+                    chan = &(deviceExtension->chan[lChannel]);
+                    LunExt = chan->lun[DeviceNumber];
+                    if(!LunExt) {
+                        goto reject_srb;
+                    }
+                    atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
 
-                        status = SRB_STATUS_SELECTION_TIMEOUT;
-                        break;
+                    if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
+                        goto reject_srb;
+                    }
+                }
+
+                switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
+                case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
+
+                    PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
+                    UCHAR deviceNumberMap;
+
+                    KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
+
+                    // Version and revision per SMART 1.03
+
+                    versionParameters->bVersion = 1;
+                    versionParameters->bRevision = 1;
+                    versionParameters->bReserved = 0;
+
+                    // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
+                    versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD);
+
+                    if (atapiDev) {
+                        goto invalid_request;
                     }
 
                     // NOTE: This will only set the bit
@@ -8668,19 +9218,20 @@ do_bus_reset:
                     //     3 2 1 0
 
                     if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
-                        deviceNumber = 1 << lChannel;
+                        deviceNumberMap = 1 << lChannel;
+                        DeviceNumber = 0;
                     } else
                     if (deviceExtension->NumberChannels == 1) {
                         if (chan->PrimaryAddress) {
-                            deviceNumber = 1 << DeviceNumber;
+                            deviceNumberMap = 1 << DeviceNumber;
                         } else {
-                            deviceNumber = 4 << DeviceNumber;
+                            deviceNumberMap = 4 << DeviceNumber;
                         }
                     } else {
-                        deviceNumber = 1 << (DeviceNumber+lChannel*2);
+                        deviceNumberMap = 1 << (DeviceNumber+lChannel*2);
                     }
 
-                    versionParameters->bIDEDeviceMap = deviceNumber;
+                    versionParameters->bIDEDeviceMap = deviceNumberMap;
 
                     status = SRB_STATUS_SUCCESS;
                     break;
@@ -8690,41 +9241,24 @@ do_bus_reset:
 
                     PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
                     SENDCMDINPARAMS   cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
-                    UCHAR             targetId;
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
                     // Extract the target.
-                    targetId = cmdInParameters.bDriveNumber;
                     KdPrint2((PRINT_PREFIX "targetId %d\n", targetId));
-                    if(deviceExtension->HwFlags & UNIATA_AHCI) {
-                        // cheat code for AHCI :)
-                        // upper layer assumes that we have 2 devices per channel
-                        // TODO: we should invent something to handle PM here
-                        targetId /= 2;
-                    }
-
-                    if((targetId >= deviceExtension->NumberChannels*deviceExtension->NumberLuns) ||
-                       !(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
-                        KdPrint2((PRINT_PREFIX "Error: xxx_ID_CMD for non-existant device\n"));
-                        status = SRB_STATUS_SELECTION_TIMEOUT;
-                        break;
-                    }
 
                     switch(cmdInParameters.irDriveRegs.bCommandReg) {
                     case ID_CMD:
-                        if((deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
+                        if(atapiDev) {
                             KdPrint2((PRINT_PREFIX "Error: ID_CMD for ATAPI\n"));
-                            status = SRB_STATUS_INVALID_REQUEST;
-                            break;
+                            goto invalid_request;
                         }
                         /* FALL THROUGH */
                     case ATAPI_ID_CMD:
 
-                        if(!(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
+                        if(!atapiDev &&
                            (cmdInParameters.irDriveRegs.bCommandReg == ATAPI_ID_CMD)) {
                             KdPrint2((PRINT_PREFIX "Error: ATAPI_ID_CMD for non-ATAPI\n"));
-                            status = SRB_STATUS_INVALID_REQUEST;
-                            break;
+                            goto invalid_request;
                         }
 
                         len = min(len, sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE);
@@ -8740,9 +9274,21 @@ do_bus_reset:
                         cmdOutParameters->DriverStatus.bIDEError = 0;
 
                         // Extract the identify data from the device extension.
-                        ScsiPortMoveMemory (cmdOutParameters->bBuffer, &deviceExtension->lun[targetId].IdentifyData,
+                        ScsiPortMoveMemory (cmdOutParameters->bBuffer, &(LunExt->IdentifyData),
                             cmdOutParameters->cBufferSize);
 
+                        if((cmdOutParameters->cBufferSize == IDENTIFY_BUFFER_SIZE) &&
+                           (LunExt->IdentifyData.ChecksumValid == ATA_ChecksumValid)) {
+                            // adjust checksum if it is possible
+                            CHAR csum = 0;
+                            ULONG i;
+
+                            for(i=0; i < IDENTIFY_BUFFER_SIZE-1; i++) {
+                                csum += (CHAR)(cmdOutParameters->bBuffer[i]);
+                            }
+                            cmdOutParameters->bBuffer[i] = -csum;
+                            KdPrint2((PRINT_PREFIX "AtapiStartIo: adjust checksum %d\n"));
+                        }
                         KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
 
                         status = SRB_STATUS_SUCCESS;
@@ -8756,7 +9302,7 @@ do_bus_reset:
                     }
                     break;
                 }
-
+/*
                 case  IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
                 case  IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
                 case  IOCTL_SCSI_MINIPORT_ENABLE_SMART:
@@ -8765,14 +9311,15 @@ do_bus_reset:
                 case  IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
                 case  IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
                 case  IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
-
+*/
+                default:
+                    // *all* IOCTLs here are SMART
                     if(commPort) {
                         KdPrint2((PRINT_PREFIX 
                                    "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
-                        // Indicate no device found at this address.
-                        KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
-                        status = SRB_STATUS_SELECTION_TIMEOUT;
-                        break;
+                    }
+                    if (atapiDev) {
+                        goto invalid_request;
                     }
 
                     PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
@@ -8791,16 +9338,17 @@ do_bus_reset:
                         KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
                     } else {
 
-                        status = IdeSendSmartCommand(HwDeviceExtension,Srb);
+                        status = IdeSendSmartCommand(HwDeviceExtension, Srb, targetId);
                     }
                     break;
 
-                default :
+                // we should not get here, checked above
+/*                default :
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
                                 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
                     status = SRB_STATUS_INVALID_REQUEST;
                     break;
-
+*/
                 }
             } else
             if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"-UNIATA-", sizeof("-UNIATA-")-1)) {
@@ -8809,8 +9357,15 @@ do_bus_reset:
                 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
                 ULONG DeviceNumber = AtaCtl->addr.TargetId;
                 BOOLEAN bad_ldev;
-                ULONG i;
+                ULONG i, pos;
+
+                pos = FIELD_OFFSET(UNIATA_CTL, RawData);
                 //chan = &(deviceExtension->chan[lChannel]);
+                if(len < pos) {
+                    KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
+                        FIELD_OFFSET(UNIATA_CTL, RawData) ));
+                    goto wrong_buffer_size;
+                }
 
                 if(AtaCtl->addr.Lun ||
                    AtaCtl->addr.TargetId >= deviceExtension->NumberLuns || 
@@ -8875,6 +9430,11 @@ handle_bad_ldev:
                     }
                     goto uata_ctl_queue;
                 case  IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
+                    if(len < pos+sizeof(AtaCtl->SetMode)) {
+                        KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
+                            pos+sizeof(AtaCtl->SetMode) ));
+                        goto wrong_buffer_size;
+                    }
                     if(!AtaCtl->SetMode.ApplyImmediately) {
                         break;
                     }
@@ -8905,6 +9465,11 @@ uata_ctl_queue:
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: rescan bus\n"));
 
+                    if(len < pos+sizeof(AtaCtl->FindDelDev)) {
+                        KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
+                            pos+sizeof(AtaCtl->FindDelDev) ));
+                        goto wrong_buffer_size;
+                    }
                     if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) {
                         KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n"));
                         if(AtaCtl->addr.TargetId != 0xff) {
@@ -8929,10 +9494,16 @@ uata_ctl_queue:
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: remove %#x:%#x\n", AtaCtl->addr.PathId, AtaCtl->addr.TargetId));
 
+                    if(len < pos+sizeof(AtaCtl->FindDelDev)) {
+                        KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
+                            pos+sizeof(AtaCtl->FindDelDev) ));
+                        goto wrong_buffer_size;
+                    }
                     LunExt->DeviceFlags = 0;
                     if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) {
                         KdPrint2((PRINT_PREFIX "AtapiStartIo: hide from further detection\n"));
-                        LunExt->DeviceFlags |= DFLAGS_HIDDEN;
+                        //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
+                        UniataForgetDevice(LunExt);
                     }
 
                     for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
@@ -8946,6 +9517,11 @@ uata_ctl_queue:
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Set transfer mode\n"));
 
+                    if(len < pos+sizeof(AtaCtl->SetMode)) {
+                        KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
+                            pos+sizeof(AtaCtl->SetMode) ));
+                        goto wrong_buffer_size;
+                    }
                     if(AtaCtl->SetMode.OrigMode != IOMODE_NOT_SPECIFIED) {
                         LunExt->OrigTransferMode = (UCHAR)(AtaCtl->SetMode.OrigMode);
                     }
@@ -8973,9 +9549,15 @@ uata_ctl_queue:
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Get transfer mode\n"));
 
+                    if(len < pos+sizeof(AtaCtl->GetMode)) {
+                        KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
+                            pos+sizeof(AtaCtl->GetMode) ));
+                        goto wrong_buffer_size;
+                    }
                     AtaCtl->GetMode.OrigMode    = LunExt->OrigTransferMode;
                     AtaCtl->GetMode.MaxMode     = LunExt->LimitedTransferMode;
                     AtaCtl->GetMode.CurrentMode = LunExt->TransferMode;
+                    AtaCtl->GetMode.PhyMode     = LunExt->PhyTransferMode;
 
                     status = SRB_STATUS_SUCCESS;
                     break;
@@ -8984,6 +9566,11 @@ uata_ctl_queue:
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Get version\n"));
 
+                    if(len < pos+sizeof(AtaCtl->Version)) {
+                        KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
+                            pos+sizeof(AtaCtl->Version) ));
+                        goto wrong_buffer_size;
+                    }
                     AtaCtl->Version.Length      = sizeof(GETDRVVERSION);
                     AtaCtl->Version.VersionMj   = UNIATA_VER_MJ;
                     AtaCtl->Version.VersionMn   = UNIATA_VER_MN;
@@ -8997,14 +9584,12 @@ uata_ctl_queue:
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Get adapter info\n"));
 
-                    AtaCtl->AdapterInfo.HeaderLength = FIELD_OFFSET(ADAPTERINFO, Chan);
-
-                    if(len < AtaCtl->AdapterInfo.HeaderLength + sizeof(AtaCtl->AdapterInfo.Chan)) {
-                        KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", len,
-                            AtaCtl->AdapterInfo.HeaderLength + sizeof(AtaCtl->AdapterInfo.Chan)));
-                        status = SRB_STATUS_DATA_OVERRUN;
-                        break;
+                    if(len < pos+sizeof(AtaCtl->AdapterInfo)) {
+                        KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
+                            pos+sizeof(AtaCtl->AdapterInfo) ));
+                        goto wrong_buffer_size;
                     }
+                    AtaCtl->AdapterInfo.HeaderLength = sizeof(ADAPTERINFO);
 
                     AtaCtl->AdapterInfo.DevID      = deviceExtension->DevID;
                     AtaCtl->AdapterInfo.RevID      = deviceExtension->RevID;
@@ -9031,8 +9616,35 @@ uata_ctl_queue:
                     }
                     AtaCtl->AdapterInfo.ChanInfoValid = FALSE;
                     AtaCtl->AdapterInfo.LunInfoValid = FALSE;
-
-                    RtlZeroMemory(&AtaCtl->AdapterInfo.Chan, sizeof(AtaCtl->AdapterInfo.Chan));
+                    AtaCtl->AdapterInfo.ChanHeaderLengthValid = TRUE;
+
+                    pos += AtaCtl->AdapterInfo.HeaderLength;
+
+                    // zero tail
+                    RtlZeroMemory(((PCHAR)AtaCtl)+pos,
+                        len-pos);
+
+                    if(len >= pos+AtaCtl->AdapterInfo.NumberChannels*sizeof(CHANINFO)) {
+                        PCHANINFO ChanInfo = (PCHANINFO)( ((PCHAR)AtaCtl)+pos );
+                        PHW_CHANNEL cur_chan;
+                        KdPrint2((PRINT_PREFIX "AtapiStartIo: Fill channel info\n"));
+                        for(i=0;i<AtaCtl->AdapterInfo.NumberChannels;i++) {
+                            KdPrint2((PRINT_PREFIX "chan[%d] %x\n", i, cur_chan));
+                            cur_chan = &(deviceExtension->chan[i]);
+                            ChanInfo->MaxTransferMode = cur_chan->MaxTransferMode;
+                            ChanInfo->ChannelCtrlFlags = cur_chan->ChannelCtrlFlags;
+                            RtlCopyMemory(&(ChanInfo->QueueStat), &(cur_chan->QueueStat), sizeof(ChanInfo->QueueStat));
+                            ChanInfo->ReorderCount        = cur_chan->ReorderCount;
+                            ChanInfo->IntersectCount      = cur_chan->IntersectCount;
+                            ChanInfo->TryReorderCount     = cur_chan->TryReorderCount;
+                            ChanInfo->TryReorderHeadCount = cur_chan->TryReorderHeadCount;
+                            ChanInfo->TryReorderTailCount = cur_chan->TryReorderTailCount;
+                            //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
+                            ChanInfo++;
+                        }
+                        AtaCtl->AdapterInfo.ChanInfoValid = TRUE;
+                        AtaCtl->AdapterInfo.ChanHeaderLength = sizeof(*ChanInfo);
+                    }
 
                     status = SRB_STATUS_SUCCESS;
                     break;
@@ -9103,8 +9715,10 @@ complete_req:
             // Set status in SRB.
             Srb->SrbStatus = (UCHAR)status;
 
-            KdPrint2((PRINT_PREFIX "AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan, Srb));
-            AtapiDmaDBSync(chan, Srb);
+            if(chan && Srb) {
+                KdPrint2((PRINT_PREFIX "AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan, Srb));
+                AtapiDmaDBSync(chan, Srb);
+            }
             KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan, Srb));
             UniataRemoveRequest(chan, Srb);
             // Indicate command complete.
@@ -9343,7 +9957,7 @@ DriverEntry(
     ULONG                  statusToReturn, newStatus;
     PUNICODE_STRING        RegistryPath = (PUNICODE_STRING)Argument2;
     BOOLEAN                ReEnter = FALSE;
-    WCHAR                  a;
+//    WCHAR                  a;
 #ifndef USE_REACTOS_DDK
     NTSTATUS               status;
 #endif
@@ -9356,7 +9970,7 @@ DriverEntry(
 
     Connect_DbgPrint();
     KdPrint2((PRINT_PREFIX "%s", (PCCHAR)ver_string));
-    a = (WCHAR)strlen(ver_string);
+    //a = (WCHAR)strlen(ver_string);
 
     g_opt_Verbose = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PrintLogo", 0);
     if(g_opt_Verbose) {
@@ -9539,6 +10153,15 @@ DriverEntry(
         if(GlobalConfig->AtDiskSecondaryAddressClaimed)
             SecondaryClaimed = TRUE;
 
+        if(!WinVer_WDM_Model && !PrimaryClaimed && !SecondaryClaimed &&
+            !(BMList[i].ChanInitOk & 0x80)) {
+            newStatus = UniataClaimLegacyPCIIDE(i);
+            if(newStatus != STATUS_SUCCESS) {
+                KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
+                break;
+            }
+        }
+
         if(g_opt_Verbose) {
             _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
         }
@@ -9597,7 +10220,15 @@ DriverEntry(
                     statusToReturn = newStatus;
                 }
                 if (newStatus == STATUS_SUCCESS) {
-                    BMList[i].ChanInitOk |= 0x01 << c;
+                    if(WinVer_Id() < WinVer_2k) {
+                        // This should be done in HwInitialize under w2k+ to ensure that 
+                        // channel is actually initialized
+                        BMList[i].ChanInitOk |= 0x01 << c;
+                    } else {
+                        if(BMList[i].ChanInitOk & (0x01 << c)) {
+                            KdPrint2((PRINT_PREFIX "HwInit passed\n"));
+                        }
+                    }
 /*
                     if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
                         c = 1; // this will break our for()
@@ -9606,43 +10237,28 @@ DriverEntry(
 */
                 }
             }
-            if(WinVer_Id() >= WinVer_2k) {
-                // the following doesn't work under higher OSes
+/*            if(WinVer_Id() >= WinVer_2k) {
+                // the following didn't work under higher OSes,
+                // until we move setting of FLAGS to HwInit
                 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
                 continue;
-            }
+            }*/
             if(BMList[i].ChanInitOk & 0x03) {
-                // under NT we receive status immediately, so
-                // we can omit alternative init method id STATUS_SUCCESS returned
+                // Under NT we receive status immediately, so
+                // we can omit alternative init method if STATUS_SUCCESS returned.
+                // Under w2k+ we relay on flags, set in HwInitialize.
                 KdPrint2((PRINT_PREFIX "Ok, no more retries required\n"));
                 break;
+            } else
+            if(WinVer_Id() >= WinVer_2k) {
+                // try AltInit if HwInit was not called immediately under w2k+
+                KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n"));
+            } else {
+                // if (WinVer_Id() == WinVer_NT) and some error occured
+                // try alternative init method
+                KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n"));
             }
-            // if (WinVer_Id() == WinVer_NT) and some error occured
-            // try alternative init method
         } // for(alt...)
-#if 0
-        if(WinVer_WDM_Model) {
-            hwInitializationData.comm.HwFindAdapter = UniataFindFakeBusMasterController;
-            hwInitializationData.comm.NumberOfAccessRanges = 5;
-            hwInitializationData.comm.AdapterInterfaceType = PCIBus;
-
-            hwInitializationData.comm.VendorId             = BMList[i].VendorId;
-            hwInitializationData.comm.VendorIdLength       = (USHORT) BMList[i].VendorIdLength;
-            hwInitializationData.comm.DeviceId             = BMList[i].DeviceId;
-            hwInitializationData.comm.DeviceIdLength       = (USHORT) BMList[i].DeviceIdLength;
-
-            //BMList[i].channel = 0/*(UCHAR)c*/;
-
-            KdPrint2((PRINT_PREFIX "Try init fake: %4.4s %4.4s \n",
-                                   hwInitializationData.comm.VendorId,
-                                   hwInitializationData.comm.DeviceId));
-            newStatus = ScsiPortInitialize(DriverObject,
-                                           Argument2,
-                                           &hwInitializationData.comm,
-                                           (PVOID)i);
-            KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
-        }
-#endif //0
         if(g_opt_Verbose) {
             if(BMList[i].ChanInitOk & 0x03) {
                 _PrintNtConsole("  OK\n");
@@ -9680,9 +10296,9 @@ DriverEntry(
         hwInitializationData.comm.NumberOfAccessRanges = 6;
         hwInitializationData.comm.AdapterInterfaceType = PCIBus;
 
-        hwInitializationData.comm.VendorId             = BMList[i].VendorId;
+        hwInitializationData.comm.VendorId             = (PVOID)BMList[i].VendorId;
         hwInitializationData.comm.VendorIdLength       = (USHORT) BMList[i].VendorIdLength;
-        hwInitializationData.comm.DeviceId             = BMList[i].DeviceId;
+        hwInitializationData.comm.DeviceId             = (PVOID)BMList[i].DeviceId;
         hwInitializationData.comm.DeviceIdLength       = (USHORT) BMList[i].DeviceIdLength;
 
         BMList[i].channel = 0/*(UCHAR)c*/;
@@ -10188,7 +10804,7 @@ AtapiAdapterControl(
             }
             if(deviceExtension->AdapterInterfaceType == PCIBus) {
                 // we must never get here for non-PCI
-                status = UniataDisconnectIntr2(HwDeviceExtension);
+                /*status =*/ UniataDisconnectIntr2(HwDeviceExtension);
                 BMList[deviceExtension->DevIndex].Isr2Enable = FALSE;
             }
             break;
@@ -10201,15 +10817,17 @@ AtapiAdapterControl(
 
             AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
             status = UniataConnectIntr2(HwDeviceExtension);
-            for (c = 0; c < numberChannels; c++) {
-                AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, c);
-                FindDevices(HwDeviceExtension, 0, c);
-                AtapiEnableInterrupts(deviceExtension, c);
-                AtapiHwInitialize__(deviceExtension, c);
-            }
-            if(deviceExtension->Isr2DevObj) {
-                // we must never get here for non-PCI
-                BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
+            if(NT_SUCCESS(status)) {
+                for (c = 0; c < numberChannels; c++) {
+                    AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, c);
+                    FindDevices(HwDeviceExtension, 0, c);
+                    AtapiEnableInterrupts(deviceExtension, c);
+                    AtapiHwInitialize__(deviceExtension, c);
+                }
+                if(deviceExtension->Isr2DevObj) {
+                    // we must never get here for non-PCI
+                    BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
+                }
             }
 
             break;
@@ -10234,6 +10852,8 @@ HalDisplayString (
     PUCHAR String
     );
 
+#define DEBUG_MSG_BUFFER_SIZE   512
+
 extern "C"
 VOID
 _cdecl
@@ -10242,19 +10862,25 @@ _PrintNtConsole(
     ...
     )
 {
-    int len;
-    UCHAR dbg_print_tmp_buff[512];
+    //int len;
+    UCHAR dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE];
 //    UNICODE_STRING msgBuff;
     va_list ap;
     va_start(ap, DebugMessage);
 
-    len = _vsnprintf((PCHAR)&dbg_print_tmp_buff[0], 511, DebugMessage, ap);
+    /*len =*/ _vsnprintf((PCHAR)&dbg_print_tmp_buff[0], DEBUG_MSG_BUFFER_SIZE-1, DebugMessage, ap);
 
-    dbg_print_tmp_buff[511] = 0;
+    dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE-1] = 0;
 
-    KdPrint(((PCHAR)&(dbg_print_tmp_buff[0])));
+    //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro
     HalDisplayString(dbg_print_tmp_buff);
 
+#ifdef _DEBUG
+    if(g_LogToDisplay > 1) {
+        AtapiStallExecution(g_LogToDisplay*1000);
+    }
+#endif // _DEBUG
+
     va_end(ap);
 
 } // end PrintNtConsole()