Index: drivers/storage/ide/uniata/atapi.h
===================================================================
--- drivers/storage/ide/uniata/atapi.h	(revision 69324)
+++ drivers/storage/ide/uniata/atapi.h	(working copy)
@@ -1486,6 +1486,23 @@
     IN struct _HW_CHANNEL* chan
     );
 
+VOID
+UniataInitIoRes(
+    IN struct _HW_CHANNEL* chan,
+    IN ULONG idx,
+    IN ULONG addr,
+    IN BOOLEAN MemIo,
+    IN BOOLEAN Proc
+    );
+
+VOID
+UniataInitIoResEx(
+    IN struct _IORES* IoRes,
+    IN ULONG addr,
+    IN BOOLEAN MemIo,
+    IN BOOLEAN Proc
+    );
+
 UCHAR
 DDKFASTAPI
 UniataIsIdle(
Index: drivers/storage/ide/uniata/bsmaster.h
===================================================================
--- drivers/storage/ide/uniata/bsmaster.h	(revision 69324)
+++ drivers/storage/ide/uniata/bsmaster.h	(working copy)
@@ -1865,6 +1865,7 @@
 #define VM_VBOX      0x02
 #define VM_VMWARE    0x03
 #define VM_QEMU      0x04
+#define VM_BOCHS     0x05
 
 #define VM_MAX_KNOWN VM_QEMU
 
Index: drivers/storage/ide/uniata/id_ata.cpp
===================================================================
--- drivers/storage/ide/uniata/id_ata.cpp	(revision 69324)
+++ drivers/storage/ide/uniata/id_ata.cpp	(working copy)
@@ -267,7 +267,8 @@
         return; \
     } \
     if(res->Proc) {             \
-    } else  \
+        ASSERT(FALSE); /* We should never get here */ \
+    } \
     if(!res->MemIo) {             \
         ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
     } else {                                      \
@@ -302,7 +303,8 @@
         return; \
     } \
     if(res->Proc) {             \
-    } else  \
+        ASSERT(FALSE); /* We should never get here */ \
+    } \
     if(!res->MemIo) {             \
         ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
     } else {                                      \
@@ -335,8 +337,8 @@
         return (_type)(-1); \
     } \
     if(res->Proc) {             \
-        return 0; \
-    } else  \
+        ASSERT(FALSE); /* We should never get here */ \
+    } \
     if(!res->MemIo) {             \
         /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
         return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
@@ -370,8 +372,8 @@
         return (_type)(-1); \
     } \
     if(res->Proc) {             \
-        return 0; \
-    } else  \
+        ASSERT(FALSE); /* We should never get here */ \
+    } \
     if(!res->MemIo) {             \
         return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
     } else {                                      \
@@ -796,6 +798,8 @@
         {
             AtapiStallExecution(30);
         }
+        KdPrint2((PRINT_PREFIX " set DFLAGS_REINIT_DMA\n"));
+        chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_REINIT_DMA;
     }
 
     SelectDrive(chan, DeviceNumber);
@@ -1002,6 +1006,7 @@
     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;
@@ -1008,16 +1013,20 @@
             }
             KdPrint2((PRINT_PREFIX "  try to continue\n"));
             statusByte &= ~IDE_STATUS_ERROR;
+
+        } else {
+            //KdPrint2((PRINT_PREFIX "  send Status %#x\n", statusByte));
         }
         UniataExpectChannelInterrupt(chan, TRUE);
         // !!!!!
         InterlockedExchange(&(chan->CheckIntr),
                                       CHECK_INTR_IDLE);
-        statusByte = 0;
+
+        statusByte = IDE_STATUS_SUCCESS;
         break;
     }
 
-    KdPrint2((PRINT_PREFIX "  Status %#x\n", statusByte));
+    //KdPrint2((PRINT_PREFIX "  Status %#x\n", statusByte));
 
     return statusByte;
 } // end AtaCommand48()
@@ -1319,6 +1328,9 @@
                    chan->RegTranslation[IDX_IO1+j].Addr,
                    statusByteAlt));
     }
+    if(!chan->RegTranslation[IDX_BM_IO].Addr) {
+        return;
+    }
     for(j=0; j<IDX_BM_IO_SZ-1; j++) {
         statusByteAlt = AtapiReadPort1(chan, IDX_BM_IO+j);
         KdPrint2((PRINT_PREFIX
@@ -2023,10 +2035,12 @@
 
         if(NumOfSectors)
             LunExt->NumOfSectors = NumOfSectors;
-/*        if(deviceExtension->FullIdentifyData.MajorRevision &&
+    } else {
+        if(deviceExtension->FullIdentifyData.MajorRevision &&
            deviceExtension->FullIdentifyData.DoubleWordIo) {
-            LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
-        }*/
+            //LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
+            KdPrint2((PRINT_PREFIX "IssueIdentify: DFLAGS_DWORDIO_ENABLED.\n"));
+        }
     }
 
     ScsiPortMoveMemory(&LunExt->IdentifyData,
@@ -2219,7 +2233,7 @@
 
     for (; j < numberChannels; j++) {
 
-        KdPrint2((PRINT_PREFIX "AtapiResetController: Reset channel %d\n", j));
+        KdPrint2((PRINT_PREFIX "AtapiResetController: Reset lchannel %d[%d]\n", j, deviceExtension->Channel));
         chan = &(deviceExtension->chan[j]);
         MaxLuns = chan->NumberLuns;
         KdPrint2((PRINT_PREFIX "  CompleteType %#x, Luns %d, chan %#x, sptr %#x\n", CompleteType, MaxLuns, chan, &chan));
@@ -2613,6 +2627,7 @@
                 GetBaseStatus(chan, statusByte);
             }
             // force DMA mode reinit
+            KdPrint2((PRINT_PREFIX " set DFLAGS_REINIT_DMA\n"));
             chan->lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
         }
 #endif //0
@@ -4129,7 +4144,7 @@
             //SelectDrive(chan, 0);
             //GetBaseStatus(chan, statusByte);
             AtapiWritePort1(chan, IDX_IO2_o_Control,
-                                   IDE_DC_A_4BIT );
+                                   0 | IDE_DC_A_4BIT );
             //if(chan->NumberLuns) {
             //    SelectDrive(chan, 1);
             //    GetBaseStatus(chan, statusByte);
@@ -5264,7 +5279,7 @@
               LunExt->BlockIoCount
               ));
         LunExt->RecoverCount[AtaReq->retry]++;
-        if(LunExt->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->BlockIoCount/3 ||
+        if(LunExt->RecoverCount[AtaReq->retry] >= LunExt->BlockIoCount/3 ||
            (deviceExtension->HwFlags & UNIATA_NO80CHK)
            ) {
 #else
@@ -5490,7 +5505,8 @@
 
             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,
@@ -5628,7 +5644,8 @@
 
             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));
 
