diff -ruN v45j5\chglog.txt v46d2\chglog.txt
--- v45j5\chglog.txt	Sun Jan 24 14:59:18 2016
+++ v46d2\chglog.txt	Sat Mar 26 19:47:02 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
 
 --
@@ -736,6 +736,7 @@
 e) Added "PortMask" option for AHCI channels and partially for SATA (like "Exclude").
 This option can reduce available cannels.
 e) Added "NumberChannels" option for SATA, this option can only reduce available cannels.
+i) works on nVidia SATA MCP51 PATA/SATA
 
 --
 2015.02.08 - v0.45f, v0.45f1
@@ -753,7 +754,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.
@@ -784,6 +785,7 @@
 system performance. 
 Interrupt masking behavior is managed by AtapiSendDisableIntr registry 
 option and is defaulted to FALSE
+ROS BUG-9119
 
 --
 2015.02.18 - v0.45f7
@@ -794,19 +796,19 @@
 --
 2015.02.18 - v0.45f8
 
-e) try to wait for WordCount in DPC
+e) try to wait for WordCount in DPC (ROS BUG-9119)
 
 --
 2015.02.18 - v0.45f9
 
-e) force SATA ATAPI to send Packet in ISR
+e) force SATA ATAPI to send Packet in ISR (ROS BUG-9119)
 
 --
 2015.02.18 - v0.45f10
 
 e) roll-back to v0.45f7
 e) do not use AtaSetTransferMode() for SATA ATAPI devices
-according to Linux ata drivers
+according to Linux ata drivers (ROS BUG-9119)
 e) try blind reading data for ATAPI if no WordCount reported
 
 --
@@ -816,12 +818,14 @@
 Problem with zero wordCount persists, but we get PIO timing problem.
 !) force read data from ATAPI device on 'strange' (zero wordCount, but raised DRQ)
 condition seems to work properly
+ROS BUG-9119
 
 --
 2015.02.19 - v0.45g
 
 !) added check for ATAPI if IDE identify fails (some devices doesn't report
 ATAPI signature in wrong internal states)
+ROS BUG-9119
 
 --
 2015.02.22 - v0.45g1
@@ -840,6 +844,7 @@
 
 !) AtapiSuckPort2() is not called automatically if AtapiSuckDataPort2() get 
 less data than expected. Rest of data may come later.
+ROS BUG-9119
 
 --
 2015.02.22 - v0.45g3
@@ -992,7 +997,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 +1005,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
@@ -1012,4 +1017,304 @@
 2016.01.24 - v0.45j5
 
 !) fixed bug with missing AtapiDmaStart() on HDD Read in IdeReadWrite()
+i) hangs on nVidia MCP51 (not sure that since this version)
 
