diff -ruN v45j5\chglog.txt v46b4\chglog.txt
--- v45j5\chglog.txt	Sun Jan 24 14:59:18 2016
+++ v46b4\chglog.txt	Mon Mar 21 12:34:04 2016
@@ -549,7 +549,7 @@
 --
 2012.09.24 - v0.44b2
 
-*) experimental fix for SATA ATAPI, check for DRQ (appeared, it is not not asserted on error)
+*) experimental fix for SATA ATAPI, check for DRQ (appeared, it is not asserted on error)
 
 --
 2012.09.25 - v0.44b3
@@ -704,7 +704,7 @@
 see ReactOS BUG-7020
 
 !) Added LUN 1->2 reallocation in case of fall-back to 'compatible' mode on Intel chips
-acording to 0x90 PCI reg.
+according to 0x90 PCI reg.
 see ReactOS BUG-7020
 
 --
@@ -753,7 +753,7 @@
 2015.02.08 - v0.45f3
 
 e) Added UniataSataClearErr() on ATAPI errors and controller reset
-e) Added extra wait for ready delay for SATA ATAPI reporting wrond device 
+e) Added extra wait for ready delay for SATA ATAPI reporting wrong device 
 state after reset
 !) perform generic device reset for nVidia SATA controllers if device 
 reports valid state. Previously, reset was never performed for SATA nVidia.
@@ -992,7 +992,7 @@
 --
 2016.01.18 - v0.45j2
 
-e) detect wrong Boch ATA DMA behavior. Versions prior to 2.6.8 expect 
+e) detect wrong Bochs ATA DMA behavior. Versions prior to 2.6.8 expect 
 ATA_DMA_READ *after* DMA start, however BM DMA specs declare opposite order.
 CTRFLAGS_DMA_BEFORE_R flag is introduced in order to manage this.
 (ROS BUG-6774)
@@ -1000,7 +1000,7 @@
 --
 2016.01.24 - v0.45j3
 
-e) more logs for detect wrong Boch ATA DMA behavior. (ROS BUG-6774)
+e) more logs for detect wrong Bochs ATA DMA behavior. (ROS BUG-6774)
 
 --
 2016.01.24 - v0.45j4
@@ -1013,3 +1013,180 @@
 
 !) fixed bug with missing AtapiDmaStart() on HDD Read in IdeReadWrite()
 
+--
+2016.03.05 - v0.45j6
+
+e) try use CTRFLAGS_DMA_BEFORE_R for ATAPI too
+!) move CTRFLAGS_DMA_BEFORE_R to global g_opt_BochDmaReadWorkaround
+e) do not use DMA on ATAPI under Bochs
+(ROS BUG-6774)
+!) fixed bug with completly cleared ChannelCtrlFlags on bus reset. Permanent 
+bits are masked with CTRFLAGS_PERMANENT
+
+--
+2016.03.06 - v0.45j7
+
+!) use g_opt_AtapiNoDma = TRUE for Bochs by default (ROS BUG-6774)
+e) try use g_opt_BochDmaReadWorkaround for both Read and Write operations
+(ROS BUG-6774)
+
+--
+2016.03.07 - v0.45j8
+
+e) do not use g_opt_BochDmaReadWorkaround for Write operations
+since DMA Start before ATA WRITE cause Boch DMA command abort immediately 
+after DMA Start w/o any error reports after ATA WRITE.
+!) Fixed bug in DMA Start / ATA WRITE sequence (missing DMA Start) for Bochs 
+in workaround mode
+
+See ROS BUG-6774
+
+--
+2016.03.07 - v0.45j9
+
+eo) try use DWORD-IO for ATAPI
+
+--
+2016.03.07 - v0.45j10
+
+*) added extra Bochs detection via ATA device S/N and FW (it is possible
+to meet no Boch VendorId on PCI bus)
+and absence of non-zero SubDevice/SubVendor on Intel chipsets
++) Added old PIIX DMA support
+
+--
+2016.03.08 - v0.46
+
+!) Fixed bug with PIO multiblock transfer (wordCount was not updated on each 
+iteration), which may cause buffer overflow
+!) Fixed bug with uninitialized max_bcount on PIO transfers on LBA-enabled devices,
+which could cause unnecessary request fragmentation in PIO mode.
+e) do not try automatically initialize CD-changers, since it may cause
+ATAPI CD-ROM freeze. Let CD-ROM driver do it itself for its own risk (and 
+knowledge). We shall jusy parse output on success.
+Original changer behavior can be reverted by UNIATA_INIT_CHANGERS define.
+(ROS BUG-9119)
+-) removed unnecessary calls of AtapiHwInitializeChanger()
++) track last used Lun on the channel chan->last_cdev
+
+--
+2016.03.09 - v0.46a
+
+*) fixed KeNumberProcessors ROS/NT DDK incompatibility issue
+*) fixed g_opt_BochDmaReadWorkaround variable name (use 'Bochs')
+*) fixed DBG vs _DEBUG ROS compilation issue
+!) check for DRQ is taken back. However, it is not always asserted on 
+error (v0.44b2), problem reported by RayeR
+
+--
+2016.03.09 - v0.46a1
+
+e) force PIO on SATA ATAPI (experiment for Pioneer, ROS BUG-9119)
+
+--
+2016.03.12 - v0.46a2
+
+e!) check ATAPI status (iReason) for CoD bit set before sending packet 
+command and wait for it (experiment for Pioneer, ROS BUG-9119)
+*) added logging of DMADirRequired bit from ATAPI Identify
+
+--
+2016.03.12 - v0.46a3
+
+!) IDE_STATUS_INDEX is excluded from Status vs AltStatus verification on 
+ISA, extra log added
+
+--
+2016.03.13 - v0.46a4
+
+!) IDE_STATUS_INDEX is excluded from StatusByte DRQ/Ready condition checks
+o) rewritten DRQ+CoD wait for ATAPI after ATA_PACKET command (ROS BUG-9119)
+
+--
+2016.03.14 - v0.46a5
+
+e) change ATAPI regs setting order
+e) add DriveSelect + IDE_USE_LBA for ATAPI
+e) set ByteCount regs to 0 for ATAPI DMA
+
+--
+2016.03.14 - v0.46a6
+
+e) allow DMA for short/unaligned data blocks for SATA ATAPI (ROS BUG-9119)
+
+--
+2016.03.14 - v0.46a7
+
+*) reverted to normal values of ByteCount regs on ATAPI DMA (ROS BUG-9119)
+*) updated IDENTIFY structure according to ATA8-d2015r2-ATAATAPI
+o) unified ATAPI regs setting code
+*) added Error reg logging if DRQ+CoD never comes (ROS BUG-9119)
+
+--
+2016.03.14 - v0.46a8
+
+e) added 16-byte alignment check for ATAPI DMA transfers
+e) added zero-filling of 'unused' ATAPI regs
+e) DRQ+CoD timeout is set to 1 sec
+e) defer ATAPI command packet sending to ISR for SATA ATAPI
+e) log port claiming operations on ISA init (we have problem with floppy.sys 
+on ISA, reported by KtP)
++) added IoRange cleanup on ISA init
+
+--
+2016.03.17 - v0.46b
+
+-) removed experimental changes for ROS BUG-9119:
+long DRQ+CoD delay, omited PIO/DMA setup for SATA ATAPI, forced DMA mode
+i) all actual improvements and bugfixes from v0.46ax are preserved
+-) removed extra AtaSetTransferMode() call in AMD/NVidia/VIA PIO setup
+!) VIA-specific PIO setup is now conditional in AMD/NVidia/VIA code
+!) fixed IO-range cleanup on unsuccessfull ISA detection attempt
+!) fixed out-or-range cleanup attempt on ISA detect (buffer overflow with 
+possible crash later)
+
+--
+2016.03.19 - v0.46b1
+
++) wait 1us for BUSY raise after write command registers on "old" ISA 
+systems. Original ATAPI.SYS does this.
++) use long timeout 2s on hard reset after unsuccessfull soft reset on 
+detect phase on "old" ISA systems. Original ATAPI.SYS does this.
+*) do not enumerate PCI bus if both IgnoreIsaCompatiblePci and 
+IgnoreNativePci options are set.
+*) fixed several 'prefast' warnings
+
+--
+2016.03.19 - v0.46b2
+
+!!) use ATA_IOSIZE and ATA_ALTIOSIZE for I/O range length in ISA detect part.
+Note, that historically used value of 2 for AltStatus range is definitly 
+wrong. There must be 1. The ambiguity comes from rudimentary definition of
+IDE_REGISTERS_2 with unused DriveAddress member
+e) do not report 0x3f6 register usage on old ISA hardware to avoid 
+interference with Floppy. However, it should use only 0x3f0-3f5,3f7
++) track last selected device via chan->last_devsel to avoid unnecessary
+I/O and possible wait for ready delay.
+Move SelectDrive() from macro to function.
+Create AtapiHardReset() for channel hard reset and related operations
+
+--
+2016.03.20 - v0.46b3
+
+-) removed extra delays, appeared in 0.46b1, 0.46b2
++) added tunable delay in SelectDrive() after write to register
+e) try report 0x3f6 register usage even on old ISA
+!) fix bug with blocked UniataEnumBusMasterController() call
+!) declare IDE_REGISTERS_2 as union and use DriveAddress
+(which is now aliased with AltStatus) as Control register
+
+--
+2016.03.20 - v0.46b4
+
+!) fixed bug with sending packet command in ISR. This didn't happen on SATA
+because of error in code unification in v0.46a8
+!) clarified AtaSetTransferMode() behavior for SATA devices. When device is
+switched from PIO to SATA_xxx mode, use highest UDMA mode from Identify 
+data.
+e) use PIO0_TIMING delay between comamnd packet bytes when deal to ATAPI
+(ROS BUG-9119)
diff -ruN v45j5\driver\atapi.h v46b4\driver\atapi.h
--- v45j5\driver\atapi.h	Wed Sep 23 02:05:38 2015
+++ v46b4\driver\atapi.h	Sun Mar 20 18:53:50 2016
@@ -211,21 +211,21 @@
 #define IDX_IO1_o_DriveSelect       (FIELD_OFFSET(IDE_REGISTERS_1, o.DriveSelect )+IDX_IO1_o)
 #define IDX_IO1_o_Command           (FIELD_OFFSET(IDE_REGISTERS_1, o.Command     )+IDX_IO1_o)
 