@@ -6281,6 +6298,15 @@
                     interruptReason,
                     statusByte));
 
+        if(g_opt_VirtualMachine == VM_QEMU) {
+            if(interruptReason == ATAPI_IR_IO_toDev && !(statusByte & IDE_STATUS_DRQ) && !DmaTransfer) {
+                statusByte = WaitForDrq(chan);
+                if(statusByte & IDE_STATUS_DRQ) {
+                    goto continue_PIO;
+                }
+            }
+        }
+
         if(OldReqState == REQ_STATE_DPC_WAIT_BUSY0 &&
            AtaReq->WordsLeft == 0) {
             KdPrint2((PRINT_PREFIX "AtapiInterrupt: pending WAIT_BUSY0. Complete.\n"));
@@ -6791,15 +6817,19 @@
                      (USHORT)(AtaReq->bcount),
 //                     (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
                      0, ATA_IMMEDIATE);
-        if(statusByte2 != IDE_STATUS_WRONG) {
+/*        if(statusByte2 != IDE_STATUS_WRONG) {
             GetStatus(chan, statusByte2);
-        }
+        }*/
         if(statusByte2 & IDE_STATUS_ERROR) {
+            // Unfortunately, we cannot handle errors in such a way in real life (except known bad blocks).
+            // Because some devices doesn't reset ERR from previous command immediately after getting new one.
+            // On the other hand we cannot wait here because of possible timeout condition
             statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
             KdPrint2((PRINT_PREFIX "IdeReadWrite: status %#x, error %#x\n", statusByte2, statusByte));
             return SRB_STATUS_ERROR;
         }
         if(use_dma) {
+            //GetStatus(chan, statusByte2);
             AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
         }
         return SRB_STATUS_PENDING;
@@ -6842,7 +6872,7 @@
                                   CHECK_INTR_IDLE);
 
     // Write next DEV_BSIZE/2*N words.