+--
+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
+i) UniataClaimLegacyPCIIDE() doesn't work on NT4 SMP (by KtP)
+CSB5 device has ISA ports exposed via PCI BARs 0-3
+
+--
+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)
+
+--
+2016.03.20 - v0.46b5
+
+!-) removed unnecessary ExFreePool() from UniataClaimLegacyPCIIDE() because 
+buffer is deallocated inside HalAssignSlotResources()
+!) do not report 0x3f6 register usage on old ISA, even with correct 1-byte 
+range length
+e) do not call UniataClaimLegacyPCIIDE() if ISA ranges are exposed via PCI 
+BARs 0-3
+
+--
+2016.03.21 - v0.46b6
+
+!) according to newer FBSD/Linux code SiS chipset programming is not the 
+same as nVidia
+e) try to disable NVQ option use (code seems to be much more different for NCQ mode)
+and clear NVQ flag in HwFlags in oder to operate in old-style mode.
+This option affects interrupt management registers layout.
+i) according to Linux sources, NVQ mode should be specially enabled. 
+Otherwise use old-style mechanism.
+
+--
+2016.03.22 - v0.46b7
+
+e) try to continue init if UniataClaimLegacyPCIIDE() fails on SMP HAL under 
+NT3/4.
+i) Some NT3/4 SMP HALs cannot reallocate IO resources of BusMaster PCI controller
+Since nobody claimed PrimarySecondary yet, try init and claim them
+However it is not 100% safe way.
+!) fixed bug with DeviceID/VendorID in atactl output
+*) align DeviceID/VendorID length in atactl output
+!) fixed bug with ISA-on-PCI detect (used BMList[i] instead of newBMListPtr
+i) doesn't work (hangs) on MCP51 SATA/PATA
+
+--
+2016.03.22 - v0.46b8
+
+-) removed old nVidia updates related to ROS BUG-9119
+i) doesn't work (hangs) on MCP51 SATA/PATA
+
+--
+2016.03.22 - v0.46c
+
+i) roll-back to 45e
++) commit general updates and optimizations from 0.46b8
+expect nVidia-related, DriveSelect optimization, DWORD_IO,
+MECHANISM_STATUS, ATAPI iReason, error recovery context,
+ISA-related changes
+
+--
+2016.03.22 - v0.46c1
+
++) commit DriveSelect optimization
++) commit fix for set (U)DMA mode on SATA
+i) MCP51 SATA/PATA ok (UDMA2 ATAPI + SATA150 HDD)
+
+--
+2016.03.23 - v0.46c2
+
++) commit DWORD_IO
++) commit DMADir
++) commit new VIA timings
++) commit ISA-related changes (w/o PCI detect)
+
+--
+2016.03.23 - v0.46c3
+
++) commit MECHANISM_STATUS fix
+
+--
+2016.03.23 - v0.46c4
+
++) commit ISA-only fixes
+
+--
+2016.03.23 - v0.46c5
+
+!) fixed check for conflicting IO resources (ISA vs PCI).
+Also, the check is unified and performed in AtapiCheckIOInterference()
+In some cases we could touch PCI-allocated ISA (BusMaster) IO resources
+on pure ISA detect.
+*) AtapiFindController() is renamed to AtapiFindIsaController()
+
+--
+2016.03.25 - v0.46c6-8
+
+!) fixes in AtapiFindIsaController() scan algorithm
+
+--
+2016.03.25 - v0.46c9
+
++) commit SATA ATAPI-specific changes (ROS BUG-9119)
+
+--
+2016.03.25 - v0.46c10
+
++) commit new nVidia chipset setup
+i) we get back to 0.46b8 with Isa detect fixes and without very specific 
+ATAPI continue-PIO-read code
+i) MCP51 SATA/PATA ok (UDMA2 ATAPI + SATA150 HDD), Bochs ok
+
+--
+2016.03.25 - v0.46d
+
+e) prefer AltInit if UniataClaimLegacyPCIIDE() fails
+for CSB5 (see above, 0.46b3) and similar cases
+*) fixed dev/vendor logs
+--
+2016.03.25 - v0.46d1
+
+!) commited temporary commented resourceList allocation for 
+HalAssignSlotResources(). e.g. ICH4 fails PCI init on UP system.
+i) in general, resource use claiming should be completly rewritten.
+
+--
+2016.03.25 - v0.46d2
+
+e) always attempt to init Compatible controller if HalAssignSlotResources() fails
+and Primary/Secondary not claimed yes
diff -ruN v45j5\driver\atapi.h v46d2\driver\atapi.h
--- v45j5\driver\atapi.h	Wed Sep 23 02:05:38 2015
+++ v46d2\driver\atapi.h	Thu Mar 24 12:11:32 2016
@@ -1,6 +1,6 @@
 /*++
 
-Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2002-2016 Alexandr A. Telyatnikov (Alter)
 
 Module Name:
     atapi.h
@@ -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
     );
 
 
@@ -1266,7 +1300,7 @@
     );
 
 ULONG NTAPI
-AtapiFindController(
+AtapiFindIsaController(
     IN PVOID HwDeviceExtension,
     IN PVOID Context,
     IN PVOID BusInformation,
diff -ruN v45j5\driver\bm_devs.h v46d2\driver\bm_devs.h
--- v45j5\driver\bm_devs.h	Wed Sep 23 19:05:02 2015
+++ v46d2\driver\bm_devs.h	Tue Mar 22 16:49:48 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 v46d2\driver\bsmaster.h
--- v45j5\driver\bsmaster.h	Sun Jan 24 12:51:36 2016
+++ v46d2\driver\bsmaster.h	Tue Mar 22 16:50:10 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 v46d2\driver\Dist\2K\uata_2k.inf
--- v45j5\driver\Dist\2K\uata_2k.inf	Sun Jan 24 15:05:14 2016
+++ v46d2\driver\Dist\2K\uata_2k.inf	Sat Mar 26 19:51:50 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/26/2016,0.46.4.2
 
 ;
 ; Source file information
diff -ruN v45j5\driver\Dist\2K\uata_2kh.inf v46d2\driver\Dist\2K\uata_2kh.inf
--- v45j5\driver\Dist\2K\uata_2kh.inf	Sun Jan 24 15:05:14 2016
+++ v46d2\driver\Dist\2K\uata_2kh.inf	Sat Mar 26 19:51:50 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/26/2016,0.46.4.2
 
 ;
 ; Source file information
diff -ruN v45j5\driver\Dist\2K\uniata_w2k.reg v46d2\driver\Dist\2K\uniata_w2k.reg
--- v45j5\driver\Dist\2K\uniata_w2k.reg	Sun Jan 24 15:05:14 2016
+++ v46d2\driver\Dist\2K\uniata_w2k.reg	Sat Mar 26 19:51:50 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.4.2"
 "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 v46d2\driver\Dist\atactl.exe differ
diff -ruN v45j5\driver\Dist\NT4\uata_nt4.inf v46d2\driver\Dist\NT4\uata_nt4.inf
--- v45j5\driver\Dist\NT4\uata_nt4.inf	Sun Jan 24 15:05:14 2016
+++ v46d2\driver\Dist\NT4\uata_nt4.inf	Sat Mar 26 19:51:50 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/26/2016,0.46.4.2
 
 ;
 ; Source file information
Binary files v45j5\driver\Dist\tools\build_inf.exe and v46d2\driver\Dist\tools\build_inf.exe differ
diff -ruN v45j5\driver\Dist\XP\uata_xp.inf v46d2\driver\Dist\XP\uata_xp.inf
--- v45j5\driver\Dist\XP\uata_xp.inf	Sun Jan 24 15:05:14 2016
+++ v46d2\driver\Dist\XP\uata_xp.inf	Sat Mar 26 19:51:50 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/26/2016,0.46.4.2
 
 ;
 ; Source file information
diff -ruN v45j5\driver\Dist\XP\uata_xph.inf v46d2\driver\Dist\XP\uata_xph.inf
--- v45j5\driver\Dist\XP\uata_xph.inf	Sun Jan 24 15:05:14 2016
+++ v46d2\driver\Dist\XP\uata_xph.inf	Sat Mar 26 19:51:50 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/26/2016,0.46.4.2
 
 ;
 ; Source file information
diff -ruN v45j5\driver\id_ata.cpp v46d2\driver\id_ata.cpp
--- v45j5\driver\id_ata.cpp	Sun Jan 24 14:57:52 2016
+++ v46d2\driver\id_ata.cpp	Sat Mar 26 19:41: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
@@ -100,6 +106,7 @@
 BOOLEAN g_opt_Verbose = 0;
 
 BOOLEAN WinVer_WDM_Model = FALSE;
+ULONG CPU_num = 1;
 
 //UCHAR EnableDma = FALSE;
 //UCHAR EnableReorder = FALSE;
@@ -561,6 +568,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 +789,7 @@
 DDKFASTAPI
 AtapiSoftReset(
     IN PHW_CHANNEL   chan,
-    ULONG            DeviceNumber
+    IN ULONG         DeviceNumber
     )
 {
     //ULONG c = chan->lChannel;
@@ -770,10 +808,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 +864,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 +893,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
@@ -998,7 +1063,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) {
@@ -1020,7 +1085,6 @@
     case ATA_IMMEDIATE:
         GetStatus(chan, statusByte);
         if (statusByte & IDE_STATUS_ERROR) {
-            // Note: some diveces doesn't clear ERR immediately
             KdPrint2((PRINT_PREFIX "  Warning: Immed Status %#x :(\n", statusByte));
             if(statusByte == (IDE_STATUS_IDLE | IDE_STATUS_ERROR)) {
                 break;
@@ -1465,6 +1529,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,27 +1737,28 @@
         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
-            // specifying manual delay in the way you see below.
+            // spacifying manual delay in the way you see below.
             ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
 
             // Work around for some IDE and one model Atapi that will present more than
@@ -1713,6 +1785,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 +2173,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,
@@ -2125,7 +2228,6 @@
             LunExt->RwSwitchMCost = REORDER_MCOST_SWITCH_RW_CD;
             LunExt->SeekBackMCost = REORDER_MCOST_SEEK_BACK_CD;
             statusByte = WaitForDrq(chan);
-
         } else {
             KdPrint2((PRINT_PREFIX "IssueIdentify: ATAPI drive type %#x.\n",
                 LunExt->IdentifyData.DeviceType));
@@ -2327,7 +2429,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 +2458,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 +2469,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 +2506,7 @@
                     // Indicate ready for next request.
                     ScsiPortNotification(NextLuRequest,
                                          deviceExtension, 
-                                         PathId,
+                                         CurPathId,
                                          TargetId,
                                          Lun);
                 }
@@ -2401,7 +2519,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);
         
@@ -2479,11 +2597,22 @@
                     AtapiStallExecution(10000);
                 }
                 break; }
-            case ATA_SIS_ID:
+            case ATA_SIS_ID: {
+                KdPrint2((PRINT_PREFIX "  SIS\n"));
+                if(!(ChipFlags & UNIATA_SATA))
+                    goto default_reset;
+                break; }
+#if 0
+            case ATA_NVIDIA_ID: {
+                KdPrint2((PRINT_PREFIX "  nVidia\n"));
+                if(!(ChipFlags & UNIATA_SATA))
+                    goto default_reset;
+                break; }
+#else
             case ATA_NVIDIA_ID: {
                 ULONG offs;
                 ULONG Channel = deviceExtension->Channel + j;
-                KdPrint2((PRINT_PREFIX "  SIS/nVidia\n"));
+                KdPrint2((PRINT_PREFIX "  nVidia\n"));
                 if(!(ChipFlags & UNIATA_SATA)) {
                     goto default_reset;
                 }
@@ -2516,6 +2645,7 @@
                     goto default_reset;
                 }
                 break; }
+#endif //0
             case ATA_SILICON_IMAGE_ID: {
                 ULONG offset;
                 ULONG Channel = deviceExtension->Channel + j;
@@ -2544,9 +2674,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 +2688,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;
@@ -3685,7 +3823,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]));
     }
@@ -3830,7 +3968,7 @@
     ULONG hIS;
     ULONG checked;
 
-    KdPrint2((PRINT_PREFIX "Intr: VendorID+DeviceID/Rev %#x/%#x (ex %d)\n",
+    KdPrint2((PRINT_PREFIX "Intr: DeviceID+VendorID/Rev %#x/%#x (ex %d)\n",
         deviceExtension->DevID, deviceExtension->RevID, deviceExtension->ExpectingInterrupt ));
 
     if(deviceExtension->HwFlags & UNIATA_AHCI) {
@@ -4458,7 +4596,7 @@
         KdPrint2((PRINT_PREFIX "NVIDIA\n"));
 
         ULONG offs = (ChipFlags & NV4OFF) ? 0x0440 : 0x0010;
-        ULONG shift = Channel << ((ChipFlags & NVQ) ? 4 : 2);
+        ULONG shift = Channel * ((ChipFlags & NVQ) ? 4 : 16);
 
         /* get and clear interrupt status */
         if(ChipFlags & NVQ) {
@@ -4632,7 +4770,7 @@
         if(dma_status & BM_STATUS_INTR) {
             // bullshit, we have DMA interrupt, but had never initiate DMA operation
             KdPrint2((PRINT_PREFIX "  clear unexpected DMA intr\n"));
-            AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL);
+            AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL);
             // catch it !
             OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
         }
