Document what r44552 is all about.
[reactos.git] / reactos / drivers / storage / ide / uniata / id_ata.cpp
index 02c1e70..7097668 100644 (file)
@@ -1,6 +1,6 @@
 /*++
 
-Copyright (c) 2002-2007 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2002-2008 Alexandr A. Telyatnikov (Alter)
 
 Module Name:
     id_ata.cpp
@@ -61,6 +61,8 @@ Revision History:
 
 static const CHAR ver_string[] = "\n\nATAPI IDE MiniPort Driver (UniATA) v 0." UNIATA_VER_STR "\n";
 
+static const CHAR uniata_comm_name[] = UNIATA_COMM_PORT_VENDOR_STR "    \n";
+
 UNICODE_STRING SavedRegPath;
 WCHAR SavedRegPathBuffer[256];
 
@@ -85,6 +87,7 @@ BOOLEAN InDriverEntry = TRUE;
 
 BOOLEAN g_opt_Verbose = 0;
 
+BOOLEAN WinVer_WDM_Model = FALSE;
 //UCHAR EnableDma = FALSE;
 //UCHAR EnableReorder = FALSE;
 
@@ -99,6 +102,7 @@ AtapiResetController__(
     );
 
 VOID
+NTAPI
 AtapiHwInitialize__(
     IN PHW_DEVICE_EXTENSION deviceExtension,
     IN ULONG lChannel
@@ -137,6 +141,7 @@ AtapiEnableInterrupts__(
     );
 
 VOID
+NTAPI
 AtapiQueueTimerDpc(
     IN PVOID HwDeviceExtension,
     IN ULONG lChannel,
@@ -155,6 +160,7 @@ AtapiAdapterControl(
 #endif //UNIATA_CORE
 
 BOOLEAN
+NTAPI
 AtapiCheckInterrupt__(
     IN PVOID HwDeviceExtension,
     IN UCHAR c
@@ -164,6 +170,7 @@ AtapiCheckInterrupt__(
 #ifndef UNIATA_CORE
 
 BOOLEAN
+NTAPI
 AtapiRegGetStringParameterValue(
     IN PWSTR RegistryPath,
     IN PWSTR Name,
@@ -171,7 +178,7 @@ AtapiRegGetStringParameterValue(
     IN ULONG MaxLen
     )
 {
-#define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
+#define ITEMS_TO_QUERY 2 // always 1 greater than what is searched 
     NTSTATUS          status;
     RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY];
     UNICODE_STRING ustr;
@@ -211,6 +218,10 @@ UniataNanoSleep(
     LONGLONG t;
     LARGE_INTEGER t0;
 
+#ifdef NAVO_TEST
+    return;
+#endif //NAVO_TEST
+
     if(!nano || !g_Perf || !g_PerfDt)
         return;
     t = (g_Perf * nano) / g_PerfDt / 1000;
@@ -351,7 +362,7 @@ AtapiReadPortExN_template(ULONG,  Ulong,  4);
 //AtapiReadPortExN_template(USHORT, Ushort, 2);
 AtapiReadPortExN_template(UCHAR,  Uchar,  1);
 
-#define AtapiReadPortBufferN_template(type, Type, sz) \
+#define AtapiReadPortBufferN_template(_type, _Type, sz) \
 VOID \
 DDKFASTAPI \
 AtapiReadBuffer##sz( \
@@ -362,17 +373,41 @@ AtapiReadBuffer##sz( \
     IN ULONG Timing   \
     ) \
 { \
-    ULONG i=0; \
+    PIORES res; \
+                 \
+    if(Timing) { \
+        while(Count) { \
+            (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
+            Count--; \
+            Buffer = ((_type*)Buffer)+1; \
+            UniataNanoSleep(Timing); \
+        } \
+        return; \
+    } \
+           \
+    if(_port >= IDX_MAX_REG) { \
+        res = (PIORES)(_port);  \
+    } else \
+    if(chan) { \
+        res = &chan->RegTranslation[_port];  \
+    } else {                                     \
+        KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
+        return; \
+    } \
+    if(!res->MemIo) {             \
+        /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
+        ScsiPortReadPortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
+        return; \
+    }                                                        \
     while(Count) { \
-        ((type*)Buffer)[i] = AtapiReadPort##sz(chan, _port); \
-        i++; \
+        (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
         Count--; \
-        UniataNanoSleep(Timing); \
+        Buffer = ((_type*)Buffer)+1; \
     } \
     return;                                                  \
 }
 
-#define AtapiWritePortBufferN_template(type, Type, sz) \
+#define AtapiWritePortBufferN_template(_type, _Type, sz) \
 VOID \
 DDKFASTAPI \
 AtapiWriteBuffer##sz( \
@@ -383,12 +418,36 @@ AtapiWriteBuffer##sz( \
     IN ULONG Timing   \
     ) \
 { \
-    ULONG i=0; \
+    PIORES res; \
+                 \
+    if(Timing) { \
+        while(Count) { \
+            AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
+            Buffer = ((_type*)Buffer)+1; \
+            Count--; \
+            UniataNanoSleep(Timing); \
+        } \
+        return;                                                  \
+    } \
+           \
+    if(_port >= IDX_MAX_REG) { \
+        res = (PIORES)(_port);  \
+    } else \
+    if(chan) { \
+        res = &chan->RegTranslation[_port];  \
+    } else {                                     \
+        KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
+        return; \
+    } \
+    if(!res->MemIo) {             \
+        /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
+        ScsiPortWritePortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
+        return; \
+    }                                                        \
     while(Count) { \
-        AtapiWritePort##sz(chan, _port, ((type*)Buffer)[i]); \
-        i++; \
+        ScsiPortWriteRegister##_Type((_type*)(res->Addr), *((_type*)Buffer)); \
         Count--; \
-        UniataNanoSleep(Timing); \
+        Buffer = ((_type*)Buffer)+1; \
     } \
     return;                                                  \
 }
@@ -530,7 +589,7 @@ UniataIsIdle(
         return Status;
     }
 //    if(deviceExtension->HwFlags & UNIATA_SATA) {
-    if(deviceExtension->BaseIoAddressSATA_0.Addr) {
+    if(UniataIsSATARangeAvailable(deviceExtension, 0)) {
         if(Status & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
             return Status;
         }
@@ -620,7 +679,7 @@ AtapiSoftReset(
     )
 {
     //ULONG c = chan->lChannel;
-    ULONG i;
+    ULONG i = 30 * 1000;
     UCHAR dma_status = 0;
     KdPrint2((PRINT_PREFIX "AtapiSoftReset:\n"));
     UCHAR statusByte2;
@@ -630,9 +689,17 @@ AtapiSoftReset(
     SelectDrive(chan, DeviceNumber);
     AtapiStallExecution(10000);
     AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
-    for (i = 0; i < 1000; i++) {
-        AtapiStallExecution(999);
+
+    // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
+    // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
+    // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
+    // implementation. (which is around 1 second)
+    while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
+           i--)
+    {
+        AtapiStallExecution(30);
     }
+
     SelectDrive(chan, DeviceNumber);
     WaitOnBusy(chan);
     GetBaseStatus(chan, statusByte2);
@@ -663,6 +730,7 @@ AtapiSoftReset(
     Translate to 48-Lba form if required
 */
 UCHAR
+NTAPI
 AtaCommand48(
     IN PHW_DEVICE_EXTENSION deviceExtension,
     IN ULONG DeviceNumber,
@@ -701,7 +769,7 @@ AtaCommand48(
     //>>>>>> NV: 2006/08/03
     if((AtaCommandFlags[command] & ATA_CMD_FLAG_LBAIOsupp) &&
        CheckIfBadBlock(&(deviceExtension->lun[ldev]), lba, count)) {
-        KdPrint2((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count));
+        KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count));
         return IDE_STATUS_ERROR;
         //return SRB_STATUS_ERROR;
     }
@@ -723,10 +791,10 @@ AtaCommand48(
         chan->ChannelCtrlFlags |= CTRFLAGS_LBA48;
         plba = (PUCHAR)&lba;
 
-        AtapiWritePort1(chan, IDX_IO1_o_Feature,      (UCHAR)(feature>>8) & 0xff);
+        AtapiWritePort1(chan, IDX_IO1_o_Feature,      (UCHAR)(feature>>8));
         AtapiWritePort1(chan, IDX_IO1_o_Feature,      (UCHAR)feature);
-        AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   (UCHAR)(count>>8) & 0xff);
-        AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   (UCHAR)count & 0xff);
+        AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   (UCHAR)(count>>8));
+        AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   (UCHAR)count);
         AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  (UCHAR)(plba[3]));
         AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  (UCHAR)(plba[0]));
         AtapiWritePort1(chan, IDX_IO1_o_CylinderLow,  (UCHAR)(plba[4]));
@@ -738,22 +806,23 @@ AtaCommand48(
         AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) );
     } else {
 
+        plba = (PUCHAR)&lba; //ktp
         chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48;
-
+        
         //if(feature ||
         //   (deviceExtension->lun[ldev].DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
             AtapiWritePort1(chan, IDX_IO1_o_Feature,      (UCHAR)feature);
         //}
         AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   (UCHAR)count);