-typedef struct _IDE_REGISTERS_2 {
+typedef union _IDE_REGISTERS_2 {
     UCHAR AltStatus;
-    UCHAR DriveAddress;
+    UCHAR Control;
 } IDE_REGISTERS_2, *PIDE_REGISTERS_2;
 
 #define IDX_IO2                     (IDX_IO1_o+IDX_IO1_o_SZ)
 #define IDX_IO2_SZ                  sizeof(IDE_REGISTERS_2)
 
 #define IDX_IO2_AltStatus           (FIELD_OFFSET(IDE_REGISTERS_2, AltStatus   )+IDX_IO2)
-#define IDX_IO2_DriveAddress        (FIELD_OFFSET(IDE_REGISTERS_2, DriveAddress)+IDX_IO2)
+//#define IDX_IO2_DriveAddress        (FIELD_OFFSET(IDE_REGISTERS_2, DriveAddress)+IDX_IO2)
 
 #define IDX_IO2_o                   (IDX_IO2+IDX_IO2_SZ)
 #define IDX_IO2_o_SZ                sizeof(IDE_REGISTERS_2)
 
-#define IDX_IO2_o_Control           (FIELD_OFFSET(IDE_REGISTERS_2, AltStatus   )+IDX_IO2_o)
+#define IDX_IO2_o_Control           (FIELD_OFFSET(IDE_REGISTERS_2, Control)+IDX_IO2_o)
 //
 // Device Extension Device Flags
 //
@@ -657,6 +657,7 @@
     USHORT StandbyOverlap:1;
     USHORT SupportQTag:1;                                 /* supports queuing overlap */
     USHORT SupportIDma:1;                                 /* interleaved DMA supported */
+
 /*    USHORT Capabilities;                    // 62  49
 #define IDENTIFY_CAPABILITIES_SUPPORT_DMA   0x0100
 #define IDENTIFY_CAPABILITIES_SUPPORT_LBA   0x0200
@@ -708,7 +709,7 @@
             USHORT UDMASupport : 7;        //     62  ATAPI
             USHORT MultiWordDMASupport : 3;
             USHORT DMASupport : 1;         
-            USHORT Reaseved62_11_14 : 4;         
+            USHORT Reseved62_11_14 : 4;         
             USHORT DMADirRequired : 1;         
         } AtapiDMA;
     };
@@ -867,10 +868,28 @@
 
     ULONG  LargeSectorSize;                 //     117-118
     
-    USHORT Reserved119[8];                  //     119-126
+    struct {
+        USHORT Reserved;
+    } CommandFeatureSetSupport, CommandFeatureSetEnabled; // 119-120
+    USHORT Reserved121[4];                  //     121-124
+    USHORT AtapiByteCount0;                 //     125
+    USHORT Reserved126;                     //     126
     
     USHORT RemovableStatus;                 //     127
-    USHORT SecurityStatus;                  //     128
+    union {
+        USHORT SecurityStatus;                  //     128
+        struct {
+            USHORT Support:1;
+            USHORT Enabled:1;
+            USHORT Locked:1;
+            USHORT Frozen:1;
+            USHORT CountExpired:1;
+            USHORT EnhancedEraseSupport:1;
+            USHORT Reserved7_8:2;
+            USHORT MasterPasswdCap:1; // 0 - high, 1 - max
+            USHORT Reserved9_15:7;
+        } SecurityStatusOpt;
+    };
 
     USHORT Reserved129[31];                 //     129-159
     USHORT CfAdvPowerMode;                  //     160
@@ -1073,12 +1092,12 @@
 #define WriteCommand(chan, _Command) \
     AtapiWritePort1(chan, IDX_IO1_o_Command, _Command);
 
-
+/*
 #define SelectDrive(chan, unit) { \
     if(chan && chan->lun[unit] && chan->lun[unit]->DeviceFlags & DFLAGS_ATAPI_CHANGER) KdPrint3(("  Select %d\n", unit)); \
     AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, (unit) ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1); \
 }
-
+*/
 
 #define ReadBuffer(chan, Buffer, Count, timing) \
     AtapiReadBuffer2(chan, IDX_IO1_i_Data, \
@@ -1106,6 +1125,13 @@
 
 UCHAR
 DDKFASTAPI
+SelectDrive(
+    IN struct _HW_CHANNEL*   chan,
+    IN ULONG                 DeviceNumber
+    );
+
+UCHAR
+DDKFASTAPI
 WaitOnBusy(
     IN struct _HW_CHANNEL*   chan/*,
     PIDE_REGISTERS_2 BaseIoAddress*/
@@ -1151,7 +1177,15 @@
 AtapiSoftReset(
     IN struct _HW_CHANNEL*   chan,/*
     PIDE_REGISTERS_1 BaseIoAddress*/
-    ULONG            DeviceNumber
+    IN ULONG            DeviceNumber
+    );
+
+VOID
+DDKFASTAPI
+AtapiHardReset(
+    IN struct _HW_CHANNEL*   chan,
+    IN BOOLEAN               DisableInterrupts,
+    IN ULONG                 Delay
     );
 
 
diff -ruN v45j5\driver\bm_devs.h v46b4\driver\bm_devs.h
--- v45j5\driver\bm_devs.h	Wed Sep 23 19:05:02 2015
+++ v46b4\driver\bm_devs.h	Thu Mar 17 20:36:58 2016
@@ -609,13 +609,15 @@
 #define CHIPFLAG_MASK   0xffffff00
 
 #define UNIATA_RAID_CONTROLLER  0x80000000
-#define UNIATA_SIMPLEX_ONLY     0x40000000
+#define UNIATA_SIMPLEX_ONLY     0x40000000 /* contoller cannot perform operations
+                                              on both channels on the same time */
 #define UNIATA_NO_SLAVE         0x20000000
 #define UNIATA_SATA             0x10000000
 #define UNIATA_NO_DPC           0x08000000
 #define UNIATA_NO_DPC_ATAPI     0x04000000
 #define UNIATA_AHCI             0x02000000
 #define UNIATA_NO80CHK          0x01000000
+#define UNIATA_CHAN_TIMINGS     0x00800000 /* controller has common timing settings for master/slave */
 
 #define ATPOLD		0x0100
 
@@ -683,6 +685,7 @@
 #define NV4OFF          0x0100
 #define NVQ             0x0200
 
+#define VIANEW		5
 #define VIA33		4
 #define VIA66		1
 #define VIA100		2
@@ -777,7 +780,7 @@
     PCI_DEV_HW_SPEC_BM( 0007, 1103, 0x01, ATA_UDMA6, "HighPoint HPT371" , HPT372 | 0x00   | UNIATA_RAID_CONTROLLER),
     PCI_DEV_HW_SPEC_BM( 0008, 1103, 0x07, ATA_UDMA6, "HighPoint HPT374" , HPT374 | 0x00   | UNIATA_RAID_CONTROLLER),
 
-    PCI_DEV_HW_SPEC_BM( 1230, 8086, 0x00, ATA_WDMA2, "Intel PIIX"       , 0                                       ),
+    PCI_DEV_HW_SPEC_BM( 1230, 8086, 0x00, ATA_WDMA2, "Intel PIIX"       , UNIATA_CHAN_TIMINGS                     ),
     PCI_DEV_HW_SPEC_BM( 7010, 8086, 0x00, ATA_WDMA2, "Intel PIIX3"      , 0                                       ),
     PCI_DEV_HW_SPEC_BM( 7111, 8086, 0x00, ATA_UDMA2, "Intel PIIX3"      , 0                                       ),
     PCI_DEV_HW_SPEC_BM( 7199, 8086, 0x00, ATA_UDMA2, "Intel PIIX4"      , 0                                       ),
diff -ruN v45j5\driver\bsmaster.h v46b4\driver\bsmaster.h
--- v45j5\driver\bsmaster.h	Sun Jan 24 12:51:36 2016
+++ v46b4\driver\bsmaster.h	Sat Mar 19 22:45:28 2016
@@ -75,6 +75,7 @@
 #define	IO_WD1	        0x1F0		/* Primary Fixed Disk Controller */
 #define	IO_WD2	        0x170		/* Secondary Fixed Disk Controller */
 #define IP_PC98_BANK    0x432
+#define	IO_FLOPPY_INT	0x3F6		/* AltStatus inside Floppy I/O range */
 
 #define PCI_ADDRESS_IOMASK              0xfffffff0
 
@@ -1008,6 +1009,8 @@
 
     PATA_REQ            cur_req;
     ULONG               cur_cdev;
+    ULONG               last_cdev; /* device for which we have configured timings last time */
+    ULONG               last_devsel; /* device selected during last call to SelectDrive() */
 /*    PATA_REQ            first_req;
     PATA_REQ            last_req;*/
     ULONG               queue_depth;
@@ -1123,7 +1126,7 @@
 #define CTRFLAGS_LBA48                  0x0040
 #define CTRFLAGS_DSC_BSY                0x0080
 #define CTRFLAGS_NO_SLAVE               0x0100
-#define CTRFLAGS_DMA_BEFORE_R           0x0200
+//#define CTRFLAGS_DMA_BEFORE_R           0x0200
 //#define CTRFLAGS_PATA                   0x0200
 //#define CTRFLAGS_NOT_PRESENT            0x0200
 #define CTRFLAGS_AHCI_PM                0x0400
@@ -1878,6 +1881,8 @@
 
 extern BOOLEAN g_opt_Verbose;
 extern ULONG   g_opt_VirtualMachine;
+
+extern ULONG   g_opt_WaitBusyResetCount;
 
 #define VM_AUTO      0x00
 #define VM_NONE      0x01
diff -ruN v45j5\driver\Dist\2K\uata_2k.inf v46b4\driver\Dist\2K\uata_2k.inf
--- v45j5\driver\Dist\2K\uata_2k.inf	Sun Jan 24 15:05:14 2016
+++ v46b4\driver\Dist\2K\uata_2k.inf	Mon Mar 21 12:40:30 2016
@@ -6,7 +6,7 @@
 ClassGUID={4D36E97B-E325-11CE-BFC1-08002BE10318}
 Class=SCSIAdapter
 CatalogFile=uniata.cat
-DriverVer=01/24/2016,0.45.10.5
+DriverVer=03/21/2016,0.46.2.4
 
 ;
 ; Source file information
diff -ruN v45j5\driver\Dist\2K\uata_2kh.inf v46b4\driver\Dist\2K\uata_2kh.inf
--- v45j5\driver\Dist\2K\uata_2kh.inf	Sun Jan 24 15:05:14 2016
+++ v46b4\driver\Dist\2K\uata_2kh.inf	Mon Mar 21 12:40:30 2016
@@ -6,7 +6,7 @@
 ClassGUID={4D36E97B-E325-11CE-BFC1-08002BE10318}
 Class=hdc
 CatalogFile=uniata.cat
-DriverVer=01/24/2016,0.45.10.5
+DriverVer=03/21/2016,0.46.2.4
 
 ;
 ; Source file information
diff -ruN v45j5\driver\Dist\2K\uniata_w2k.reg v46b4\driver\Dist\2K\uniata_w2k.reg
--- v45j5\driver\Dist\2K\uniata_w2k.reg	Sun Jan 24 15:05:14 2016
+++ v46b4\driver\Dist\2K\uniata_w2k.reg	Mon Mar 21 12:40:30 2016
@@ -6,7 +6,7 @@
 "Start"=dword:00000000
 "Tag"=dword:00000019
 "Type"=dword:00000001
-"DisplayName"="Universal BusMaster SATA/ATA/ATAPI Driver v0.45.10.5"
+"DisplayName"="Universal BusMaster SATA/ATA/ATAPI Driver v0.46.2.4"
 "ImagePath"=hex(2):53,79,73,74,65,6d,33,32,5c,44,52,49,56,45,52,53,5c,75,6e,69,\
   61,74,61,2e,73,79,73,00
 
Binary files v45j5\driver\Dist\atactl.exe and v46b4\driver\Dist\atactl.exe differ
diff -ruN v45j5\driver\Dist\NT4\uata_nt4.inf v46b4\driver\Dist\NT4\uata_nt4.inf
--- v45j5\driver\Dist\NT4\uata_nt4.inf	Sun Jan 24 15:05:14 2016
+++ v46b4\driver\Dist\NT4\uata_nt4.inf	Mon Mar 21 12:40:30 2016
@@ -6,7 +6,7 @@
 ClassGUID={4D36E97B-E325-11CE-BFC1-08002BE10318}
 Class=SCSIAdapter
 CatalogFile=uniata.cat
-DriverVer=01/24/2016,0.45.10.5
+DriverVer=03/21/2016,0.46.2.4
 
 ;
 ; Source file information
Binary files v45j5\driver\Dist\tools\build_inf.exe and v46b4\driver\Dist\tools\build_inf.exe differ
diff -ruN v45j5\driver\Dist\XP\uata_xp.inf v46b4\driver\Dist\XP\uata_xp.inf
--- v45j5\driver\Dist\XP\uata_xp.inf	Sun Jan 24 15:05:14 2016
+++ v46b4\driver\Dist\XP\uata_xp.inf	Mon Mar 21 12:40:30 2016
@@ -6,7 +6,7 @@
 ClassGUID={4D36E97B-E325-11CE-BFC1-08002BE10318}
 Class=SCSIAdapter
 CatalogFile=uniata.cat
-DriverVer=01/24/2016,0.45.10.5
+DriverVer=03/21/2016,0.46.2.4
 
 ;
 ; Source file information
diff -ruN v45j5\driver\Dist\XP\uata_xph.inf v46b4\driver\Dist\XP\uata_xph.inf
--- v45j5\driver\Dist\XP\uata_xph.inf	Sun Jan 24 15:05:14 2016
+++ v46b4\driver\Dist\XP\uata_xph.inf	Mon Mar 21 12:40:30 2016
@@ -6,7 +6,7 @@
 ClassGUID={4D36E97B-E325-11CE-BFC1-08002BE10318}
 Class=hdc
 CatalogFile=uniata.cat
-DriverVer=01/24/2016,0.45.10.5
+DriverVer=03/21/2016,0.46.2.4
 
 ;
 ; Source file information
diff -ruN v45j5\driver\id_ata.cpp v46b4\driver\id_ata.cpp
--- v45j5\driver\id_ata.cpp	Sun Jan 24 14:57:52 2016
+++ v46b4\driver\id_ata.cpp	Sun Mar 20 21:30:22 2016
@@ -1,6 +1,6 @@
 /*++
 
-Copyright (c) 2002-2015 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2002-2016 Alexandr A. Telyatnikov (Alter)
 
 Module Name:
     id_ata.cpp
@@ -83,14 +83,20 @@
 
 ULONG  g_WaitBusyInISR = 1;
 
+ULONG  g_opt_WaitBusyResetCount = 10000; // 20000
 ULONG  g_opt_WaitBusyCount = 200; // 20000
 ULONG  g_opt_WaitBusyDelay = 10;  // 150
 ULONG  g_opt_WaitDrqDelay  = 10; // 100
 ULONG  g_opt_WaitBusyLongCount = 2000; // 2000
 ULONG  g_opt_WaitBusyLongDelay = 250;  // 250
-ULONG  g_opt_MaxIsrWait = 40; //
+ULONG  g_opt_MaxIsrWait = 40;
+
+ULONG  g_opt_DriveSelectNanoDelay = 0; // 400; // ns
+
 BOOLEAN g_opt_AtapiSendDisableIntr = 0; // 0
 BOOLEAN g_opt_AtapiDmaRawRead = 1; // 0
+BOOLEAN g_opt_AtapiNoDma = FALSE;
+BOOLEAN g_opt_BochsDmaReadWorkaround = FALSE;
 BOOLEAN hasPCI = FALSE;
 
 ULONG g_opt_VirtualMachine = 0; // Auto
@@ -496,7 +502,7 @@
     UCHAR statusByte;
     ULONG i;
 
-    // Assume, proper drive is already seleted
+    // Assume, proper drive is already selected
     WaitOnBusyLong(chan);
     for (i = 0; i < 0x10000; i++) {
 
@@ -561,6 +567,37 @@
 
 UCHAR
 DDKFASTAPI
+SelectDrive(
+    IN PHW_CHANNEL   chan,
+    IN ULONG         DeviceNumber
+    )
+{
+    if(!chan) {
+        return 0;
+    }
+/*
+    if(chan->lun[DeviceNumber] &&
+       (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_CHANGER)) {
+        KdPrint3(("  Select %d\n", DeviceNumber));
+    }
+*/
+    if(chan->last_devsel == DeviceNumber) {
+        //KdPrint3(("  Selected %d\n", DeviceNumber));
+        return 1;
+    }
+    AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1); \
+    chan->last_devsel = DeviceNumber ? 1 : 0;
+    if(!g_opt_DriveSelectNanoDelay) {
+        //KdPrint3(("  Select %d\n", DeviceNumber));
+        return 2;
+    }
+    //KdPrint3(("  Select %d (%d ns)\n", DeviceNumber, g_opt_DriveSelectNanoDelay));
+    UniataNanoSleep(g_opt_DriveSelectNanoDelay);
+    return 2;
+} // end SelectDrive()
+
+UCHAR
+DDKFASTAPI
 WaitOnBusy(
     IN PHW_CHANNEL   chan
     )
@@ -751,7 +788,7 @@
 DDKFASTAPI
 AtapiSoftReset(
     IN PHW_CHANNEL   chan,
-    ULONG            DeviceNumber
+    IN ULONG         DeviceNumber
     )
 {
     //ULONG c = chan->lChannel;
@@ -770,10 +807,20 @@
     SelectDrive(chan, DeviceNumber);
     if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MANUAL_CHS) {
         // For ESDI/MFM
+        KdPrint2((PRINT_PREFIX "  ESDI/MFM\n"));
         AtapiStallExecution(10000);
         for (i = 0; i < 1000; i++) {
             AtapiStallExecution(999);
         }
+/*    } else
+    // Seems to be unnecessary, verified by KtP
+    if(!hasPCI) {
+        // original atapi.sys behavior for old ISA-only hardware
+        AtapiStallExecution(10000);
+        AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
+        for (i = 0; i < 1000; i++) {
+            AtapiStallExecution(999);
+        } */
     } else {
         AtapiStallExecution(500);
         GetBaseStatus(chan, statusByte2);
@@ -816,6 +863,7 @@
         chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_REINIT_DMA;
     }
 
+    chan->last_devsel = -1; // make sure proper drive would be selected
     SelectDrive(chan, DeviceNumber);
     WaitOnBusy(chan);
     GetBaseStatus(chan, statusByte2);
@@ -844,6 +892,22 @@
 
 } // end AtapiSoftReset()
 
+VOID
+DDKFASTAPI
+AtapiHardReset(
+    IN struct _HW_CHANNEL*   chan,
+    IN BOOLEAN               DisableInterrupts,
+    IN ULONG                 Delay
+    )
+{
+    KdPrint2((PRINT_PREFIX "AtapiHardReset: %d, dis=%d\n", Delay, DisableInterrupts));
+    AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_RESET_CONTROLLER |
+                              (DisableInterrupts ? IDE_DC_DISABLE_INTERRUPTS : 0));
+    chan->last_devsel = -1;
+    AtapiStallExecution(Delay);
+    AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_REENABLE_CONTROLLER);
+} // end AtapiHardReset()
+
 /*
     Send command to device.
     Translate to 48-Lba form if required
@@ -964,6 +1028,12 @@
 
     // write command code to device
     AtapiWritePort1(chan, IDX_IO1_o_Command, command);
+    /*
+    // unnecessary, by KtP
+    if(!hasPCI) {
+        AtapiStallExecution(1); // wait for busy to be set
+    }
+    */
 
     switch (wait_flags) {
     case ATA_WAIT_INTR:
@@ -998,7 +1068,7 @@
                 AtapiStallExecution(100);
                 continue;
             } else