@@ -4668,7 +4806,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;
         }
@@ -4684,7 +4823,7 @@
             /* clear interrupt and get status */
             GetBaseStatus(chan, statusByte);
             if(!(dma_status & BM_STATUS_ACTIVE)) {
-                AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL);
+                AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL);
             }
             KdPrint3((PRINT_PREFIX "  base status %#x (+BM_STATUS_INTR)\n", statusByte));
             return INTERRUPT_REASON_OUR;
@@ -4783,9 +4922,9 @@
 
     BOOLEAN atapiDev = FALSE;
 
-#ifdef DBG
+#ifdef _DEBUG
     UCHAR Channel;
-#endif //DBG
+#endif //_DEBUG
     UCHAR lChannel;
     UCHAR DeviceNumber;
     BOOLEAN DmaTransfer = FALSE;
@@ -4818,11 +4957,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 +5628,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 +5637,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 +5647,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) {
@@ -5575,25 +5714,25 @@
         // Ensure that this is a write command.
         if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
 
-            KdPrint2((PRINT_PREFIX 
-                       "AtapiInterrupt: Write interrupt\n"));
+           KdPrint2((PRINT_PREFIX 
+                      "AtapiInterrupt: Write interrupt\n"));
 
-            statusByte = WaitOnBusy(chan);
+           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,
-                            AtaReq->DataBuffer,
-                            wordCount,
-                            UniataGetPioTiming(LunExt));
-            } else {
+               WriteBuffer(chan,
+                           AtaReq->DataBuffer,
+                           wordCount,
+                           UniataGetPioTiming(LunExt));
+           } else {
 
-                WriteBuffer2(chan,
-                            (PULONG)(AtaReq->DataBuffer),
-                            wordCount / 2,
-                            UniataGetPioTiming(LunExt));
-            }
+               WriteBuffer2(chan,
+                           (PULONG)(AtaReq->DataBuffer),
+                           wordCount / 2,
+                           UniataGetPioTiming(LunExt));
+           }
         } else {
 
             KdPrint3((PRINT_PREFIX 
@@ -5601,28 +5740,6 @@
                         interruptReason,
                         srb));
 
-            if(!wordCount && atapiDev && 
-                !(statusByte & (IDE_STATUS_ERROR | IDE_STATUS_BUSY)) &&
-                 (statusByte & IDE_STATUS_DRQ)) {
-                // this can be late Packet interrupt after packet sending
-                KdPrint2((PRINT_PREFIX "  unreliable wordCount ?\n"));
-
-                wordCount = AtapiSuckPortBuffer2(chan,
-                                                 AtaReq->DataBuffer,
-                                                 AtaReq->WordsLeft);
-                KdPrint2((PRINT_PREFIX "  transferred %#x\n", wordCount));
-                GetBaseStatus(chan, statusByte);
-                KdPrint2((PRINT_PREFIX "  status %#x, statusByte\n"));
-                if(wordCount) {
-                    interruptReason = ATAPI_IR_IO_toHost;
-#ifdef _DEBUG
-                    UniataDumpATARegs(chan);
-#endif
-                }
-                if(wordCount && AtaReq->WordsLeft) {
-                    goto continue_atapi_pio_read;
-                }
-            }
             // Fail this request.
             status = SRB_STATUS_ERROR;
             if(!wordCount && atapiDev && (srb->Cdb[0] != SCSIOP_REQUEST_SENSE)) {
@@ -5653,6 +5770,7 @@
 
     } else if (interruptReason == ATAPI_IR_IO_toHost && (statusByte & IDE_STATUS_DRQ)) {
 
+continue_read_drq:
 
         if (atapiDev) {
 
@@ -5710,7 +5828,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 +5836,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 +5845,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 +5854,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 +5903,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 +5976,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;
                 }
@@ -5901,7 +6032,7 @@
             }
 
             KdPrint(("--\n"));
-            KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
+            KdPrint2(("DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
             KdPrint2(("P:T:D=%d:%d:%d\n",
                                       Srb->PathId,
                                       Srb->TargetId,
@@ -5946,7 +6077,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 +6119,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 +6138,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 +6149,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 +6189,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 +6723,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 +6747,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 +6812,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 +7028,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 +7051,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 +7274,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];
@@ -7178,7 +7306,7 @@
         }
 
         KdPrint(("--\n"));
-        KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
+        KdPrint2(("DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
         KdPrint2(("P:T:D=%d:%d:%d\n",
                                   Srb->PathId,
                                   Srb->TargetId,
@@ -7262,20 +7390,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 +7451,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,6 +7524,10 @@
         }
 
         // check if DMA read/write
+        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;
@@ -7404,8 +7541,9 @@
         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 +7613,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 +7635,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;
+                    }
                 }
             }
 
@@ -7690,9 +7830,8 @@
         }
 */
         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 +7898,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);
+    KdPrint3((PRINT_PREFIX "AtapiSendCommand: F:%#x, CntHL:%#x:%#x.\n", FeatureReg, byteCountHigh, byteCountLow));
 
     if (flags & DFLAGS_INT_DRQ) {
-
         // 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 +7924,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 +7975,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 +8033,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 +8045,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 +8058,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 +8072,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"));
@@ -9041,7 +9220,7 @@
         KdPrint2((PRINT_PREFIX 
                    "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
                    Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId));
-        KdPrint2((PRINT_PREFIX "   VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
+        KdPrint2((PRINT_PREFIX "   DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
 
         if(lChannel == deviceExtension->NumberChannels &&
            !Srb->Lun && !Srb->TargetId &&
@@ -10306,7 +10485,7 @@
 {
     HW_INITIALIZATION_DATA_COMMON hwInitializationData;
     ULONG                  adapterCount;
-    ULONG                  i, c, alt;
+    ULONG                  i, c, alt, pref_alt;
     ULONG                  statusToReturn, newStatus;
     PUNICODE_STRING        RegistryPath = (PUNICODE_STRING)Argument2;
     BOOLEAN                ReEnter = FALSE;
@@ -10318,6 +10497,8 @@
     PCONFIGURATION_INFORMATION GlobalConfig = IoGetConfigurationInformation();
     BOOLEAN PrimaryClaimed   = FALSE;
     BOOLEAN SecondaryClaimed = FALSE;
+    BOOLEAN IgnoreIsaCompatiblePci = FALSE;
+    BOOLEAN IgnoreNativePci = FALSE;
 
     LARGE_INTEGER t0, t1;
 
@@ -10329,6 +10510,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 +10520,7 @@
         MajorVersion=0x04;
         MinorVersion=0x01;
         BuildNumber=1;
+        CPU_num = KeNumberProcessors;
 #else
         // we are here for the 1st time
         // init CrossNT and get OS version
@@ -10345,8 +10529,9 @@
             //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
             return status;
         }
+        CPU_num = *KeNumberProcessors;
 #endif // USE_REACTOS_DDK
-        KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion, MinorVersion, BuildNumber, *KeNumberProcessors));
+        KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion, MinorVersion, BuildNumber, CPU_num));
 
         KeQuerySystemTime(&t0);
         do {
@@ -10430,8 +10615,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 +10626,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 +10644,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 > VM_NONE) {
+            g_opt_DriveSelectNanoDelay = 0;
         }
 
         g_opt_WaitBusyCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyCount", g_opt_WaitBusyCount); // 200 vs 20000
@@ -10475,8 +10671,10 @@
         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);
+    } // end !re-enter
 
     // Look for legacy ISA-bridged PCI IDE controller (onboard)
     KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
@@ -10487,7 +10685,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) {
@@ -10505,10 +10703,33 @@
             PrimaryClaimed = TRUE;
         if(GlobalConfig->AtDiskSecondaryAddressClaimed)
             SecondaryClaimed = TRUE;
+        pref_alt = 0;
 
         if(!WinVer_WDM_Model && !PrimaryClaimed && !SecondaryClaimed &&
             !(BMList[i].ChanInitOk & 0x80)) {
+            
+            // We just want to claim our PCI device in compatible mode, since we shall not
+            // tell system that we use it inside HwInitialize
+            // Even more, we shall cheat system, that work with ISA
+            // Note: this call may (but not 'must' or 'can') cause IO resource
+            // reallocation and switch to native mode if HAL supports this
             newStatus = UniataClaimLegacyPCIIDE(i);
+            // Special check for NT3.51/NT4 (not ReactOS !!!)
+            if((newStatus == STATUS_CONFLICTING_ADDRESSES) &&
+               //(BMList[i].ChanInitOk & 0x40) &&
+               /*CPU_num > 1 &&*/
+               (WinVer_Id() <= WinVer_NT)) {
+                // Some NT3/4 SMP (but not only) HALs cannot reallocate IO resources of
+                // BusMaster PCI controller
+                // Since nobody claimed Primary/Secondary yet, try init and claim them
+                // However it is not 100% safe way, especially under ReactOS, which doesn't resolve
+                // conflicts yet.
+                // We relay on ScsiPort internal checks
+                KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster on SMP NT3/4 system, try init anyway.\n"));
+                newStatus = STATUS_SUCCESS;
+                // Prefer alternative init method (try to change Isa -> PCI in ConfigInfo first)
+                pref_alt = 1;
+            }
             if(newStatus != STATUS_SUCCESS) {
                 KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
                 break;
@@ -10519,11 +10740,10 @@
             _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
         }
 
-
         for(alt = 0; alt < (ULONG)(WinVer_WDM_Model ? 1 : 2) ; alt++) {
 
             for(c=0; c<2; c++) {
-
+                // check is channel is manually excluded
                 if(AtapiRegCheckDevValue(NULL, c, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) {
                     break;
                 }
@@ -10567,7 +10787,7 @@
                 newStatus = ScsiPortInitialize(DriverObject,
                                                Argument2,
                                                &hwInitializationData.comm,
-                                               (PVOID)(i | (alt ? 0x80000000 : 0)));
+                                               (PVOID)(i | ((alt ^ pref_alt) ? 0x80000000 : 0)));
                 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
                 if (newStatus < statusToReturn) {
                     statusToReturn = newStatus;
@@ -10632,7 +10852,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)
@@ -10714,7 +10934,7 @@
 
     // Indicate 2 access ranges and reset FindAdapter.
     hwInitializationData.comm.NumberOfAccessRanges = 2;
-    hwInitializationData.comm.HwFindAdapter = AtapiFindController;
+    hwInitializationData.comm.HwFindAdapter = AtapiFindIsaController;
 
     if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsa", 0)) {
         // Indicate ISA bustype.
diff -ruN v45j5\driver\id_dma.cpp v46d2\driver\id_dma.cpp
--- v45j5\driver\id_dma.cpp	Tue Sep 29 19:24:50 2015
+++ v46d2\driver\id_dma.cpp	Wed Mar 23 09:37:30 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 v46d2\driver\id_init.cpp
--- v45j5\driver\id_init.cpp	Thu Oct 22 13:59:20 2015
+++ v46d2\driver\id_init.cpp	Fri Mar 25 22:52:40 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);
@@ -397,6 +397,8 @@
         if(!UniataAllocateLunExt(deviceExtension, UNIATA_ALLOCATE_NEW_LUNS)) {
             return STATUS_UNSUCCESSFUL;
         }
+        // DEBUG, we shall return success when AHCI is completly supported
+        //return STATUS_NOT_FOUND;
         return STATUS_SUCCESS;
     }
 
@@ -463,10 +465,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 )
         };
 