-    if (!(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED)) {
+    if (!(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) || (wordCount & 1)) {
         KdPrint2((PRINT_PREFIX 
                    "IdeReadWrite: Write %#x words\n", wordCount));
 
Index: drivers/storage/ide/uniata/id_dma.cpp
===================================================================
--- drivers/storage/ide/uniata/id_dma.cpp	(revision 69324)
+++ drivers/storage/ide/uniata/id_dma.cpp	(working copy)
@@ -1,6 +1,6 @@
 /*++
 
-Copyright (c) 2002-2014 Alexander A. Telyatnikov (Alter)
+Copyright (c) 2002-2015 Alexander A. Telyatnikov (Alter)
 
 Module Name:
     id_dma.cpp
@@ -254,11 +254,12 @@
     BOOLEAN use_AHCI = (deviceExtension->HwFlags & UNIATA_AHCI) ? TRUE : FALSE;
     ULONG orig_count = count;
     ULONG max_entries = use_AHCI ? ATA_AHCI_DMA_ENTRIES : ATA_DMA_ENTRIES;
-    //ULONG max_frag = use_AHCI ? (0x3fffff+1) : (4096); // DEBUG, replace 4096 for procer chipset-specific value
+    //ULONG max_frag = use_AHCI ? (0x3fffff+1) : (4096); // DEBUG, replace 4096 for proper chipset-specific value
     ULONG max_frag = deviceExtension->DmaSegmentLength;
     ULONG seg_align = deviceExtension->DmaSegmentAlignmentMask;
 
     if(AtaReq->dma_entries) {
+        AtaReq->Flags |= REQ_FLAG_DMA_OPERATION;
         KdPrint2((PRINT_PREFIX "AtapiDmaSetup: already setup, %d entries\n", AtaReq->dma_entries));
         return TRUE;
     }
@@ -554,15 +555,18 @@
 
     ULONG VendorID =  deviceExtension->DevID        & 0xffff;
     ULONG ChipType  = deviceExtension->HwFlags & CHIPTYPE_MASK;
-
+//    UCHAR statusByte2;
+/*
+    GetStatus(chan, statusByte2);
     KdPrint2((PRINT_PREFIX "AtapiDmaStart: %s on %#x:%#x\n",
         (Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? "read" : "write",
         lChannel, DeviceNumber ));
-
+*/
     if(!AtaReq->ata.dma_base) {
         KdPrint2((PRINT_PREFIX "AtapiDmaStart: *** !AtaReq->ata.dma_base\n"));
         return;
     }
+//    GetStatus(chan, statusByte2);
     if(AtaReq->Flags & REQ_FLAG_DMA_DBUF_PRD) {
         KdPrint2((PRINT_PREFIX "  DBUF_PRD\n"));
         ASSERT(FALSE);
@@ -791,6 +795,9 @@
         KdPrint2((PRINT_PREFIX
                     "AtapiDmaReinit: restore IO mode on Device %d\n", LunExt->Lun));
         AtapiDmaInit__(deviceExtension, LunExt);
+    } else {
+        KdPrint2((PRINT_PREFIX
+                    "AtapiDmaReinit: LimitedTransferMode == TransferMode = %x (%x)\n", LunExt->TransferMode, LunExt->DeviceFlags));
     }
 
 exit:
@@ -1435,6 +1442,7 @@
         /* Intel */
         /*********/
 
+        KdPrint2((PRINT_PREFIX "Intel %d\n", Channel));
         BOOLEAN udma_ok = FALSE;
         ULONG  idx = 0;
         ULONG  reg40;
@@ -1451,6 +1459,7 @@
         UCHAR  intel_utimings[] = { 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02 };
 
         if(deviceExtension->DevID == ATA_I82371FB) {
+            KdPrint2((PRINT_PREFIX "  I82371FB\n"));
             if (wdmamode >= 2 && apiomode >= 4) {
                 ULONG word40;
 
@@ -1473,6 +1482,7 @@
 
         if(deviceExtension->DevID == ATA_ISCH) {
             ULONG tim;
+            KdPrint2((PRINT_PREFIX "  ISCH\n"));
             GetPciConfig4(0x80 + dev*4, tim);
 
             for(i=udmamode; i>=0; i--) {
@@ -1556,6 +1566,7 @@
                 udma_ok = TRUE;
                 idx = i+8;
                 if(ChipFlags & ICH4_FIX) {
+                    KdPrint2((PRINT_PREFIX "  ICH4_FIX udma\n"));
                     return;
                 }
                 break;
@@ -1573,6 +1584,7 @@
                     udma_ok = TRUE;
                     idx = i+5;
                     if(ChipFlags & ICH4_FIX) {
+                        KdPrint2((PRINT_PREFIX "  ICH4_FIX wdma\n"));
                         return;
                     }
                     break;
@@ -1589,10 +1601,13 @@
         GetPciConfig1(0x44, reg44);
 
 	/* Allow PIO/WDMA timing controls. */
+	reg40 &= ~0x00ff00ff;
+	reg40 |= 0x40774077;
+
         mask40 = 0x000000ff;
 	/* Set PIO/WDMA timings. */
         if(!(DeviceNumber & 1)) {
-            mask40 |= 0x00003300;
+            mask40 = 0x00003300;
             new40 = ((USHORT)(intel_timings[idx]) << 8);
         } else {
             mask44 = 0x0f;
@@ -1599,7 +1614,6 @@
             new44 = ((intel_timings[idx] & 0x30) >> 2) |
                      (intel_timings[idx] & 0x03);
         }
-        new40 |= 0x00004077;
 
         if (Channel) {
             mask40 <<= 16;
@@ -1608,6 +1622,7 @@
             new44 <<= 4;
         }
 
+        KdPrint2((PRINT_PREFIX "  0x40 %x/%x, 0x44 %x/%x\n", mask40, new40, mask44, new44));
         SetPciConfig4(0x40, (reg40 & ~mask40) | new40);
         SetPciConfig1(0x44, (reg44 & ~mask44) | new44);
 
Index: drivers/storage/ide/uniata/id_init.cpp
===================================================================
--- drivers/storage/ide/uniata/id_init.cpp	(revision 69324)
+++ drivers/storage/ide/uniata/id_init.cpp	(working copy)
@@ -397,8 +397,6 @@
         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;
     }
 
@@ -570,8 +568,7 @@
                 ScsiPortFreeDeviceBase(HwDeviceExtension,
                                        deviceExtension->BaseIoAddressBM_0);
 
-            deviceExtension->BaseIoAddressBM_0.Addr = 0;
-            deviceExtension->BaseIoAddressBM_0.MemIo = 0;
+            UniataInitIoResEx(&deviceExtension->BaseIoAddressBM_0, 0, FALSE, FALSE);
             deviceExtension->BusMaster = DMA_MODE_NONE;
             deviceExtension->MaxTransferMode = ATA_PIO4;
             break;
@@ -682,13 +679,13 @@
                 chan = &deviceExtension->chan[c];
 
                 for (i=0; i<=IDX_IO1_SZ; i++) {
-                    chan->RegTranslation[IDX_IO1+i].Addr           = BaseIoAddress1  + i + (unit10 ? 8 : 0);
+                    UniataInitIoRes(chan, IDX_IO1+i, BaseIoAddress1 + i + (unit10 ? 8 : 0), FALSE, FALSE);
                 }
-                chan->RegTranslation[IDX_IO2_AltStatus].Addr       = BaseIoAddress2  + 2 + (unit10 ? 4 : 0);
+                UniataInitIoRes(chan, IDX_IO2_AltStatus, BaseIoAddress2  + 2 + (unit10 ? 4 : 0), FALSE, FALSE);
                 UniataInitSyncBaseIO(chan);
 
                 for (i=0; i<=IDX_BM_IO_SZ; i++) {
-                    chan->RegTranslation[IDX_BM_IO+i].Addr         = BaseIoAddressBM + i + (c * sizeof(IDE_BUSMASTER_REGISTERS));
+                    UniataInitIoRes(chan, IDX_BM_IO+i, BaseIoAddressBM + i + (c * sizeof(IDE_BUSMASTER_REGISTERS)), FALSE, FALSE);
                 }
 
                 // SATA not supported yet
@@ -714,17 +711,13 @@
                 KdPrint2((PRINT_PREFIX "MemIo\n"));
                 MemIo = TRUE;
             }
-            deviceExtension->BaseIoAddressSATA_0.Addr  = BaseMemAddress;
-            deviceExtension->BaseIoAddressSATA_0.MemIo = MemIo;
+            UniataInitIoResEx(&deviceExtension->BaseIoAddressSATA_0, BaseMemAddress, MemIo, FALSE);
             for(c=0; c<deviceExtension->NumberChannels; c++) {
                 chan = &deviceExtension->chan[c];
 
-                chan->RegTranslation[IDX_SATA_SStatus].Addr   = BaseMemAddress +     (c << 6);
-                chan->RegTranslation[IDX_SATA_SStatus].MemIo  = MemIo;
-                chan->RegTranslation[IDX_SATA_SError].Addr    = BaseMemAddress + 4 + (c << 6);
-                chan->RegTranslation[IDX_SATA_SError].MemIo   = MemIo;
-                chan->RegTranslation[IDX_SATA_SControl].Addr  = BaseMemAddress + 8 + (c << 6);
-                chan->RegTranslation[IDX_SATA_SControl].MemIo = MemIo;
+                UniataInitIoRes(chan, IDX_SATA_SStatus,  BaseMemAddress +     (c << 6), MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_SATA_SError,   BaseMemAddress + 4 + (c << 6), MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_SATA_SControl, BaseMemAddress + 8 + (c << 6), MemIo, FALSE);
 
                 chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
             }
@@ -751,8 +744,7 @@
             KdPrint2((PRINT_PREFIX "MemIo\n"));
             MemIo = TRUE;
         }
-        deviceExtension->BaseIoAddressSATA_0.Addr  = BaseMemAddress;
-        deviceExtension->BaseIoAddressSATA_0.MemIo = MemIo;
+        UniataInitIoResEx(&deviceExtension->BaseIoAddressSATA_0, BaseMemAddress, MemIo, FALSE);
 
         /* BAR3 -> res2 */
         BaseMemAddress = AtapiGetIoRange(HwDeviceExtension, ConfigInfo, pciData, SystemIoBusNumber,
@@ -765,8 +757,7 @@
             KdPrint2((PRINT_PREFIX "MemIo\n"));
             MemIo = TRUE;
         }
-        deviceExtension->BaseIoAddressBM_0.Addr  = BaseMemAddress;
-        deviceExtension->BaseIoAddressBM_0.MemIo = MemIo;
+        UniataInitIoResEx(&deviceExtension->BaseIoAddressBM_0, BaseMemAddress, MemIo, FALSE);
 
         if(!(ChipFlags & UNIATA_SATA)) {
             UCHAR reg48;
@@ -789,31 +780,23 @@
             offs7 = c << 7;
 
             for (i=0; i<=IDX_IO1_SZ; i++) {
-                chan->RegTranslation[IDX_IO1+i].Addr           = BaseMemAddress + 0x200 + (i << 2) + offs7;
-                chan->RegTranslation[IDX_IO1+i].MemIo          = MemIo;
+                UniataInitIoRes(chan, IDX_IO1+i,          BaseMemAddress + 0x200 + (i << 2) + offs8, MemIo, FALSE);
             }
-            chan->RegTranslation[IDX_IO2_AltStatus].Addr       = BaseMemAddress + 0x238 + offs7;
-            chan->RegTranslation[IDX_IO2_AltStatus].MemIo      = MemIo;
+            UniataInitIoRes(chan, IDX_IO2_AltStatus,      BaseMemAddress + 0x238 + offs7, MemIo, FALSE);
 
             UniataInitSyncBaseIO(chan);
 
-            chan->RegTranslation[IDX_BM_Command].Addr          = BaseMemAddress + 0x260 + offs7;
-            chan->RegTranslation[IDX_BM_Command].MemIo         = MemIo;
-            chan->RegTranslation[IDX_BM_PRD_Table].Addr        = BaseMemAddress + 0x244 + offs7;
-            chan->RegTranslation[IDX_BM_PRD_Table].MemIo       = MemIo;
-            chan->RegTranslation[IDX_BM_DeviceSpecific0].Addr  = BaseMemAddress + (c << 2);
-            chan->RegTranslation[IDX_BM_DeviceSpecific0].MemIo = MemIo;
+            UniataInitIoRes(chan, IDX_BM_Command,         BaseMemAddress + 0x260 + offs7, MemIo, FALSE);
+            UniataInitIoRes(chan, IDX_BM_PRD_Table,       BaseMemAddress + 0x244 + offs7, MemIo, FALSE);
+            UniataInitIoRes(chan, IDX_BM_DeviceSpecific0, BaseMemAddress + (c << 2),      MemIo, FALSE);
 
             if((ChipFlags & PRSATA) ||
                ((ChipFlags & PRCMBO) && c<2)) {
                 KdPrint2((PRINT_PREFIX "Promise SATA\n"));
 
-                chan->RegTranslation[IDX_SATA_SStatus].Addr        = BaseMemAddress + 0x400 + offs7;
-                chan->RegTranslation[IDX_SATA_SStatus].MemIo       = MemIo;
-                chan->RegTranslation[IDX_SATA_SError].Addr         = BaseMemAddress + 0x404 + offs7;
-                chan->RegTranslation[IDX_SATA_SError].MemIo        = MemIo;
-                chan->RegTranslation[IDX_SATA_SControl].Addr       = BaseMemAddress + 0x408 + offs7;
-                chan->RegTranslation[IDX_SATA_SControl].MemIo      = MemIo;
+                UniataInitIoRes(chan, IDX_SATA_SStatus,  BaseMemAddress + 0x400 + offs7, MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_SATA_SError,   BaseMemAddress + 0x404 + offs7, MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_SATA_SControl, BaseMemAddress + 0x408 + offs7, MemIo, FALSE);
 
                 chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
             } else {
@@ -864,8 +847,7 @@
             KdPrint2((PRINT_PREFIX "MemIo\n"));
             MemIo = TRUE;
         }
-        deviceExtension->BaseIoAddressSATA_0.Addr  = BaseMemAddress;
-        deviceExtension->BaseIoAddressSATA_0.MemIo = MemIo;
+        UniataInitIoResEx(&deviceExtension->BaseIoAddressSATA_0, BaseMemAddress, MemIo, FALSE);
 
         for(c=0; c<deviceExtension->NumberChannels; c++) {
             ULONG unit01 = (c & 1);
@@ -875,25 +857,16 @@
 
             if(deviceExtension->AltRegMap) {
                 for (i=0; i<=IDX_IO1_SZ; i++) {
-                    chan->RegTranslation[IDX_IO1+i].Addr           = BaseMemAddress + 0x80 + i + (unit01 << 6) + (unit10 << 8);
-                    chan->RegTranslation[IDX_IO1+i].MemIo          = MemIo;
+                    UniataInitIoRes(chan, IDX_IO1+i, BaseMemAddress + 0x80 + i + (unit01 << 6) + (unit10 << 8), MemIo, FALSE);
                 }
-                chan->RegTranslation[IDX_IO2_AltStatus].Addr       = BaseMemAddress + 0x8a + (unit01 << 6) + (unit10 << 8);
-                chan->RegTranslation[IDX_IO2_AltStatus].MemIo      = MemIo;
+                UniataInitIoRes(chan, IDX_IO2_AltStatus, BaseMemAddress + 0x8a + (unit01 << 6) + (unit10 << 8), MemIo, FALSE);
                 UniataInitSyncBaseIO(chan);
 
-                chan->RegTranslation[IDX_BM_Command].Addr          = BaseMemAddress + 0x00 + (unit01 << 3) + (unit10 << 8);
-                chan->RegTranslation[IDX_BM_Command].MemIo         = MemIo;
-                chan->RegTranslation[IDX_BM_Status].Addr           = BaseMemAddress + 0x02 + (unit01 << 3) + (unit10 << 8);
-                chan->RegTranslation[IDX_BM_Status].MemIo          = MemIo;
-                chan->RegTranslation[IDX_BM_PRD_Table].Addr        = BaseMemAddress + 0x04 + (unit01 << 3) + (unit10 << 8);
-                chan->RegTranslation[IDX_BM_PRD_Table].MemIo       = MemIo;
-                //chan->RegTranslation[IDX_BM_DeviceSpecific0].Addr  = BaseMemAddress + 0xa1 + (unit01 << 6) + (unit10 << 8);
-                //chan->RegTranslation[IDX_BM_DeviceSpecific0].MemIo = MemIo;
-                chan->RegTranslation[IDX_BM_DeviceSpecific0].Addr  = BaseMemAddress + 0x10 + (unit01 << 3) + (unit10 << 8);
-                chan->RegTranslation[IDX_BM_DeviceSpecific0].MemIo = MemIo;
-                chan->RegTranslation[IDX_BM_DeviceSpecific1].Addr  = BaseMemAddress + 0x40 + (unit01 << 2) + (unit10 << 8);
-                chan->RegTranslation[IDX_BM_DeviceSpecific1].MemIo = MemIo;
+                UniataInitIoRes(chan, IDX_BM_Command,   BaseMemAddress + 0x00 + (unit01 << 3) + (unit10 << 8), MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_BM_Status,    BaseMemAddress + 0x02 + (unit01 << 3) + (unit10 << 8), MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_BM_PRD_Table, BaseMemAddress + 0x04 + (unit01 << 3) + (unit10 << 8), MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_BM_DeviceSpecific0, BaseMemAddress + 0x10 + (unit01 << 3) + (unit10 << 8), MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_BM_DeviceSpecific1, BaseMemAddress + 0x40 + (unit01 << 2) + (unit10 << 8), MemIo, FALSE);
             }
 
             if(chan->MaxTransferMode < ATA_SA150) {
@@ -901,12 +874,9 @@
                 KdPrint2((PRINT_PREFIX "No SATA regs for PATA part\n"));
             } else
             if(ChipFlags & UNIATA_SATA) {
-                chan->RegTranslation[IDX_SATA_SStatus].Addr        = BaseMemAddress + 0x104 + (unit01 << 7) + (unit10 << 8);
-                chan->RegTranslation[IDX_SATA_SStatus].MemIo       = MemIo;
-                chan->RegTranslation[IDX_SATA_SError].Addr         = BaseMemAddress + 0x108 + (unit01 << 7) + (unit10 << 8);
-                chan->RegTranslation[IDX_SATA_SError].MemIo        = MemIo;
-                chan->RegTranslation[IDX_SATA_SControl].Addr       = BaseMemAddress + 0x100 + (unit01 << 7) + (unit10 << 8);
-                chan->RegTranslation[IDX_SATA_SControl].MemIo      = MemIo;
+                UniataInitIoRes(chan, IDX_SATA_SStatus,  BaseMemAddress + 0x104 + (unit01 << 7) + (unit10 << 8), MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_SATA_SError,   BaseMemAddress + 0x108 + (unit01 << 2) + (unit10 << 8), MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_SATA_SControl, BaseMemAddress + 0x100 + (unit01 << 2) + (unit10 << 8), MemIo, FALSE);
 
                 chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
             }
@@ -935,8 +905,7 @@
             KdPrint2((PRINT_PREFIX "MemIo\n"));
             MemIo = TRUE;
         }
-        deviceExtension->BaseIoAddressSATA_0.Addr  = BaseMemAddress;
-        deviceExtension->BaseIoAddressSATA_0.MemIo = MemIo;
+        UniataInitIoResEx(&deviceExtension->BaseIoAddressSATA_0, BaseMemAddress, MemIo, FALSE);
 
         for(c=0; c<deviceExtension->NumberChannels; c++) {
             ULONG offs = c*0x100;
@@ -943,26 +912,18 @@
 
             chan = &deviceExtension->chan[c];
             for (i=0; i<=IDX_IO1_SZ; i++) {
-                chan->RegTranslation[IDX_IO1+i].Addr           = BaseMemAddress + offs + i*4;
-                chan->RegTranslation[IDX_IO1+i].MemIo          = MemIo;
+                UniataInitIoRes(chan, IDX_IO1+i, BaseMemAddress + offs + i*4, MemIo, FALSE);
             }
-            chan->RegTranslation[IDX_IO2_AltStatus].Addr       = BaseMemAddress + offs + 0x20;
-            chan->RegTranslation[IDX_IO2_AltStatus].MemIo      = MemIo;
+            UniataInitIoRes(chan, IDX_IO2_AltStatus, BaseMemAddress + offs + 0x20, MemIo, FALSE);
             UniataInitSyncBaseIO(chan);
 
-            chan->RegTranslation[IDX_BM_Command].Addr          = BaseMemAddress + offs + 0x30;
-            chan->RegTranslation[IDX_BM_Command].MemIo         = MemIo;
-            chan->RegTranslation[IDX_BM_Status].Addr           = BaseMemAddress + offs + 0x32;
-            chan->RegTranslation[IDX_BM_Status].MemIo          = MemIo;
-            chan->RegTranslation[IDX_BM_PRD_Table].Addr        = BaseMemAddress + offs + 0x34;
-            chan->RegTranslation[IDX_BM_PRD_Table].MemIo       = MemIo;
+            UniataInitIoRes(chan, IDX_BM_Command,   BaseMemAddress + offs + 0x30, MemIo, FALSE);
+            UniataInitIoRes(chan, IDX_BM_Status,    BaseMemAddress + offs + 0x32, MemIo, FALSE);
+            UniataInitIoRes(chan, IDX_BM_PRD_Table, BaseMemAddress + offs + 0x34, MemIo, FALSE);
 
-            chan->RegTranslation[IDX_SATA_SStatus].Addr        = BaseMemAddress + offs + 0x40;
-            chan->RegTranslation[IDX_SATA_SStatus].MemIo       = MemIo;               
-            chan->RegTranslation[IDX_SATA_SError].Addr         = BaseMemAddress + offs + 0x44;
-            chan->RegTranslation[IDX_SATA_SError].MemIo        = MemIo;               
-            chan->RegTranslation[IDX_SATA_SControl].Addr       = BaseMemAddress + offs + 0x48;
-            chan->RegTranslation[IDX_SATA_SControl].MemIo      = MemIo;
+            UniataInitIoRes(chan, IDX_SATA_SStatus,  BaseMemAddress + offs + 0x40, MemIo, FALSE);
+            UniataInitIoRes(chan, IDX_SATA_SError,   BaseMemAddress + offs + 0x44, MemIo, FALSE);
+            UniataInitIoRes(chan, IDX_SATA_SControl, BaseMemAddress + offs + 0x48, MemIo, FALSE);
 
             chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
         }
@@ -1039,19 +1000,15 @@
                         KdPrint2((PRINT_PREFIX "MemIo\n"));
                         MemIo = TRUE;
                     }
-                    deviceExtension->BaseIoAddressSATA_0.Addr  = BaseMemAddress;
-                    deviceExtension->BaseIoAddressSATA_0.MemIo = MemIo;
+                    UniataInitIoResEx(&deviceExtension->BaseIoAddressSATA_0, BaseMemAddress, MemIo, FALSE);
 
                     for(c=0; c<deviceExtension->NumberChannels; c++) {
                         ULONG offs = c << (SIS_182 ? 5 : 6);
 
                         chan = &deviceExtension->chan[c];
-                        chan->RegTranslation[IDX_SATA_SStatus].Addr        = BaseMemAddress + 0 + offs;
-                        chan->RegTranslation[IDX_SATA_SStatus].MemIo       = MemIo;
-                        chan->RegTranslation[IDX_SATA_SError].Addr         = BaseMemAddress + 4 + offs;
-                        chan->RegTranslation[IDX_SATA_SError].MemIo        = MemIo;
-                        chan->RegTranslation[IDX_SATA_SControl].Addr       = BaseMemAddress + 8 + offs;
-                        chan->RegTranslation[IDX_SATA_SControl].MemIo      = MemIo;
+                        UniataInitIoRes(chan, IDX_SATA_SStatus,  BaseMemAddress + 0 + offs, MemIo, FALSE);
+                        UniataInitIoRes(chan, IDX_SATA_SError,   BaseMemAddress + 4 + offs, MemIo, FALSE);
+                        UniataInitIoRes(chan, IDX_SATA_SControl, BaseMemAddress + 8 + offs, MemIo, FALSE);
 
                         chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
                     }
@@ -1092,8 +1049,7 @@
                     KdPrint2((PRINT_PREFIX "MemIo\n"));
                     MemIo = TRUE;
                 }
-                deviceExtension->BaseIoAddressSATA_0.Addr  = BaseMemAddress;
-                deviceExtension->BaseIoAddressSATA_0.MemIo = MemIo;
+                UniataInitIoResEx(&deviceExtension->BaseIoAddressSATA_0, BaseMemAddress, MemIo, FALSE);
             }
             if(/*deviceExtension->*/BaseMemAddress) {
                 KdPrint2((PRINT_PREFIX "UniataChipDetect: BAR5 %x\n", /*deviceExtension->*/BaseMemAddress));
@@ -1114,13 +1070,13 @@
                         BaseIo = AtapiGetIoRange(HwDeviceExtension, ConfigInfo, pciData, SystemIoBusNumber, c, 0, /*0x80*/ sizeof(IDE_REGISTERS_1) + sizeof(IDE_REGISTERS_2)*2);
 
                         for (i=0; i<=IDX_IO1_SZ; i++) {
-                            chan->RegTranslation[IDX_IO1+i].Addr           = BaseIo + i;
+                            UniataInitIoRes(chan, IDX_IO1+i, BaseIo + i, FALSE, FALSE);
                         }
-                        chan->RegTranslation[IDX_IO2_AltStatus].Addr       = BaseIo + sizeof(IDE_REGISTERS_1) + 2;
+                        UniataInitIoRes(chan, IDX_IO2_AltStatus, BaseIo + sizeof(IDE_REGISTERS_1) + 2, FALSE, FALSE);
                         UniataInitSyncBaseIO(chan);
 
                         for (i=0; i<=IDX_BM_IO_SZ; i++) {
-                            chan->RegTranslation[IDX_BM_IO+i].Addr         = BaseIoAddressBM_0 + sizeof(IDE_BUSMASTER_REGISTERS)*c + i;
+                            UniataInitIoRes(chan, IDX_BM_IO+i, BaseIoAddressBM_0 + sizeof(IDE_BUSMASTER_REGISTERS)*c + i, FALSE, FALSE);
                         }
 
                     }
@@ -1130,17 +1086,13 @@
                     if((ChipFlags & VIABAR) && (c==2)) {
                         // Do not setup SATA registers for PATA part
                         for (i=0; i<=IDX_SATA_IO_SZ; i++) {
-                            chan->RegTranslation[IDX_SATA_IO+i].Addr = 0;
-                            chan->RegTranslation[IDX_SATA_IO+i].MemIo = 0;
+                            UniataInitIoRes(chan, IDX_SATA_IO+i, 0, FALSE, FALSE);
                         }
                         break;
                     }
-                    chan->RegTranslation[IDX_SATA_SStatus].Addr        = BaseMemAddress + (c * IoSize);
-                    chan->RegTranslation[IDX_SATA_SStatus].MemIo       = MemIo;
-                    chan->RegTranslation[IDX_SATA_SError].Addr         = BaseMemAddress + 4 + (c * IoSize);
-                    chan->RegTranslation[IDX_SATA_SError].MemIo        = MemIo;
-                    chan->RegTranslation[IDX_SATA_SControl].Addr       = BaseMemAddress + 8 + (c * IoSize);
-                    chan->RegTranslation[IDX_SATA_SControl].MemIo      = MemIo;
+                    UniataInitIoRes(chan, IDX_SATA_SStatus,  BaseMemAddress + (c * IoSize), MemIo, FALSE);
+                    UniataInitIoRes(chan, IDX_SATA_SError,   BaseMemAddress + 4 + (c * IoSize), MemIo, FALSE);
+                    UniataInitIoRes(chan, IDX_SATA_SControl, BaseMemAddress + 8 + (c * IoSize), MemIo, FALSE);
 
                     chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
                 }