-            if(statusByte == IDE_STATUS_IDLE) {
+            if((statusByte & ~IDE_STATUS_INDEX) == IDE_STATUS_IDLE) {
                 break;
             } else {
                 //if(deviceExtension->HwFlags & UNIATA_SATA) {
@@ -1465,6 +1535,13 @@
         statusByte = WaitOnBusyLong(chan);
         // Check that the status register makes sense.
         GetBaseStatus(chan, statusByte);
+        /*
+        // unnecessary
+        if(!hasPCI) {
+            // original atapi.sys behavior for old ISA-only hardware
+            AtapiStallExecution(100);
+        }
+        */
     }
 
     if (Command == IDE_COMMAND_IDENTIFY) {
@@ -1666,23 +1743,24 @@
         GetBaseStatus(chan, statusByte);
         KdPrint2((PRINT_PREFIX "IssueIdentify: BASE statusByte %#x\n", statusByte));
 
-        if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
-
-            KdPrint2((PRINT_PREFIX "  use 16bit IO\n"));
 #ifdef _DEBUG
-            if(atapiDev) {
-              j = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
-              KdPrint3((PRINT_PREFIX "IssueIdentify: iReason %x\n", j));
+        if(atapiDev) {
+          j = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
+          KdPrint3((PRINT_PREFIX "IssueIdentify: iReason %x\n", j));
+
+          j =
+              AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
+
+          j |=
+              (USHORT)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8;
+          KdPrint3((PRINT_PREFIX "IssueIdentify: wCount %x\n", j));
 
-              j =
-                  AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
+        }
+#endif //_DEBUG
 
-              j |=
-                  (USHORT)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8;
-              KdPrint3((PRINT_PREFIX "IssueIdentify: wCount %x\n", j));
+        if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
 
-            }
-#endif //DBG
+            KdPrint2((PRINT_PREFIX "  use 16bit IO\n"));
             // 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
@@ -1713,6 +1791,24 @@
     KdPrint2((PRINT_PREFIX "Model: %20.20s\n", deviceExtension->FullIdentifyData.ModelNumber));
     KdPrint2((PRINT_PREFIX "FW:    %4.4s\n", deviceExtension->FullIdentifyData.FirmwareRevision));
     KdPrint2((PRINT_PREFIX "S/N:   %20.20s\n", deviceExtension->FullIdentifyData.SerialNumber));
+    if(g_opt_VirtualMachine == VM_AUTO) {
+        if((deviceExtension->FullIdentifyData.FirmwareRevision[0] == 0 ||
+           deviceExtension->FullIdentifyData.FirmwareRevision[0] == ' ') &&
+           (deviceExtension->FullIdentifyData.FirmwareRevision[1] == 0 ||
+           deviceExtension->FullIdentifyData.FirmwareRevision[1] == ' ')) {
+            // Check for BOCHS VM signature. If no additional PCI devices (e.g. VGA)
+            // are declared BOCHS looks like regular PC
+            if (!atapiDev && !AtapiStringCmp ((PCCHAR)(deviceExtension->FullIdentifyData.SerialNumber), "XBDH00", 6)) {
+                KdPrint2((PRINT_PREFIX "IssueIdentify: BOCHS HDD\n"));
+                g_opt_VirtualMachine = VM_BOCHS;
+            } else
+            if (atapiDev && !AtapiStringCmp ((PCCHAR)(deviceExtension->FullIdentifyData.SerialNumber), "XBDC00", 6)) {
+                KdPrint2((PRINT_PREFIX "IssueIdentify: BOCHS CD\n"));
+                g_opt_VirtualMachine = VM_BOCHS;
+            }
+        }
+    }
+
     KdPrint2((PRINT_PREFIX "Pio:   %x\n", deviceExtension->FullIdentifyData.PioCycleTimingMode));
     if(deviceExtension->FullIdentifyData.PioTimingsValid) {
         KdPrint2((PRINT_PREFIX "APio:  %x\n", deviceExtension->FullIdentifyData.AdvancedPIOModes));
@@ -2083,14 +2179,27 @@
                   deviceExtension->FullIdentifyData.CurrentSectorsPerTrack
                   ));
 
-        if(NumOfSectors)
+        if(NumOfSectors) {
             LunExt->NumOfSectors = NumOfSectors;
+        }
+        if(deviceExtension->FullIdentifyData.MajorRevision &&
+           deviceExtension->FullIdentifyData.DoubleWordIo) {
+            LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
+            KdPrint2((PRINT_PREFIX "IssueIdentify: DWORDIO supported\n"));
+        }
     } else {
+        // ATAPI
         if(deviceExtension->FullIdentifyData.MajorRevision &&
            deviceExtension->FullIdentifyData.DoubleWordIo) {
             LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
             KdPrint2((PRINT_PREFIX "IssueIdentify: DFLAGS_DWORDIO_ENABLED.\n"));
         }
+        if(deviceExtension->FullIdentifyData.AtapiDMA.DMADirRequired) {
+            KdPrint2((PRINT_PREFIX "DMADirRequired.\n"));
+        }
+        if(deviceExtension->FullIdentifyData.AtapiByteCount0) {
+            KdPrint2((PRINT_PREFIX "AtapiByteCount0=%x\n", deviceExtension->FullIdentifyData.AtapiByteCount0));
+        }
     }
 
     ScsiPortMoveMemory(&LunExt->IdentifyData,
@@ -2327,7 +2436,7 @@
                 ASSERT(AtaReq->Srb == CurSrb);
                 if (CurSrb) {
                     // Complete outstanding request with SRB_STATUS_BUS_RESET.
-                    UCHAR PathId   = CurSrb->PathId;
+                    UCHAR CurPathId = CurSrb->PathId;
                     UCHAR TargetId = CurSrb->TargetId;
                     UCHAR Lun = CurSrb->Lun;
 
@@ -2356,7 +2465,7 @@
                     }
 
                     if(!ATAPI_DEVICE(chan, i) && AtaReq->bcount && AtaReq->retry < MAX_RETRIES) {
-                        KdPrint2((PRINT_PREFIX "Save retry status %d\n", AtaReq->retry));
+                        KdPrint2((PRINT_PREFIX "Save IDE retry status %d\n", AtaReq->retry));
                         LunExt->errLastLba = AtaReq->lba;
                         LunExt->errBCount = AtaReq->bcount;
                         LunExt->errRetry = AtaReq->retry+1;
@@ -2367,7 +2476,23 @@
                            (ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) &&
                            (g_opt_VirtualMachine == VM_BOCHS)) {
                             KdPrint2((PRINT_PREFIX "set CTRFLAGS_DMA_BEFORE_R on BOCHS\n"));
-                            chan->ChannelCtrlFlags |= CTRFLAGS_DMA_BEFORE_R;
+                            g_opt_BochsDmaReadWorkaround = TRUE;
+                            g_opt_AtapiNoDma = TRUE;
+                        } else {
+                            KdPrint2((PRINT_PREFIX "do nothing\n"));
+                        }
+                    } else
+                    if(ATAPI_DEVICE(chan, i) && AtaReq->bcount && !AtaReq->retry) {
+                        KdPrint2((PRINT_PREFIX "Save ATAPI retry status %d\n", AtaReq->retry));
+                        LunExt->errLastLba = AtaReq->lba;
+                        LunExt->errBCount = AtaReq->bcount;
+                        LunExt->errRetry = AtaReq->retry+1;
+                        if(((AtaReq->Flags & REQ_FLAG_RW_MASK) == REQ_FLAG_READ) &&
+                           (ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) &&
+                           (g_opt_VirtualMachine == VM_BOCHS)) {
+                            KdPrint2((PRINT_PREFIX "set CTRFLAGS_DMA_BEFORE_R on BOCHS ATAPI\n"));
+                            //g_opt_BochsDmaReadWorkaround = TRUE;
+                            g_opt_AtapiNoDma = TRUE;
                         } else {
                             KdPrint2((PRINT_PREFIX "do nothing\n"));
                         }
@@ -2388,7 +2513,7 @@
                     // Indicate ready for next request.
                     ScsiPortNotification(NextLuRequest,
                                          deviceExtension, 
-                                         PathId,
+                                         CurPathId,
                                          TargetId,
                                          Lun);
                 }
@@ -2401,7 +2526,7 @@
         // Clear expecting interrupt flag.
         UniataExpectChannelInterrupt(chan, FALSE);
         chan->RDP = FALSE;
-        chan->ChannelCtrlFlags = 0;
+        chan->ChannelCtrlFlags = ChannelCtrlFlags & CTRFLAGS_PERMANENT;
         InterlockedExchange(&(chan->CheckIntr),
                                       CHECK_INTR_IDLE);
         
@@ -2544,9 +2669,10 @@
                     UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0);
                 }
 default_reset:
-                KdPrint2((PRINT_PREFIX "  send reset\n"));
+/*
                 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS |
                                                                         IDE_DC_RESET_CONTROLLER );
+                chan->last_devsel = -1;
                 KdPrint2((PRINT_PREFIX "  wait a little\n"));
                 AtapiStallExecution(10000);
                 // Disable interrupts
@@ -2557,6 +2683,13 @@
                 AtapiEnableInterrupts(deviceExtension, j);
                 KdPrint2((PRINT_PREFIX "  wait a little (2)\n"));
                 AtapiStallExecution(100000);
+*/
+                AtapiHardReset(chan, TRUE, 100000);
+                KdPrint2((PRINT_PREFIX "  disable intr\n"));
+                AtapiDisableInterrupts(deviceExtension, j);
+                AtapiStallExecution(100);
+                KdPrint2((PRINT_PREFIX "  re-enable intr\n"));
+                AtapiEnableInterrupts(deviceExtension, j);
                 KdPrint2((PRINT_PREFIX "  done\n"));
 
                 break;
@@ -3461,6 +3594,8 @@
     ULONG DeviceNumber = GET_CDEV(Srb);
     PHW_LU_EXTENSION     LunExt = chan->lun[DeviceNumber];
 