@@ -656,13 +658,11 @@
     }
 
     if(ChipFlags & UNIATA_AHCI) {
-
         deviceExtension->NumberChannels = 0;
         if(!UniataAhciDetect(HwDeviceExtension, pciData, ConfigInfo)) {
             KdPrint2((PRINT_PREFIX "  AHCI detect failed\n"));
             return STATUS_UNSUCCESSFUL;
         }
-
     } else
     if(!UniataChipDetectChannels(HwDeviceExtension, pciData, DeviceNumber, ConfigInfo)) {
         return STATUS_UNSUCCESSFUL;
@@ -1038,7 +1038,7 @@
         if(ChipFlags & UNIATA_SATA) {
 
             ULONG IoSize = 0;
-            ULONG BaseMemAddress = 0;
+            BaseMemAddress = 0;
 
             switch(DeviceID) {
             case 0x3149: // VIA 6420
@@ -1876,7 +1876,7 @@
     PHW_CHANNEL chan;
     UCHAR  tmp8;
     USHORT tmp16;
-    //ULONG  tmp32;
+    ULONG  tmp32;
     ULONG  c; // logical channel (for Compatible Mode controllers)
     BOOLEAN CheckCable = FALSE;
     BOOLEAN GlobalInit = FALSE;
@@ -2045,7 +2045,6 @@
     case ATA_INTEL_ID: {
         BOOLEAN IsPata;
         USHORT reg54;
-        UCHAR tmp8;
         if(ChipFlags & UNIATA_SATA) {
 
             KdPrint2((PRINT_PREFIX "Intel SATA\n"));
@@ -2195,13 +2194,29 @@
                 AtapiStallExecution(10);
                 KdPrint2((PRINT_PREFIX "BaseIoAddressSATA_0=%x\n", deviceExtension->BaseIoAddressSATA_0.Addr));
                 if(ChipFlags & NVQ) {
+                    KdPrint2((PRINT_PREFIX "Disable NCQ\n"));
+                    tmp32 = AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x0400);
+                    KdPrint2((PRINT_PREFIX "MODE=%#x\n", tmp32));
+                    if(tmp32 & ~0xfffffff9) {
+                        AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x0400, 
+                             tmp32 & 0xfffffff9);
+                    }
+                    ChipFlags &= ~NVQ;
+                    deviceExtension->HwFlags = ChipFlags;
+                }
+                if(ChipFlags & NVQ) {
+                    /* disable  ECO 398 */
+                    ChangePciConfig1(0x7f, (a & ~(1 << 7)));
+
+                    KdPrint2((PRINT_PREFIX "Enable NCQ\n"));
+                    /* enable NCQ support */
+                    AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x0400, 
+                         tmp32 | ~0x00000006);
+
                     /* clear interrupt status */
                     AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, 0x00ff00ff);
                     /* enable device and PHY state change interrupts */
                     AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4, 0x000d000d);
-                    /* disable NCQ support */
-                    AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x0400, 
-                        AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),0x0400) & 0xfffffff9);
                 } else {
                     /* clear interrupt status */
                     AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, 0xff);