-        AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  (UCHAR)lba & 0xff);
-        AtapiWritePort1(chan, IDX_IO1_o_CylinderLow,  (UCHAR)(lba>>8) & 0xff);
-        AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(lba>>16) & 0xff);
+        AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  (UCHAR)plba[0]);
+        AtapiWritePort1(chan, IDX_IO1_o_CylinderLow,  (UCHAR)plba[1]);
+        AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)plba[2]);
         if(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_LBA_ENABLED) {
             //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_LBA\n", ldev ));
-            AtapiWritePort1(chan, IDX_IO1_o_DriveSelect,  (UCHAR)((lba>>24) & 0xf) | IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
+            AtapiWritePort1(chan, IDX_IO1_o_DriveSelect,  (UCHAR)(plba[3] & 0xf) | IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
         } else {
             //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_CHS\n", ldev ));
-            AtapiWritePort1(chan, IDX_IO1_o_DriveSelect,  (UCHAR)((lba>>24) & 0xf) | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
+            AtapiWritePort1(chan, IDX_IO1_o_DriveSelect,  (UCHAR)(plba[3] & 0xf) | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
         }
     }
 
@@ -797,7 +866,7 @@ AtaCommand48(
                 break;
             } else {
                 //if(deviceExtension->HwFlags & UNIATA_SATA) {
-                if(deviceExtension->BaseIoAddressSATA_0.Addr) {
+                if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
                     break;
                 }
                 AtapiStallExecution(100);
@@ -840,6 +909,7 @@ AtaCommand48(
     This is simply wrapper for AtaCommand48()
 */
 UCHAR
+NTAPI
 AtaCommand(
     IN PHW_DEVICE_EXTENSION deviceExtension,
     IN ULONG DeviceNumber,
@@ -860,6 +930,7 @@ AtaCommand(
 } // end AtaCommand()
 
 LONG
+NTAPI
 AtaPio2Mode(LONG pio)
 {
     switch (pio) {
@@ -874,6 +945,7 @@ AtaPio2Mode(LONG pio)
 } // end AtaPio2Mode()
 
 LONG
+NTAPI
 AtaPioMode(PIDENTIFY_DATA2 ident)
 {
     if (ident->PioTimingsValid) {
@@ -894,6 +966,7 @@ AtaPioMode(PIDENTIFY_DATA2 ident)
 } // end AtaPioMode()
 
 LONG
+NTAPI
 AtaWmode(PIDENTIFY_DATA2 ident)
 {
     if (ident->MultiWordDMASupport & 0x04)
@@ -906,6 +979,7 @@ AtaWmode(PIDENTIFY_DATA2 ident)
 } // end AtaWmode()
 
 LONG
+NTAPI
 AtaUmode(PIDENTIFY_DATA2 ident)
 {
     if (!ident->UdmaModesValid)
@@ -947,7 +1021,7 @@ AtapiTimerDpc(
     KdPrint2((PRINT_PREFIX "AtapiTimerDpc:\n"));
 
     lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
-    if(lChannel == (ULONG)-1) {
+    if(lChannel == CHAN_NOT_SPECIFIED) {
         KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no items\n"));
         return;
     }
@@ -959,19 +1033,19 @@ AtapiTimerDpc(
         chan->HwScsiTimer = NULL;
 
         deviceExtension->FirstDpcChan = chan->NextDpcChan;
-        if(deviceExtension->FirstDpcChan != (ULONG)-1) {
+        if(deviceExtension->FirstDpcChan != CHAN_NOT_SPECIFIED) {
             recall = TRUE;
         }
 
         HwScsiTimer(HwDeviceExtension);
 
-        chan->NextDpcChan = -1;
+        chan->NextDpcChan = CHAN_NOT_SPECIFIED;
 
         lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
-        if(lChannel == (ULONG)-1) {
+        if(lChannel == CHAN_NOT_SPECIFIED) {
             KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no more items\n"));
             deviceExtension->FirstDpcChan =
-            deviceExtension->ActiveDpcChan = -1;
+            deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
             return;
         }
 
@@ -989,7 +1063,7 @@ AtapiTimerDpc(
     }
 
     if(recall) {
-        deviceExtension->ActiveDpcChan = -1;
+        deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
         MiniportTimerValue = (ULONG)(time.QuadPart - chan->DpcTime)/10;
         if(!MiniportTimerValue)
             MiniportTimerValue = 1;
@@ -1011,6 +1085,7 @@ AtapiTimerDpc(
     cancels previous Dpc request (if any), but we need Dpc queue.
 */
 VOID
+NTAPI
 AtapiQueueTimerDpc(
     IN PVOID HwDeviceExtension,
     IN ULONG lChannel,
@@ -1037,7 +1112,7 @@ AtapiQueueTimerDpc(
 
     i = deviceExtension->FirstDpcChan;
     chan = prev_chan = NULL;
-    while(i != (ULONG)-1) {
+    while(i != CHAN_NOT_SPECIFIED) {
         prev_chan = chan;
         chan = &deviceExtension->chan[i];
         if(chan->DpcTime > time.QuadPart) {
@@ -1072,6 +1147,7 @@ AtapiQueueTimerDpc(
 #endif //UNIATA_CORE
 
 VOID
+NTAPI
 UniataDumpATARegs(
     IN PHW_CHANNEL chan
     )
@@ -1119,6 +1195,7 @@ Return Value:
 
 --*/
 BOOLEAN
+NTAPI
 IssueIdentify(
     IN PVOID HwDeviceExtension,
     IN ULONG DeviceNumber,
@@ -1143,6 +1220,10 @@ IssueIdentify(
         KdPrint2((PRINT_PREFIX "IssueIdentify: NO SLAVE\n"));
         return FALSE;
     }
+    if(LunExt->DeviceFlags & DFLAGS_HIDDEN) {
+        KdPrint2((PRINT_PREFIX "IssueIdentify: HIDDEN\n"));
+        return FALSE;
+    }
 
     SelectDrive(chan, DeviceNumber);
     AtapiStallExecution(10);
@@ -1164,7 +1245,7 @@ IssueIdentify(
             KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
 
             //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
-            if(!deviceExtension->BaseIoAddressSATA_0.Addr) {
+            if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
                 SelectDrive(chan, DeviceNumber);
                 WaitOnBusyLong(chan);
 
@@ -1215,7 +1296,7 @@ IssueIdentify(
     } else {
         KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte));
         //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
-        if(!deviceExtension->BaseIoAddressSATA_0.Addr) {
+        if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
             statusByte = WaitForIdleLong(chan);
             KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte));
         }
@@ -1223,7 +1304,7 @@ IssueIdentify(
     }
 
 //    if(deviceExtension->HwFlags & UNIATA_SATA) {
-    if(deviceExtension->BaseIoAddressSATA_0.Addr) {
+    if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
         j = 4;
     } else {
         j = 0;
@@ -1709,6 +1790,7 @@ Return Value:
 
 --*/
 BOOLEAN
+NTAPI
 SetDriveParameters(
     IN PVOID HwDeviceExtension,
     IN ULONG DeviceNumber,
@@ -1750,6 +1832,15 @@ SetDriveParameters(
 
 } // end SetDriveParameters()
 
+VOID
+NTAPI
+UniataForgetDevice(
+    PHW_LU_EXTENSION   LunExt
+    )
+{
+    LunExt->DeviceFlags &= DFLAGS_HIDDEN;
+} // end UniataForgetDevice()
+
 
 /*++
 
@@ -1777,6 +1868,7 @@ AtapiResetController(
 
 
 BOOLEAN
+NTAPI
 AtapiResetController__(
     IN PVOID HwDeviceExtension,
     IN ULONG PathId,
@@ -1796,7 +1888,9 @@ AtapiResetController__(
     ULONG slotNumber = deviceExtension->slotNumber;
     ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
     ULONG VendorID =  deviceExtension->DevID        & 0xffff;
+#ifdef _DEBUG
     ULONG DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
+#endif
     //ULONG RevID    =  deviceExtension->RevID;
     ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
     UCHAR tmp8;
@@ -1804,11 +1898,11 @@ AtapiResetController__(
 
     KdPrint2((PRINT_PREFIX "AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID, DeviceID, slotNumber));
 
-    if(!deviceExtension->simplexOnly) {
+    if(!deviceExtension->simplexOnly && (PathId != CHAN_NOT_SPECIFIED)) {
         // we shall reset both channels on SimplexOnly devices,
         // It's not worth doing so on normal controllers
         j = PathId;
-        numberChannels = j+1;
+        numberChannels = min(j+1, deviceExtension->NumberChannels);
     } else {
         j=0;
         numberChannels = deviceExtension->NumberChannels;
@@ -1873,6 +1967,7 @@ AtapiResetController__(
                     // Clear request tracking fields.
                     AtaReq->WordsLeft = 0;
                     AtaReq->DataBuffer = NULL;
+                    AtaReq->TransferLength = 0;
 
                     ScsiPortNotification(RequestComplete,
                                          deviceExtension,
@@ -1910,7 +2005,7 @@ AtapiResetController__(
             ULONG timeout;
             if(!(ChipFlags & UNIATA_SATA))
                 goto default_reset;
-            if(!deviceExtension->BaseIoAddressSATA_0.Addr) {
+            if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
                 goto default_reset;
             }
 
@@ -1981,6 +2076,7 @@ default_reset:
             // Disable interrupts
             KdPrint2((PRINT_PREFIX "  disable intr\n"));
             AtapiDisableInterrupts(deviceExtension, j);
+            AtapiStallExecution(100);
             KdPrint2((PRINT_PREFIX "  re-enable intr\n"));
             AtapiEnableInterrupts(deviceExtension, j);
             KdPrint2((PRINT_PREFIX "  wait a little (2)\n"));
@@ -1991,7 +2087,7 @@ default_reset:
         }
 
         //if(!(ChipFlags & UNIATA_SATA)) {
-        if(!deviceExtension->BaseIoAddressSATA_0.Addr) {
+        if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
             // Reset DMA engine if active
             KdPrint2((PRINT_PREFIX "  check DMA engine\n"));
             dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
@@ -2010,6 +2106,9 @@ default_reset:
 
             // Check if device present.
             if (!(deviceExtension->lun[i + (j * 2)].DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
+#ifdef NAVO_TEST
+                continue;
+#else //NAVO_TEST
                 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
                 if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
                     continue;
@@ -2020,8 +2119,9 @@ default_reset:
             } else {
                 if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
                     KdPrint2((PRINT_PREFIX "  device have gone\n"));
-                    deviceExtension->lun[i + (j * 2)].DeviceFlags &= ~DFLAGS_DEVICE_PRESENT;
+                    UniataForgetDevice(&(deviceExtension->lun[i + (j * 2)]));
                 }
+#endif //NAVO_TEST
             }
 
             SelectDrive(chan, i);
@@ -2032,7 +2132,7 @@ default_reset:
                 KdPrint2((PRINT_PREFIX
                            "no drive, status %#x\n",
                            statusByte));
-                deviceExtension->lun[i + (j * 2)].DeviceFlags = 0;
+                UniataForgetDevice(&(deviceExtension->lun[i + (j * 2)]));
             } else
             // Check for ATAPI disk.
             if (deviceExtension->lun[i + (j * 2)].DeviceFlags & DFLAGS_ATAPI_DEVICE) {
@@ -2117,6 +2217,7 @@ Return Value:
 
 --*/
 ULONG
+NTAPI
 MapError(
     IN PVOID HwDeviceExtension,
     IN PSCSI_REQUEST_BLOCK Srb
@@ -2508,6 +2609,10 @@ AtapiHwInitialize(
 
     KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base)\n"));
 
+    if(WinVer_WDM_Model) {
+        AtapiResetController__(HwDeviceExtension, CHAN_NOT_SPECIFIED, RESET_COMPLETE_ALL);
+    }
+
     /* do extra chipset specific setups */
     AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
 /*
@@ -2524,6 +2629,7 @@ AtapiHwInitialize(
 } // end AtapiHwInitialize()
 
 VOID
+NTAPI
 AtapiHwInitialize__(
     IN PHW_DEVICE_EXTENSION deviceExtension,
     IN ULONG lChannel
@@ -2537,11 +2643,11 @@ AtapiHwInitialize__(
     ULONG PreferedMode = 0xffffffff;
 
     AtapiChipInit(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel);
-    FindDevices(deviceExtension, FALSE, lChannel);
+    FindDevices(deviceExtension, 0, lChannel);
 
     for (i = lChannel*2; i < (lChannel+1)*2; i++) {
 
-        KdPrint2((PRINT_PREFIX "AtapiHwInitialize: lChannel %#x\n", lChannel));
+        KdPrint3((PRINT_PREFIX "AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel, i));
 
         LunExt = &(deviceExtension->lun[i]);
         // skip empty slots
@@ -2559,32 +2665,41 @@ AtapiHwInitialize__(
             IdeMediaStatus(TRUE,deviceExtension,(UCHAR)i);
 
             // If supported, setup Multi-block transfers.
-            if (LunExt->MaximumBlockXfer) {
+            statusByte = AtaCommand(deviceExtension, i & 1, lChannel,
+                                IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
+                                LunExt->MaximumBlockXfer, 0, ATA_WAIT_BASE_READY);
+
+            // Check for errors. Reset the value to 0 (disable MultiBlock) if the
+            // command was aborted.
+            if (statusByte & IDE_STATUS_ERROR) {
+
+                // Read the error register.
+                errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
+
+                KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
+                            statusByte,
+                            errorByte));
 
                 statusByte = AtaCommand(deviceExtension, i & 1, lChannel,
                                     IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
                                     LunExt->MaximumBlockXfer, 0, ATA_WAIT_BASE_READY);
 
-                // Check for errors. Reset the value to 0 (disable MultiBlock) if the
-                // command was aborted.
                 if (statusByte & IDE_STATUS_ERROR) {
-
                     // Read the error register.
                     errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
 
-                    KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
+                    KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
                                 statusByte,
                                 errorByte));
-
-                    // Adjust the devExt. value, if necessary.
-                    LunExt->MaximumBlockXfer = 0;
-
-                } else {
-                    KdPrint2((PRINT_PREFIX
-                                "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
-                                i,
-                                LunExt->MaximumBlockXfer));
                 }
+                // Adjust the devExt. value, if necessary.
+                LunExt->MaximumBlockXfer = 0;
+
+            } else {
+                KdPrint2((PRINT_PREFIX 
+                            "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
+                            i,
+                            LunExt->MaximumBlockXfer));
             }
 
             if(LunExt->IdentifyData.MajorRevision) {
@@ -2737,6 +2852,7 @@ AtapiHwInitialize__(
 #ifndef UNIATA_CORE
 
 VOID
+NTAPI
 AtapiHwInitializeChanger(
     IN PVOID HwDeviceExtension,
     IN PSCSI_REQUEST_BLOCK Srb,
@@ -2771,13 +2887,14 @@ Return Values:
 
 --*/
 ULONG
+NTAPI
 AtapiParseArgumentString(
-    IN PCHAR String,
-    IN PCHAR KeyWord
+    IN PCCH String,
+    IN PCCH KeyWord
     )
 {
-    PCHAR cptr;
-    PCHAR kptr;
+    PCCH cptr;
+    PCCH kptr;
     ULONG value;
     ULONG stringLength = 0;
     ULONG keyWordLength = 0;
@@ -2790,24 +2907,15 @@ AtapiParseArgumentString(
         return 0;
     }
 
-    // Calculate the string length and lower case all characters.
+    // Calculate the string length.
     cptr = String;
-    while (*cptr) {
-        if (*cptr >= 'A' && *cptr <= 'Z') {
-            *cptr = *cptr + ('a' - 'A');
-        }
-        cptr++;
+    while (*cptr++) {
         stringLength++;
     }
 
-    // Calculate the keyword length and lower case all characters.
-    cptr = KeyWord;
-    while (*cptr) {
-
-        if (*cptr >= 'A' && *cptr <= 'Z') {
-            *cptr = *cptr + ('a' - 'A');
-        }
-        cptr++;
+    // Calculate the keyword length.
+    kptr = KeyWord;
+    while (*kptr++) {
         keyWordLength++;
     }
 
@@ -2833,18 +2941,21 @@ ContinueSearch:
     }
 
     kptr = KeyWord;
-    while (*cptr++ == *kptr++) {
+    while ((*cptr == *kptr) ||
+           (*cptr <= 'Z' && *cptr + ('a' - 'A') == *kptr) ||
+           (*cptr >= 'a' && *cptr - ('a' - 'A') == *kptr)) {
+        cptr++;
+        kptr++;
 
-        if (*(cptr - 1) == '\0') {
+        if (*cptr == '\0') {
             // end of string
             return 0;
         }
     }
 
-    if (*(kptr - 1) == '\0') {
+    if (*kptr == '\0') {
 
         // May have a match backup and check for blank or equals.
-        cptr--;
         while (*cptr == ' ' || *cptr == '\t') {
             cptr++;
         }
@@ -2880,7 +2991,7 @@ ContinueSearch:
         }
 
         value = 0;
-        if ((*cptr == '0') && (*(cptr + 1) == 'x')) {
+        if ((*cptr == '0') && ((*(cptr + 1) == 'x') || (*(cptr + 1) == 'X'))) {
             // Value is in Hex.  Skip the "0x"
             cptr += 2;
             for (index = 0; *(cptr + index); index++) {
@@ -2896,6 +3007,8 @@ ContinueSearch:
                 } else {
                     if ((*(cptr + index) >= 'a') && (*(cptr + index) <= 'f')) {
                         value = (16 * value) + (*(cptr + index) - 'a' + 10);
+                    } else if ((*(cptr + index) >= 'A') && (*(cptr + index) <= 'F')) {
+                        value = (16 * value) + (*(cptr + index) - 'A' + 10);
                     } else {
                         // Syntax error, return not found.
                         return 0;
@@ -2941,6 +3054,7 @@ ContinueSearch:
     Timer callback
 */
 VOID
+NTAPI
 AtapiCallBack__(
     IN PVOID HwDeviceExtension,
     IN UCHAR lChannel
@@ -2971,7 +3085,7 @@ AtapiCallBack__(
         goto ReturnCallback;
     }
 
-#ifdef DBG
+#if DBG
     if (!IS_RDP((srb->Cdb[0]))) {
         KdPrint2((PRINT_PREFIX "AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb->Cdb[0]));
     }
@@ -3070,6 +3184,7 @@ ReturnCallback:
 } // end AtapiCallBack__()
 
 VOID
+NTAPI
 AtapiCallBack_X(
     IN PVOID HwDeviceExtension
     )
@@ -3125,7 +3240,7 @@ AtapiInterrupt(
             if(checked[c])
                 continue;
 
-            // check non-empty and execting interrupt channels first
+            // check non-empty and expecting interrupt channels first
             if(!pass && !deviceExtension->chan[c].ExpectingInterrupt)
                 continue;
 
@@ -3215,6 +3330,7 @@ AtapiInterrupt(
 #ifndef UNIATA_CORE
 
 BOOLEAN
+NTAPI
 AtapiInterrupt2(
     IN PKINTERRUPT Interrupt,
     IN PVOID Isr2HwDeviceExtension
@@ -3228,6 +3344,7 @@ AtapiInterrupt2(
     ULONG c_count = 0;
     ULONG i_res;
 
+    // we should never get here for ISA/MCA
     if(!BMList[deviceExtension->DevIndex].Isr2Enable) {
         KdPrint2((PRINT_PREFIX "AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension->DevIndex, deviceExtension->Channel));
         return FALSE;
@@ -3384,6 +3501,7 @@ AtapiEnableInterrupts__(
 
 
 VOID
+NTAPI
 AtapiEnableInterrupts(
     IN PVOID HwDeviceExtension,
     IN ULONG c
@@ -3406,6 +3524,7 @@ AtapiEnableInterrupts(
 } // end AtapiEnableInterrupts()
 
 VOID
+NTAPI
 AtapiDisableInterrupts(
     IN PVOID HwDeviceExtension,
     IN ULONG c
@@ -3431,6 +3550,7 @@ AtapiDisableInterrupts(
     Check hardware for interrupt state
  */
 BOOLEAN
+NTAPI
 AtapiCheckInterrupt__(
     IN PVOID HwDeviceExtension,
     IN UCHAR c // logical channel
@@ -3438,6 +3558,7 @@ AtapiCheckInterrupt__(
 {
     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
     PHW_CHANNEL chan = &(deviceExtension->chan[c]);
+    PHW_LU_EXTENSION LunExt;
 
     ULONG VendorID  = deviceExtension->DevID & 0xffff;
     ULONG ChipType  = deviceExtension->HwFlags & CHIPTYPE_MASK;
@@ -3446,7 +3567,7 @@ AtapiCheckInterrupt__(
     ULONG pr_status = 0;
     UCHAR dma_status = 0;
     UCHAR reg8 = 0;
-    UCHAR reg32 = 0;
+    ULONG reg32 = 0;
     UCHAR statusByte;
     ULONG slotNumber = deviceExtension->slotNumber;
     ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
@@ -3455,7 +3576,7 @@ AtapiCheckInterrupt__(
     UCHAR lChannel;
     BOOLEAN DmaTransfer = FALSE;
     BOOLEAN OurInterrupt = FALSE;
-    ULONG k;
+//    ULONG k;
     UCHAR interruptReason;
     BOOLEAN EarlyIntr = FALSE;
 
@@ -3481,6 +3602,12 @@ AtapiCheckInterrupt__(
         goto check_unknown;
     }
 
+    if((ChipFlags & UNIATA_AHCI) &&
+        UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
+        OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel);
+        return OurInterrupt;
+    }
+
     // Attention !
     // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
     // Such behavior was observed with Intel ICH-xxx chips
@@ -3581,9 +3708,9 @@ AtapiCheckInterrupt__(
 
         if(ChipType == SIIMIO) {
 
-            reg32 = AtapiReadPort1(chan, IDX_BM_DeviceSpecific0);
+            reg32 = AtapiReadPort4(chan, IDX_BM_DeviceSpecific0);
             KdPrint2((PRINT_PREFIX "  Sii DS0 %x\n", reg32));
-            if(reg32 == (UCHAR)-1) {
+            if(reg32 == 0xffffffff) {
                 KdPrint2((PRINT_PREFIX "  Sii mio unexpected\n"));
                 return FALSE;
             }
@@ -3645,10 +3772,14 @@ AtapiCheckInterrupt__(
             AtapiReadPort1(chan, IDX_BM_Command) & ~BM_COMMAND_START_STOP);
         goto skip_dma_stat_check;
     default:
-        if(deviceExtension->BaseIoAddressSATA_0.Addr &&
-           (ChipFlags & UNIATA_SATA)) {
-            if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT)) {
-                OurInterrupt = 2;
+        if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
+            if(ChipFlags & UNIATA_AHCI) {
+                // Do nothing here
+            } else
+            if(ChipFlags & UNIATA_SATA) {
+                if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT)) {
+                    OurInterrupt = 2;
+                }
             }
         }
     }
@@ -3686,53 +3817,57 @@ skip_dma_stat_check:
         AtapiStallExecution(1);
     }
 
+    LunExt = &(deviceExtension->lun[c*2 + chan->cur_cdev]);
     /* if drive is busy it didn't interrupt */
-    /* the exception is DCS + BSY state of ATAPI dvices */
+    /* the exception is DCS + BSY state of ATAPI devices */
     KdPrint2((PRINT_PREFIX "  getting status...\n"));
     GetStatus(chan, statusByte);
-    KdPrint2((PRINT_PREFIX "  status %#x\n", statusByte));
+    if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
+        KdPrint3((PRINT_PREFIX "  ATAPI status %#x\n", statusByte));
+    } else {
+        KdPrint2((PRINT_PREFIX "  IDE status %#x\n", statusByte));
+    }
     if (statusByte == 0xff) {
         // interrupt from empty controller ?
-    } else
+    } else 
     if (statusByte & IDE_STATUS_BUSY) {
         if(!chan->ExpectingInterrupt) {
-            KdPrint2((PRINT_PREFIX "  unexpected intr + BUSY\n"));
+            KdPrint3((PRINT_PREFIX "  unexpected intr + BUSY\n"));
             return OurInterrupt;
         }
 
-        if(deviceExtension->lun[c*2 + chan->cur_cdev].DeviceFlags & DFLAGS_ATAPI_DEVICE) {
+        if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
             KdPrint2((PRINT_PREFIX "  ATAPI additional check\n"));
         } else {
             KdPrint2((PRINT_PREFIX "  expecting intr + BUSY (3), non ATAPI\n"));
             return FALSE;
         }
-        if(statusByte != (IDE_STATUS_BUSY | IDE_STATUS_DRDY | IDE_STATUS_DSC)) {
-            KdPrint2((PRINT_PREFIX "  unexpected status, seems it is not our\n"));
+        if((statusByte & ~IDE_STATUS_DRQ) != (IDE_STATUS_BUSY | IDE_STATUS_DRDY | IDE_STATUS_DSC)) {
+            KdPrint3((PRINT_PREFIX "  unexpected status, seems it is not our\n"));
+            return FALSE;
+        }
+        if(!(LunExt->DeviceFlags & DFLAGS_INT_DRQ) && (statusByte & IDE_STATUS_DRQ)) {
+            KdPrint3((PRINT_PREFIX "  unexpected DRQ, seems it is not our\n"));
             return FALSE;
         }
 
         EarlyIntr = TRUE;
 
         if(dma_status & BM_STATUS_INTR) {
-            KdPrint2((PRINT_PREFIX "  our interrupt with BSY set, try wait in ISR or post to DPC\n"));
+            KdPrint3((PRINT_PREFIX "  our interrupt with BSY set, try wait in ISR or post to DPC\n"));
             /* clear interrupt and get status */
             GetBaseStatus(chan, statusByte);
-            KdPrint2((PRINT_PREFIX "  base status %#x\n", statusByte));
+            KdPrint3((PRINT_PREFIX "  base status %#x (+BM_STATUS_INTR)\n", statusByte));
             return TRUE;
         }
 
         if(g_WaitBusyInISR) {
-            for(k=20; k; k--) {
-                GetStatus(chan, statusByte);
-                KdPrint2((PRINT_PREFIX "  status re-check %#x\n", statusByte));
-                KdPrint2((PRINT_PREFIX "  Error reg (%#x)\n",
-                            AtapiReadPort1(chan, IDX_IO1_i_Error)));
-                if (!(statusByte & IDE_STATUS_BUSY)) {
-                    KdPrint2((PRINT_PREFIX "  expecting intr + cleared BUSY\n"));
-                    break;
-                }
-                break;
-                //AtapiStallExecution(25);
+            GetStatus(chan, statusByte);
+            KdPrint2((PRINT_PREFIX "  status re-check %#x\n", statusByte));
+            reg8 = AtapiReadPort1(chan, IDX_IO1_i_Error);
+            KdPrint2((PRINT_PREFIX "  Error reg (%#x)\n", reg8));
+            if (!(statusByte & IDE_STATUS_BUSY)) {
+                KdPrint2((PRINT_PREFIX "  expecting intr + cleared BUSY\n"));
             }
             if (statusByte & IDE_STATUS_BUSY) {
                 KdPrint2((PRINT_PREFIX "  still BUSY, seems it is not our\n"));
@@ -3775,14 +3910,14 @@ skip_dma_stat_check:
 
         KdPrint2((PRINT_PREFIX "  Unexpected interrupt.\n"));
 
-        if(deviceExtension->lun[c*2 + chan->cur_cdev * 2].DeviceFlags & DFLAGS_ATAPI_DEVICE) {
+        if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
             KdPrint2((PRINT_PREFIX "  ATAPI additional check\n"));
         } else {
             KdPrint2((PRINT_PREFIX "  OurInterrupt = %d\n", OurInterrupt));
             return OurInterrupt;
         }
         interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
-        KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason));
+        KdPrint3((PRINT_PREFIX "AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason));
         return OurInterrupt;
     }
     //ASSERT(!chan->queue_depth || chan->cur_req);
@@ -3794,6 +3929,7 @@ skip_dma_stat_check:
 
 
 BOOLEAN
+NTAPI
 AtapiInterrupt__(
     IN PVOID HwDeviceExtension,
     IN UCHAR c
@@ -3905,6 +4041,7 @@ AtapiInterrupt__(
 
     switch(OldReqState) {
     case REQ_STATE_ATAPI_EXPECTING_CMD_INTR:
+        KdPrint3((PRINT_PREFIX "  EXPECTING_CMD_INTR\n"));
     case REQ_STATE_ATAPI_EXPECTING_DATA_INTR:
     case REQ_STATE_DPC_WAIT_BUSY0:
     case REQ_STATE_DPC_WAIT_BUSY1:
@@ -4008,7 +4145,7 @@ ServiceInterrupt:
 #else
 ServiceInterrupt:
 #endif //UNIATA_CORE
-
+/*
     // make additional delay for old devices (if we are not in DPC)
     if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
              &&
@@ -4019,10 +4156,14 @@ ServiceInterrupt:
         KdPrint2((PRINT_PREFIX "  additional delay 10us for old devices\n"));
         AtapiStallExecution(10);
     }
-
+*/
     /* clear interrupt and get status */
     GetBaseStatus(chan, statusByte);
-    KdPrint2((PRINT_PREFIX "AtapiInterrupt: Entered with status (%#x)\n", statusByte));
+    if(atapiDev) {
+        KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte));
+    } else {
+        KdPrint2((PRINT_PREFIX "AtapiInterrupt: Entered with status (%#x)\n", statusByte));
+    }
 
     if(!UseDpc) {
         KdPrint2((PRINT_PREFIX "  operate like in DPC\n"));
@@ -4086,18 +4227,18 @@ try_dpc_wait:
         }
         if (statusByte & IDE_STATUS_BUSY) {
         //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {
-            KdPrint2((PRINT_PREFIX "  BUSY on ATAPI device, waiting\n"));
+            KdPrint3((PRINT_PREFIX "  BUSY on ATAPI device, waiting\n"));
             for(k=20; k; k--) {
                 GetStatus(chan, statusByte);
-                KdPrint2((PRINT_PREFIX "  status re-check %#x\n", statusByte));
-                KdPrint2((PRINT_PREFIX "  Error reg (%#x)\n",
+                KdPrint3((PRINT_PREFIX "  status re-check %#x\n", statusByte));
+                KdPrint3((PRINT_PREFIX "  Error reg (%#x)\n",
                             AtapiReadPort1(chan, IDX_IO1_i_Error)));
                 if (!(statusByte & IDE_STATUS_BUSY)) {
                     KdPrint2((PRINT_PREFIX "  expecting intr + cleared BUSY\n"));
                     break;
                 }
                 if(k <= 18) {
-                    KdPrint2((PRINT_PREFIX "  too long wait -> DPC\n"));
+                    KdPrint3((PRINT_PREFIX "  too long wait -> DPC\n"));
                     if(!InDpc) {
                         KdPrint2((PRINT_PREFIX "  too long wait: ISR -> DPC\n"));
                         TimerValue = 100;
@@ -4117,7 +4258,7 @@ try_dpc_wait:
                 AtapiStallExecution(10);
             }
             if (statusByte & IDE_STATUS_BUSY) {
-                KdPrint2((PRINT_PREFIX "  expecting intr + BUSY (2), try DPC wait\n"));
+                KdPrint3((PRINT_PREFIX "  expecting intr + BUSY (2), try DPC wait\n"));
                 goto try_dpc_wait;
             }
         }
@@ -4156,22 +4297,23 @@ try_dpc_wait:
             KdPrint2((PRINT_PREFIX "  Bad Lba unknown\n"));
         }
 
-        KdPrint2((PRINT_PREFIX "  wait ready after error\n"));
 
         if(!atapiDev) {
+            KdPrint2((PRINT_PREFIX "  wait 100 ready after IDE error\n"));
             AtapiStallExecution(100);
         } else {
+            KdPrint2((PRINT_PREFIX "  wait 10 ready after ATAPI error\n"));
             AtapiStallExecution(10);
         }
 continue_err:
 
-        KdPrint2((PRINT_PREFIX "  Intr on DRQ %x\n",
+        KdPrint3((PRINT_PREFIX "  Intr on DRQ %x\n",
             LunExt->DeviceFlags & DFLAGS_INT_DRQ));
 
         for (k = atapiDev ? 0 : 200; k; k--) {
             GetStatus(chan, statusByte);
             if (!(statusByte & IDE_STATUS_DRQ)) {
-                AtapiStallExecution(50);
+                AtapiStallExecution(100);
             } else {
                 break;
             }
@@ -4204,10 +4346,27 @@ continue_err:
             }
         } else {
             interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
-            KdPrint2((PRINT_PREFIX "AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason));
+            KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason));
+
+            if(DmaTransfer && (chan->lun[DeviceNumber]->TransferMode > ATA_UDMA2) &&
+               ((error >> 4) == SCSI_SENSE_HARDWARE_ERROR)) {
+                if(AtaReq->retry < MAX_RETRIES) {
+//fallback_pio:
+                    AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
+                    AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
+//                        LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
+                    AtaReq->ReqState = REQ_STATE_QUEUED;
+                    goto reenqueue_req;
+                }
+            } else {
+                if(!(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE)) {
+                    AtaReq->retry++;
+                }
+                KdPrint3((PRINT_PREFIX "Errors in PIO mode\n"));
+            }
         }
 
-        KdPrint2((PRINT_PREFIX "AtapiInterrupt: Error\n"));
+        KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error\n"));
         if (srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
             // Fail this request.
             status = SRB_STATUS_ERROR;
@@ -4215,7 +4374,6 @@ continue_err:
         } else {
             KdPrint2((PRINT_PREFIX "  continue with SCSIOP_REQUEST_SENSE\n"));
         }
-#ifdef IO_STATISTICS
     } else
     if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE_LBA48) {
         KdPrint2((PRINT_PREFIX "DMA doesn't work right with LBA48\n"));
@@ -4223,12 +4381,18 @@ continue_err:
     } else
     if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE) {
         KdPrint2((PRINT_PREFIX "Some higher mode doesn't work right :((\n"));
+#ifdef IO_STATISTICS
         chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry]++;
-        if(chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->IoCount/3) {
+        if(chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->IoCount/3 ||
+           (deviceExtension->HwFlags & UNIATA_NO80CHK)
+           ) {
+#else
+        if(deviceExtension->HwFlags & UNIATA_NO80CHK) {
+#endif //IO_STATISTICS
+            KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", deviceExtension->lun[DeviceNumber].TransferMode));
             deviceExtension->lun[DeviceNumber].LimitedTransferMode =
                 deviceExtension->lun[DeviceNumber].TransferMode;
         }
-#endif //IO_STATISTICS
     }
 #ifdef IO_STATISTICS
     chan->lun[DeviceNumber]->IoCount++;
@@ -4243,11 +4407,11 @@ continue_PIO:
         // ATAPI branch
 
         interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3);
-        KdPrint2((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
+        KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
         if(DmaTransfer) {
             wordsThisInterrupt = DEV_BSIZE/2*512;
         } else {
-            wordsThisInterrupt = DEV_BSIZE;
+            wordsThisInterrupt = DEV_BSIZE/2;
         }
 
     } else {
@@ -4334,7 +4498,7 @@ IntrPrepareResetController:
     KdPrint2((PRINT_PREFIX "AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason, statusByte));
     if (interruptReason == 0x1 && (statusByte & IDE_STATUS_DRQ)) {
         // Write the packet.
-        KdPrint2((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n"));
+        KdPrint3((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n"));
         // Send CDB to device.
         WriteBuffer(chan, (PUSHORT)srb->Cdb, 6, 0);
         AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
@@ -4422,7 +4586,7 @@ IntrPrepareResetController:
            }
         } else {
 
-            KdPrint2((PRINT_PREFIX
+            KdPrint3((PRINT_PREFIX
                         "AtapiInterrupt: Int reason %#x, but srb is for a write %#x.\n",
                         interruptReason,
                         srb));
@@ -4453,7 +4617,7 @@ IntrPrepareResetController:
                 (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8);
 
             // Covert bytes to words.
-            wordCount >>= 1;
+            wordCount /= 2;
             KdPrint2((PRINT_PREFIX "AtapiInterrupt: get R wordCount %#x\n", wordCount));
 
             if (wordCount != AtaReq->WordsLeft) {
@@ -4509,6 +4673,9 @@ IntrPrepareResetController:
                           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);
+                }
 
                 GetStatus(chan, statusByte);
                 KdPrint2((PRINT_PREFIX "  status re-check %#x\n", statusByte));
@@ -4529,7 +4696,7 @@ IntrPrepareResetController:
             }
         } else {
 
-            KdPrint2((PRINT_PREFIX
+            KdPrint3((PRINT_PREFIX 
                         "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
                         interruptReason,
                         srb));
@@ -4663,7 +4830,7 @@ CompleteRequest:
             KdPrint2((PRINT_PREFIX "AtapiInterrupt: OriginalSrb != NULL\n"));
             if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
 
-                KdPrint2((PRINT_PREFIX "AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status));
+                KdPrint3((PRINT_PREFIX "AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status));
                 if (status == SRB_STATUS_SUCCESS) {
                     // Bingo!!
                     AtapiHwInitializeChanger (HwDeviceExtension,
@@ -4690,7 +4857,7 @@ CompleteRequest:
 */
                 srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL);
 
-                KdPrint2((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt));
+                KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt));
 
                 if (srbStatus == SRB_STATUS_PENDING) {
                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
@@ -4708,7 +4875,7 @@ CompleteRequest:
 
                 PSENSE_DATA senseData = (PSENSE_DATA) srb->DataBuffer;
 
-                KdPrint2((PRINT_PREFIX "AtapiInterrupt: ATAPI command status %#x\n", status));
+                KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI command status %#x\n", status));
                 if (status == SRB_STATUS_DATA_OVERRUN) {
                     // Check to see if we at least get mininum number of bytes
                     if ((srb->DataTransferLength - AtaReq->WordsLeft) >
@@ -4749,7 +4916,7 @@ CompleteRequest:
 */
                     srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL);
 
-                    KdPrint2((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan->ExpectingInterrupt));
+                    KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan->ExpectingInterrupt));
 
                     if (srbStatus == SRB_STATUS_PENDING) {
                         KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
@@ -4768,7 +4935,7 @@ CompleteRequest:
             // If we get here, it means AtapiSendCommand() has failed
             // Can't recover.  Pretend the original srb has failed and complete it.
 
-            KdPrint2((PRINT_PREFIX "AtapiInterrupt: Error. complete OriginalSrb\n"));
+            KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. complete OriginalSrb\n"));
 
             if (AtaReq->OriginalSrb) {
                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
@@ -4791,7 +4958,7 @@ CompleteRequest:
         } else if (status == SRB_STATUS_ERROR) {
 
             // Map error to specific SRB status and handle request sense.
-            KdPrint2((PRINT_PREFIX "AtapiInterrupt: Error. Begin mapping...\n"));
+            KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. Begin mapping...\n"));
             status = MapError(deviceExtension,
                               srb);
 
@@ -4800,6 +4967,7 @@ CompleteRequest:
         } else if(!DmaTransfer) {
 
             KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion\n"));
+            // Command complete.
 PIO_wait_busy:
             KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion, wait BUSY\n"));
             // Wait for busy to drop.
@@ -4904,24 +5072,38 @@ PIO_wait_DRQ:
                                       CHECK_INTR_IDLE);
 
         // Sanity check that there is a current request.
-        if (srb != NULL) {
+        if(srb != NULL) {
             // Set status in SRB.
             srb->SrbStatus = (UCHAR)status;
 
             // Check for underflow.
-            if (AtaReq->WordsLeft) {
+            if(AtaReq->WordsLeft) {
 
                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq->WordsLeft));
                 // Subtract out residual words and update if filemark hit,
                 // setmark hit , end of data, end of media...
                 if (!(LunExt->DeviceFlags & DFLAGS_TAPE_DEVICE)) {
                     if (status == SRB_STATUS_DATA_OVERRUN) {
-                        srb->DataTransferLength -= AtaReq->WordsLeft;
+                        srb->DataTransferLength -= AtaReq->WordsLeft*2;
                     } else {
                         srb->DataTransferLength = 0;
                     }
                 } else {
-                    srb->DataTransferLength -= AtaReq->WordsLeft;
+                    srb->DataTransferLength -= AtaReq->WordsLeft*2;
+                }
+            }
+            if(status == SRB_STATUS_SUCCESS) {
+                AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
+                if(!atapiDev &&
+                   AtaReq->WordsTransfered*2 < AtaReq->TransferLength) {
+                    KdPrint2((PRINT_PREFIX "AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
+                         AtaReq->WordsTransfered*2, AtaReq->TransferLength));
+                    AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
+                    AtaReq->ReqState = REQ_STATE_PREPARE_TO_NEXT;
+                    goto reenqueue_req;
+                } else {
+                    KdPrint2((PRINT_PREFIX "   Transfered %x, full size %x\n",
+                        AtaReq->WordsTransfered*2, AtaReq->TransferLength));
                 }
             }
 
@@ -5134,6 +5316,7 @@ Return Value:
 
 --*/
 ULONG
+NTAPI
 IdeSendSmartCommand(
     IN PVOID HwDeviceExtension,
     IN PSCSI_REQUEST_BLOCK Srb
@@ -5247,16 +5430,25 @@ IdeSendSmartCommand(
 #endif //UNIATA_CORE
 
 ULONGLONG
+NTAPI
 UniAtaCalculateLBARegs(
     PHW_LU_EXTENSION     LunExt,
-    ULONG                startingSector
+    ULONG                startingSector,
+    PULONG               max_bcount
     )
 {
     UCHAR                drvSelect,sectorNumber;
     USHORT               cylinder;
     ULONG                tmp;
 
+    (*max_bcount) = 0;
+
     if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
+        if(LunExt->LimitedTransferMode >= ATA_DMA) {
+            if(LunExt->DeviceExtension) {
+                (*max_bcount) = LunExt->DeviceExtension->MaximumDmaTransferLength / DEV_BSIZE;
+            }
+        }
         return startingSector;
     }
     tmp = LunExt->IdentifyData.SectorsPerTrack *
@@ -5266,16 +5458,21 @@ UniAtaCalculateLBARegs(
         cylinder     = 0;
         drvSelect    = 0;
         sectorNumber = 1;
+        (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack;
     } else {
         cylinder =    (USHORT)(startingSector / tmp);
-        drvSelect =   (UCHAR)((startingSector % tmp) / LunExt->IdentifyData.SectorsPerTrack);
+        drvSelect =   (UCHAR)((startingSector % tmp) / LunExt->IdentifyData.SectorsPerTrack); 
         sectorNumber = (UCHAR)(startingSector % LunExt->IdentifyData.SectorsPerTrack) + 1;
+        (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack - sectorNumber + 1;
+        KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
+            cylinder, drvSelect, sectorNumber, (*max_bcount)));
     }
 
     return (ULONG)(sectorNumber&0xff) | (((ULONG)cylinder&0xffff)<<8) | (((ULONG)drvSelect&0xf)<<24);
 } // end UniAtaCalculateLBARegs()
 
 ULONGLONG
+NTAPI
 UniAtaCalculateLBARegsBack(
     PHW_LU_EXTENSION     LunExt,
     ULONGLONG            lba
@@ -5320,6 +5517,7 @@ Return Value:
 
 --*/
 ULONG
+NTAPI
 IdeReadWrite(
     IN PVOID HwDeviceExtension,
     IN PSCSI_REQUEST_BLOCK Srb,
@@ -5334,6 +5532,7 @@ IdeReadWrite(
     ULONG                ldev = GET_LDEV(Srb);
     UCHAR                DeviceNumber = (UCHAR)(ldev & 1);
     ULONG                startingSector;
+    ULONG                max_bcount;
     ULONG                wordCount = 0;
     UCHAR                statusByte,statusByte2;
     UCHAR                cmd;
@@ -5346,23 +5545,53 @@ IdeReadWrite(
     if((CmdAction & CMD_ACTION_PREPARE) &&
        (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
 
+        if(LunExt->opt_ReadOnly && 
+           (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) {
+            if(LunExt->opt_ReadOnly == 1) {
+                KdPrint2((PRINT_PREFIX "Abort WRITE (Soft R/O)\n"));
+                return SRB_STATUS_ERROR;
+            } else {
+                KdPrint2((PRINT_PREFIX "Ignore WRITE (Soft R/O)\n"));
+                return SRB_STATUS_SUCCESS;
+            }
+        }
+
         // Set data buffer pointer and words left.
-        AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
+        AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
 
-        MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
-        //ASSERT(Srb->DataTransferLength == AtaReq->bcount * DEV_BSIZE);
-        AtaReq->WordsLeft = min(Srb->DataTransferLength,
-                                AtaReq->bcount * DEV_BSIZE) / 2;
+        if(AtaReq->WordsTransfered) {
+            AtaReq->DataBuffer = ((PUSHORT)(Srb->DataBuffer)) + AtaReq->WordsTransfered;
+            startingSector = (ULONG)(UniAtaCalculateLBARegsBack(LunExt, AtaReq->lba)) /* latest lba */ + AtaReq->bcount /* previous bcount */;
+            AtaReq->bcount = (AtaReq->TransferLength - AtaReq->WordsTransfered*2 + DEV_BSIZE-1) / DEV_BSIZE;
+            KdPrint2((PRINT_PREFIX "IdeReadWrite (Chained REQ): Starting sector %#x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
+                       startingSector,
+                       AtaReq->TransferLength/2,
+                       AtaReq->WordsTransfered,
+                       AtaReq->bcount));
+        } else {
+            AtaReq->DataBuffer = (PUSHORT)(Srb->DataBuffer);
+            AtaReq->TransferLength = Srb->DataTransferLength;
+            // Set up 1st block.
+            MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA);
+            MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
+            KdPrint2((PRINT_PREFIX "IdeReadWrite (Orig REQ): Starting sector %#x, OrigWordsRequested %#x, DevSize %#x\n",
+                       startingSector,
+                       AtaReq->TransferLength/2,
+                       AtaReq->bcount));
+        }
+        lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount);
 
-        // Set up 1st block.
-        MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA);
+        if(max_bcount) {
+            AtaReq->bcount = min(AtaReq->bcount, max_bcount);
+        }
+        AtaReq->WordsLeft = min(AtaReq->TransferLength - AtaReq->WordsTransfered*2,
+                                AtaReq->bcount * DEV_BSIZE) / 2;
 
         KdPrint2((PRINT_PREFIX "IdeReadWrite (REQ): Starting sector is %#x, Number of WORDS %#x, DevSize %#x\n",
                    startingSector,
                    AtaReq->WordsLeft,
                    AtaReq->bcount));
 
-        lba = UniAtaCalculateLBARegs(LunExt, startingSector);
         AtaReq->lba = lba;
 
         // assume best case here
@@ -5372,7 +5601,7 @@ IdeReadWrite(
             // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
             if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
                           (PUCHAR)(AtaReq->DataBuffer),
-                          ((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1)))) {
+                          AtaReq->bcount * DEV_BSIZE)) {
                 use_dma = FALSE;
             }
         }
@@ -5416,7 +5645,7 @@ IdeReadWrite(
 
         // Prepare write command.
         if (use_dma) {
-            wordCount = Srb->DataTransferLength/2;
+            wordCount = AtaReq->bcount*DEV_BSIZE/2;
             cmd = IDE_COMMAND_WRITE_DMA;
         } else
         if (LunExt->MaximumBlockXfer) {
@@ -5448,10 +5677,12 @@ IdeReadWrite(
         use_dma) {
         statusByte2 = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
                      cmd, lba,
-                     (UCHAR)((Srb->DataTransferLength + DEV_BSIZE-1) / DEV_BSIZE),
+                     (USHORT)(AtaReq->bcount),
 //                     (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
                      0, ATA_IMMEDIATE);
-        GetStatus(chan, statusByte2);
+        if(statusByte2 != 0xff) {
+            GetStatus(chan, statusByte2);
+        }
         if(statusByte2 & IDE_STATUS_ERROR) {
             statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
             KdPrint2((PRINT_PREFIX "IdeReadWrite: status %#x, error %#x\n", statusByte2, statusByte));
@@ -5465,15 +5696,22 @@ IdeReadWrite(
 
     statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
                  cmd, lba,
-                 (UCHAR)((Srb->DataTransferLength + DEV_BSIZE-1) / DEV_BSIZE),
+                 (USHORT)(AtaReq->bcount),
 //                 (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
                  0, ATA_WAIT_INTR);
 
-    if (!(statusByte & IDE_STATUS_DRQ)) {
+    if (!(statusByte & IDE_STATUS_DRQ) ||
+        statusByte == 0xff) {
 
-        KdPrint2((PRINT_PREFIX
-                   "IdeReadWrite: DRQ never asserted (%#x)\n",
-                   statusByte));
+        if(statusByte == 0xff) {
+            KdPrint2((PRINT_PREFIX 
+                       "IdeReadWrite: error sending command (%#x)\n",
+                       statusByte));
+        } else {
+            KdPrint2((PRINT_PREFIX 
+                       "IdeReadWrite: DRQ never asserted (%#x)\n",
+                       statusByte));
+        }
 
         AtaReq->WordsLeft = 0;
 
@@ -5485,7 +5723,7 @@ IdeReadWrite(
         // Clear current SRB.
         UniataRemoveRequest(chan, Srb);
 
-        return SRB_STATUS_TIMEOUT;
+        return (statusByte == 0xff) ? SRB_STATUS_ERROR : SRB_STATUS_TIMEOUT;
     }
 
     chan->ExpectingInterrupt = TRUE;
@@ -5538,6 +5776,7 @@ Return Value:
 
 --*/
 ULONG
+NTAPI
 IdeVerify(
     IN PVOID HwDeviceExtension,
     IN PSCSI_REQUEST_BLOCK Srb
@@ -5551,6 +5790,7 @@ IdeVerify(
     ULONG                ldev = GET_LDEV(Srb);
     UCHAR                statusByte;
     ULONG                startingSector;
+    ULONG                max_bcount;
     ULONG                sectors;
     ULONG                endSector;
     USHORT               sectorCount;
@@ -5564,7 +5804,7 @@ IdeVerify(
                   LunExt->IdentifyData.NumberOfCylinders;
     }
 
-    KdPrint2((PRINT_PREFIX
+    KdPrint2((PRINT_PREFIX 
                 "IdeVerify: Total sectors %#x\n",
                 sectors));
 
@@ -5572,21 +5812,21 @@ IdeVerify(
     MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA);
     MOV_DW_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
 
-    KdPrint2((PRINT_PREFIX
+    KdPrint2((PRINT_PREFIX 
                 "IdeVerify: Starting sector %#x. Number of blocks %#x\n",
                 startingSector,
                 sectorCount));
 
     endSector = startingSector + sectorCount;
 
-    KdPrint2((PRINT_PREFIX
+    KdPrint2((PRINT_PREFIX 
                 "IdeVerify: Ending sector %#x\n",
                 endSector));
 
     if (endSector > sectors) {
 
         // Too big, round down.
-        KdPrint2((PRINT_PREFIX
+        KdPrint2((PRINT_PREFIX 
                     "IdeVerify: Truncating request to %#x blocks\n",
                     sectors - startingSector - 1));
 
@@ -5608,7 +5848,7 @@ IdeVerify(
     InterlockedExchange(&(chan->CheckIntr),
                                   CHECK_INTR_IDLE);
 
-    lba = UniAtaCalculateLBARegs(LunExt, startingSector);
+    lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount);
 
     statusByte = AtaCommand48(deviceExtension, ldev & 0x01, GET_CHANNEL(Srb),
                  IDE_COMMAND_VERIFY, lba,
@@ -5638,6 +5878,7 @@ Return Value:
 
 --*/
 ULONG
+NTAPI
 AtapiSendCommand(
     IN PVOID HwDeviceExtension,
     IN PSCSI_REQUEST_BLOCK Srb,
@@ -5654,8 +5895,9 @@ AtapiSendCommand(
     UCHAR statusByte,byteCountLow,byteCountHigh;
     BOOLEAN use_dma = FALSE;
     BOOLEAN dma_reinited = FALSE;
+    BOOLEAN retried = FALSE;
 
-    KdPrint2((PRINT_PREFIX "AtapiSendCommand: req state %#x\n", AtaReq->ReqState));
+    KdPrint3((PRINT_PREFIX "AtapiSendCommand: req state %#x, Action %x\n", AtaReq->ReqState, CmdAction));
     if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
         AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER;
 
@@ -5863,7 +6105,7 @@ call_dma_setup:
         KdPrint2((PRINT_PREFIX "AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
         return SRB_STATUS_PENDING;
     }
-    KdPrint2((PRINT_PREFIX "AtapiSendCommand: use_dma=%d\n", use_dma));
+    KdPrint3((PRINT_PREFIX "AtapiSendCommand: use_dma=%d\n", use_dma));
     if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
         KdPrint2((PRINT_PREFIX "  REQ_FLAG_DMA_OPERATION\n"));
     }
@@ -5913,7 +6155,7 @@ call_dma_setup:
 
         ULONG srbStatus;
 
-        KdPrint2((PRINT_PREFIX "AtapiSendCommand: BuildMechanismStatusSrb()\n"));
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: BuildMechanismStatusSrb()\n"));
         // Set this flag now. If the device hangs on the mech. status
         // command, we will not have the chance to set it.
         deviceExtension->lun[ldev].DeviceFlags |= DFLAGS_CHANGER_INITED;
@@ -5924,7 +6166,7 @@ call_dma_setup:
                                         HwDeviceExtension,
                                         Srb);
 
-        KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiSendCommand recursive\n"));
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: AtapiSendCommand recursive\n"));
         srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL);
         if (srbStatus == SRB_STATUS_PENDING) {
             KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
@@ -5940,51 +6182,53 @@ call_dma_setup:
     }
 #endif //UNIATA_CORE
 
-    KdPrint2((PRINT_PREFIX "AtapiSendCommand: Command %#x to TargetId %d lun %d\n",
+    KdPrint3((PRINT_PREFIX "AtapiSendCommand: Command %#x to TargetId %d lun %d\n",
                Srb->Cdb[0], Srb->TargetId, Srb->Lun));
-
+    
     // Make sure command is to ATAPI device.
     flags = deviceExtension->lun[ldev].DeviceFlags;
-    if (flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
-        if ((Srb->Lun) > (deviceExtension->lun[ldev].DiscsPresent - 1)) {
+    if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
+        if((Srb->Lun) > (deviceExtension->lun[ldev].DiscsPresent - 1)) {
 
             // Indicate no device found at this address.
             AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
             return SRB_STATUS_SELECTION_TIMEOUT;
         }
-    } else if (Srb->Lun > 0) {
+    } else if(Srb->Lun > 0) {
         AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
         return SRB_STATUS_SELECTION_TIMEOUT;
     }
 
-    if (!(flags & DFLAGS_ATAPI_DEVICE)) {
+    if(!(flags & DFLAGS_ATAPI_DEVICE)) {
         AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
         return SRB_STATUS_SELECTION_TIMEOUT;
     }
-
+retry:
     // Select device 0 or 1.
     SelectDrive(chan, ldev & 0x1);
 
     // Verify that controller is ready for next command.
     GetStatus(chan, statusByte);
-    KdPrint2((PRINT_PREFIX "AtapiSendCommand: Entered with status %#x\n", statusByte));
+    KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status %#x\n", statusByte));
 
-    if (statusByte == 0xff) {
+    if(statusByte == 0xff) {
         KdPrint2((PRINT_PREFIX "AtapiSendCommand: bad status 0xff on entry\n"));
         goto make_reset;
     }
-    if (statusByte & IDE_STATUS_BUSY) {
+    if(statusByte & IDE_STATUS_BUSY) {
         if(statusByte & IDE_STATUS_DSC) {
             KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte));
+        } else {
+            KdPrint2((PRINT_PREFIX "AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte));
+            // We have to make reset here, since we are expecting device to be available
+            //return SRB_STATUS_BUSY; // this cause queue freeze
+            goto make_reset;
         }
-        KdPrint2((PRINT_PREFIX "AtapiSendCommand: Device busy (%#x)\n", statusByte));
-        AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
-        return SRB_STATUS_BUSY;
     }
-    if (statusByte & IDE_STATUS_ERROR) {
+    if(statusByte & IDE_STATUS_ERROR) {
         if (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
 
-            KdPrint2((PRINT_PREFIX "AtapiSendCommand: Error on entry: (%#x)\n", statusByte));
+            KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on entry: (%#x)\n", statusByte));
             // Read the error reg. to clear it and fail this request.
             AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
             return MapError(deviceExtension, Srb);
@@ -5994,7 +6238,7 @@ call_dma_setup:
     }
     // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
     // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
-    if ((!(statusByte & IDE_STATUS_DSC)) &&
+    if((!(statusByte & IDE_STATUS_DSC)) &&
           (flags & (DFLAGS_TAPE_DEVICE | DFLAGS_ATAPI_DEVICE)) && chan->RDP) {
 
         AtapiStallExecution(200);
@@ -6003,22 +6247,22 @@ call_dma_setup:
         return SRB_STATUS_PENDING;
     }
 
-    if (IS_RDP(Srb->Cdb[0])) {
+    if(IS_RDP(Srb->Cdb[0])) {
         chan->RDP = TRUE;
         KdPrint2((PRINT_PREFIX "AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb->Cdb[0]));
     } else {
         chan->RDP = FALSE;
     }
-    if (statusByte & IDE_STATUS_DRQ) {
+    if(statusByte & IDE_STATUS_DRQ) {
 
-        KdPrint2((PRINT_PREFIX "AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
                     statusByte));
         // Try to drain the data that one preliminary device thinks that it has
         // to transfer. Hopefully this random assertion of DRQ will not be present
         // in production devices.
         for (i = 0; i < 0x10000; i++) {
             GetStatus(chan, statusByte);
-            if (statusByte & IDE_STATUS_DRQ) {
+            if(statusByte & IDE_STATUS_DRQ) {
                 AtapiReadPort2(chan, IDX_IO1_i_Data);
             } else {
                 break;
@@ -6027,7 +6271,7 @@ call_dma_setup:
 
         if (i == 0x10000) {
 make_reset:
-            KdPrint2((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte));
+            KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte));
 
             AtapiDisableInterrupts(deviceExtension, lChannel);
 
@@ -6035,8 +6279,11 @@ make_reset:
 
             KdPrint2((PRINT_PREFIX "AtapiSendCommand: Issued soft reset to Atapi device. \n"));
             // Re-initialize Atapi device.
+            CheckDevice(HwDeviceExtension, GET_CHANNEL(Srb), ldev & 1, TRUE);
+/*
             IssueIdentify(HwDeviceExtension, ldev & 1, GET_CHANNEL(Srb),
                           IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
+*/
             // Inform the port driver that the bus has been reset.
             ScsiPortNotification(ResetDetected, HwDeviceExtension, 0);
             // Clean up device extension fields that AtapiStartIo won't.
@@ -6046,17 +6293,25 @@ make_reset:
                                           CHECK_INTR_IDLE);
 
             AtapiEnableInterrupts(deviceExtension, lChannel);
-
+/*
             AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
             return SRB_STATUS_BUS_RESET;
-
+*/
+            if(!retried) {
+                KdPrint3((PRINT_PREFIX "AtapiSendCommand: retry after reset.\n"));
+                retried = TRUE;
+                goto retry;
+            }
+            KdPrint3((PRINT_PREFIX "AtapiSendCommand: selection timeout.\n"));
+            AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
+            return SRB_STATUS_SELECTION_TIMEOUT;
         }
     }
 
-    if (flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
+    if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
         // As the cdrom driver sets the LUN field in the cdb, it must be removed.
         Srb->Cdb[1] &= ~0xE0;
-        if ((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY) && (flags & DFLAGS_SANYO_ATAPI_CHANGER)) {
+        if((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY) && (flags & DFLAGS_SANYO_ATAPI_CHANGER)) {
             // Torisan changer. TUR's are overloaded to be platter switches.
             Srb->Cdb[7] = Srb->Lun;
         }
@@ -6071,7 +6326,7 @@ make_reset:
     }
 
     statusByte = WaitOnBusy(chan);
-    KdPrint2((PRINT_PREFIX "AtapiSendCommand: Entry Status (%#x)\n",
+    KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entry Status (%#x)\n",
                statusByte));
 
     AtapiWritePort1(chan, IDX_IO1_o_Feature,
@@ -6092,7 +6347,7 @@ make_reset:
 
         // This device interrupts when ready to receive the packet.
 
-        KdPrint2((PRINT_PREFIX "AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
                    statusByte));
 
         chan->ExpectingInterrupt = TRUE;
@@ -6103,7 +6358,7 @@ make_reset:
         // Write ATAPI packet command.
         AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
 
-        KdPrint2((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING\n"));
+        KdPrint3((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
         return SRB_STATUS_PENDING;
 
     } else {
@@ -6118,7 +6373,7 @@ make_reset:
         InterlockedExchange(&(chan->CheckIntr),
                                       CHECK_INTR_IDLE);
 
-        AtapiDisableInterrupts(deviceExtension, lChannel);
+        //AtapiDisableInterrupts(deviceExtension, lChannel);
 
         // Write ATAPI packet command.
         AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
@@ -6133,14 +6388,14 @@ make_reset:
         if (!(statusByte & IDE_STATUS_DRQ)) {
 
             AtapiEnableInterrupts(deviceExtension, lChannel);
-            KdPrint2((PRINT_PREFIX "AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte));
+            KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte));
             AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
             return SRB_STATUS_ERROR;
         }
     }
 
     GetStatus(chan, statusByte);
-    KdPrint2((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte));
+    KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte));
 
     // Send CDB to device.
     statusByte = WaitOnBaseBusy(chan);
@@ -6153,7 +6408,7 @@ make_reset:
 
     GetBaseStatus(chan, statusByte);
 
-    AtapiEnableInterrupts(deviceExtension, lChannel);
+    //AtapiEnableInterrupts(deviceExtension, lChannel);
 
     WriteBuffer(chan,
                 (PUSHORT)Srb->Cdb,
@@ -6164,7 +6419,7 @@ make_reset:
         AtapiDmaStart(HwDeviceExtension, ldev & 1, lChannel, Srb);
     }
 
-    KdPrint2((PRINT_PREFIX "AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan->ExpectingInterrupt));
+    KdPrint3((PRINT_PREFIX "AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan->ExpectingInterrupt));
 
     KdPrint2((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
     return SRB_STATUS_PENDING;
@@ -6196,6 +6451,7 @@ ULONG check_point = 0;
 #endif
 
 ULONG
+NTAPI
 IdeSendCommand(
     IN PVOID HwDeviceExtension,
     IN PSCSI_REQUEST_BLOCK Srb,
@@ -6259,7 +6515,9 @@ IdeSendCommand(
 
     if(CmdAction == CMD_ACTION_PREPARE) {
         switch (Srb->Cdb[0]) {
-        //case SCSIOP_INQUIRY: // now it requires device access
+#ifdef NAVO_TEST
+        case SCSIOP_INQUIRY: // now it requires device access
+#endif //NAVO_TEST
         case SCSIOP_READ_CAPACITY:
         case SCSIOP_READ:
         case SCSIOP_WRITE:
@@ -6279,7 +6537,7 @@ IdeSendCommand(
     switch (Srb->Cdb[0]) {
     case SCSIOP_INQUIRY:
 
-        KdPrint2((PRINT_PREFIX
+        KdPrint2((PRINT_PREFIX 
                    "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
                    Srb->PathId, Srb->Lun, Srb->TargetId));
         // Filter out all TIDs but 0 and 1 since this is an IDE interface
@@ -6308,6 +6566,7 @@ IdeSendCommand(
                     KdPrint2((PRINT_PREFIX
                                "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
                     // Indicate no device found at this address.
+#ifndef NAVO_TEST
                     status = SRB_STATUS_SELECTION_TIMEOUT;
                     break;
                 }
@@ -6316,7 +6575,8 @@ IdeSendCommand(
                     KdPrint2((PRINT_PREFIX
                                "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
                     // Indicate no device found at this address.
-                    deviceExtension->lun[ldev].DeviceFlags &= ~DFLAGS_DEVICE_PRESENT;
+                    UniataForgetDevice(&(deviceExtension->lun[ldev]));
+#endif //NAVO_TEST
                     status = SRB_STATUS_SELECTION_TIMEOUT;
                     break;
                 }
@@ -6366,7 +6626,7 @@ IdeSendCommand(
 
     case SCSIOP_MODE_SENSE:
 
-        KdPrint2((PRINT_PREFIX
+        KdPrint2((PRINT_PREFIX 
                    "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
                    Srb->PathId, Srb->Lun, Srb->TargetId));
         // This is used to determine if the media is write-protected.
@@ -6507,7 +6767,8 @@ IdeSendCommand(
     case SCSIOP_WRITE:
 
         KdPrint2((PRINT_PREFIX
-                   "IdeSendCommand: SCSIOP_READ/SCSIOP_WRITE PATH:LUN:TID = %#x:%#x:%#x\n",
+                   "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
+                   (Srb->Cdb[0] == SCSIOP_WRITE) ? "WRITE" : "READ",
                    Srb->PathId, Srb->Lun, Srb->TargetId));
         AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
         AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE) ? REQ_FLAG_WRITE : REQ_FLAG_READ;
@@ -6593,7 +6854,7 @@ IdeSendCommand(
         regs->bDriveHeadReg &= 0x0f;
         regs->bDriveHeadReg |= (UCHAR) (((Srb->TargetId & 0x1) << 4) | 0xA0);
 
-        if((regs->bReserved & 1) == 0) {      // execute ATA command
+        if((regs->bOpFlags & 1) == 0) {      // execute ATA command
 
             KdPrint2((PRINT_PREFIX
                        "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
@@ -6602,7 +6863,7 @@ IdeSendCommand(
 
             AtapiDisableInterrupts(deviceExtension, lChannel);
 
-            if(AtaCommandFlags[regs->bCommandReg] & ATA_CMD_FLAG_DMA) {
+            if((AtaCommandFlags[regs->bCommandReg] & ATA_CMD_FLAG_DMA) || (regs->bOpFlags & UNIATA_SPTI_EX_USE_DMA)) {
                 if((chan->lun[Srb->TargetId & 0x1]->LimitedTransferMode >= ATA_DMA)) {
                     use_dma = TRUE;
                     // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
@@ -6617,7 +6878,7 @@ IdeSendCommand(
             AtapiWritePort1(chan, IDX_IO1_o_DriveSelect,  regs->bDriveHeadReg);
             AtapiStallExecution(10);
 
-            if((regs->bReserved & ATA_FLAGS_48BIT_COMMAND) == 0) {      // execute ATA command
+            if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) {      // execute ATA command
                 AtapiWritePort1(chan, IDX_IO1_o_Feature,      regs->bFeaturesReg);
                 AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   regs->bSectorCountReg);
                 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  regs->bSectorNumberReg);
@@ -6647,7 +6908,7 @@ IdeSendCommand(
 
             ScsiPortStallExecution(1);                  // wait for busy to be set
 
-            if(regs->bReserved & UNIATA_SPTI_EX_SPEC_TO) {
+            if(regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) {
                 to_lim = Srb->TimeOutValue;
             } else {
                 if(Srb->TimeOutValue <= 2) {
@@ -6667,7 +6928,7 @@ IdeSendCommand(
                 }
             }
             if(i >= to_lim) {
-                //if(regs->bReserved & UNIATA_SPTI_EX_FREEZE_TO) {
+                //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
                 //}
                 AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_NONE);
                 goto passthrough_err;
@@ -6725,7 +6986,7 @@ passthrough_err:
 
             regs->bDriveHeadReg    = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect);
 
-            if((regs->bReserved & ATA_FLAGS_48BIT_COMMAND) == 0) {      // execute ATA command
+            if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) {      // execute ATA command
                 regs->bFeaturesReg     = AtapiReadPort1(chan, IDX_IO1_i_Error);
                 regs->bSectorCountReg  = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
                 regs->bSectorNumberReg = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
@@ -6785,6 +7046,7 @@ Arguments:
 
 --*/
 VOID
+NTAPI
 IdeMediaStatus(
     BOOLEAN EnableMSN,
     IN PVOID HwDeviceExtension,
@@ -6859,6 +7121,7 @@ Return Value:
 
 --*/
 ULONG
+NTAPI
 IdeBuildSenseBuffer(
     IN PVOID HwDeviceExtension,
     IN PSCSI_REQUEST_BLOCK Srb
@@ -6911,6 +7174,7 @@ IdeBuildSenseBuffer(
 }// End of IdeBuildSenseBuffer
 
 VOID
+NTAPI
 UniataUserDeviceReset(
     PHW_DEVICE_EXTENSION deviceExtension,
     PHW_LU_EXTENSION LunExt,
@@ -6925,6 +7189,8 @@ UniataUserDeviceReset(
     } else {
         KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
         AtapiResetController__(deviceExtension, PathId, RESET_COMPLETE_NONE);
+        deviceExtension->chan[PathId].lun[0]->DeviceFlags |= DFLAGS_REINIT_DMA;
+        deviceExtension->chan[PathId].lun[1]->DeviceFlags |= DFLAGS_REINIT_DMA;
     }
     LunExt->DeviceFlags |= DFLAGS_REINIT_DMA;  // force PIO/DMA reinit
     AtapiEnableInterrupts(deviceExtension, PathId);
@@ -6932,6 +7198,7 @@ UniataUserDeviceReset(
 } // end UniataUserDeviceReset()
 
 BOOLEAN
+NTAPI
 UniataNeedQueueing(
     PHW_DEVICE_EXTENSION deviceExtension,
     PHW_CHANNEL          chan,
@@ -6940,6 +7207,7 @@ UniataNeedQueueing(
 {
     BOOLEAN PostReq = FALSE;
     if(TopLevel) {
+        KdPrint3((PRINT_PREFIX "UniataNeedQueueing: TopLevel, qd=%x\n", chan->queue_depth));
         if(chan->queue_depth > 0) {
 #if 0
             if(atapiDev &&
@@ -6959,6 +7227,8 @@ UniataNeedQueueing(
         if(deviceExtension->simplexOnly && deviceExtension->queue_depth > 0) {
             PostReq = TRUE;
         }
+    } else {
+        KdPrint3((PRINT_PREFIX "UniataNeedQueueing: qd=%x\n", chan->queue_depth));
     }
     return PostReq;
 } // end UniataNeedQueueing()
@@ -6991,6 +7261,7 @@ AtapiStartIo(
 } // end AtapiStartIo()
 
 BOOLEAN
+NTAPI
 AtapiStartIo__(
     IN PVOID HwDeviceExtension,
     IN PSCSI_REQUEST_BLOCK Srb,
@@ -7009,7 +7280,9 @@ AtapiStartIo__(
     PSCSI_REQUEST_BLOCK tmpSrb;
     BOOLEAN PostReq = FALSE;
     BOOLEAN atapiDev;
+    BOOLEAN commPort = FALSE;
 
+    // deviceExtension->Isr2DevObj must always be NULL for non-PCI
     if(deviceExtension->Isr2DevObj && !BMList[deviceExtension->DevIndex].Isr2Enable) {
         KdPrint2((PRINT_PREFIX "Isr2Enable -> 1\n"));
         BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
@@ -7040,6 +7313,33 @@ AtapiStartIo__(
                    Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId));
         KdPrint2((PRINT_PREFIX "   VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
 
+        if(lChannel == deviceExtension->NumberChannels &&
+           !Srb->Lun && !Srb->TargetId &&
+           ((Srb->Function == SRB_FUNCTION_IO_CONTROL) ||
+            (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI && Srb->Cdb[0] == SCSIOP_INQUIRY))
+           ) {
+            KdPrint2((PRINT_PREFIX 
+                       "AtapiStartIo: Communication port\n"));
+            if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
+
+                PINQUIRYDATA    inquiryData  = (PINQUIRYDATA)(Srb->DataBuffer);
+
+                KdPrint2((PRINT_PREFIX 
+                           "  INQUIRY\n"));
+                // Zero INQUIRY data structure.
+                RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength);
+
+                inquiryData->DeviceType = COMMUNICATION_DEVICE;
+
+                // Fill in vendor identification fields.
+                RtlCopyMemory(&inquiryData->VendorId, &uniata_comm_name, 28);
+
+                status = SRB_STATUS_SUCCESS;
+                goto complete_req;
+            }
+            commPort = TRUE;
+            /* Pass IOCTL request down */
+        } else
         if(GET_CDEV(Srb) >= 2 ||
            ldev >= deviceExtension->NumberChannels*2 ||
            lChannel >= deviceExtension->NumberChannels ||
@@ -7051,7 +7351,7 @@ AtapiStartIo__(
 
 reject_srb:
             //if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) {
-                KdPrint2((PRINT_PREFIX
+                KdPrint3((PRINT_PREFIX
                            "AtapiStartIo: SRB rejected\n"));
                 // Indicate no device found at this address.
                 KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
@@ -7063,7 +7363,8 @@ reject_srb:
         atapiDev = (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
 
 #ifdef _DEBUG
-        if(!(chan->lun[ldev & 1])) {
+        if(!commPort && !(chan->lun[ldev & 1])) {
+#if 0
             PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
                 deviceExtension,
                 chan, ldev & 1,
@@ -7072,6 +7373,7 @@ reject_srb:
                 lChannel, ldev, GET_CDEV(Srb), deviceExtension->chan[0].lun[0]);
             PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
                        Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId);
+#endif //0
 /*
             int i;
             for(i=0; i<1000; i++) {
@@ -7081,7 +7383,6 @@ reject_srb:
             goto reject_srb;
         }
 #endif //_DEBUG
-        //ASSERT(chan->lun[ldev & 1]);
 
         // Determine which function.
         switch (Srb->Function) {
@@ -7114,10 +7415,10 @@ reject_srb:
                     g_foo += a;
                 }
             } __except(EXCEPTION_EXECUTE_HANDLER) {
-                KdPrint2((PRINT_PREFIX
+                KdPrint3((PRINT_PREFIX 
                            "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
                 // Indicate no device found at this address.
-                KdPrint2((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
+                KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
                 status = SRB_STATUS_ERROR;
                 KdPrint2((PRINT_PREFIX "  *** Exception...\n"));
                 ASSERT(FALSE);
@@ -7128,10 +7429,10 @@ reject_srb:
 
             if(PostReq) {
 
-                KdPrint2((PRINT_PREFIX "Non-empty queue\n"));
+                KdPrint3((PRINT_PREFIX "Non-empty queue\n"));
                 if (atapiDev &&
                     (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) {
-                    KdPrint2((PRINT_PREFIX "Try ATAPI prepare\n"));
+                    KdPrint3((PRINT_PREFIX "Try ATAPI prepare\n"));
 
                     status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE);
                 } else {
@@ -7168,6 +7469,7 @@ reject_srb:
                     //ASSERT(!AtaReq->Flags);
                 }
 
+#ifndef NAVO_TEST
                 if(!(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
                     if(Srb->Cdb[0] == SCSIOP_INQUIRY) {
                         if(UniataAnybodyHome(deviceExtension, chan->lChannel, ldev & 1)) {
@@ -7185,10 +7487,11 @@ reject_srb:
                         goto reject_srb;
                     }
                 }
+#endif //NAVO_TEST
 
                 if(atapiDev &&
                    (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) {
-                    KdPrint2((PRINT_PREFIX "Try ATAPI send\n"));
+                    KdPrint3((PRINT_PREFIX "Try ATAPI send\n"));
                     status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
                 } else {
                     KdPrint2((PRINT_PREFIX "Try IDE send\n"));
@@ -7238,7 +7541,7 @@ reject_srb:
                 if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_CURRENT)) {
                       KdPrint2((PRINT_PREFIX "AtapiStartIo: Abort command failed\n"));
                     // Log reset failure.
-                    KdPrint2((PRINT_PREFIX
+                    KdPrint3((PRINT_PREFIX 
                                 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
                                       HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
                                 ));
@@ -7293,7 +7596,7 @@ reject_srb:
             break;
 
         case SRB_FUNCTION_RESET_BUS:
-
+do_bus_reset:
             // Reset Atapi and SCSI bus.
 
             // Note: reset is immediate command, it cannot be queued since it is usually used to
@@ -7302,7 +7605,7 @@ reject_srb:
             if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_ALL)) {
                   KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus failed\n"));
                 // Log reset failure.
-                KdPrint2((PRINT_PREFIX
+                KdPrint3((PRINT_PREFIX 
                             "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
                                   HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
                             ));
@@ -7435,6 +7738,15 @@ reject_srb:
 
                     deviceNumber = versionParameters->bIDEDeviceMap;
 
+                    if(commPort) {
+                        KdPrint2((PRINT_PREFIX 
+                                   "AtapiStartIo: SCSIDISK IOCTL for commPort -> EXECUTE_SCSI rejected (2)\n"));
+                        // Indicate no device found at this address.
+                        KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
+                        status = SRB_STATUS_SELECTION_TIMEOUT;
+                        break;
+                    }
+
                     if (!(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT) ||
                         atapiDev) {
 
@@ -7539,6 +7851,15 @@ reject_srb:
                 case  IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
                 case  IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
 
+                    if(commPort) {
+                        KdPrint2((PRINT_PREFIX 
+                                   "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
+                        // Indicate no device found at this address.
+                        KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
+                        status = SRB_STATUS_SELECTION_TIMEOUT;
+                        break;
+                    }
+
                     PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
 
                     if(PostReq || TopLevel) {
@@ -7571,14 +7892,14 @@ reject_srb:
 
                 PUNIATA_CTL AtaCtl = (PUNIATA_CTL)(Srb->DataBuffer);
                 ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
-                PHW_LU_EXTENSION LunExt = &(deviceExtension->lun[ldev]);
+                PHW_LU_EXTENSION LunExt;
                 BOOLEAN bad_ldev;
                 ULONG i;
                 //chan = &(deviceExtension->chan[lChannel]);
 
                 if(AtaCtl->addr.Lun ||
                    ldev >= deviceExtension->NumberChannels*2 ||
-                   AtaCtl->addr.PathId > deviceExtension->NumberChannels) {
+                   AtaCtl->addr.PathId >= deviceExtension->NumberChannels) {
 
                     bad_ldev = TRUE;
                     LunExt = NULL;
@@ -7586,6 +7907,8 @@ reject_srb:
                 } else {
                     bad_ldev = FALSE;
                     LunExt = &(deviceExtension->lun[ldev]);
+                    lChannel = AtaCtl->addr.PathId;
+                    chan = &(deviceExtension->chan[lChannel]);
                 }
 
                 KdPrint2((PRINT_PREFIX "AtapiStartIo: -UNIATA- %#x, ldev %#x\n", AtaCtl->hdr.ControlCode, ldev));
@@ -7593,13 +7916,32 @@ reject_srb:
                 /* check for valid LUN */
                 switch (AtaCtl->hdr.ControlCode) {
                 case  IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
+                case  IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE:
+                    if(bad_ldev &&
+                       (AtaCtl->addr.PathId >= deviceExtension->NumberChannels ||
+                        AtaCtl->addr.TargetId != 0xff ||
+                        AtaCtl->addr.Lun != 0
+                        )) {
+                        if(AtaCtl->hdr.ControlCode == IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES &&
+                           ldev < deviceExtension->NumberChannels*2) { // AtaCtl->addr.TargetId != 0xff
+                            LunExt = &(deviceExtension->lun[ldev]);
+                            // OK
+                        } else {
+                            goto handle_bad_ldev;
+                        }
+                    }
+                    // this would be BUS reset
+                    lChannel = AtaCtl->addr.PathId;
+                    chan = &(deviceExtension->chan[lChannel]);
+                    break;
                 case  IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE:
                 case  IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
                 case  IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE:
                 case  IOCTL_SCSI_MINIPORT_UNIATA_RESETBB:
-                case  IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE:
+//                case  IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
                     if(bad_ldev) {
-                        KdPrint2((PRINT_PREFIX
+handle_bad_ldev:
+                        KdPrint2((PRINT_PREFIX 
                                    "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
                         // Indicate no device found at this address.
                         goto reject_srb;
@@ -7635,8 +7977,8 @@ uata_ctl_queue:
 
                         KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
                         goto complete_req;
-                     }
-                }
+                    } 
+                } // end switch (AtaCtl->hdr.ControlCode)
 
                 /* process request */
                 switch (AtaCtl->hdr.ControlCode) {
@@ -7644,11 +7986,22 @@ uata_ctl_queue:
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: rescan bus\n"));
 
+                    if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) {
+                        KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n"));
+                        if(AtaCtl->addr.TargetId != 0xff) {
+                            deviceExtension->lun[ldev].DeviceFlags &= ~DFLAGS_HIDDEN;
+                        } else {
+                        }
+                    }
+
                     for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
                         AtapiStallExecution(1000 * 1000);
                     }
 
-                    FindDevices(HwDeviceExtension, FALSE, AtaCtl->addr.PathId);
+                    FindDevices(HwDeviceExtension,
+                                ((AtaCtl->addr.TargetId == 0xff) && (AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE))
+                                     ? UNIATA_FIND_DEV_UNHIDE : 0,
+                                AtaCtl->addr.PathId);
                     status = SRB_STATUS_SUCCESS;
 
                     break;
@@ -7658,6 +8011,10 @@ uata_ctl_queue:
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: remove %#x:%#x\n", AtaCtl->addr.PathId, AtaCtl->addr.TargetId));
 
                     deviceExtension->lun[ldev].DeviceFlags = 0;
+                    if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) {
+                        KdPrint2((PRINT_PREFIX "AtapiStartIo: hide from further detection\n"));
+                        deviceExtension->lun[ldev].DeviceFlags |= DFLAGS_HIDDEN;
+                    }
 
                     for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
                         AtapiStallExecution(1000 * 1000);
@@ -7670,19 +8027,19 @@ uata_ctl_queue:
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Set transfer mode\n"));
 
-                    if(AtaCtl->SetMode.OrigMode != (ULONG)-1) {
+                    if(AtaCtl->SetMode.OrigMode != IOMODE_NOT_SPECIFIED) {
                         LunExt->OrigTransferMode = (UCHAR)(AtaCtl->SetMode.OrigMode);
                     }
-                    if(AtaCtl->SetMode.MaxMode != (ULONG)-1) {
+                    if(AtaCtl->SetMode.MaxMode != IOMODE_NOT_SPECIFIED) {
                         LunExt->LimitedTransferMode = (UCHAR)(AtaCtl->SetMode.MaxMode);
-                        if(LunExt->LimitedTransferMode >
+                        if(LunExt->LimitedTransferMode > 
                            LunExt->OrigTransferMode) {
                             // check for incorrect value
                             LunExt->LimitedTransferMode =
                                 LunExt->OrigTransferMode;
                         }
                     }
-                    LunExt->TransferMode = LunExt->OrigTransferMode;
+                    LunExt->TransferMode = min(LunExt->LimitedTransferMode, LunExt->OrigTransferMode);
 
                     LunExt->DeviceFlags |= DFLAGS_REINIT_DMA;  // force PIO/DMA reinit
                     if(AtaCtl->SetMode.ApplyImmediately) {
@@ -7735,7 +8092,10 @@ uata_ctl_queue:
                     AtaCtl->AdapterInfo.InterruptMode = deviceExtension->InterruptMode;
                     AtaCtl->AdapterInfo.BusInterruptVector = deviceExtension->BusInterruptVector;
                     AtaCtl->AdapterInfo.NumberChannels = deviceExtension->NumberChannels;
-
+                    AtaCtl->AdapterInfo.AdapterInterfaceType = deviceExtension->AdapterInterfaceType;
+                    if(deviceExtension->FullDevName) {
+                        strncpy(AtaCtl->AdapterInfo.DeviceName, deviceExtension->FullDevName, 64);
+                    }
                     AtaCtl->AdapterInfo.ChanInfoValid = FALSE;
 
                     RtlZeroMemory(&AtaCtl->AdapterInfo.Chan, sizeof(AtaCtl->AdapterInfo.Chan));
@@ -7756,7 +8116,11 @@ uata_ctl_queue:
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device\n"));
 
-                    UniataUserDeviceReset(deviceExtension, LunExt, AtaCtl->addr.PathId, ldev);
+                    if(bad_ldev) {
+                        goto do_bus_reset;
+                    } else {
+                        UniataUserDeviceReset(deviceExtension, LunExt, AtaCtl->addr.PathId, ldev);
+                    }
 
                     status = SRB_STATUS_SUCCESS;
                     break;
@@ -7847,13 +8211,21 @@ complete_req:
 
 
 void
+NTAPI
 UniataInitAtaCommands()
 {
     int i;
     UCHAR command;
-    UCHAR flags = 0;
+    UCHAR flags;
+
+    KdPrint2((PRINT_PREFIX "UniataInitAtaCommands:\n"));
+
+    for(i=0; i<256; i++) {
+
+        flags = 0;
+        command = i;
 
-    for(i=0, command=0; i<256; i++, command++) {
+        KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
 
         switch(command) {
         case IDE_COMMAND_READ_DMA48:
@@ -7874,6 +8246,7 @@ UniataInitAtaCommands()
         case IDE_COMMAND_WRITE_LOG_DMA48:
         case IDE_COMMAND_TRUSTED_RCV_DMA:
         case IDE_COMMAND_TRUSTED_SEND_DMA:
+            KdPrint2((PRINT_PREFIX "DMA "));
             flags |= ATA_CMD_FLAG_DMA;
         }
 
@@ -7896,6 +8269,7 @@ UniataInitAtaCommands()
         case IDE_COMMAND_FLUSH_CACHE48:
         case IDE_COMMAND_VERIFY48:
 
+            KdPrint2((PRINT_PREFIX "48 "));
             flags |= ATA_CMD_FLAG_48;
             /* FALL THROUGH */
 
@@ -7910,6 +8284,7 @@ UniataInitAtaCommands()
         case IDE_COMMAND_FLUSH_CACHE:
         case IDE_COMMAND_VERIFY:
 
+            KdPrint2((PRINT_PREFIX "LBA "));
             flags |= ATA_CMD_FLAG_LBAIOsupp;
         }
 
@@ -7934,16 +8309,18 @@ UniataInitAtaCommands()
             command = IDE_COMMAND_WRITE_DMA_Q48; break;
         case IDE_COMMAND_FLUSH_CACHE:
             command = IDE_COMMAND_FLUSH_CACHE48; break;
-        case IDE_COMMAND_READ_NATIVE_SIZE:
+    //    case IDE_COMMAND_READ_NATIVE_SIZE:
     //            command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
         case IDE_COMMAND_SET_NATIVE_SIZE:
             command = IDE_COMMAND_SET_NATIVE_SIZE48; break;
         case IDE_COMMAND_VERIFY:
             command = IDE_COMMAND_VERIFY48; break;
         default:
+            KdPrint2((PRINT_PREFIX "!28->48 "));
             flags &= ~ATA_CMD_FLAG_48supp;
         }
 
+        KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
         AtaCommands48[i]   = command;
         AtaCommandFlags[i] = flags;
     }
@@ -7987,7 +8364,7 @@ DriverEntry(
     LARGE_INTEGER t0, t1;
 
     Connect_DbgPrint();
-    KdPrint2((PRINT_PREFIX (PCCHAR)ver_string));
+    KdPrint2((PRINT_PREFIX "%s", (PCCHAR)ver_string));
     a = (WCHAR)strlen(ver_string);
 
     g_opt_Verbose = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PrintLogo", 0);
@@ -8013,6 +8390,7 @@ DriverEntry(
         KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt, g_Perf ));
 
     } else {
+        KdPrint(("UniATA Init: ReEnter\n"));
         ReEnter = TRUE;
     }
 
@@ -8031,6 +8409,17 @@ DriverEntry(
         SavedRegPath.Buffer[SavedRegPath.Length/sizeof(WCHAR)] = 0;
     }
 
+    if(WinVer_Id() >= WinVer_2k) {
+        if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"1", 0)) {
+            KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
+            WinVer_WDM_Model = TRUE;
+        }
+        if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"5", 0)) {
+            KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
+            WinVer_WDM_Model = TRUE;
+        }
+    }
+
     SkipRaids = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"SkipRaids", 1);
     ForceSimplex = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"ForceSimplex", 0);
 #ifdef _DEBUG
@@ -8047,6 +8436,7 @@ DriverEntry(
       sizeof(hwInitializationData.comm) +
 //      sizeof(hwInitializationData.nt4) +
       ((WinVer_Id() <= WinVer_NT) ? 0 : sizeof(hwInitializationData.w2k));
+    KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData.comm.HwInitializationDataSize));
 
     // Set entry points.
     hwInitializationData.comm.HwInitialize = (PHW_INITIALIZE)AtapiHwInitialize;
@@ -8063,7 +8453,9 @@ DriverEntry(
     hwInitializationData.comm.MapBuffers = TRUE;
     // Set PnP-specific API
     if(WinVer_Id() > WinVer_NT) {
+        KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
         hwInitializationData.comm.NeedPhysicalAddresses = TRUE;
+        KdPrint(("set AtapiAdapterControl() ptr\n"));
         hwInitializationData.w2k.HwAdapterControl = (PHW_ADAPTER_CONTROL)AtapiAdapterControl;
     }
 
@@ -8104,7 +8496,7 @@ DriverEntry(
         if(g_opt_Verbose) {
             _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
         }
-        for(alt = 0; alt < 2; alt++) {
+        for(alt = 0; alt < (ULONG)(WinVer_WDM_Model ? 1 : 2) ; alt++) {
 
             for(c=0; c<2; c++) {
 
@@ -8124,7 +8516,7 @@ DriverEntry(
                     }
                 }
 
-                if((WinVer_Id() <= WinVer_NT)) {
+                if((WinVer_Id() < WinVer_2k)) {
                     // do not even try if already claimed
                     if(c==0) {
                         GlobalConfig->AtDiskPrimaryAddressClaimed = FALSE;
@@ -8133,11 +8525,19 @@ DriverEntry(
                         GlobalConfig->AtDiskSecondaryAddressClaimed = FALSE;
                     }
                 }
-                hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
+                if(!WinVer_WDM_Model) {
+                    hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
+                } else {
+                    // in WDM model things are different....
+                    hwInitializationData.comm.HwFindAdapter = (c == 0) ?
+                        UniataFindCompatBusMasterController1 : UniataFindCompatBusMasterController2;
+                }
                 hwInitializationData.comm.NumberOfAccessRanges = 6;
                 hwInitializationData.comm.AdapterInterfaceType = Isa;
 
-                BMList[i].channel = (UCHAR)c;
+                if(!WinVer_WDM_Model) {
+                    BMList[i].channel = (UCHAR)c;
+                }
 
                 KdPrint2((PRINT_PREFIX "Try init channel %d, method %d\n", c, alt));
                 newStatus = ScsiPortInitialize(DriverObject,
@@ -8158,7 +8558,7 @@ DriverEntry(
 */
                 }
             }
-            if(WinVer_Id() > WinVer_NT) {
+            if(WinVer_Id() >= WinVer_2k) {
                 // the following doesn't work under higher OSes
                 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
                 continue;
@@ -8171,7 +8571,30 @@ DriverEntry(
             }
             // if (WinVer_Id() == WinVer_NT) and some error occured
             // try alternative init method
+        } // for(alt...)
+#if 0
+        if(WinVer_WDM_Model) {
+            hwInitializationData.comm.HwFindAdapter = UniataFindFakeBusMasterController;
+            hwInitializationData.comm.NumberOfAccessRanges = 5;
+            hwInitializationData.comm.AdapterInterfaceType = PCIBus;
+
+            hwInitializationData.comm.VendorId             = BMList[i].VendorId;
+            hwInitializationData.comm.VendorIdLength       = (USHORT) BMList[i].VendorIdLength;
+            hwInitializationData.comm.DeviceId             = BMList[i].DeviceId;
+            hwInitializationData.comm.DeviceIdLength       = (USHORT) BMList[i].DeviceIdLength;
+
+            //BMList[i].channel = 0/*(UCHAR)c*/;
+
+            KdPrint2((PRINT_PREFIX "Try init fake: %4.4s %4.4s \n",
+                                   hwInitializationData.comm.VendorId,
+                                   hwInitializationData.comm.DeviceId));
+            newStatus = ScsiPortInitialize(DriverObject,
+                                           Argument2,
+                                           &hwInitializationData.comm,
+                                           (PVOID)i);
+            KdPrint2((PRINT_PREFIX "Status %#x\n", newStatus));
         }
+#endif //0
         if(g_opt_Verbose) {
             if(BMList[i].ChanInitOk & 0x03) {
                 _PrintNtConsole("  OK\n");
@@ -8238,7 +8661,7 @@ DriverEntry(
 
 /*    KeBugCheckEx(0xc000000e,
                  i,
-                 c,
+                 c, 
                  newStatus, statusToReturn);*/
 
     // --------------
@@ -8292,6 +8715,7 @@ DriverEntry(
 
 
 PSCSI_REQUEST_BLOCK
+NTAPI
 BuildMechanismStatusSrb(
     IN PVOID HwDeviceExtension,
     IN PSCSI_REQUEST_BLOCK Srb
@@ -8333,6 +8757,7 @@ BuildMechanismStatusSrb(
 #endif //UNIATA_CORE
 
 PSCSI_REQUEST_BLOCK
+NTAPI
 BuildRequestSenseSrb (
     IN PVOID HwDeviceExtension,
     IN PSCSI_REQUEST_BLOCK Srb
@@ -8374,12 +8799,13 @@ BuildRequestSenseSrb (
 #ifndef UNIATA_CORE
 
 ULONG
+NTAPI
 AtapiRegCheckDevLunValue(
     IN PVOID HwDeviceExtension,
-    IN PWCHAR NamePrefix,
+    IN PCWCH NamePrefix,
     IN ULONG chan,
     IN ULONG dev,
-    IN PWSTR Name,
+    IN PCWSTR Name,
     IN ULONG Default
     )
 {
@@ -8403,6 +8829,7 @@ AtapiRegCheckDevLunValue(
 } // end AtapiRegCheckDevLunValue()
 
 ULONG
+NTAPI
 EncodeVendorStr(
    OUT PWCHAR Buffer,
     IN PUCHAR Str,
@@ -8442,11 +8869,12 @@ EncodeVendorStr(
 } // end EncodeVendorStr()
 
 ULONG
+NTAPI
 AtapiRegCheckDevValue(
     IN PVOID HwDeviceExtension,
     IN ULONG chan,
     IN ULONG dev,
-    IN PWSTR Name,
+    IN PCWSTR Name,
     IN ULONG Default
     )
 {
@@ -8484,21 +8912,56 @@ AtapiRegCheckDevValue(
         HwDeviceExtension, L"Parameters", chan, dev, Name, val);
 
     if(deviceExtension) {
-        swprintf(namev, L"\\Ven_%4.4x", VendorID);
-        swprintf(named, L"\\Dev_%4.4x", DeviceID);
-        swprintf(names, L"\\Slot_%8.8x", SlotNumber);
+        if(deviceExtension->AdapterInterfaceType == PCIBus) {
+            // PCI
+            swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex);
+            swprintf(namex, L"Parameters%s", namev);
+            val = AtapiRegCheckDevLunValue(
+                HwDeviceExtension, namex, chan, dev, Name, val);
 
-        swprintf(namex, L"Parameters%s", namev);
-        val = AtapiRegCheckDevLunValue(
-            HwDeviceExtension, namex, chan, dev, Name, val);
 
-        swprintf(namex, L"Parameters%s%s", namev, named);
-        val = AtapiRegCheckDevLunValue(
-            HwDeviceExtension, namex, chan, dev, Name, val);
+            swprintf(namev, L"\\Ven_%4.4x", VendorID);
+            swprintf(named, L"\\Dev_%4.4x", DeviceID);
+            swprintf(names, L"\\Slot_%8.8x", SlotNumber);
+
+            swprintf(namex, L"Parameters%s", namev);
+            val = AtapiRegCheckDevLunValue(
+                HwDeviceExtension, namex, chan, dev, Name, val);
+
+            swprintf(namex, L"Parameters%s%s", namev, named);
+            val = AtapiRegCheckDevLunValue(
+                HwDeviceExtension, namex, chan, dev, Name, val);
+
+            swprintf(namex, L"Parameters%s%s%s", namev, named, names);
+            val = AtapiRegCheckDevLunValue(
+                HwDeviceExtension, namex, chan, dev, Name, val);
+        } else
+        if(deviceExtension->AdapterInterfaceType == Isa) {
+            // Isa
+            swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen);
+            swprintf(namex, L"Parameters%s", namev);
+            val = AtapiRegCheckDevLunValue(
+                HwDeviceExtension, namex, chan, dev, Name, val);
+
+            swprintf(namev, L"\\ISA_%d", deviceExtension->DevIndex);
+            swprintf(namex, L"Parameters%s", namev);
+            val = AtapiRegCheckDevLunValue(
+                HwDeviceExtension, namex, chan, dev, Name, val);
 
-        swprintf(namex, L"Parameters%s%s%s", namev, named, names);
-        val = AtapiRegCheckDevLunValue(
-            HwDeviceExtension, namex, chan, dev, Name, val);
+        } else
+        if(deviceExtension->AdapterInterfaceType == MicroChannel) {
+            // MicroChannel
+            swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen+IsaCount);
+            swprintf(namex, L"Parameters%s", namev);
+            val = AtapiRegCheckDevLunValue(
+                HwDeviceExtension, namex, chan, dev, Name, val);
+
+            swprintf(namev, L"\\MCA_%d", deviceExtension->DevIndex);
+            swprintf(namex, L"Parameters%s", namev);
+            val = AtapiRegCheckDevLunValue(
+                HwDeviceExtension, namex, chan, dev, Name, val);
+
+        }
     }
 
     KdPrint(( " Parameter %ws = %#x\n", Name, val));
@@ -8527,14 +8990,15 @@ AtapiRegCheckDevValue(
     Returns:    Registry Key value
  */
 ULONG
+NTAPI
 AtapiRegCheckParameterValue(
     IN PVOID HwDeviceExtension,
-    IN PWSTR PathSuffix,
-    IN PWSTR Name,
+    IN PCWSTR PathSuffix,
+    IN PCWSTR Name,
     IN ULONG Default
     )
 {
-#define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
+#define ITEMS_TO_QUERY 2 // always 1 greater than what is searched 
 
 //    PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
     NTSTATUS          status;
@@ -8579,7 +9043,7 @@ AtapiRegCheckParameterValue(
 
     status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/,
                                     paramPath.Buffer, parameters, NULL, NULL);
-    KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun));
+    //KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun));
 
     ExFreePool(paramPath.Buffer);
 
@@ -8645,8 +9109,11 @@ AtapiAdapterControl(
                 AtapiResetController(deviceExtension, c);
                 AtapiDisableInterrupts(deviceExtension, c);
             }
-            status = UniataDisconnectIntr2(HwDeviceExtension);
-            BMList[deviceExtension->DevIndex].Isr2Enable = FALSE;
+            if(deviceExtension->AdapterInterfaceType == PCIBus) {
+                // we must never get here for non-PCI
+                status = UniataDisconnectIntr2(HwDeviceExtension);
+                BMList[deviceExtension->DevIndex].Isr2Enable = FALSE;
+            }
             break;
         }
         case ScsiRestartAdapter: {
@@ -8659,11 +9126,12 @@ AtapiAdapterControl(
             status = UniataConnectIntr2(HwDeviceExtension);
             for (c = 0; c < numberChannels; c++) {
                 AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, c);
-                FindDevices(HwDeviceExtension, FALSE, c);
+                FindDevices(HwDeviceExtension, 0, c);
                 AtapiEnableInterrupts(deviceExtension, c);
                 AtapiHwInitialize__(deviceExtension, c);
             }
             if(deviceExtension->Isr2DevObj) {
+                // we must never get here for non-PCI
                 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
             }
 
@@ -8693,7 +9161,7 @@ extern "C"
 VOID
 _cdecl
 _PrintNtConsole(
-    PCHAR DebugMessage,
+    PCCH DebugMessage,
     ...
     )
 {
@@ -8713,3 +9181,4 @@ _PrintNtConsole(
 
 } // end PrintNtConsole()
 
+