+    //LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED;
+    //KdPrint2((PRINT_PREFIX "AtapiHwInitializeChanger: set DFLAGS_CHANGER_INITED\n"));
     if (MechanismStatus) {
         LunExt->DiscsPresent = MechanismStatus->NumberAvailableSlots;
         if (LunExt->DiscsPresent > 1) {
@@ -3685,7 +3820,7 @@
         goto ReturnCallback;
     }
 
-#ifdef DBG
+#ifdef _DEBUG
     if (!IS_RDP((srb->Cdb[0]))) {
         KdPrint2((PRINT_PREFIX "AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb->Cdb[0]));
     }
@@ -4668,7 +4803,8 @@
             KdPrint2((PRINT_PREFIX "  expecting intr + BUSY (3), non ATAPI\n"));
             return INTERRUPT_REASON_IGNORE;
         }
-        if((statusByte & ~IDE_STATUS_DRQ) != (IDE_STATUS_BUSY | IDE_STATUS_DRDY | IDE_STATUS_DSC)) {
+        if((statusByte & ~(IDE_STATUS_DRQ | IDE_STATUS_INDEX)) !=
+           (IDE_STATUS_BUSY | IDE_STATUS_DRDY | IDE_STATUS_DSC)) {
             KdPrint3((PRINT_PREFIX "  unexpected status, seems it is not our\n"));
             return INTERRUPT_REASON_IGNORE;
         }
@@ -4783,9 +4919,9 @@
 
     BOOLEAN atapiDev = FALSE;
 
-#ifdef DBG
+#ifdef _DEBUG
     UCHAR Channel;
-#endif //DBG
+#endif //_DEBUG
     UCHAR lChannel;
     UCHAR DeviceNumber;
     BOOLEAN DmaTransfer = FALSE;
@@ -4818,11 +4954,11 @@
 
     lChannel = c;
 
-#ifdef DBG
+#ifdef _DEBUG
     Channel = (UCHAR)(deviceExtension->Channel + lChannel);
 
     KdPrint2((PRINT_PREFIX "  cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension->DevIndex, Channel, KeGetCurrentIrql(), c));
-#endif //DBG
+#endif //_DEBUG
 
     if((chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
        (AtaReq && (AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) ||
@@ -5489,7 +5625,7 @@
         chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
         goto CompleteRequest;
     } else
-    if (interruptReason == ATAPI_IR_COD_Cmd && (statusByte & IDE_STATUS_DRQ)) {
+    if ((interruptReason == ATAPI_IR_COD_Cmd) && (statusByte & IDE_STATUS_DRQ)) {
         if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
             AtapiDmaDBPreSync(HwDeviceExtension, chan, srb);
         }
@@ -5498,7 +5634,7 @@
         // Send CDB to device.
         WriteBuffer(chan, (PUSHORT)srb->Cdb, 
                           LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
-                          0);
+                          /*0*/ PIO0_TIMING);
         AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
 
         if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
@@ -5508,7 +5644,7 @@
 
         goto ReturnEnableIntr;
 
-    } else if (interruptReason == ATAPI_IR_IO_toDev && (statusByte & IDE_STATUS_DRQ)) {
+    } else if ((interruptReason == ATAPI_IR_IO_toDev) && (statusByte & IDE_STATUS_DRQ)) {
 
         // Write the data.
         if (atapiDev) {
@@ -5580,7 +5716,7 @@
 
             statusByte = WaitOnBusy(chan);
 
-            if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/
+            if (/*atapiDev || */ !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/
                 || (wordCount & 1)) {
 
                 WriteBuffer(chan,
@@ -5653,6 +5789,7 @@
 
     } else if (interruptReason == ATAPI_IR_IO_toHost && (statusByte & IDE_STATUS_DRQ)) {
 
+continue_read_drq:
 
         if (atapiDev) {
 
@@ -5679,7 +5816,6 @@
             }
 
         } else {
-
             // Check if words left is at least 256.
             if (AtaReq->WordsLeft < wordsThisInterrupt) {
                // Transfer only words requested.
@@ -5710,7 +5846,6 @@
             chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
             goto CompleteRequest;
         }
-continue_read_drq:
         // Ensure that this is a read command.
         if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
 
@@ -5719,7 +5854,7 @@
 
             statusByte = WaitOnBusy(chan);
 
-            if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/
+            if (/*atapiDev ||*/ !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/
                 || (wordCount & 1)) {
                 KdPrint2((PRINT_PREFIX 
                            "IdeIntr: Read %#x words\n", wordCount));
@@ -5728,30 +5863,6 @@
                           AtaReq->DataBuffer,
                           wordCount,
                           UniataGetPioTiming(LunExt));
-                KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)-1) ));
-                //KdDump(AtaReq->DataBuffer, wordCount*2);
-                if(srb && atapiDev && srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
-                    KdDump(AtaReq->DataBuffer, wordCount*2);
-                }
-
-                GetBaseStatus(chan, statusByte);
-                KdPrint2((PRINT_PREFIX "  status re-check %#x\n", statusByte));
-
-                if(DataOverrun) {
-                    KdPrint2((PRINT_PREFIX "  DataOverrun\n"));
-                    AtapiSuckPort2(chan);
-                    GetBaseStatus(chan, statusByte);
-                }
-
-                if(statusByte & IDE_STATUS_BUSY) {
-                    for (i = 0; i < 2; i++) {
-                        AtapiStallExecution(10);
-                        GetBaseStatus(chan, statusByte);
-                        if (!(statusByte & IDE_STATUS_BUSY)) {
-                            break;
-                        }
-                    }
-                }
             } else {
                 KdPrint2((PRINT_PREFIX 
                           "IdeIntr: Read %#x Dwords\n", wordCount/2));
@@ -5761,6 +5872,32 @@
                            wordCount / 2,
                            UniataGetPioTiming(LunExt));
             }
+
+            KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)-1) ));
+            //KdDump(AtaReq->DataBuffer, wordCount*2);
+            if(srb && atapiDev && srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
+                KdDump(AtaReq->DataBuffer, wordCount*2);
+            }
+
+            GetBaseStatus(chan, statusByte);
+            KdPrint2((PRINT_PREFIX "  status re-check %#x\n", statusByte));
+
+            if(DataOverrun) {
+                KdPrint2((PRINT_PREFIX "  DataOverrun\n"));
+                AtapiSuckPort2(chan);
+                GetBaseStatus(chan, statusByte);
+            }
+
+            if(statusByte & IDE_STATUS_BUSY) {
+                for (i = 0; i < 2; i++) {
+                    AtapiStallExecution(10);
+                    GetBaseStatus(chan, statusByte);
+                    if (!(statusByte & IDE_STATUS_BUSY)) {
+                        break;
+                    }
+                }
+            }
+
         } else {
 
             KdPrint3((PRINT_PREFIX 
@@ -5784,23 +5921,35 @@
             KdPrint2((PRINT_PREFIX "AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
             if (atapiDev) {
 
-                // Work around to make many atapi devices return correct sector size
-                // of 2048. Also certain devices will have sector count == 0x00, check
-                // for that also.
-                if ((srb->Cdb[0] == SCSIOP_READ_CAPACITY) &&
-                    (LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM)) {
-
-                    AtaReq->DataBuffer -= wordCount;
-                    if (AtaReq->DataBuffer[0] == 0x00) {
+                if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM) {
 
-                        *((ULONG *) &(AtaReq->DataBuffer[0])) = 0xFFFFFF7F;
+                    // Work around to make many atapi devices return correct sector size
+                    // of 2048. Also certain devices will have sector count == 0x00, check
+                    // for that also.
+                    if (srb->Cdb[0] == SCSIOP_READ_CAPACITY) {
+
+                        AtaReq->DataBuffer -= wordCount;
+                        if (AtaReq->DataBuffer[0] == 0x00) {
+                            *((ULONG *) &(AtaReq->DataBuffer[0])) = 0xFFFFFF7F;
+                        }
 
+                        *((ULONG *) &(AtaReq->DataBuffer[2])) = 0x00080000;
+                        AtaReq->DataBuffer += wordCount;
                     }
+#ifndef UNIATA_INIT_CHANGERS
+                    else
+                    if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
 
-                    *((ULONG *) &(AtaReq->DataBuffer[2])) = 0x00080000;
-                    AtaReq->DataBuffer += wordCount;
+                        KdPrint3((PRINT_PREFIX "AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status));
+                        // Bingo!!
+                        AtapiHwInitializeChanger (HwDeviceExtension,
+                                                  srb,
+                                                  (PMECHANICAL_STATUS_INFORMATION_HEADER) srb->DataBuffer);
+                        LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED;
+                        KdPrint2((PRINT_PREFIX "  set DFLAGS_CHANGER_INITED\n"));
+                    }
+#endif // UNIATA_INIT_CHANGERS
                 }
-
                 GetStatus(chan, statusByte);
                 if(!(statusByte & IDE_STATUS_BUSY)) {
                     // Assume command is completed if BUSY is cleared
@@ -5845,7 +5994,7 @@
                 }
             } else {
                 if(!atapiDev && !DataOverrun && (srb->SrbFlags & SRB_FLAGS_DATA_IN) &&
-                    (statusByte == (IDE_STATUS_IDLE | IDE_STATUS_DRQ))) {
+                    ((statusByte & ~IDE_STATUS_INDEX) == (IDE_STATUS_IDLE | IDE_STATUS_DRQ))) {
                     KdPrint2((PRINT_PREFIX "  HDD read data ready \n"));
                     goto continue_read_drq;
                 }
@@ -5946,7 +6095,8 @@
 
             KdPrint2((PRINT_PREFIX "AtapiInterrupt: OriginalSrb != NULL\n"));
             if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
-
+#ifdef UNIATA_INIT_CHANGERS
+                // We can get here only when UNIATA_INIT_CHANGERS is defined
                 KdPrint3((PRINT_PREFIX "AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status));
                 if (status == SRB_STATUS_SUCCESS) {
                     // Bingo!!
@@ -5987,7 +6137,10 @@
                     AtapiDisableInterrupts(HwDeviceExtension, c);
                 }
 */
-
+#else 
+                KdPrint((PRINT_PREFIX "AtapiInterrupt: ERROR: internal SCSIOP_MECHANISM_STATUS !!!!\n"));
+                ASSERT(FALSE);
+#endif // UNIATA_INIT_CHANGERS
             } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
 
                 PSENSE_DATA senseData = (PSENSE_DATA) srb->DataBuffer;
@@ -6003,7 +6156,9 @@
 
                 if (status == SRB_STATUS_SUCCESS) {
 #ifndef UNIATA_CORE
+#ifdef UNIATA_INIT_CHANGERS
                     if ((senseData->SenseKey != SCSI_SENSE_ILLEGAL_REQUEST) &&
+                        FALSE &&
                         chan->MechStatusRetryCount) {
 
                         KdPrint3((PRINT_PREFIX "AtapiInterrupt: MechStatusRetryCount %#x\n", chan->MechStatusRetryCount));
@@ -6012,14 +6167,9 @@
                         srb = AtaReq->Srb = BuildMechanismStatusSrb (
                                                               HwDeviceExtension,
                                                               AtaReq->OriginalSrb);
-                    } else {
-
-                        // last request was illegal.  No point trying again.
-                        // Do-nothing call ?
-                        AtapiHwInitializeChanger (HwDeviceExtension,
-                                                  srb,
-                                                  (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
-
+                    } else
+#endif // UNIATA_INIT_CHANGERS
+                    {
                         // Get ready to issue the original srb
                         srb = AtaReq->Srb = AtaReq->OriginalSrb;
                         AtaReq->OriginalSrb = NULL;
@@ -6057,11 +6207,6 @@
             KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. complete OriginalSrb\n"));
 
             if (AtaReq->OriginalSrb) {
-                KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
-                // Do-nothing call ?
-                AtapiHwInitializeChanger (HwDeviceExtension,
-                                          srb,
-                                          (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
                 srb = AtaReq->Srb = AtaReq->OriginalSrb;
                 AtaReq->OriginalSrb = NULL;
             }
@@ -6596,6 +6741,7 @@
     ULONG                tmp;
 
     if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
+        (*max_bcount) = 0;
         if(LunExt->LimitedTransferMode >= ATA_DMA) {
             if(LunExt->DeviceExtension) {
                 (*max_bcount) = LunExt->DeviceExtension->MaximumDmaTransferLength / DEV_BSIZE;
@@ -6619,7 +6765,6 @@
         KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
             cylinder, drvSelect, sectorNumber, (*max_bcount)));
     }
-        (*max_bcount) = 0;
 
     return (ULONG)(sectorNumber&0xff) | (((ULONG)cylinder&0xffff)<<8) | (((ULONG)drvSelect&0xf)<<24);
 } // end UniAtaCalculateLBARegs()
@@ -6685,7 +6830,7 @@
     //ULONG                ldev = GET_LDEV(Srb);
     UCHAR                DeviceNumber = GET_CDEV(Srb);;
     ULONGLONG            startingSector=0;
-    ULONG                max_bcount;
+    ULONG                max_bcount = 0;
     ULONG                wordCount = 0;
     UCHAR                statusByte,statusByte2;
     UCHAR                cmd;
@@ -6901,9 +7046,9 @@
         use_dma) {
         if(use_dma) {
             AtapiDmaDBPreSync(HwDeviceExtension, chan, Srb);
-            if((chan->ChannelCtrlFlags & CTRFLAGS_DMA_BEFORE_R) &&
-               (Srb->SrbFlags & SRB_FLAGS_DATA_IN) /* probably, this is double-check, but keep it */) {
-                KdPrint2((PRINT_PREFIX "set CTRFLAGS_DMA_BEFORE_R on BOCHS\n"));
+            if(g_opt_BochsDmaReadWorkaround &&
+               (Srb->SrbFlags & SRB_FLAGS_DATA_IN)) {
+                KdPrint2((PRINT_PREFIX "CTRFLAGS_DMA_BEFORE_R on BOCHS\n"));
                 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
             }
         }
@@ -6924,8 +7069,8 @@
             return SRB_STATUS_ERROR;
         }
         if(use_dma) {
-           if(!(chan->ChannelCtrlFlags & CTRFLAGS_DMA_BEFORE_R) &&
-               (Srb->SrbFlags & SRB_FLAGS_DATA_IN) /* probably, this is double-check, but keep it */) {
+           if(!g_opt_BochsDmaReadWorkaround ||
+              !(Srb->SrbFlags & SRB_FLAGS_DATA_IN)) {
                 //GetStatus(chan, statusByte2);
                 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
             }
@@ -7147,10 +7292,11 @@
     ULONG                DeviceNumber = GET_CDEV(Srb);
     ULONG flags;
     UCHAR statusByte,statusByte0,byteCountLow,byteCountHigh;
+    UCHAR interruptReason;
     BOOLEAN use_dma = FALSE;
     BOOLEAN dma_reinited = FALSE;
     BOOLEAN retried = FALSE;
-    ULONG                fis_size;
+    ULONG                fis_size, i;
     UCHAR FeatureReg=0;
 
     LunExt = chan->lun[DeviceNumber];
@@ -7262,20 +7408,30 @@
             return SRB_STATUS_BUSY;
         }
         //
+#ifdef UNIATA_INIT_CHANGERS
         if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
             !AtaReq->OriginalSrb) {
             KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
             return SRB_STATUS_BUSY;
         }
+#endif // UNIATA_INIT_CHANGERS
     }
 
 #ifndef UNIATA_CORE
+    // standard atapi.sys claims:
+
     // We need to know how many platters our atapi cd-rom device might have.
     // Before anyone tries to send a srb to our target for the first time,
     // we must "secretly" send down a separate mechanism status srb in order to
     // initialize our device extension changer data.  That's how we know how
     // many platters our target has.
 
+    // BUT!
+    // some devices freeze (sometimes) forever on this command
+    // Let CD-ROM driver send this command itself, if it find it necessary
+    // We shall just parse output (if any)
+
+#ifdef UNIATA_INIT_CHANGERS
     if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
         !AtaReq->OriginalSrb) {
 
@@ -7313,17 +7469,12 @@
             }
 
             // 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
         }
     }
+#endif // UNIATA_INIT_CHANGERS
 #endif //UNIATA_CORE
 
     if((CmdAction & CMD_ACTION_PREPARE) &&
@@ -7391,21 +7542,28 @@
         }
 
         // check if DMA read/write
+        //KdPrint2((PRINT_PREFIX "AtapiSendCommand: chan %#x flags %#x\n", chan, chan->ChannelCtrlFlags));
+        if(g_opt_AtapiNoDma) {
+            KdPrint2((PRINT_PREFIX "AtapiSendCommand: CTRFLAGS_DMA_BEFORE_R => no dma\n"));
+            use_dma = FALSE;
+        } else
         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"));
+            // experimental, see ROS BUG-9119, v0.46a6
+            KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use DMA (sata)\n"));
             use_dma = TRUE;
             goto setup_dma;
-        } else*/
+        } else */
         if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
             KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
         } else
-        if(AtaReq->TransferLength) {
-            // try use DMA
+        if(AtaReq->TransferLength && !(AtaReq->TransferLength & 0x0f)) {
+            KdPrint2((PRINT_PREFIX "AtapiSendCommand: try DMA setup\n"));
+            // try use DMA if TransferLength is 16-byte aligned
             switch(Srb->Cdb[0]) {
             case SCSIOP_WRITE:
             case SCSIOP_WRITE12:
@@ -7475,7 +7633,7 @@
                 }
             }
         } else {
-            KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer, no DMA setup\n"));
+            KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero/unaligned transfer %x, no DMA setup\n", AtaReq->TransferLength));
         }
 
 
@@ -7497,9 +7655,11 @@
                 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
             } else {
                 FeatureReg |= ATA_F_DMA;
-                if(LunExt->IdentifyData.AtapiDMA.DMADirRequired &&
-                   (Srb->SrbFlags & SRB_FLAGS_DATA_IN)) {
-                    FeatureReg |= ATA_F_DMAREAD;
+                if(LunExt->IdentifyData.AtapiDMA.DMADirRequired) {
+                    if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
+                        KdPrint2((PRINT_PREFIX "Set DMADir.\n"));
+                        FeatureReg |= ATA_F_DMAREAD;
+                    }
                 }
             }
 
@@ -7679,20 +7839,10 @@
         // 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) {
-                AtapiReadPort2(chan, IDX_IO1_i_Data);
-            } else {
-                break;
-            }
-        }
-*/
+
         if (statusByte & IDE_STATUS_DRQ) {
+            KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted. Status (%#x)\n", statusByte));
 make_reset:
-            KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte));
-
             AtapiDisableInterrupts(deviceExtension, lChannel);
 
             AtapiSoftReset(chan, DeviceNumber);
@@ -7759,29 +7909,25 @@
 
     if(use_dma) {
         FeatureReg |= ATA_F_DMA;
-        if(LunExt->IdentifyData.AtapiDMA.DMADirRequired &&
-           (Srb->SrbFlags & SRB_FLAGS_DATA_IN)) {
-            FeatureReg |= ATA_F_DMAREAD;
+        if(LunExt->IdentifyData.AtapiDMA.DMADirRequired) {
+            if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
+                FeatureReg |= ATA_F_DMAREAD;
+            }
         }
     }
 
-    AtapiWritePort1(chan, IDX_IO1_o_Feature, FeatureReg);
-
     // Write transfer byte count to registers.
-    byteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF);
-    byteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8);
-
     if (Srb->DataTransferLength >= 0x10000) {
         byteCountLow = byteCountHigh = 0xFF;
+    } else {
+        byteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF);
+        byteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8);
     }
 