@@ -2465,7 +2480,6 @@
             // do nothing for SATA
         } else
         if(ChipType == SIS133NEW) {
-            USHORT tmp16;
             // check 80-pin cable
             if(c == CHAN_NOT_SPECIFIED) {
                 // do nothing
@@ -2755,6 +2769,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 v46d2\driver\id_probe.cpp
--- v45j5\driver\id_probe.cpp	Thu Sep 24 12:13:42 2015
+++ v46d2\driver\id_probe.cpp	Sat Mar 26 12:39:18 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
@@ -285,6 +285,8 @@
     return TRUE;
 } // end UniataCheckPCISubclass()
 
+static CONST ULONG StdIsaPorts[] = {IO_WD1, IO_WD1 + ATA_ALTOFFSET, IO_WD2, IO_WD2 + ATA_ALTOFFSET, 0, 0};
+
 /*
     Device initializaton callback
     Builds PCI device list using Hal routines (not ScsiPort wrappers)
@@ -305,6 +307,7 @@
     ULONG                 funcNumber;
     BOOLEAN               no_buses = FALSE;
     BOOLEAN               no_ranges = FALSE;
+    BOOLEAN               non_isa = TRUE;
     ULONG                 busDataRead;
 //    BOOLEAN               SimplexOnly;
 
@@ -330,6 +333,7 @@
     BOOLEAN found;
     BOOLEAN known;
     BOOLEAN NeedPciAltInit;
+    BOOLEAN NonZeroSubId = 0;
 
     UCHAR IrqForCompat = 10;
 
@@ -337,22 +341,26 @@
     deviceStrPtr = deviceString;
     slotData.u.AsULONG = 0;
 
+    KdPrint2((PRINT_PREFIX "UniataEnumBusMasterController__: maxPciBus=%d\n", maxPciBus));
     if(!maxPciBus) {
         return(SP_RETURN_NOT_FOUND);
     }
     /*HwDeviceExtension =*/
     deviceExtension = (PHW_DEVICE_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(HW_DEVICE_EXTENSION));
     if(!deviceExtension) {
+        KdPrint2((PRINT_PREFIX "!deviceExtension\n"));
         return(SP_RETURN_NOT_FOUND);
     }
     RtlZeroMemory(deviceExtension, sizeof(HW_DEVICE_EXTENSION));
     PciDevMap = (PCHAR)ExAllocatePool(NonPagedPool, maxPciBus*PCI_MAX_DEVICES);
     if(!PciDevMap) {
+        KdPrint2((PRINT_PREFIX "!PciDevMap\n"));
         goto exit;
     }
     RtlZeroMemory(PciDevMap, maxPciBus*PCI_MAX_DEVICES);
 
     for(pass=0; pass<3; pass++) {
+        KdPrint2((PRINT_PREFIX "  pass %d\n", pass));
         no_buses = FALSE;
         for(busNumber=0 ;busNumber<maxPciBus && !no_buses; busNumber++) {
             for(slotNumber=0; slotNumber<PCI_MAX_DEVICES  && !no_buses; slotNumber++) {
@@ -360,6 +368,7 @@
             for(funcNumber=0; funcNumber<PCI_MAX_FUNCTION && !no_buses; funcNumber++) {
 
                 if(pass) {
+                    // use cached device presence map from the 1st pass
                     if(PciDevMap[busNumber*PCI_MAX_DEVICES + slotNumber] & (1 << funcNumber)) {
                         // ok
                     } else {
@@ -383,7 +392,7 @@
                     break;
                 }
                 // indicate that system has PCI bus(es)
-                hasPCI =TRUE;
+                hasPCI = TRUE;
 
                 // no device in this slot
                 if(busDataRead == 2) {
@@ -405,12 +414,17 @@
                 SubVendorID = pciData.u.type0.SubVendorID;
                 SubSystemID = pciData.u.type0.SubSystemID;
 
-                //KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id, BaseClass, SubClass ));
+                if(SubVendorID && SubSystemID) {
+                  NonZeroSubId = 1;
+                }
+
+                KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X, SubVen/Sys %4.4x/%4.4x\n", dev_id, BaseClass, SubClass, SubVendorID, SubSystemID));
 
                 // 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 +448,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) {
@@ -520,17 +543,26 @@
                 }
                 // validate Mem/Io ranges
                 no_ranges = TRUE;
+                non_isa = TRUE;
                 for(i=0; i<PCI_TYPE0_ADDRESSES; i++) {
                     if(pciData.u.type0.BaseAddresses[i] & ~0x7) {
                         no_ranges = FALSE;
                         //break;
                         KdPrint2((PRINT_PREFIX "Range %d = %#x\n", i, pciData.u.type0.BaseAddresses[i]));
+                        if(i<4) {
+                            if(StdIsaPorts[i] == (pciData.u.type0.BaseAddresses[i] & ~0x7)) {
+                                non_isa = FALSE;
+                            }
+                        }
                     }
                 }
                 if(no_ranges) {
                     KdPrint2((PRINT_PREFIX "No PCI Mem/Io ranges found on device, skip it\n"));
                     continue;
                 }
+                if(!non_isa) {
+                    KdPrint2((PRINT_PREFIX "standard ISA ranges on PCI, special case ?\n"));
+                }
 
                 if(pass) {
                     // fill list of detected devices
@@ -621,8 +653,9 @@
                         }
                     } else
                     if(pass == 2) {
-                        if(IsMasterDev(&pciData))
+                        if(IsMasterDev(&pciData)) {
                             continue;
+                        }
                     }
 
 /*                        if(known) {
@@ -650,6 +683,13 @@
                     newBMListPtr->NeedAltInit = NeedPciAltInit;
                     newBMListPtr->Known = known;
 
+                    if(!non_isa) {
+                        KdPrint2((PRINT_PREFIX "* ISA ranges on PCI, special case !\n"));
+                        // Do not fail init after unseccessfull call of UniataClaimLegacyPCIIDE()
+                        // some SMP HALs fails to reallocate IO range
+                        newBMListPtr->ChanInitOk |= 0x40;
+                    }
+
                     KdPrint2((PRINT_PREFIX "Add to BMList, AltInit %d\n", NeedPciAltInit));
                 } else {
                     KdPrint2((PRINT_PREFIX "count: BMListLen++\n"));
@@ -1255,12 +1295,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]));
                 }
             }
         }
@@ -1890,7 +1930,7 @@
     )
 {
     NTSTATUS status;
-    PCM_RESOURCE_LIST resourceList;
+    PCM_RESOURCE_LIST resourceList = NULL;
     UNICODE_STRING devname;
 
     KdPrint2((PRINT_PREFIX "UniataClaimLegacyPCIIDE:\n"));
@@ -1928,6 +1968,10 @@
 
     // IoReportDetectedDevice() should be used for WDM OSes
 
+    // TODO: check if resourceList is actually used inside HalAssignSlotResources()
+    // Note: with empty resourceList call to HalAssignSlotResources() fails on some HW
+    // e.g. Intel ICH4, but works with non-empty.
+
     resourceList->Count = 1;
     resourceList->List[0].InterfaceType = PCIBus;
     resourceList->List[0].BusNumber = BMList[i].busNumber;
@@ -1946,8 +1990,12 @@
 
     if (!NT_SUCCESS(status)) {
         KdPrint2((PRINT_PREFIX "HalAssignSlotResources failed %#x\n", status));
-        ExFreePool(resourceList);
-        goto del_do;
+        // this is always deallocated inside HalAssignSlotResources() implementation
+        //ExFreePool(resourceList); 
+        //goto del_do;
+        IoDeleteDevice(BMList[i].PciIdeDevObj);
+        BMList[i].PciIdeDevObj          = NULL;
+        return status;
     }
 
     KdPrint2((PRINT_PREFIX "ok %#x\n", status));
@@ -1983,7 +2031,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 +2063,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;
@@ -2114,6 +2163,25 @@
 
 #endif //UNIATA_CORE
 
+BOOLEAN
+NTAPI
+AtapiCheckIOInterference(
+    IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
+    ULONG portBase) {
+    // check if Primary/Secondary Master IDE claimed
+    if((portBase == IO_WD1) &&
+       (ConfigInfo->AtdiskPrimaryClaimed || AtdiskPrimaryClaimed)) {
+        KdPrint2((PRINT_PREFIX "AtapiCheckIOInterference: AtdiskPrimaryClaimed\n"));
+        return TRUE;
+    } else
+    if((portBase == IO_WD2) &&
+       (ConfigInfo->AtdiskSecondaryClaimed || AtdiskSecondaryClaimed)) {
+        KdPrint2((PRINT_PREFIX "AtapiCheckIOInterference: AtdiskSecondaryClaimed\n"));
+        return TRUE;
+    }
+    return FALSE;
+} // end AtapiCheckIOInterference()
+
 /*++
 
 Routine Description:
@@ -2137,7 +2205,7 @@
 --*/
 ULONG
 NTAPI
-AtapiFindController(
+AtapiFindIsaController(
     IN PVOID HwDeviceExtension,
     IN PVOID Context,
     IN PVOID BusInformation,
@@ -2152,10 +2220,10 @@
     PUCHAR               ioSpace = NULL;
     ULONG                i;
     ULONG                irq=0;
-    ULONG                portBase;
+    ULONG                portBase=0;
     ULONG                retryCount;
 //    BOOLEAN              atapiOnly;
-    UCHAR                statusByte;
+    UCHAR                statusByte, statusByte2;
     BOOLEAN              preConfig = FALSE;
     //
     PIDE_REGISTERS_1 BaseIoAddress1;
@@ -2170,7 +2238,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 "AtapiFindIsaController (ISA):\n"));
 
     if (!deviceExtension) {
         return SP_RETURN_ERROR;
@@ -2217,23 +2285,40 @@
     }
 
 #endif //UNIATA_CORE
-
-
-    // Scan though the adapter address looking for adapters.
-    if (ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[0].RangeStart) != 0) {
-        ioSpace =  (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
-                                         ConfigInfo->AdapterInterfaceType,
-                                         ConfigInfo->SystemIoBusNumber,
-                                         (*ConfigInfo->AccessRanges)[0].RangeStart,
-                                         (*ConfigInfo->AccessRanges)[0].RangeLength,
-                                         (BOOLEAN) !((*ConfigInfo->AccessRanges)[0].RangeInMemory));
+/*
+    for(i=0; i<2; i++) {
+        if((*ConfigInfo->AccessRanges)[i].RangeStart) {
+            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
+                ));
+        }
+    }
+*/
+//    if((*ConfigInfo->AccessRanges)[0].RangeStart) {
+        portBase = ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[0].RangeStart);
+//    }
+    if(portBase) {
+        if(!AtapiCheckIOInterference(ConfigInfo, portBase)) {
+            ioSpace =  (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
+                                             ConfigInfo->AdapterInterfaceType,
+                                             ConfigInfo->SystemIoBusNumber,
+                                             (*ConfigInfo->AccessRanges)[0].RangeStart,
+                                             (*ConfigInfo->AccessRanges)[0].RangeLength,
+                                             (BOOLEAN) !((*ConfigInfo->AccessRanges)[0].RangeInMemory));
+        } else {
+            // do not touch resources, just fail later inside loop on next call to
+            // AtapiCheckIOInterference()
+        }
         *Again = FALSE;
         // 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));
     }
 
+    // Scan through the adapter address looking for adapters.
 #ifndef UNIATA_CORE
     while (AdapterAddresses[*adapterCount] != 0) {
 #else
@@ -2241,10 +2326,8 @@
 #endif //UNIATA_CORE
 
         retryCount = 4;
-        deviceExtension->DevIndex = (*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);
+        deviceExtension->DevIndex = (*adapterCount); // this is used inside AtapiRegCheckDevValue()
+        KdPrint2((PRINT_PREFIX "AtapiFindIsaController: adapterCount=%d\n", *adapterCount));
         
         for (i = 0; i < deviceExtension->NumberLuns; i++) {
             // Zero device fields to ensure that if earlier devices were found,
@@ -2257,50 +2340,51 @@
         // 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));
+            }
+            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(AtapiCheckIOInterference(ConfigInfo, portBase)) {
+                goto next_adapter;
             }
+            ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
+                                            ConfigInfo->AdapterInterfaceType,
+                                            ConfigInfo->SystemIoBusNumber,
+                                            ScsiPortConvertUlongToPhysicalAddress(portBase),
+                                            ATA_IOSIZE,
+                                            TRUE);
 
-        } 
+        } else {
+            KdPrint2((PRINT_PREFIX "preconfig portBase=%x\n", portBase));
+            // Check if Primary/Secondary Master IDE claimed
+            // We can also get here from preConfig branc with conflicting portBase
+            //   (and thus, w/o ioSpace allocated)
+            if(AtapiCheckIOInterference(ConfigInfo, portBase)) {
+                goto not_found;
+            }
+        }
         BaseIoAddress1 = (PIDE_REGISTERS_1)ioSpace;
-
+next_adapter:
         // Update the adapter count.
         (*adapterCount)++;
 
         // Check if ioSpace accessible.
         if (!ioSpace) {
-            KdPrint2((PRINT_PREFIX "AtapiFindController: !ioSpace\n"));
+            KdPrint2((PRINT_PREFIX "AtapiFindIsaController: !ioSpace\n"));
+            portBase = 0;
             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) {
             if(preConfig && 
                !ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[1].RangeStart)) {
-                KdPrint2((PRINT_PREFIX "AtapiFindController: PCMCIA ?\n"));
+                KdPrint2((PRINT_PREFIX "AtapiFindIsaController: PCMCIA ?\n"));
                 ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
                                                 ConfigInfo->AdapterInterfaceType,
                                                 ConfigInfo->SystemIoBusNumber,
@@ -2334,9 +2418,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 "AtapiFindIsaController: Status %x vs AltStatus %x missmatch, abort init ?\n", statusByte, statusByte2));
 
             if(BaseIoAddress2) {
                 ScsiPortFreeDeviceBase(HwDeviceExtension,
@@ -2344,6 +2428,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 +2441,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;
             }
         }
@@ -2375,7 +2462,7 @@
         if (AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) != 0xAA ||
             statusByte == IDE_STATUS_WRONG) {
 
-            KdPrint2((PRINT_PREFIX "AtapiFindController: Identifier read back from Master (%#x)\n",
+            KdPrint2((PRINT_PREFIX "AtapiFindIsaController: Identifier read back from Master (%#x)\n",
                         statusByte));
 
             statusByte = AtapiReadPort1(chan, IDX_IO2_AltStatus);
@@ -2390,7 +2477,7 @@
                     AtapiStallExecution(1000);
                     statusByte = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Status);
                     KdPrint2((PRINT_PREFIX
-                                "AtapiFindController: First access to status %#x\n",
+                                "AtapiFindIsaController: First access to status %#x\n",
                                 statusByte));
                 } while ((statusByte & IDE_STATUS_BUSY) && ++i < 10);
 
@@ -2410,21 +2497,9 @@
                 statusByte == IDE_STATUS_WRONG) {
 
                 KdPrint2((PRINT_PREFIX
-                            "AtapiFindController: Identifier read back from Slave (%#x)\n",
+                            "AtapiFindIsaController: 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 +2516,25 @@
                     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].RangeInMemory = FALSE;
+                if(hasPCI) {
+                    (*ConfigInfo->AccessRanges)[1].RangeStart = ScsiPortConvertUlongToPhysicalAddress((ULONG)BaseIoAddress2);
+                    (*ConfigInfo->AccessRanges)[1].RangeLength = ATA_ALTIOSIZE;
+                    (*ConfigInfo->AccessRanges)[1].RangeInMemory = FALSE;
+                } else {
+                    // NT4 and NT3.51 on ISA-only hardware definitly fail floppy.sys load
+                    // when this range is claimed by other driver.
+                    // However, floppy should use only 0x3f0-3f5,3f7
+                    if((ULONG)BaseIoAddress2 >= 0x3f0 && (ULONG)BaseIoAddress2 <= 0x3f7) {
+                        KdPrint2((PRINT_PREFIX "!!! Possible AltStatus vs Floppy IO range interference !!!\n"));
+                    }
+                    KdPrint2((PRINT_PREFIX "Do not expose to OS on old ISA\n"));
+                    (*ConfigInfo->AccessRanges)[i].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0);
+                    (*ConfigInfo->AccessRanges)[i].RangeLength = 0;
+                }
             }
 
             // Indicate the interrupt level corresponding to this IO range.