@@ -1169,8 +1121,7 @@
                 MemIo = TRUE;
             }
             deviceExtension->AltRegMap = TRUE; // inform generic resource allocator
-            deviceExtension->BaseIoAddressSATA_0.Addr  = BaseMemAddress;
-            deviceExtension->BaseIoAddressSATA_0.MemIo = MemIo;
+            UniataInitIoResEx(&deviceExtension->BaseIoAddressSATA_0, BaseMemAddress, MemIo, FALSE);
 
             for(c=0; c<deviceExtension->NumberChannels; c++) {
                 ULONG offs = 0x200 + c*0x200;
@@ -1177,41 +1128,24 @@
 
                 chan = &deviceExtension->chan[c];
                 for (i=0; i<=IDX_IO1_SZ; i++) {
-                    chan->RegTranslation[IDX_IO1+i].MemIo          = MemIo;
-                    chan->RegTranslation[IDX_IO1_o+i].MemIo        = MemIo;
+                    UniataInitIoRes(chan, IDX_BM_IO+i, BaseMemAddress + i*4 + offs, MemIo, FALSE);
                 }
 
-                chan->RegTranslation[IDX_IO1_i_Data        ].Addr       = BaseMemAddress + 0x00 + offs;
-                chan->RegTranslation[IDX_IO1_i_Error       ].Addr       = BaseMemAddress + 0x04 + offs;
-                chan->RegTranslation[IDX_IO1_i_BlockCount  ].Addr       = BaseMemAddress + 0x08 + offs;
-                chan->RegTranslation[IDX_IO1_i_BlockNumber ].Addr       = BaseMemAddress + 0x0c + offs;
-                chan->RegTranslation[IDX_IO1_i_CylinderLow ].Addr       = BaseMemAddress + 0x10 + offs;
-                chan->RegTranslation[IDX_IO1_i_CylinderHigh].Addr       = BaseMemAddress + 0x14 + offs;
-                chan->RegTranslation[IDX_IO1_i_DriveSelect ].Addr       = BaseMemAddress + 0x18 + offs;
-                chan->RegTranslation[IDX_IO1_i_Status      ].Addr       = BaseMemAddress + 0x1c + offs;
-
                 UniataInitSyncBaseIO(chan);
 
-                chan->RegTranslation[IDX_IO1_o_Command     ].Addr       = BaseMemAddress + 0x1d + offs;
-                chan->RegTranslation[IDX_IO1_o_Feature     ].Addr       = BaseMemAddress + 0x06 + offs;
-                chan->RegTranslation[IDX_IO2_o_Control     ].Addr       = BaseMemAddress + 0x29 + offs;
+                UniataInitIoRes(chan, IDX_IO1_o_Command, BaseMemAddress + 0x1d + offs, MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_IO1_o_Feature, BaseMemAddress + 0x06 + offs, MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_IO2_o_Control, BaseMemAddress + 0x29 + offs, MemIo, FALSE);
 
-                chan->RegTranslation[IDX_IO2_AltStatus].Addr       = BaseMemAddress + 0x28 + offs;
-                chan->RegTranslation[IDX_IO2_AltStatus].MemIo      = MemIo;
+                UniataInitIoRes(chan, IDX_IO2_AltStatus, BaseMemAddress + 0x28 + offs, MemIo, FALSE);
 
-                chan->RegTranslation[IDX_BM_Command].Addr          = BaseMemAddress + offs + 0x70;
-                chan->RegTranslation[IDX_BM_Command].MemIo         = MemIo;
-                chan->RegTranslation[IDX_BM_Status].Addr           = BaseMemAddress + offs + 0x72;
-                chan->RegTranslation[IDX_BM_Status].MemIo          = MemIo;
-                chan->RegTranslation[IDX_BM_PRD_Table].Addr        = BaseMemAddress + offs + 0x74;
-                chan->RegTranslation[IDX_BM_PRD_Table].MemIo       = MemIo;
+                UniataInitIoRes(chan, IDX_BM_Command,   BaseMemAddress + 0x70 + offs, MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_BM_Status,    BaseMemAddress + 0x72 + offs, MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_BM_PRD_Table, BaseMemAddress + 0x74 + offs, MemIo, FALSE);
 
-                chan->RegTranslation[IDX_SATA_SStatus].Addr        = BaseMemAddress + 0x100 + offs;
-                chan->RegTranslation[IDX_SATA_SStatus].MemIo       = MemIo;
-                chan->RegTranslation[IDX_SATA_SError].Addr         = BaseMemAddress + 0x104 + offs;
-                chan->RegTranslation[IDX_SATA_SError].MemIo        = MemIo;
-                chan->RegTranslation[IDX_SATA_SControl].Addr       = BaseMemAddress + 0x108 + offs;
-                chan->RegTranslation[IDX_SATA_SControl].MemIo      = MemIo;
+                UniataInitIoRes(chan, IDX_SATA_SStatus,  BaseMemAddress + 0x100 + offs, MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_SATA_SError,   BaseMemAddress + 0x104 + offs, MemIo, FALSE);
+                UniataInitIoRes(chan, IDX_SATA_SControl, BaseMemAddress + 0x108 + offs, MemIo, FALSE);
 
                 chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
             }