-    AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountLow, byteCountLow);
-    AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh, byteCountHigh);
-
-    if (flags & DFLAGS_INT_DRQ) {
+    KdPrint3((PRINT_PREFIX "AtapiSendCommand: F:%#x, CntHL:%#x:%#x.\n", FeatureReg, byteCountHigh, byteCountLow));
 
+    if ((flags & DFLAGS_INT_DRQ) || (deviceExtension->HwFlags & UNIATA_SATA)) {
         // This device interrupts when ready to receive the packet.
-
         KdPrint3((PRINT_PREFIX "AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
                    statusByte));
 
@@ -7789,43 +7935,50 @@
         AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_CMD_INTR;
         InterlockedExchange(&(chan->CheckIntr),
                                       CHECK_INTR_IDLE);
+        // inform driver that packet command must be sent in ISR
+        flags |= DFLAGS_INT_DRQ;
+    } else {
+        // This device quickly sets DRQ when ready to receive the packet.
+        KdPrint2((PRINT_PREFIX "AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
+                   statusByte));
 
-        // Write ATAPI packet command.
-        AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
-
-        KdPrint3((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
-        return SRB_STATUS_PENDING;
+        UniataExpectChannelInterrupt(chan, TRUE);
+        AtaReq->ReqState = REQ_STATE_ATAPI_DO_NOTHING_INTR;
+        InterlockedExchange(&(chan->CheckIntr),
+                                      CHECK_INTR_IDLE);
 
+        if(g_opt_AtapiSendDisableIntr) {
+            AtapiDisableInterrupts(deviceExtension, lChannel);
+        }
+        // remember status. Later we may check if error appeared after cmd packet 
+        statusByte0 = statusByte;
     }
 
-    // This device quickly sets DRQ when ready to receive the packet.
-
-    KdPrint2((PRINT_PREFIX "AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
-               statusByte));
-
-    UniataExpectChannelInterrupt(chan, TRUE);
-    AtaReq->ReqState = REQ_STATE_ATAPI_DO_NOTHING_INTR;
-    InterlockedExchange(&(chan->CheckIntr),
-                                  CHECK_INTR_IDLE);
+    // must be already selected, experimental for ROS BUG-9119
+    //AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) );
+    AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Feature /*IDX_IO1_o_Feature*/, FeatureReg);
+    //AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Unused0, 0);  // experimental for ROS BUG-9119
+    //AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Unused1, 0);  // experimental for ROS BUG-9119
+    AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountLow, byteCountLow);
+    AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh, byteCountHigh);
+    // Write ATAPI packet command.
+    AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Command /*IDX_IO1_o_Command*/, IDE_COMMAND_ATAPI_PACKET);
 
-    if(g_opt_AtapiSendDisableIntr) {
-        AtapiDisableInterrupts(deviceExtension, lChannel);
+    if (flags & DFLAGS_INT_DRQ) {
+        // Wait for interrupt and send PACKET there
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
+        return SRB_STATUS_PENDING;
     }
-    // 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);
-
-    // Wait for DRQ.
     WaitOnBusy(chan);
+/*
+    // Wait for DRQ.
     statusByte = WaitForDrq(chan);
 
     // Need to read status register and clear interrupt (if any)
     GetBaseStatus(chan, statusByte);
 
     if (!(statusByte & IDE_STATUS_DRQ)) {
-
         if(g_opt_AtapiSendDisableIntr) {
             AtapiEnableInterrupts(deviceExtension, lChannel);
         }
@@ -7833,27 +7986,57 @@
         AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
         return SRB_STATUS_ERROR;
     }
-
+*/
     GetStatus(chan, statusByte);
     KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte));
 
-    // Send CDB to device.
-    statusByte = WaitOnBaseBusy(chan);
+    //statusByte = WaitOnBaseBusy(chan);
 
     // Indicate expecting an interrupt and wait for it.
     UniataExpectChannelInterrupt(chan, TRUE);
-    InterlockedExchange(&(chan->CheckIntr),
-                                  CHECK_INTR_IDLE);
-    AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
 
+    for(i=0; i<5000; i++) {
+        if(g_opt_AtapiSendDisableIntr) {
+            GetStatus(chan, statusByte);
+        } else {
+            GetBaseStatus(chan, statusByte);
+        }
+        interruptReason = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason);
+        //KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x (%d)\n", interruptReason, i));
+        if(((interruptReason & ATAPI_IR_COD) == ATAPI_IR_COD_Cmd) &&
+           (((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)) == IDE_STATUS_DRQ))) {
+            break;
+        }
+        AtapiStallExecution(g_opt_WaitDrqDelay*2);
+#ifdef _DEBUG
+//        KdPrint3((PRINT_PREFIX "AtapiSendCommand: wait CoD, status (%#x)\n", interruptReason));
+#endif // _DEBUG
+    }
+    if(((interruptReason & ATAPI_IR_COD) != ATAPI_IR_COD_Cmd) ||
+       (((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)) != IDE_STATUS_DRQ)) ) {
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: no CoD raised, abort cmd\n"));
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x (%d)\n", interruptReason, i));
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte));
+        if(g_opt_AtapiSendDisableIntr) {
+            AtapiEnableInterrupts(deviceExtension, lChannel);
+        }
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ+CoD never asserted\n"));
+        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);
+        }
+        goto make_reset;
+//        AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
+//        return SRB_STATUS_ERROR;
+    } else {
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: ready for packet, status %#x, i=%d\n", interruptReason, i));
+    }
     // clear interrupt
     GetBaseStatus(chan, statusByte);
 
-#ifdef _DEBUG
-    statusByte = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
-    KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x\n", statusByte));
-#endif //DBG
-
     if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
         AtapiDmaDBPreSync(HwDeviceExtension, chan, Srb);
     }
@@ -7861,10 +8044,11 @@
         AtapiEnableInterrupts(deviceExtension, lChannel);
     }
 
+    // Send CDB to device.
     WriteBuffer(chan,
                 (PUSHORT)Srb->Cdb,
                 LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
-                0);
+                /*0*/ PIO0_TIMING);
 
     GetStatus(chan, statusByte);
     KdPrint3((PRINT_PREFIX "AtapiSendCommand: cmd status (%#x)\n", statusByte));
@@ -7872,7 +8056,6 @@
     // 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));
@@ -7886,8 +8069,11 @@
         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));
+    if(statusByte & IDE_STATUS_DRQ) {
+        // Some devices require this. If error condition is not checked in such a way,
+        // device may not operate correctly and would be treated as failed
+        // (and finally invisible for OS)
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ 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));
@@ -7897,11 +8083,15 @@
             return MapError(deviceExtension, Srb);
         }
     }
-*/
+
     if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
         AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
     }
 
+    InterlockedExchange(&(chan->CheckIntr),
+                                  CHECK_INTR_IDLE);
+    AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
+
     KdPrint3((PRINT_PREFIX "AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan->ExpectingInterrupt));
 
     KdPrint2((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
@@ -10318,6 +10508,8 @@
     PCONFIGURATION_INFORMATION GlobalConfig = IoGetConfigurationInformation();
     BOOLEAN PrimaryClaimed   = FALSE;
     BOOLEAN SecondaryClaimed = FALSE;
+    BOOLEAN IgnoreIsaCompatiblePci = FALSE;
+    BOOLEAN IgnoreNativePci = FALSE;
 
     LARGE_INTEGER t0, t1;
 
@@ -10329,6 +10521,8 @@
     if(g_opt_Verbose) {
         _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR "\n");
     }
+    IgnoreIsaCompatiblePci = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", IgnoreIsaCompatiblePci) ? TRUE : FALSE;
+    IgnoreNativePci = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreNativePci", IgnoreNativePci) ? TRUE : FALSE;
 
     if(!SavedDriverObject) {
         SavedDriverObject = (PDRIVER_OBJECT)DriverObject;
@@ -10337,6 +10531,7 @@
         MajorVersion=0x04;
         MinorVersion=0x01;
         BuildNumber=1;
+        KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion, MinorVersion, BuildNumber, KeNumberProcessors));
 #else
         // we are here for the 1st time
         // init CrossNT and get OS version
@@ -10345,8 +10540,8 @@
             //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
             return status;
         }
-#endif // USE_REACTOS_DDK
         KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion, MinorVersion, BuildNumber, *KeNumberProcessors));
+#endif // USE_REACTOS_DDK
 
         KeQuerySystemTime(&t0);
         do {
@@ -10430,8 +10625,7 @@
         hwInitializationData.w2k.HwAdapterControl = (PHW_ADAPTER_CONTROL)AtapiAdapterControl;
     }
 
-    KdPrint2((PRINT_PREFIX "\n\nATAPI IDE enum supported BusMaster Devices\n"));
-
+    KdPrint2((PRINT_PREFIX "\n\nUniATA init... (%d)\n", ReEnter));
     if(!ReEnter) {
 
         g_opt_VirtualMachine = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualMachineType", g_opt_VirtualMachine);
@@ -10442,7 +10636,11 @@
             g_opt_VirtualMachine = VM_VBOX;
         }
         // Pre-scan PCI bus, also check if we are under VM
-        UniataEnumBusMasterController(DriverObject, Argument2);
+        // But do not perform scan if PCI bus is claimed as unused
+        if(!IgnoreIsaCompatiblePci || !IgnoreNativePci) {
+            KdPrint2((PRINT_PREFIX "\nATAPI IDE enum supported PCI BusMaster Devices\n"));
+            UniataEnumBusMasterController(DriverObject, Argument2);
+        }
 
         switch(g_opt_VirtualMachine) {
         case VM_VBOX:
@@ -10456,16 +10654,24 @@
             g_opt_AtapiSendDisableIntr = FALSE;
             g_opt_AtapiDmaRawRead = FALSE;
             break;
+        case VM_BOCHS:
+            KdPrint2((PRINT_PREFIX "adjust options for Bochs\n"));
+            g_opt_AtapiNoDma = TRUE;
         }
 
         if(!hasPCI) {
             KdPrint2((PRINT_PREFIX "old slow machine, adjust timings\n"));
-            // old slow machine, adjust timings
+            // old slow machine, adjust timings (us)
+            g_opt_WaitBusyResetCount = 20000;
             g_opt_WaitBusyCount = 20000;
             g_opt_WaitBusyDelay = 150;
             g_opt_WaitDrqDelay  = 100;
             g_opt_WaitBusyLongCount = 20000;
             g_opt_MaxIsrWait = 200;
+            g_opt_DriveSelectNanoDelay = 400;
+        }
+        if(g_opt_VirtualMachine) {
+            g_opt_DriveSelectNanoDelay = 0;
         }
 
         g_opt_WaitBusyCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyCount", g_opt_WaitBusyCount); // 200 vs 20000
@@ -10475,7 +10681,9 @@
         g_opt_WaitBusyLongDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongDelay", g_opt_WaitBusyLongDelay); // 250 vs 250
         g_opt_AtapiSendDisableIntr = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiSendDisableIntr",  g_opt_AtapiSendDisableIntr) ? TRUE : FALSE;  // 1 vs 0
         g_opt_AtapiDmaRawRead      = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiDmaRawRead",       g_opt_AtapiDmaRawRead) ? TRUE : FALSE;       // 1 vs 0
-        g_opt_MaxIsrWait    = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"MaxIsrWait",       g_opt_MaxIsrWait);       // 40 vs xxx
+        g_opt_AtapiNoDma    = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiNoDma", g_opt_AtapiNoDma) ? TRUE : FALSE;       // 1 vs 0
+        g_opt_MaxIsrWait    = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"MaxIsrWait", g_opt_MaxIsrWait);       // 40 vs xxx
+        g_opt_DriveSelectNanoDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"DriveSelectNanoDelay", g_opt_DriveSelectNanoDelay);
     }
 
     // Look for legacy ISA-bridged PCI IDE controller (onboard)
@@ -10487,7 +10695,7 @@
             KdPrint2((PRINT_PREFIX "!BMList[i].MasterDev\n"));
             break;
         }
-        if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) {
+        if(IgnoreIsaCompatiblePci) {
             break;
         }
         if(ReEnter) {
@@ -10632,7 +10840,7 @@
     KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: i %d, BMListLen %d\n", i, BMListLen));
     for (; i <BMListLen; i++) {
 
-        if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreNativePci", 0)) {
+        if(IgnoreNativePci) {
             break;
         }
 /*        if(BMList[i].MasterDev)
diff -ruN v45j5\driver\id_dma.cpp v46b4\driver\id_dma.cpp
--- v45j5\driver\id_dma.cpp	Tue Sep 29 19:24:50 2015
+++ v46b4\driver\id_dma.cpp	Mon Mar 21 12:36:06 2016
@@ -378,7 +378,7 @@
             AtaReq->ahci.ahci_base64 = NULL;
             return FALSE;
         }
-        KdPrint2((PRINT_PREFIX "  get Phys(data[n=%d]=%x)\n", i, data ));
+        KdPrint2((PRINT_PREFIX "  get Phys(data[n=%d+%x]=%x)\n", i, dma_count0, data ));
         dma_base = AtapiVirtToPhysAddr(HwDeviceExtension, Srb, data, &dma_count, &dma_baseu);
         if(dma_baseu && dma_count) {
             KdPrint2((PRINT_PREFIX "AtapiDmaSetup: block of buffer above 4Gb: %8.8x%8.8x, cnt=%x\n", dma_baseu, dma_base, dma_count));
@@ -828,14 +828,15 @@
     if(/*!(LunExt->DeviceFlags & DFLAGS_FORCE_DOWNRATE) &&*/
         (LunExt->LimitedTransferMode >
          LunExt->TransferMode) ||
-         (LunExt->DeviceFlags & DFLAGS_REINIT_DMA)) {
+         (LunExt->DeviceFlags & DFLAGS_REINIT_DMA) ||
+         ((deviceExtension->HwFlags & UNIATA_CHAN_TIMINGS) && ((ULONG)LunExt->Lun != LunExt->chan->last_cdev))) {
         // restore IO mode
         KdPrint2((PRINT_PREFIX
-                    "AtapiDmaReinit: restore IO mode on Device %d\n", LunExt->Lun));
+                    "AtapiDmaReinit: restore IO mode on Device %d, last dev %d\n", LunExt->Lun, LunExt->chan->last_cdev));
         AtapiDmaInit__(deviceExtension, LunExt);
     } else {
         KdPrint2((PRINT_PREFIX
-                    "AtapiDmaReinit: LimitedTransferMode == TransferMode = %x (%x)\n", LunExt->TransferMode, LunExt->DeviceFlags));
+                    "AtapiDmaReinit: LimitedTransferMode == TransferMode = %x (%x), Device %d, last dev %d\n", LunExt->TransferMode, LunExt->DeviceFlags, LunExt->Lun, LunExt->chan->last_cdev));
     }
 
 exit:
@@ -891,16 +892,29 @@
                 "AtaSetTransferMode: Set %#x on Device %d/%d\n", mode, lChannel, DeviceNumber));
     LONG statusByte = 0;
     CHAR apiomode;
-
+/*
+    if(deviceExtension->HwFlags & UNIATA_SATA) {
+        // experimental do nothing, see ROS BUG-9119, v0.46a1
+        statusByte = IDE_STATUS_IDLE;
+    } else */
     if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) {
         statusByte = mode <= ATA_PIO2 ? IDE_STATUS_IDLE : IDE_STATUS_ERROR;
     } else {
+        UCHAR umode;
         if(deviceExtension->HwFlags & UNIATA_AHCI) {
             AtapiDisableInterrupts(deviceExtension, lChannel);
         }
+        if(mode > ATA_UDMA6) {
+            // for SATA, it doesn't have option to set transfer rate
+            // We need this just to switch between PIO and DMA modes
+            // Devices may support only some lower transfer rates (e.g. UDMA0-4)
+            umode = min((UCHAR)AtaUmode(&(LunExt->IdentifyData)), ATA_UDMA6);
+        } else {
+            umode = (UCHAR)mode;
+        }
         statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
                             IDE_COMMAND_SET_FEATURES, 0, 0, 0,
-                            (UCHAR)((mode > ATA_UDMA6) ? ATA_UDMA6 : mode), ATA_C_F_SETXFER, ATA_WAIT_BASE_READY);
+                            (UCHAR)umode, ATA_C_F_SETXFER, ATA_WAIT_BASE_READY);
         if(deviceExtension->HwFlags & UNIATA_AHCI) {
             AtapiEnableInterrupts(deviceExtension, lChannel);
         }