@@ -2489,7 +2576,7 @@
         AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, 0);
 
         KdPrint2((PRINT_PREFIX
-                   "AtapiFindController: Found IDE at %#x\n",
+                   "AtapiFindIsaController: Found IDE at %#x\n",
                    BaseIoAddress1));
 
         // For Daytona, the atdisk driver gets the first shot at the
@@ -2505,12 +2592,12 @@
 #ifndef UNIATA_CORE
                     if (AtapiParseArgumentString(ArgumentString, "dump") == 1) {
                         KdPrint2((PRINT_PREFIX
-                                   "AtapiFindController: Crash dump\n"));
+                                   "AtapiFindIsaController: Crash dump\n"));
                         //atapiOnly = FALSE;
                         deviceExtension->DriverMustPoll = TRUE;
                     } else {
                         KdPrint2((PRINT_PREFIX
-                                   "AtapiFindController: Atapi Only\n"));
+                                   "AtapiFindIsaController: Atapi Only\n"));
                         //atapiOnly = TRUE;
                         deviceExtension->DriverMustPoll = FALSE;
                     }
@@ -2518,7 +2605,7 @@
                 } else {
 
                     KdPrint2((PRINT_PREFIX
-                               "AtapiFindController: Atapi Only (2)\n"));
+                               "AtapiFindIsaController: Atapi Only (2)\n"));
                     //atapiOnly = TRUE;
                     deviceExtension->DriverMustPoll = FALSE;
                 }