@@ -1243,15 +1177,13 @@
                         KdPrint2((PRINT_PREFIX "MemIo[4]\n"));
                         MemIo = TRUE;
                     }
-                    deviceExtension->BaseIoAddressBM_0.Addr  = BaseIoAddressBM;
-                    deviceExtension->BaseIoAddressBM_0.MemIo = MemIo;
+                    UniataInitIoResEx(&deviceExtension->BaseIoAddressBM_0, BaseIoAddressBM, MemIo, FALSE);
 
                     tmp8 = AtapiReadPortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),IDX_BM_Status);
                     KdPrint2((PRINT_PREFIX "BM status: %x\n", tmp8));
                     /* cleanup */
                     ScsiPortFreeDeviceBase(HwDeviceExtension, (PCHAR)BaseIoAddressBM);
-                    deviceExtension->BaseIoAddressBM_0.Addr = 0;
-                    deviceExtension->BaseIoAddressBM_0.MemIo = 0;
+                    UniataInitIoResEx(&deviceExtension->BaseIoAddressBM_0, 0, 0, FALSE);
 
                     if(tmp8 == 0xff) {
                         KdPrint2((PRINT_PREFIX "invalid BM status, keep AHCI mode\n"));
@@ -1287,8 +1219,7 @@
                     MemIo = TRUE;
                 }
             }