@@ -1049,6 +1063,7 @@
         }
     //}
 
+    chan->last_cdev = DeviceNumber;
     if(UniataIsSATARangeAvailable(deviceExtension, lChannel) ||
         (ChipFlags & UNIATA_AHCI) || (chan->MaxTransferMode >= ATA_SA150)
        ) {
@@ -1226,33 +1241,48 @@
         /********************/
         /* AMD, nVidia, VIA */
         /********************/
-        if((VendorID == ATA_VIA_ID) &&
-           (ChipFlags & VIASATA) &&
-           (Channel == 0)) {
-            AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_SA150);
-            return;
+        if(VendorID == ATA_VIA_ID) {
+            if((ChipFlags & VIASATA) &&
+               (Channel == 0)) {
+                AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_SA150);
+                return;
+            }
+            if((ChipFlags & VIABAR) &&
+               (Channel < 2)) {
+                AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_SA150);
+                return;
+            }
         }
 
-        static const UCHAR via_modes[5][7] = {
+        static const UCHAR via_modes[6][7] = {
             { 0xc2, 0xc1, 0xc0, 0x00, 0x00, 0x00, 0x00 },        /* ATA33 and New Chips */
             { 0xee, 0xec, 0xea, 0xe9, 0xe8, 0x00, 0x00 },        /* ATA66 */
             { 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0, 0x00 },        /* ATA100 */
             { 0xf7, 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0 },        /* VIA ATA133 */
-            { 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 0xc7 }};       /* AMD/nVIDIA */
+            { 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 0xc7 },        /* AMD/nVIDIA */
+            { 0xee, 0xe8, 0xe6, 0xe4, 0xe2, 0xe1, 0xe0 }};       /* VIA new */
 	static const UCHAR via_pio[] =
             { 0xa8, 0x65, 0x42, 0x22, 0x20, 0x42, 0x22, 0x20,
               0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
         const UCHAR *reg_val = NULL;
         UCHAR reg = 0x53-(UCHAR)dev;
+        UCHAR reg2 = reg-0x08;
+
+        if(ChipFlags & VIABAR) {
+            reg = 0xb3;
+            reg2 = 0xab;
+        }
 
         reg_val = &via_modes[ChipType][0];
 
-        if(VendorID == ATA_NVIDIA_ID)
+        if(VendorID == ATA_NVIDIA_ID) {
             reg += 0x10;
+            reg2 += 0x10;
+        }
 
         for(i = udmamode; i>=0; i--) {
-            SetPciConfig1(reg-0x08, via_pio[8+i]);
             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
+                SetPciConfig1(reg2, via_pio[8+i]);
                 SetPciConfig1(reg, (UCHAR)reg_val[i]);
                 return;
             }
@@ -1260,19 +1290,20 @@
         if(!(ChipFlags & VIABAR)) {
 	    /* This chip can't do WDMA. */
             for(i = wdmamode; i>=0; i--) {
-                SetPciConfig1(reg-0x08, via_pio[5+i]);
                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
+                    SetPciConfig1(reg2, via_pio[5+i]);
                     SetPciConfig1(reg, 0x8b);
                     return;
                 }
             }
         }
         /* set PIO mode timings */
-        AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
         if((apiomode >= 0) && (ChipType != VIA133)) {
-            SetPciConfig1(reg-0x08, via_pio[apiomode]);
+            SetPciConfig1(reg2, via_pio[apiomode]);
+        }
+        if(VendorID == ATA_VIA_ID /*&& (ChipType == VIA33 || ChipType == VIA66)*/) {
+            via82c_timing(deviceExtension, dev, ATA_PIO0 + apiomode);
         }
-        via82c_timing(deviceExtension, dev, ATA_PIO0 + apiomode);
         AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
         return;
 
@@ -1495,27 +1526,50 @@
         UCHAR  intel_timings[] = { 0x00, 0x00, 0x10, 0x21, 0x23, 0x10, 0x21, 0x23,
     		                   0x23, 0x23, 0x23, 0x23, 0x23, 0x23 };
         UCHAR  intel_utimings[] = { 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02 };
+	const UCHAR needed_pio[3] = {
+		ATA_PIO0, ATA_PIO3, ATA_PIO4
+	};
 
         if(deviceExtension->DevID == ATA_I82371FB) {
             KdPrint2((PRINT_PREFIX "  I82371FB\n"));
-            if (wdmamode >= 2 && apiomode >= 4) {
-                ULONG word40;
-
-                GetPciConfig4(0x40, word40);
-                word40 >>= Channel * 16;
-
-                /* Check for timing config usable for DMA on controller */
-                if (!((word40 & 0x3300) == 0x2300 &&
-                      ((word40 >> ((!(DeviceNumber & 1)) ? 0 : 4)) & 1) == 1)) {
-                    udmamode = wdmamode = -1;
+            USHORT reg4x;
+            USHORT control;
+            for(i=wdmamode; i>=0; i--) {
+                idx = 5+i;
+                if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
+                    udma_ok = TRUE;
                     break;
                 }
-
-                if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA2)) {
-                    return;
+            }
+            if(!udma_ok) {
+                AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
+                idx = apiomode;
+            } else {
+                /* If the drive MWDMA is faster than it can do PIO then
+                   we must force PIO into PIO0 */
+                if (apiomode < needed_pio[wdmamode]) {
+                    /* Enable DMA timing only */
+                    control |= 8;	/* PIO cycles in PIO0 */
                 }
             }
-            break;
+            GetPciConfig2(0x40+Channel*2, reg4x);
+            if(apiomode > ATA_PIO0) {
+                control = 0x03;	/* IORDY|TIME0 */
+            } else {
+                control = 0x02;	/* IORDY */
+            }
+	    // if (ata_pio_need_iordy(adev))
+		//control |= 2;	/* IE */
+            if (!isAtapi) {
+                control |= 4;	/* PPE enable */
+            }
+            /* Mask out the relevant control and timing bits we will load. Also
+               clear the other drive TIME register as a precaution */
+            reg4x &= 0xCC00 | (0x0E << (DeviceNumber*4));
+            reg4x |= control << (DeviceNumber*4);
+            reg4x |= intel_timings[idx] << 8;
+            SetPciConfig2(0x40+Channel*2, reg4x);
+            return;
         }
 
         if(deviceExtension->DevID == ATA_ISCH) {
@@ -1558,7 +1612,7 @@
             tim |= (apiomode & 0x7);
             SetPciConfig4(0x80 + dev*4, tim);
 
-            break;
+            return;
         }
 
         GetPciConfig2(0x48, reg48);
@@ -2595,6 +2649,12 @@
     ULONG slotNumber = deviceExtension->slotNumber;
     ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
 
+    // Newer chips dislike this:
+    if(/*!(deviceExtension->HwFlags & VIAAST)*/
+        deviceExtension->MaxTransferMode < ATA_UDMA6) {
+        return;
+    }
+
     USHORT T = 1000 / /* PciBusClockMHz()*/ 33;
 
     USHORT setup   = 0;
@@ -2624,14 +2684,10 @@
         recover = cycle - active;
     }
 
-    // Newer chips dislike this:
-    if(/*!(deviceExtension->HwFlags & VIAAST)*/
-        deviceExtension->MaxTransferMode < ATA_UDMA6) {
-        /* PIO address setup */
-        GetPciConfig1(0x4c, t);
-        t = (t & ~(3 << ((3 - dev) << 1))) | (FIT(setup - 1, 0, 3) << ((3 - dev) << 1));
-        SetPciConfig1(0x4c, t);
-    }
+    /* PIO address setup */
+    GetPciConfig1(0x4c, t);
+    t = (t & ~(3 << ((3 - dev) << 1))) | (FIT(setup - 1, 0, 3) << ((3 - dev) << 1));
+    SetPciConfig1(0x4c, t);
 
     /* PIO active & recover */
     SetPciConfig1(0x4b-dev, (FIT(active - 1, 0, 0xf) << 4) | FIT(recover - 1, 0, 0xf) );