@@ -2540,14 +2627,14 @@
         deviceExtension->BusInterruptVector = ConfigInfo->BusInterruptVector;
 
         KdPrint2((PRINT_PREFIX
-                   "AtapiFindController: look for devices\n"));
+                   "AtapiFindIsaController: look for devices\n"));
         // Search for devices on this controller.
         if (FindDevices(HwDeviceExtension,
                         0,
                         0 /* Channel */)) {
 
             KdPrint2((PRINT_PREFIX
-                       "AtapiFindController: detected\n"));
+                       "AtapiFindIsaController: detected\n"));
             // Claim primary or secondary ATA IO range.
             if (portBase) {
                 switch (portBase) {
@@ -2581,8 +2668,28 @@
 
             ConfigInfo->NumberOfBuses++; // add virtual channel for communication port
             KdPrint2((PRINT_PREFIX 
-                       "AtapiFindController: return SP_RETURN_FOUND\n"));
+                       "AtapiFindIsaController: 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 
+                           "AtapiFindIsaController: cleanup AccessRanges %d\n", i));
+                (*ConfigInfo->AccessRanges)[i].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0);
+                (*ConfigInfo->AccessRanges)[i].RangeLength = 0;
+                (*ConfigInfo->AccessRanges)[i].RangeInMemory = FALSE;
+            }
         }
 #ifndef UNIATA_CORE
     }