-            deviceExtension->BaseIoAddressSATA_0.Addr  = BaseMemAddress;
-            deviceExtension->BaseIoAddressSATA_0.MemIo = MemIo;
+            UniataInitIoResEx(&deviceExtension->BaseIoAddressSATA_0, BaseMemAddress, MemIo, FALSE);
 
             for(c=0; c<deviceExtension->NumberChannels; c++) {
                 chan = &deviceExtension->chan[c];
@@ -1337,10 +1268,8 @@
 
                     if(!(ChipFlags & ICH7) && BaseMemAddress) {
                         KdPrint2((PRINT_PREFIX "BaseMemAddress[5] -> indexed\n"));
-                        chan->RegTranslation[IDX_INDEXED_ADDR].Addr        = BaseMemAddress + 0;
-                        chan->RegTranslation[IDX_INDEXED_ADDR].MemIo       = MemIo;
-                        chan->RegTranslation[IDX_INDEXED_DATA].Addr        = BaseMemAddress + 4;
-                        chan->RegTranslation[IDX_INDEXED_DATA].MemIo       = MemIo;
+                        UniataInitIoRes(chan, IDX_INDEXED_ADDR,   BaseMemAddress + 0, MemIo, FALSE);
+                        UniataInitIoRes(chan, IDX_INDEXED_DATA,   BaseMemAddress + 4, MemIo, FALSE);
                     }
                     if((ChipFlags & ICH5) || BaseMemAddress) {
 
@@ -1353,12 +1282,9 @@
                         if(ChipFlags & ICH7) {
                             KdPrint2((PRINT_PREFIX "ICH7 way\n"));
                         }
-                        chan->RegTranslation[IDX_SATA_SStatus].Addr        = 0x200*c + 0; // this is fake non-zero value
-                        chan->RegTranslation[IDX_SATA_SStatus].Proc        = 1;
-                        chan->RegTranslation[IDX_SATA_SError].Addr         = 0x200*c + 2; // this is fake non-zero value
-                        chan->RegTranslation[IDX_SATA_SError].Proc         = 1;
-                        chan->RegTranslation[IDX_SATA_SControl].Addr       = 0x200*c + 1; // this is fake non-zero value
-                        chan->RegTranslation[IDX_SATA_SControl].Proc       = 1;
+                        UniataInitIoRes(chan, IDX_SATA_SStatus,  0x200*c + 0, FALSE, TRUE); // this is fake non-zero value
+                        UniataInitIoRes(chan, IDX_SATA_SError,   0x200*c + 2, FALSE, TRUE);
+                        UniataInitIoRes(chan, IDX_SATA_SControl, 0x200*c + 1, FALSE, TRUE);
                     }
                 }
 