diff -ruN v45j5\driver\id_init.cpp v46b4\driver\id_init.cpp
--- v45j5\driver\id_init.cpp	Thu Oct 22 13:59:20 2015
+++ v46b4\driver\id_init.cpp	Sat Mar 19 22:58:42 2016
@@ -165,7 +165,7 @@
         case ATA_ATI_IXP700: {
             UCHAR satacfg = 0;
             PCI_SLOT_NUMBER slotData;
-            ULONG i, slotNumber;
+            ULONG j, slotNumber;
                  
             KdPrint2((PRINT_PREFIX "  IXP700\n"));
             /*
@@ -173,8 +173,8 @@
              * emulated with two SATA ports and appears on this device.
              * This mode can only be detected via SMB controller.
              */
-            i = AtapiFindListedDev((BUSMASTER_CONTROLLER_INFORMATION*)&AtiSouthAdapters[0], -1, HwDeviceExtension, SystemIoBusNumber, PCISLOTNUM_NOT_SPECIFIED, &slotData);
-            if(i != BMLIST_TERMINATOR) {
+            j = AtapiFindListedDev((BUSMASTER_CONTROLLER_INFORMATION*)&AtiSouthAdapters[0], -1, HwDeviceExtension, SystemIoBusNumber, PCISLOTNUM_NOT_SPECIFIED, &slotData);
+            if(j != BMLIST_TERMINATOR) {
                 slotNumber = slotData.u.AsULONG;
 
                 GetPciConfig1(0xad, satacfg);
@@ -463,10 +463,10 @@
         PCI_DEV_HW_SPEC_BM( 5372, 1106, 0x00, ATA_UDMA6, "VIA 8237"   , VIA133 | 0x00 ),
         PCI_DEV_HW_SPEC_BM( 7372, 1106, 0x00, ATA_UDMA6, "VIA 8237"   , VIA133 | 0x00 ),
         PCI_DEV_HW_SPEC_BM( 3349, 1106, 0x00, ATA_UDMA6, "VIA 8251"   , VIA133 | 0x00 ),
-        PCI_DEV_HW_SPEC_BM( 8324, 1106, 0x00, ATA_SA150, "VIA CX700"  , VIA133 | VIASATA),
-        PCI_DEV_HW_SPEC_BM( 8353, 1106, 0x00, ATA_SA150, "VIA VX800"  , VIA133 | VIASATA),
+        PCI_DEV_HW_SPEC_BM( 8324, 1106, 0x00, ATA_SA150, "VIA CX700"  , VIANEW | VIASATA),
+        PCI_DEV_HW_SPEC_BM( 8353, 1106, 0x00, ATA_SA150, "VIA VX800"  , VIANEW | VIASATA),
         PCI_DEV_HW_SPEC_BM( 8409, 1106, 0x00, ATA_UDMA6, "VIA VX855"  , VIA133 | 0x00 ),
-        PCI_DEV_HW_SPEC_BM( 8410, 1106, 0x00, ATA_SA300, "VIA VX900"  , VIA133 | VIASATA),
+        PCI_DEV_HW_SPEC_BM( 8410, 1106, 0x00, ATA_SA300, "VIA VX900"  , VIANEW | VIASATA),
         PCI_DEV_HW_SPEC_BM( ffff, ffff, 0xff, BMLIST_TERMINATOR       , NULL         , BMLIST_TERMINATOR )
         };
 
@@ -1038,7 +1038,7 @@
         if(ChipFlags & UNIATA_SATA) {
 
             ULONG IoSize = 0;
-            ULONG BaseMemAddress = 0;
+            BaseMemAddress = 0;
 
             switch(DeviceID) {
             case 0x3149: // VIA 6420
@@ -2045,7 +2045,6 @@
     case ATA_INTEL_ID: {
         BOOLEAN IsPata;
         USHORT reg54;
-        UCHAR tmp8;
         if(ChipFlags & UNIATA_SATA) {
 
             KdPrint2((PRINT_PREFIX "Intel SATA\n"));
@@ -2465,7 +2464,6 @@
             // do nothing for SATA
         } else
         if(ChipType == SIS133NEW) {
-            USHORT tmp16;
             // check 80-pin cable
             if(c == CHAN_NOT_SPECIFIED) {
                 // do nothing
@@ -2755,6 +2753,7 @@
     }
     chan->AltRegMap       = deviceExtension->AltRegMap;
     chan->NextDpcChan     = -1;
+    chan->last_devsel     = -1;
     for(i=0; i<deviceExtension->NumberLuns; i++) {
         chan->lun[i]->DeviceExtension = deviceExtension;
         chan->lun[i]->chan            = chan;
diff -ruN v45j5\driver\id_probe.cpp v46b4\driver\id_probe.cpp
--- v45j5\driver\id_probe.cpp	Thu Sep 24 12:13:42 2015
+++ v46b4\driver\id_probe.cpp	Sun Mar 20 11:33:38 2016
@@ -1,6 +1,6 @@
 /*++
 
-Copyright (c) 2002-2015 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2002-2016 Alexandr A. Telyatnikov (Alter)
 
 Module Name:
     id_probe.cpp
@@ -330,6 +330,7 @@
     BOOLEAN found;
     BOOLEAN known;
     BOOLEAN NeedPciAltInit;
+    BOOLEAN NonZeroSubId = 0;
 
     UCHAR IrqForCompat = 10;
 
@@ -405,12 +406,17 @@
                 SubVendorID = pciData.u.type0.SubVendorID;
                 SubSystemID = pciData.u.type0.SubSystemID;
 
+                if(SubVendorID && SubSystemID) {
+                  NonZeroSubId = 1;
+                }
+
                 //KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id, BaseClass, SubClass ));
 
                 // check for (g_opt_VirtualMachine == VM_AUTO) is performed inside each
                 // VM check for debug purposes
                 // Do not optimize :)
-                if(VendorID == 0x80ee && DeviceID == 0xcafe) {
+                if((VendorID == 0x80ee && DeviceID == 0xcafe) ||
+                   (VendorID == 0x80ee && DeviceID == 0xbeef)) {
                     KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - VirtualBox Guest Service\n",busNumber,slotNumber,funcNumber));
                     if(g_opt_VirtualMachine == VM_AUTO) {
                         g_opt_VirtualMachine = VM_VBOX;
@@ -434,6 +440,15 @@
                     if(g_opt_VirtualMachine == VM_AUTO) {
                         g_opt_VirtualMachine = VM_BOCHS;
                     }
+                } else
+                if(pass>0 && !NonZeroSubId &&
+                   VendorID == 0x8086 &&
+                     (DeviceID == 0x7010 ||
+                      DeviceID == 0x1230)) {
+                    KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - Bochs PIIX emulation\n",busNumber,slotNumber,funcNumber));
+                    if(g_opt_VirtualMachine == VM_AUTO) {
+                        g_opt_VirtualMachine = VM_BOCHS;
+                    }
                 }
 
                 if(BaseClass != PCI_DEV_CLASS_STORAGE) {
@@ -1255,12 +1270,12 @@
         // validate Mem/Io ranges
         //no_ranges = TRUE;
         {
-            ULONG i;
-            for(i=0; i<PCI_TYPE0_ADDRESSES; i++) {
-                if(pciData.u.type0.BaseAddresses[i] & ~0x7) {
+            ULONG j;
+            for(j=0; j<PCI_TYPE0_ADDRESSES; j++) {
+                if(pciData.u.type0.BaseAddresses[j] & ~0x7) {
                     //no_ranges = FALSE;
                     //break;
-                    KdPrint2((PRINT_PREFIX "Range %d = %#x\n", i, pciData.u.type0.BaseAddresses[i]));
+                    KdPrint2((PRINT_PREFIX "Range %d = %#x\n", j, pciData.u.type0.BaseAddresses[j]));
                 }
             }
         }
@@ -1983,7 +1998,7 @@
     ULONG i = deviceExtension->DevIndex;
     NTSTATUS status;
     PISR2_DEVICE_EXTENSION Isr2DevExt;
-    WCHAR devname_str[32];
+    WCHAR devname_str[33];
     UNICODE_STRING devname;
 
     KdPrint2((PRINT_PREFIX "Init ISR:\n"));
@@ -2015,8 +2030,9 @@
     KdPrint2((PRINT_PREFIX "Create DO\n"));
 
     devname.Length = 
-        _snwprintf(devname_str, sizeof(devname_str)/sizeof(WCHAR),
+        _snwprintf(devname_str, sizeof(devname_str)/sizeof(WCHAR)-1,
               L"\\Device\\uniata%d_2ch", i);
+    devname_str[devname.Length] = 0;
     devname.Length *= sizeof(WCHAR);
     devname.MaximumLength = devname.Length;
     devname.Buffer = devname_str;
@@ -2155,7 +2171,7 @@
     ULONG                portBase;
     ULONG                retryCount;
 //    BOOLEAN              atapiOnly;
-    UCHAR                statusByte;
+    UCHAR                statusByte, statusByte2;
     BOOLEAN              preConfig = FALSE;
     //
     PIDE_REGISTERS_1 BaseIoAddress1;
@@ -2170,7 +2186,7 @@
     // port addresses in the previous table.
     static CONST ULONG InterruptLevels[5] = {14, 15, 11, 10, 0};
 
-    KdPrint2((PRINT_PREFIX "AtapiFindController:\n"));
+    KdPrint2((PRINT_PREFIX "AtapiFindController (ISA):\n"));
 
     if (!deviceExtension) {
         return SP_RETURN_ERROR;
@@ -2218,6 +2234,14 @@
 
 #endif //UNIATA_CORE
 
+    for(i=0; i<2; i++) {
+        KdPrint2((PRINT_PREFIX "  IoRange[%d], start %#x, len %#x, mem %#x\n",
+            i,
+            ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[i].RangeStart),
+            (*ConfigInfo->AccessRanges)[i].RangeLength,
+            (*ConfigInfo->AccessRanges)[i].RangeInMemory
+            ));
+    }
 
     // Scan though the adapter address looking for adapters.
     if (ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[0].RangeStart) != 0) {
@@ -2231,7 +2255,7 @@
         // Since we have pre-configured information we only need to go through this loop once
         preConfig = TRUE;
         portBase = ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[0].RangeStart);
-        KdPrint2((PRINT_PREFIX "  preconfig, portBase=%x\n", portBase));
+        KdPrint2((PRINT_PREFIX "  preconfig, portBase=%x, len=%x\n", portBase, (*ConfigInfo->AccessRanges)[0].RangeLength));
     }
 
 #ifndef UNIATA_CORE
@@ -2242,9 +2266,22 @@
 
         retryCount = 4;
         deviceExtension->DevIndex = (*adapterCount);
+        KdPrint2((PRINT_PREFIX "AtapiFindController: adapterCount=%d\n", *adapterCount));
 
         portBase = AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PortBase", portBase);
         irq      = AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"Irq", irq);
+
+        // check if Primary/Secondary Master IDE claimed
+        if((portBase == IO_WD1) &&
+           (ConfigInfo->AtdiskPrimaryClaimed || AtdiskPrimaryClaimed)) {
+            KdPrint2((PRINT_PREFIX "AtapiFindController: AtdiskPrimaryClaimed\n"));
+            goto not_found;
+        } else
+        if((portBase == IO_WD2) &&
+           (ConfigInfo->AtdiskSecondaryClaimed || AtdiskSecondaryClaimed)) {
+            KdPrint2((PRINT_PREFIX "AtapiFindController: AtdiskSecondaryClaimed\n"));
+            goto not_found;
+        }
         
         for (i = 0; i < deviceExtension->NumberLuns; i++) {
             // Zero device fields to ensure that if earlier devices were found,
@@ -2257,23 +2294,22 @@
         // if not, we go and find ourselves
         if (preConfig == FALSE) {
 
-            if (portBase) {
-                ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
-                                                ConfigInfo->AdapterInterfaceType,
-                                                ConfigInfo->SystemIoBusNumber,
-                                                ScsiPortConvertUlongToPhysicalAddress(portBase),
-                                                8,
-                                                TRUE);
+            if (!portBase) {
+                portBase = AdapterAddresses[*adapterCount];
+                KdPrint2((PRINT_PREFIX "portBase[%d]=%x\n", *adapterCount, portBase));
             } else {
-                ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
-                                                ConfigInfo->AdapterInterfaceType,
-                                                ConfigInfo->SystemIoBusNumber,
-                                                ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses[*adapterCount]),
-                                                8,
-                                                TRUE);
+                KdPrint2((PRINT_PREFIX "portBase=%x\n", portBase));
             }
+            ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
+                                            ConfigInfo->AdapterInterfaceType,
+                                            ConfigInfo->SystemIoBusNumber,
+                                            ScsiPortConvertUlongToPhysicalAddress(portBase),
+                                            8,
+                                            TRUE);
 
-        } 
+        } else {
+            KdPrint2((PRINT_PREFIX "preconfig portBase=%x\n", portBase));
+        }
         BaseIoAddress1 = (PIDE_REGISTERS_1)ioSpace;
 
         // Update the adapter count.
@@ -2284,17 +2320,6 @@
             KdPrint2((PRINT_PREFIX "AtapiFindController: !ioSpace\n"));
             continue;
         }
-        // check if Primary/Secondary Master IDE claimed
-        if((ioSpace == (PUCHAR)IO_WD1) &&
-           (ConfigInfo->AtdiskPrimaryClaimed || AtdiskPrimaryClaimed)) {
-            KdPrint2((PRINT_PREFIX "AtapiFindController: AtdiskPrimaryClaimed\n"));
-            goto not_found;
-        } else
-        if((ioSpace == (PUCHAR)IO_WD2) &&
-           (ConfigInfo->AtdiskSecondaryClaimed || AtdiskSecondaryClaimed)) {
-            KdPrint2((PRINT_PREFIX "AtapiFindController: AtdiskSecondaryClaimed\n"));
-            goto not_found;
-        }
 
         // Get the system physical address for the second IO range.
         if (BaseIoAddress1) {
@@ -2334,9 +2359,9 @@
         SelectDrive(chan, 0);
 
         statusByte = AtapiReadPort1(chan, IDX_IO1_i_Status);
-        
-        if(statusByte != AtapiReadPort1(chan, IDX_IO2_AltStatus)) {
-            KdPrint2((PRINT_PREFIX "AtapiFindController: Status vs AlsStatus missmatch, abort init ?\n"));
+        statusByte2 = AtapiReadPort1(chan, IDX_IO2_AltStatus);
+        if((statusByte ^ statusByte2) & ~IDE_STATUS_INDEX) {
+            KdPrint2((PRINT_PREFIX "AtapiFindController: Status %x vs AltStatus %x missmatch, abort init ?\n", statusByte, statusByte2));
 
             if(BaseIoAddress2) {
                 ScsiPortFreeDeviceBase(HwDeviceExtension,
@@ -2344,6 +2369,7 @@
                 BaseIoAddress2 = NULL;
             }
             BaseIoAddress2 = (PIDE_REGISTERS_2)((ULONGIO_PTR)BaseIoAddress1 + 0x0E);
+            KdPrint2((PRINT_PREFIX "  try BaseIoAddress2=%x\n", BaseIoAddress2));
             ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
                                             ConfigInfo->AdapterInterfaceType,
                                             ConfigInfo->SystemIoBusNumber,
@@ -2356,8 +2382,10 @@
                 goto not_found;
             }
             UniataInitMapBase(chan, BaseIoAddress1, BaseIoAddress2);
-            if(statusByte != AtapiReadPort1(chan, IDX_IO2_AltStatus)) {
-                KdPrint2((PRINT_PREFIX "    abort\n"));
+            statusByte = AtapiReadPort1(chan, IDX_IO1_i_Status);
+            statusByte2 = AtapiReadPort1(chan, IDX_IO2_AltStatus);
+            if((statusByte ^ statusByte2) & ~IDE_STATUS_INDEX) {
+                KdPrint2((PRINT_PREFIX "    abort: Status %x vs AltStatus %x missmatch\n", statusByte, statusByte2));
                 goto not_found;
             }
         }
@@ -2412,19 +2440,7 @@
                 KdPrint2((PRINT_PREFIX
                             "AtapiFindController: Identifier read back from Slave (%#x)\n",
                             statusByte));
-not_found:
-                // No controller at this base address.
-                if(BaseIoAddress1) {
-                    ScsiPortFreeDeviceBase(HwDeviceExtension,
-                                           (PCHAR)BaseIoAddress1);
-                    BaseIoAddress1 = NULL;
-                }
-                if(BaseIoAddress2) {
-                    ScsiPortFreeDeviceBase(HwDeviceExtension,
-                                           (PCHAR)BaseIoAddress2);
-                    BaseIoAddress2 = NULL;
-                }
-                continue;
+                goto not_found;
             }
         }
 
@@ -2441,13 +2457,21 @@
                     ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses[*adapterCount - 1]);
             }
 
-            (*ConfigInfo->AccessRanges)[0].RangeLength = 8;
+            (*ConfigInfo->AccessRanges)[0].RangeLength = ATA_IOSIZE;
             (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE;
 
             if(BaseIoAddress2) {
                 (*ConfigInfo->AccessRanges)[1].RangeStart = ScsiPortConvertUlongToPhysicalAddress((ULONG)BaseIoAddress2);
-                (*ConfigInfo->AccessRanges)[1].RangeLength = 2;
+                (*ConfigInfo->AccessRanges)[1].RangeLength = ATA_ALTIOSIZE;
                 (*ConfigInfo->AccessRanges)[1].RangeInMemory = FALSE;
+                if((ULONG)BaseIoAddress2 == IO_FLOPPY_INT) {
+                    KdPrint2((PRINT_PREFIX "!!! Possible AltStatus vs Floppy IO range interference !!!\n"));
+/*                    if(!hasPCI) {
+                        KdPrint2((PRINT_PREFIX "Do not expose to OS on onld ISA\n"));
+                        (*ConfigInfo->AccessRanges)[i].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0);
+                        (*ConfigInfo->AccessRanges)[i].RangeLength = 0;
+                    } */
+                }
             }
 
             // Indicate the interrupt level corresponding to this IO range.
@@ -2583,9 +2607,29 @@
             KdPrint2((PRINT_PREFIX 
                        "AtapiFindController: return SP_RETURN_FOUND\n"));
             return(SP_RETURN_FOUND);
+        } else {
+not_found:
+            // No controller at this base address.
+            if(BaseIoAddress1) {
+                ScsiPortFreeDeviceBase(HwDeviceExtension,
+                                       (PCHAR)BaseIoAddress1);
+                BaseIoAddress1 = NULL;
+            }
+            if(BaseIoAddress2) {
+                ScsiPortFreeDeviceBase(HwDeviceExtension,
+                                       (PCHAR)BaseIoAddress2);
+                BaseIoAddress2 = NULL;
+            }
+            for(i=0; i<2; i++) {
+                KdPrint2((PRINT_PREFIX 
+                           "AtapiFindController: cleanup AccessRanges %d\n", i));
+                (*ConfigInfo->AccessRanges)[i].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0);
+                (*ConfigInfo->AccessRanges)[i].RangeLength = 0;
+                (*ConfigInfo->AccessRanges)[i].RangeInMemory = FALSE;
+            }
         }
 #ifndef UNIATA_CORE
-    }
+    } // while()
 #else
     } while(FALSE);
 #endif //UNIATA_CORE
@@ -2607,6 +2651,33 @@
     
 } // end AtapiFindController()
 