@@ -2597,7 +2704,7 @@
     *(adapterCount) = 0;
 
     KdPrint2((PRINT_PREFIX
-               "AtapiFindController: return SP_RETURN_NOT_FOUND\n"));
+               "AtapiFindIsaController: return SP_RETURN_NOT_FOUND\n"));
     UniataFreeLunExt(deviceExtension);
     return(SP_RETURN_NOT_FOUND);
 
@@ -2605,7 +2712,7 @@
     UniataFreeLunExt(deviceExtension);
     return SP_RETURN_ERROR;
     
-} // end AtapiFindController()
+} // end AtapiFindIsaController()
 
 ULONG
 NTAPI
@@ -2676,7 +2783,7 @@
         KdPrint2((PRINT_PREFIX "  AHCI HDD at home\n"));
         return ATA_AT_HOME_HDD;
     }
-    if(g_opt_VirtualMachine /*== VM_BOCHS ||
+    if(g_opt_VirtualMachine > VM_NONE /*== VM_BOCHS ||
        g_opt_VirtualMachine == VM_VBOX*/) {
         GetStatus(chan, signatureLow);
         if(!signatureLow) {
@@ -2744,7 +2851,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 +2914,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 {
@@ -2970,7 +3081,7 @@
             LunExt->DeviceFlags |= DFLAGS_DEVICE_PRESENT;
             LunExt->DeviceFlags &= ~DFLAGS_ATAPI_DEVICE;
         } else
-        if(!g_opt_VirtualMachine) {
+        if(g_opt_VirtualMachine <= VM_NONE) {
             // This can be ATAPI on broken hardware
             GetBaseStatus(chan, statusByte);
             if(!at_home && UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber)) {
@@ -2995,7 +3106,7 @@
 
 Routine Description:
 
-    This routine is called from AtapiFindController to identify
+    This routine is called from AtapiFindXxxController to identify
     devices attached to an IDE controller.
 
 Arguments:
@@ -3072,49 +3183,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 +3231,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 {
diff -ruN v45j5\driver\id_queue.cpp v46d2\driver\id_queue.cpp
--- v45j5\driver\id_queue.cpp	Wed Jul 11 18:26:26 2012
+++ v46d2\driver\id_queue.cpp	Tue Mar 22 16:51:20 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 v46d2\driver\id_sata.cpp
--- v45j5\driver\id_sata.cpp	Wed Sep 23 18:18:12 2015
+++ v46d2\driver\id_sata.cpp	Tue Mar 22 16:51:12 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 v46d2\driver\id_sata.h
--- v45j5\driver\id_sata.h	Wed Sep 23 18:18:02 2015
+++ v46d2\driver\id_sata.h	Tue Mar 22 16:50:34 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 v46d2\driver\uniata_ver.h
--- v45j5\driver\uniata_ver.h	Sun Jan 24 15:05:08 2016
+++ v46d2\driver\uniata_ver.h	Sat Mar 26 19:51:42 2016
@@ -1,10 +1,10 @@
-#define UNIATA_VER_STR         "45j5"
-#define UNIATA_VER_DOT         0.45.10.5
+#define UNIATA_VER_STR         "46d2"
+#define UNIATA_VER_DOT         0.46.4.2
 #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      4
+#define UNIATA_VER_SUB_MN      2
+#define UNIATA_VER_DOT_COMMA   0,46,4,2
+#define UNIATA_VER_DOT_STR     "0.46.4.2"
 #define UNIATA_VER_YEAR        2016
 #define UNIATA_VER_YEAR_STR    "2016"