@@ -2713,8 +2639,7 @@
     for(c=0; c<deviceExtension->NumberChannels; c++) {
         chan = &deviceExtension->chan[c];
         for (i=0; i<IDX_BM_IO_SZ; i++) {
-            chan->RegTranslation[IDX_BM_IO+i].Addr  = BaseIoAddressBM_0 ? ((ULONGIO_PTR)BaseIoAddressBM_0 + i) : 0;
-            chan->RegTranslation[IDX_BM_IO+i].MemIo = MemIo;
+            UniataInitIoRes(chan, IDX_BM_IO+i, BaseIoAddressBM_0 ? ((ULONGIO_PTR)BaseIoAddressBM_0 + i) : 0, MemIo, FALSE);
         }
         if(BaseIoAddressBM_0) {
             BaseIoAddressBM_0++;
@@ -2734,12 +2659,10 @@
     ULONG i;
 
     for (i=0; i<IDX_IO1_SZ; i++) {
-        chan->RegTranslation[IDX_IO1+i].Addr = BaseIoAddress1 ? ((ULONGIO_PTR)BaseIoAddress1 + i) : 0;
-        chan->RegTranslation[IDX_IO1+i].MemIo = FALSE;
+        UniataInitIoRes(chan, IDX_IO1+i, BaseIoAddress1 ? ((ULONGIO_PTR)BaseIoAddress1 + i) : 0, FALSE, FALSE);
     }
     for (i=0; i<IDX_IO2_SZ; i++) {
-        chan->RegTranslation[IDX_IO2+i].Addr = BaseIoAddress2 ? ((ULONGIO_PTR)BaseIoAddress2 + i) : 0;
-        chan->RegTranslation[IDX_IO2+i].MemIo = FALSE;
+        UniataInitIoRes(chan, IDX_IO2+i, BaseIoAddress2 ? ((ULONGIO_PTR)BaseIoAddress2 + i) : 0, FALSE, FALSE);
     }
     UniataInitSyncBaseIO(chan);
     return;
@@ -2757,6 +2680,39 @@
 } // end UniataInitSyncBaseIO()
 
 VOID
+UniataInitIoRes(
+    IN PHW_CHANNEL chan,
+    IN ULONG idx,
+    IN ULONG addr,
+    IN BOOLEAN MemIo,
+    IN BOOLEAN Proc
+    )
+{
+    if(!addr) {
+        MemIo = Proc = FALSE;
+    }
+    chan->RegTranslation[idx].Addr  = addr;
+    chan->RegTranslation[idx].MemIo = MemIo;
+    chan->RegTranslation[idx].Proc  = Proc;
+} // end UniataInitIoRes()
+
+VOID
+UniataInitIoResEx(
+    IN PIORES IoRes,
+    IN ULONG addr,
+    IN BOOLEAN MemIo,
+    IN BOOLEAN Proc
+    )
+{
+    if(!addr) {
+        MemIo = Proc = FALSE;
+    }
+    IoRes->Addr  = addr;
+    IoRes->MemIo = MemIo;
+    IoRes->Proc  = Proc;
+} // end UniataInitIoResEx()
+
+VOID
 NTAPI
 AtapiSetupLunPtrs(
     IN PHW_CHANNEL chan,
Index: drivers/storage/ide/uniata/id_probe.cpp
===================================================================
--- drivers/storage/ide/uniata/id_probe.cpp	(revision 69324)
+++ drivers/storage/ide/uniata/id_probe.cpp	(working copy)
@@ -411,9 +411,14 @@
                     if(g_opt_VirtualMachine == VM_AUTO) {
                         g_opt_VirtualMachine = VM_QEMU;
                     }
+                } else
+                if(VendorID == 0x1234 && DeviceID == 0x1111) {
+                    KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - Bochs\n",busNumber,slotNumber,funcNumber));
+                    if(g_opt_VirtualMachine == VM_AUTO) {
+                        g_opt_VirtualMachine = VM_BOCHS;
+                    }
                 }
 
-
                 if(BaseClass != PCI_DEV_CLASS_STORAGE) {
                     continue;
                 }
@@ -2302,6 +2307,9 @@
         BaseIoAddress2 = (PIDE_REGISTERS_2)ioSpace;
         KdPrint2((PRINT_PREFIX "  BaseIoAddress1=%x\n", BaseIoAddress1));
         KdPrint2((PRINT_PREFIX "  BaseIoAddress2=%x\n", BaseIoAddress2));
+        if(!irq) {
+            KdPrint2((PRINT_PREFIX "  expected InterruptLevel=%x\n", InterruptLevels[*adapterCount - 1]));
+        }
 
         UniataInitMapBase(chan, BaseIoAddress1, BaseIoAddress2);
         UniataInitMapBM(deviceExtension, 0, FALSE);
@@ -2656,6 +2664,14 @@
         KdPrint2((PRINT_PREFIX "  AHCI HDD at home\n"));
         return ATA_AT_HOME_HDD;
     }