+/*++
+
+Routine Description:
+
+    Perform quick device presence detection.
+    Method is based on ATA registers implementation specific.
+    It is used in low-level disk utilities.
+    If the device is connected (even if it is frozen, busy or
+    has some other problem) all values written to registers
+    can be read back.
+    
+    Just because of low-level interface implementation.
+    Even on very-very old drives.
+
+    So we can quickly determine if it worth to deal with channel/device
+    without long ATA reset/wait/identify sequence.
+    
+    Note, regular detect sequence on empty ATA slot cause 31 seconds delay
+    on each slot (according to specs this is standard timeout). Such
+    behavior is not convinient and not acceptable for systems with
+    many ATA channels.
+
+Return Value:
+
+    ULONG
+
+--*/
 ULONG
 NTAPI
 UniataAnybodyHome(
@@ -2744,7 +2815,7 @@
                          signatureHigh;
     UCHAR                statusByte;
     ULONG                RetVal=0;
-    ULONG                waitCount = 10000;
+    ULONG                waitCount = g_opt_WaitBusyResetCount;
     ULONG                at_home = 0;
 
     KdPrint2((PRINT_PREFIX "CheckDevice: Device %#x\n",
@@ -2807,9 +2878,13 @@
             KdPrint2((PRINT_PREFIX
                         "CheckDevice: BUSY\n"));
 
+            AtapiHardReset(chan, FALSE, 500 * 1000);
+/*
             AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_RESET_CONTROLLER );
+            chan->last_devsel = -1;
             AtapiStallExecution(500 * 1000);
             AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_REENABLE_CONTROLLER);
+*/
             SelectDrive(chan, deviceNumber & 0x01);
 
             do {
@@ -3072,49 +3147,35 @@
             // garbage geometry in the IDENTIFY data.
             // This is ONLY for the crashdump environment as
             // these are ESDI devices.
-            if (LunExt->IdentifyData.SectorsPerTrack ==
-                    0x35 &&
-                LunExt->IdentifyData.NumberOfHeads ==
-                    0x07) {
+            if (LunExt->IdentifyData.SectorsPerTrack == 0x35 &&
+                LunExt->IdentifyData.NumberOfHeads == 0x07) {
 
-                KdPrint2((PRINT_PREFIX 
-                           "FindDevices: Found nasty Compaq ESDI!\n"));
+                KdPrint2((PRINT_PREFIX "FindDevices: Found nasty Compaq ESDI!\n"));
 
                 // Change these values to something reasonable.
-                LunExt->IdentifyData.SectorsPerTrack =
-                    0x34;
-                LunExt->IdentifyData.NumberOfHeads =
-                    0x0E;
+                LunExt->IdentifyData.SectorsPerTrack = 0x34;
+                LunExt->IdentifyData.NumberOfHeads = 0x0E;
             }
 
-            if (LunExt->IdentifyData.SectorsPerTrack ==
-                    0x35 &&
-                LunExt->IdentifyData.NumberOfHeads ==
-                    0x0F) {
+            if (LunExt->IdentifyData.SectorsPerTrack == 0x35 &&
+                LunExt->IdentifyData.NumberOfHeads == 0x0F) {
 
-                KdPrint2((PRINT_PREFIX 
-                           "FindDevices: Found nasty Compaq ESDI!\n"));
+                KdPrint2((PRINT_PREFIX "FindDevices: Found nasty Compaq ESDI!\n"));
 
                 // Change these values to something reasonable.
-                LunExt->IdentifyData.SectorsPerTrack =
-                    0x34;
-                LunExt->IdentifyData.NumberOfHeads =
-                    0x0F;
+                LunExt->IdentifyData.SectorsPerTrack = 0x34;
+                LunExt->IdentifyData.NumberOfHeads = 0x0F;
             }
 
 
-            if (LunExt->IdentifyData.SectorsPerTrack ==
-                    0x36 &&
-                LunExt->IdentifyData.NumberOfHeads ==
-                    0x07) {
+            if (LunExt->IdentifyData.SectorsPerTrack == 0x36 &&
+                LunExt->IdentifyData.NumberOfHeads == 0x07) {
 
                 KdPrint2((PRINT_PREFIX "FindDevices: Found nasty UltraStor ESDI!\n"));
 
                 // Change these values to something reasonable.
-                LunExt->IdentifyData.SectorsPerTrack =
-                    0x3F;
-                LunExt->IdentifyData.NumberOfHeads =
-                    0x10;
+                LunExt->IdentifyData.SectorsPerTrack = 0x3F;
+                LunExt->IdentifyData.NumberOfHeads = 0x10;
                 skipSetParameters = TRUE;
             }
 
@@ -3134,9 +3195,13 @@
                 KdPrint2((PRINT_PREFIX
                             "FindDevices: Resetting controller before SetDriveParameters.\n"));
 
+                AtapiHardReset(chan, FALSE, 500 * 1000);
+/*
                 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_RESET_CONTROLLER );
+                chan->last_devsel = -1;
                 AtapiStallExecution(500 * 1000);
                 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_REENABLE_CONTROLLER);
+*/
                 SelectDrive(chan, i & 0x01);
 
                 do {
@@ -3189,6 +3254,7 @@
     if (!deviceResponded) {
 
         AtapiWritePort1(chan, IDX_IO2_o_Control,IDE_DC_RESET_CONTROLLER );
+        chan->last_devsel = -1;
         AtapiStallExecution(50 * 1000);
         AtapiWritePort1(chan, IDX_IO2_o_Control,IDE_DC_REENABLE_CONTROLLER);
     }
diff -ruN v45j5\driver\id_queue.cpp v46b4\driver\id_queue.cpp
--- v45j5\driver\id_queue.cpp	Wed Jul 11 18:26:26 2012
+++ v46b4\driver\id_queue.cpp	Tue Mar 08 18:34:00 2016
@@ -228,6 +228,7 @@
         AtaReq->next_req = NULL;
         LunExt->first_req =
         LunExt->last_req = AtaReq;
+        chan->cur_cdev = GET_CDEV(Srb);
     }
     LunExt->queue_depth++;
     chan->queue_depth++;
diff -ruN v45j5\driver\id_sata.cpp v46b4\driver\id_sata.cpp
--- v45j5\driver\id_sata.cpp	Wed Sep 23 18:18:12 2015
+++ v46b4\driver\id_sata.cpp	Mon Mar 14 12:08:40 2016
@@ -576,7 +576,7 @@
 
 } // end UniataSataIdentifyPM()
 
-#ifdef DBG
+#ifdef _DEBUG
 VOID
 NTAPI
 UniataDumpAhciRegs(
@@ -631,7 +631,7 @@
     }
     return;
 } // end UniataDumpAhciPortRegs()
-#endif //DBG
+#endif //_DEBUG
 
 
 BOOLEAN
@@ -654,9 +654,9 @@
 
     KdPrint2((PRINT_PREFIX "  UniataAhciInit:\n"));
 
-#ifdef DBG
+#ifdef _DEBUG
     UniataDumpAhciRegs(deviceExtension);
-#endif //DBG
+#endif //_DEBUG
 
     CAP2 = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP2);
     if(CAP2 & AHCI_CAP2_BOH) {
@@ -891,10 +891,10 @@
     ULONG CAP;
     ULONG CAP2;
     ULONG GHC, GHC0;
-#ifdef DBG
+#ifdef _DEBUG
     ULONG BOHC;
     ULONG v_Mn, v_Mj;
-#endif //DBG
+#endif //_DEBUG
     ULONG NumberChannels;
     ULONG BaseMemAddress;
     BOOLEAN MemIo = FALSE;
@@ -919,9 +919,9 @@
     deviceExtension->BaseIoAHCI_0.Addr  = BaseMemAddress;
     deviceExtension->BaseIoAHCI_0.MemIo = MemIo;
 
-#ifdef DBG
+#ifdef _DEBUG
     UniataDumpAhciRegs(deviceExtension);
-#endif //DBG
+#endif //_DEBUG
 
     GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
     if(GHC & AHCI_GHC_HR) {
@@ -961,12 +961,12 @@
         KdPrint2((PRINT_PREFIX "  64bit"));
         //deviceExtension->Host64 = TRUE; // this is just DETECT, do not update anything
     }
-#ifdef DBG
+#ifdef _DEBUG
     if(CAP2 & AHCI_CAP2_BOH) {
         BOHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_BOHC);
         KdPrint2((PRINT_PREFIX "  BOHC %#x", BOHC));
     }
-#endif //DBG
+#endif //_DEBUG
     if(CAP & AHCI_CAP_NCQ) {
         KdPrint2((PRINT_PREFIX "  NCQ"));
     }
@@ -1031,7 +1031,7 @@
     }
     KdPrint2((PRINT_PREFIX "  Adjusted Channels %d\n", NumberChannels));
 
-#ifdef DBG
+#ifdef _DEBUG
     v_Mj = ((version >> 20) & 0xf0) + ((version >> 16) & 0x0f);
     v_Mn = ((version >> 4) & 0xf0) + (version & 0x0f);
 
@@ -1039,7 +1039,7 @@
 		  v_Mj, v_Mn,
 		  NumberChannels, PI));
     KdPrint(("  AHCI SATA Gen %d\n", (((CAP & AHCI_CAP_ISS_MASK) >> 20)) ));
-#endif //DBG
+#endif //_DEBUG
 
     if(CAP & AHCI_CAP_SPM) {
         KdPrint2((PRINT_PREFIX "  PM supported\n"));
@@ -1138,9 +1138,9 @@
     KdPrint((" AHCI: complete mask %#x\n", chan->AhciCompleteCI));
     chan->AhciLastIS = IS.Reg;
     if(CI & (1 << tag)) {
-#ifdef DBG
+#ifdef _DEBUG
         UniataDumpAhciPortRegs(chan);
-#endif //DBG
+#endif //_DEBUG
         //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
         if(IS.Reg &
             (ATA_AHCI_P_IX_OF | ATA_AHCI_P_IX_INF | ATA_AHCI_P_IX_IF |
@@ -1238,8 +1238,6 @@
         if(((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp|ATA_CMD_FLAG_FUA)) == ATA_CMD_FLAG_LBAIOsupp) &&
            CheckIfBadBlock(chan->lun[DeviceNumber], lba, count)) {
             KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count));
-            //return IDE_STATUS_ERROR;
-            //return SRB_STATUS_ERROR;
             return 0;
         }
 
@@ -1279,22 +1277,15 @@
 
             chan->ChannelCtrlFlags |= CTRFLAGS_LBA48;
         } else {
-//#ifdef _MSC_VER
-//#pragma warning(push)
-//#pragma warning(disable:4333) // right shift by too large amount, data loss
-//#endif
             fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f);
             chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48;
-//#ifdef _MSC_VER
-//#pragma warning(pop)
-//#endif
         }
 
         //fis[14] = 0x00;
 
     }
 
-    KdDump(fis, 20);
+    //KdDump(fis, 20);
 
     return 20;
 } // end UniataAhciSetupFIS_H2D()
@@ -1438,7 +1429,7 @@
     UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS.Reg);
 
     if (timeout && (i >= timeout)) {
-#ifdef DBG
+#ifdef _DEBUG
         ULONG TFD;
 
         SError = AtapiReadPort4(chan, IDX_SATA_SError);
@@ -1446,7 +1437,7 @@
 
         TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
         KdPrint2(("  TFD %#x\n", TFD));
-#endif //DBG
+#endif //_DEBUG
         
         return IDE_STATUS_WRONG;
     }
@@ -1532,9 +1523,9 @@
         KdPrint(("  length/DEV_BSIZE != bcount\n"));
     }
 
-#ifdef DBG
+#ifdef _DEBUG
     //UniataDumpAhciPortRegs(chan);
-#endif // DBG
+#endif // _DEBUG
 
     if(!Srb) {
         Srb = BuildAhciInternalSrb(HwDeviceExtension, DeviceNumber, lChannel, data, length);
@@ -1590,15 +1581,15 @@
 
     AtaReq->ahci.io_cmd_flags = ahci_flags;
 
-#ifdef DBG
+#ifdef _DEBUG
     //UniataDumpAhciPortRegs(chan);
-#endif // DBG
+#endif // _DEBUG
 
     UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
 
-#ifdef DBG
+#ifdef _DEBUG
     //UniataDumpAhciPortRegs(chan);
-#endif // DBG
+#endif // _DEBUG
 
     if(wait_flags == ATA_IMMEDIATE) {
         statusByte = 0;
@@ -1645,9 +1636,9 @@
 //        KdPrint(("  length/DEV_BSIZE != bcount\n"));
 //    }
 
-#ifdef DBG
+#ifdef _DEBUG
     //UniataDumpAhciPortRegs(chan);
-#endif // DBG
+#endif // _DEBUG
 
     if(!Srb) {
         KdPrint(("  !Srb\n"));
@@ -1700,15 +1691,15 @@
 
     AtaReq->ahci.io_cmd_flags = ahci_flags;
 
-#ifdef DBG
+#ifdef _DEBUG
     //UniataDumpAhciPortRegs(chan);
-#endif // DBG
+#endif // _DEBUG
 
     UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
 
-#ifdef DBG
+#ifdef _DEBUG
     //UniataDumpAhciPortRegs(chan);
-#endif // DBG
+#endif // _DEBUG
 
     if(wait_flags == ATA_IMMEDIATE) {
         statusByte = 0;
@@ -1863,9 +1854,9 @@
     }
     KdPrint(("  TFD %#x\n", TFD));
 
-#ifdef DBG
+#ifdef _DEBUG
     UniataDumpAhciPortRegs(chan);
-#endif // DBG
+#endif // _DEBUG
 
     (*signature) = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_SIG);
     KdPrint(("  sig: %#x\n", *signature));
@@ -2178,10 +2169,10 @@
         return 0;
     }
 
-#ifdef DBG
+#ifdef _DEBUG
     KdPrint2(("  prd_length %#x, flags %#x, base %I64x\n", AHCI_CL->prd_length, AHCI_CL->cmd_flags, 
             AHCI_CL->cmd_table_phys));
-#endif // DBG
+#endif // _DEBUG
 
     CMD0 = CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
     KdPrint2(("  CMD %#x\n", CMD));
@@ -2350,9 +2341,9 @@
 
     KdPrint2(("UniataAhciResume: lChan %d\n", chan->lChannel));
 
-#ifdef DBG
+#ifdef _DEBUG
     //UniataDumpAhciPortRegs(chan);
-#endif // DBG
+#endif // _DEBUG
 
     /* Disable port interrupts */
     UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
@@ -2390,16 +2381,16 @@
 	     );
     UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */
 
-#ifdef DBG
+#ifdef _DEBUG
     //UniataDumpAhciPortRegs(chan);
-#endif // DBG
+#endif // _DEBUG
 
     UniataAhciStartFR(chan);
     UniataAhciStart(chan);
 
-#ifdef DBG
+#ifdef _DEBUG
     UniataDumpAhciPortRegs(chan);
-#endif // DBG
+#endif // _DEBUG
 
     return;
 } // end UniataAhciResume()
@@ -2575,9 +2566,9 @@
         PUCHAR prd_base0;
         ULONGLONG prd_base64_0;
     };
-#ifdef DBG
+#ifdef _DEBUG
     ULONG d;
-#endif // DBG
+#endif // _DEBUG
 
     prd_base64_0 = prd_base64 = 0;
     prd_base = (PUCHAR)(&AtaReq->ahci_cmd0);
@@ -2585,10 +2576,10 @@
 
     prd_base64 = (prd_base64 + max(FIELD_OFFSET(ATA_REQ, ahci_cmd0), AHCI_CMD_ALIGNEMENT_MASK+1)) & ~AHCI_CMD_ALIGNEMENT_MASK;
 
-#ifdef DBG
+#ifdef _DEBUG
     d = (ULONG)(prd_base64 - prd_base64_0);
     KdPrint2((PRINT_PREFIX "  AtaReq %#x: cmd aligned %I64x, d=%x\n", AtaReq, prd_base64, d));
-#endif // DBG
+#endif // _DEBUG
 
     AtaReq->ahci.ahci_cmd_ptr = (PIDE_AHCI_CMD)prd_base64;
     KdPrint2((PRINT_PREFIX "  ahci_cmd_ptr %#x\n", AtaReq->ahci.ahci_cmd_ptr));
diff -ruN v45j5\driver\id_sata.h v46b4\driver\id_sata.h
--- v45j5\driver\id_sata.h	Wed Sep 23 18:18:02 2015
+++ v46b4\driver\id_sata.h	Wed Mar 09 12:47:16 2016
@@ -414,7 +414,7 @@
     IN ULONG c
     )
 {
-#ifdef DBG
+#ifdef _DEBUG
     KdPrint2((PRINT_PREFIX "imp: %#x & %#x\n", (deviceExtension)->AHCI_PI, (1<<c) ));
 #endif
     return (((deviceExtension)->AHCI_PI) & ((ULONG)1 << c)) ? TRUE : FALSE;
diff -ruN v45j5\driver\uniata_ver.h v46b4\driver\uniata_ver.h
--- v45j5\driver\uniata_ver.h	Sun Jan 24 15:05:08 2016
+++ v46b4\driver\uniata_ver.h	Mon Mar 21 12:40:20 2016
@@ -1,10 +1,10 @@
-#define UNIATA_VER_STR         "45j5"
-#define UNIATA_VER_DOT         0.45.10.5
+#define UNIATA_VER_STR         "46b4"
+#define UNIATA_VER_DOT         0.46.2.4
 #define UNIATA_VER_MJ          0
-#define UNIATA_VER_MN          45
-#define UNIATA_VER_SUB_MJ      10
-#define UNIATA_VER_SUB_MN      5
-#define UNIATA_VER_DOT_COMMA   0,45,10,5
-#define UNIATA_VER_DOT_STR     "0.45.10.5"
+#define UNIATA_VER_MN          46
+#define UNIATA_VER_SUB_MJ      2
+#define UNIATA_VER_SUB_MN      4
+#define UNIATA_VER_DOT_COMMA   0,46,2,4
+#define UNIATA_VER_DOT_STR     "0.46.2.4"
 #define UNIATA_VER_YEAR        2016
 #define UNIATA_VER_YEAR_STR    "2016"