+    if(g_opt_VirtualMachine == VM_BOCHS) {
+        GetStatus(chan, signatureLow);
+        if(!signatureLow) {
+            KdPrint2((PRINT_PREFIX "  0-status BOCHS - not present\n"));
+            UniataForgetDevice(LunExt);
+            return ATA_AT_HOME_NOBODY;
+        }
+    }
 
     AtapiStallExecution(10);
 
Index: drivers/storage/ide/uniata/id_sata.cpp
===================================================================
--- drivers/storage/ide/uniata/id_sata.cpp	(revision 69324)
+++ drivers/storage/ide/uniata/id_sata.cpp	(working copy)
@@ -2206,12 +2206,16 @@
     UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, 0x01 << tag);
     chan->AhciPrevCI |= 0x01 << tag;
 
-    KdPrint2(("  Send CMD START\n"));
-    UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD,
-        CMD |
-        ATA_AHCI_P_CMD_ST |
-        ((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) ? ATA_AHCI_P_CMD_PMA : 0));
-    UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */
+    CMD0 = CMD;
+    CMD |= ATA_AHCI_P_CMD_ST |
+          ((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) ? ATA_AHCI_P_CMD_PMA : 0);
+    if(CMD != CMD0) {
+      KdPrint2(("  Send CMD START\n"));
+      UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD);
+      UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */
+    } else {
+      KdPrint2(("  No CMD START, already active\n"));
+    }
 
     if(!ATAPI_DEVICE(chan, DeviceNumber)) {
         // TODO: check if we send ATAPI_RESET and wait for ready of so.
Index: drivers/storage/ide/uniata/uniata_ver.h
===================================================================
--- drivers/storage/ide/uniata/uniata_ver.h	(revision 69324)
+++ drivers/storage/ide/uniata/uniata_ver.h	(working copy)
@@ -1,10 +1,10 @@
-#define UNIATA_VER_STR         "45h1"
-#define UNIATA_VER_DOT         0.45.8.1
+#define UNIATA_VER_STR         "45h6"
+#define UNIATA_VER_DOT         0.45.8.6
 #define UNIATA_VER_MJ          0
 #define UNIATA_VER_MN          45
 #define UNIATA_VER_SUB_MJ      8
-#define UNIATA_VER_SUB_MN      1
-#define UNIATA_VER_DOT_COMMA   0,45,8,1
-#define UNIATA_VER_DOT_STR     "0.45.8.1"
+#define UNIATA_VER_SUB_MN      6
+#define UNIATA_VER_DOT_COMMA   0,45,8,6
+#define UNIATA_VER_DOT_STR     "0.45.8.6"
 #define UNIATA_VER_YEAR        2015
 #define UNIATA_VER_YEAR_STR    "2015"
