xref: /reactos/drivers/storage/ide/uniata/id_ata.cpp (revision 62919904)
1 /*++
2 
3 Copyright (c) 2002-2018 Alexandr A. Telyatnikov (Alter)
4 
5 Module Name:
6     id_ata.cpp
7 
8 Abstract:
9     This is the miniport driver for ATA/ATAPI IDE/SATA/AHCI controllers
10     with Busmaster DMA and Serial ATA support
11 
12 Author:
13     Alexander A. Telyatnikov (Alter)
14 
15 Environment:
16     kernel mode only
17 
18 Notes:
19 
20     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 Revision History:
32 
33     The skeleton was taken from standard ATAPI.SYS from NT4 DDK by
34          Mike Glass (MGlass)
35          Chuck Park (ChuckP)
36 
37     Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by
38          S�ren Schmidt, Copyright (c) 1998-2007
39 
40     All parts of code are significantly changed/updated by
41          Alter, Copyright (c) 2002-2014:
42 
43     1. Internal command queueing/reordering
44     2. Drive identification
45     3. Support for 2 _independent_ channels in a single PCI device
46     4. Smart host<->drive transfer rate slowdown (for bad cable)
47     5. W2k support (binary compatibility)
48     6. HDD hot swap under NT4
49     7. XP support (binary compatibility)
50     8. Serial ATA (SATA/SATA2/SATA3) support
51     9. NT 3.51 support (binary compatibility)
52     10. AHCI support
53 
54     etc. (See todo.txt)
55 
56 Licence:
57     GPLv2
58 
59 --*/
60 
61 #include "stdafx.h"
62 
63 #ifndef UNIATA_CORE
64 
65 static const CHAR ver_string[] = "\n\nATAPI IDE MiniPort Driver (UniATA) v 0." UNIATA_VER_STR "\n";
66 
67 static const CHAR uniata_comm_name[] = UNIATA_COMM_PORT_VENDOR_STR "    \n";
68 
69 UNICODE_STRING SavedRegPath;
70 WCHAR SavedRegPathBuffer[256];
71 
72 #endif //UNIATA_CORE
73 
74 //UCHAR AtaCommands48[256];
75 //UCHAR AtaCommandFlags[256];
76 
77 ULONG  SkipRaids = 1;
78 ULONG  ForceSimplex = 0;
79 
80 LONGLONG g_Perf = 0;
81 ULONG    g_PerfDt = 0;
82 
83 #ifdef _DEBUG
84 ULONG  g_LogToDisplay = 0;
85 #endif //_DEBUG
86 
87 ULONG  g_WaitBusyInISR = 1;
88 
89 ULONG  g_opt_WaitBusyResetCount = 10000; // 20000
90 ULONG  g_opt_WaitBusyCount = 200; // 20000
91 ULONG  g_opt_WaitBusyDelay = 10;  // 150
92 ULONG  g_opt_WaitDrqDelay  = 10; // 100
93 ULONG  g_opt_WaitBusyLongCount = 2000; // 2000
94 ULONG  g_opt_WaitBusyLongDelay = 250;  // 250
95 ULONG  g_opt_MaxIsrWait = 40;
96 
97 ULONG  g_opt_DriveSelectNanoDelay = 0; // 400; // ns
98 
99 BOOLEAN g_opt_AtapiSendDisableIntr = 0; // 0
100 BOOLEAN g_opt_AtapiDmaRawRead = 1; // 0
101 BOOLEAN g_opt_AtapiNoDma = FALSE;
102 BOOLEAN g_opt_BochsDmaReadWorkaround = FALSE;
103 BOOLEAN hasPCI = FALSE;
104 
105 ULONG g_opt_VirtualMachine = 0; // Auto
106 
107 BOOLEAN InDriverEntry = TRUE;
108 BOOLEAN g_Dump = FALSE;
109 
110 BOOLEAN g_opt_Verbose = 0;
111 
112 BOOLEAN WinVer_WDM_Model = FALSE;
113 ULONG CPU_num = 1;
114 
115 //UCHAR EnableDma = FALSE;
116 //UCHAR EnableReorder = FALSE;
117 
118 UCHAR g_foo = 0;
119 
120 BOOLEAN
121 NTAPI
122 AtapiResetController__(
123     IN PVOID HwDeviceExtension,
124     IN ULONG PathId,
125     IN UCHAR CompleteType
126     );
127 
128 VOID
129 NTAPI
130 AtapiHwInitialize__(
131     IN PHW_DEVICE_EXTENSION deviceExtension,
132     IN ULONG lChannel
133     );
134 
135 VOID
136 NTAPI
137 UniataUserDeviceReset(
138     PHW_DEVICE_EXTENSION deviceExtension,
139     PHW_LU_EXTENSION LunExt,
140     ULONG lChannel
141     );
142 
143 #define RESET_COMPLETE_CURRENT  0x00
144 #define RESET_COMPLETE_ALL      0x01
145 #define RESET_COMPLETE_NONE     0x02
146 
147 #ifndef UNIATA_CORE
148 
149 VOID
150 NTAPI
151 AtapiCallBack_X(
152     IN PVOID HwDeviceExtension
153     );
154 
155 #ifdef UNIATA_USE_XXableInterrupts
156   #define RETTYPE_XXableInterrupts   BOOLEAN
157   #define RETVAL_XXableInterrupts    TRUE
158 #else
159   #define RETTYPE_XXableInterrupts   VOID
160   #define RETVAL_XXableInterrupts
161 #endif
162 
163 RETTYPE_XXableInterrupts
164 NTAPI
165 AtapiInterruptDpc(
166     IN PVOID HwDeviceExtension
167     );
168 
169 RETTYPE_XXableInterrupts
170 NTAPI
171 AtapiEnableInterrupts__(
172     IN PVOID HwDeviceExtension
173     );
174 
175 VOID
176 NTAPI
177 AtapiQueueTimerDpc(
178     IN PVOID HwDeviceExtension,
179     IN ULONG lChannel,
180     IN PHW_TIMER HwScsiTimer,
181     IN ULONG MiniportTimerValue
182     );
183 
184 SCSI_ADAPTER_CONTROL_STATUS
185 NTAPI
186 AtapiAdapterControl(
187     IN PVOID HwDeviceExtension,
188     IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
189     IN PVOID Parameters
190     );
191 
192 #endif //UNIATA_CORE
193 
194 #ifndef UNIATA_CORE
195 
196 BOOLEAN
197 NTAPI
198 AtapiRegGetStringParameterValue(
199     IN PWSTR RegistryPath,
200     IN PWSTR Name,
201     IN PWCHAR Str,
202     IN ULONG MaxLen
203     )
204 {
205 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
206     NTSTATUS          status;
207     RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY];
208     UNICODE_STRING ustr;
209 
210     ustr.Buffer = Str;
211     ustr.Length =
212     ustr.MaximumLength = (USHORT)MaxLen;
213     RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
214 
215     parameters[0].Flags         = RTL_QUERY_REGISTRY_DIRECT;
216     parameters[0].Name          = Name;
217     parameters[0].EntryContext  = &ustr;
218     parameters[0].DefaultType   = REG_SZ;
219     parameters[0].DefaultData   = Str;
220     parameters[0].DefaultLength = MaxLen;
221 
222     status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/,
223                                     RegistryPath, parameters, NULL, NULL);
224 
225     if(!NT_SUCCESS(status))
226         return FALSE;
227 
228     return TRUE;
229 
230 #undef ITEMS_TO_QUERY
231 } // end AtapiRegGetStringParameterValue()
232 
233 
234 #endif //UNIATA_CORE
235 
236 VOID
237 DDKFASTAPI
238 UniataNanoSleep(
239     ULONG nano
240     )
241 {
242     LONGLONG t;
243     LARGE_INTEGER t0;
244 
245 #ifdef NAVO_TEST
246     return;
247 #endif //NAVO_TEST
248 
249     if(!nano || !g_Perf || !g_PerfDt)
250         return;
251     t = (g_Perf * nano) / g_PerfDt / 1000;
252     if(!t) {
253         t = 1;
254     }
255     do {
256         KeQuerySystemTime(&t0);
257         t--;
258     } while(t);
259 } // end UniataNanoSleep()
260 
261 #define AtapiWritePortN_template(_type, _Type, sz) \
262 VOID \
263 DDKFASTAPI \
264 AtapiWritePort##sz( \
265     IN PHW_CHANNEL chan, \
266     IN ULONGIO_PTR _port, \
267     IN _type  data \
268     ) \
269 { \
270     PIORES res; \
271     if(_port >= IDX_MAX_REG) { \
272         res = (PIORES)(_port);  \
273     } else \
274     if(chan) { \
275         res = &chan->RegTranslation[_port];  \
276     } else {                                     \
277         KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
278         return; \
279     } \
280     if(res->Proc) {             \
281         KdPrint(("PROC io write request @ ch %x, res* %x\n", chan, _port)); \
282         ASSERT(FALSE); /* We should never get here */ \
283     } \
284     if(!res->MemIo) {             \
285         ScsiPortWritePort##_Type((_type*)(ULONGIO_PTR)(res->Addr), data); \
286     } else {                                      \
287         /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
288         ScsiPortWriteRegister##_Type((_type*)(ULONG_PTR)(res->Addr), data); \
289     }                                                        \
290     return;                                                  \
291 }
292 
293 AtapiWritePortN_template(ULONG,  Ulong,  4);
294 AtapiWritePortN_template(USHORT, Ushort, 2);
295 AtapiWritePortN_template(UCHAR,  Uchar,  1);
296 
297 #define AtapiWritePortExN_template(_type, _Type, sz) \
298 VOID \
299 DDKFASTAPI \
300 AtapiWritePortEx##sz( \
301     IN PHW_CHANNEL chan, \
302     IN ULONGIO_PTR _port, \
303     IN ULONG offs, \
304     IN _type  data \
305     ) \
306 { \
307     PIORES res; \
308     if(_port >= IDX_MAX_REG) { \
309         res = (PIORES)(_port);  \
310     } else \
311     if(chan) { \
312         res = &chan->RegTranslation[_port];  \
313     } else {                                     \
314         KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
315         return; \
316     } \
317     if(res->Proc) {             \
318         KdPrint(("PROC io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
319         ASSERT(FALSE); /* We should never get here */ \
320     } \
321     if(!res->MemIo) {             \
322         ScsiPortWritePort##_Type((_type*)(ULONGIO_PTR)(res->Addr+offs), data); \
323     } else {                                      \
324         /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
325         ScsiPortWriteRegister##_Type((_type*)(ULONG_PTR)(res->Addr+offs), data); \
326     }                                                        \
327     return;                                                  \
328 }
329 
330 AtapiWritePortExN_template(ULONG,  Ulong,  4);
331 //AtapiWritePortExN_template(USHORT, Ushort, 2);
332 AtapiWritePortExN_template(UCHAR,  Uchar,  1);
333 
334 #define AtapiReadPortN_template(_type, _Type, sz) \
335 _type \
336 DDKFASTAPI \
337 AtapiReadPort##sz( \
338     IN PHW_CHANNEL chan, \
339     IN ULONGIO_PTR _port \
340     ) \
341 { \
342     PIORES res; \
343     if(_port >= IDX_MAX_REG) { \
344         res = (PIORES)(_port);  \
345     } else \
346     if(chan) { \
347         res = &chan->RegTranslation[_port];  \
348     } else {                                     \
349         KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
350         return (_type)(-1); \
351     } \
352     if(res->Proc) {             \
353         KdPrint(("PROC io read request @ ch %x, res* %x\n", chan, _port)); \
354         ASSERT(FALSE); /* We should never get here */ \
355     } \
356     if(!res->MemIo) {             \
357         /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
358         return ScsiPortReadPort##_Type((_type*)(ULONGIO_PTR)(res->Addr)); \
359     } else {                                      \
360         /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
361         return ScsiPortReadRegister##_Type((_type*)(ULONG_PTR)(res->Addr)); \
362     }                                                        \
363 }
364 
365 AtapiReadPortN_template(ULONG,  Ulong,  4);
366 AtapiReadPortN_template(USHORT, Ushort, 2);
367 AtapiReadPortN_template(UCHAR,  Uchar,  1);
368 
369 #define AtapiReadPortExN_template(_type, _Type, sz) \
370 _type \
371 DDKFASTAPI \
372 AtapiReadPortEx##sz( \
373     IN PHW_CHANNEL chan, \
374     IN ULONGIO_PTR _port, \
375     IN ULONG offs \
376     ) \
377 { \
378     PIORES res; \
379     if(_port >= IDX_MAX_REG) { \
380         res = (PIORES)(_port);  \
381     } else \
382     if(chan) { \
383         res = &chan->RegTranslation[_port];  \
384     } else {                                     \
385         KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
386         return (_type)(-1); \
387     } \
388     if(res->Proc) {             \
389         KdPrint(("PROC io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
390         ASSERT(FALSE); /* We should never get here */ \
391     } \
392     if(!res->MemIo) {             \
393         return ScsiPortReadPort##_Type((_type*)(ULONGIO_PTR)(res->Addr+offs)); \
394     } else {                                      \
395         /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
396         return ScsiPortReadRegister##_Type((_type*)(ULONG_PTR)(res->Addr+offs)); \
397     }                                                        \
398 }
399 
400 AtapiReadPortExN_template(ULONG,  Ulong,  4);
401 //AtapiReadPortExN_template(USHORT, Ushort, 2);
402 AtapiReadPortExN_template(UCHAR,  Uchar,  1);
403 
404 #define AtapiReadPortBufferN_template(_type, _Type, sz) \
405 VOID \
406 DDKFASTAPI \
407 AtapiReadBuffer##sz( \
408     IN PHW_CHANNEL chan, \
409     IN ULONGIO_PTR _port, \
410     IN PVOID Buffer, \
411     IN ULONG Count,   \
412     IN ULONG Timing   \
413     ) \
414 { \
415     PIORES res; \
416                  \
417     if(Timing) { \
418         while(Count) { \
419             (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
420             Count--; \
421             Buffer = ((_type*)Buffer)+1; \
422             UniataNanoSleep(Timing); \
423         } \
424         return; \
425     } \
426            \
427     if(_port >= IDX_MAX_REG) { \
428         res = (PIORES)(_port);  \
429     } else \
430     if(chan) { \
431         res = &chan->RegTranslation[_port];  \
432     } else {                                     \
433         KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
434         return; \
435     } \
436     if(!res->MemIo) {             \
437         /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
438         ScsiPortReadPortBuffer##_Type((_type*)(ULONGIO_PTR)(res->Addr), (_type*)Buffer, Count); \
439         return; \
440     }                                                        \
441     while(Count) { \
442         (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(ULONG_PTR)(res->Addr)); \
443         Count--; \
444         Buffer = ((_type*)Buffer)+1; \
445     } \
446     return;                                                  \
447 }
448 
449 #define AtapiWritePortBufferN_template(_type, _Type, sz) \
450 VOID \
451 DDKFASTAPI \
452 AtapiWriteBuffer##sz( \
453     IN PHW_CHANNEL chan, \
454     IN ULONGIO_PTR _port, \
455     IN PVOID Buffer, \
456     IN ULONG Count,   \
457     IN ULONG Timing   \
458     ) \
459 { \
460     PIORES res; \
461                  \
462     if(Timing) { \
463         while(Count) { \
464             AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
465             Buffer = ((_type*)Buffer)+1; \
466             Count--; \
467             UniataNanoSleep(Timing); \
468         } \
469         return;                                                  \
470     } \
471            \
472     if(_port >= IDX_MAX_REG) { \
473         res = (PIORES)(_port);  \
474     } else \
475     if(chan) { \
476         res = &chan->RegTranslation[_port];  \
477     } else {                                     \
478         KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
479         return; \
480     } \
481     if(!res->MemIo) {             \
482         /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
483         ScsiPortWritePortBuffer##_Type((_type*)(ULONGIO_PTR)(res->Addr), (_type*)Buffer, Count); \
484         return; \
485     }                                                        \
486     while(Count) { \
487         ScsiPortWriteRegister##_Type((_type*)(ULONG_PTR)(res->Addr), *((_type*)Buffer)); \
488         Count--; \
489         Buffer = ((_type*)Buffer)+1; \
490     } \
491     return;                                                  \
492 }
493 
494 AtapiWritePortBufferN_template(ULONG,  Ulong,  4);
495 AtapiWritePortBufferN_template(USHORT, Ushort, 2);
496 
497 AtapiReadPortBufferN_template(ULONG,  Ulong,  4);
498 AtapiReadPortBufferN_template(USHORT, Ushort, 2);
499 
500 
501 UCHAR
502 DDKFASTAPI
503 AtapiSuckPort2(
504     IN PHW_CHANNEL chan
505     )
506 {
507     UCHAR statusByte;
508     ULONG i;
509 
510     // Assume, proper drive is already seleted
511     WaitOnBusyLong(chan);
512     for (i = 0; i < 0x10000; i++) {
513 
514         GetStatus(chan, statusByte);
515         if (statusByte & IDE_STATUS_DRQ) {
516             // Suck out any remaining bytes and throw away.
517             AtapiReadPort2(chan, IDX_IO1_i_Data);
518             UniataNanoSleep(PIO0_TIMING);
519         } else {
520             break;
521         }
522     }
523     if(i) {
524         KdPrint2((PRINT_PREFIX "AtapiSuckPort2: overrun detected (%#x words)\n", i ));
525     }
526     return statusByte;
527 } // AtapiSuckPort2()
528 
529 ULONG
530 DDKFASTAPI
531 AtapiSuckPortBuffer2(
532     IN PHW_CHANNEL chan,
533     IN PUSHORT Buffer,
534     IN ULONG Count
535     )
536 {
537     UCHAR statusByte;
538     ULONG i;
539     USHORT data;
540     BOOLEAN retry = FALSE;
541 
542     // Assume, proper drive is already seleted
543     WaitOnBusyLong(chan);
544     for (i = 0; i < Count; i++) {
545 
546         GetStatus(chan, statusByte);
547         if (statusByte & IDE_STATUS_DRQ) {
548             // Suck out any remaining bytes and throw away.
549             data = AtapiReadPort2(chan, IDX_IO1_i_Data);
550             (*Buffer) = data;
551             Count--;
552             Buffer++;
553             UniataNanoSleep(PIO0_TIMING);
554             retry = FALSE;
555         } else {
556             if(i<Count && !retry) {
557                 KdPrint2((PRINT_PREFIX "  wait...\n"));
558                 WaitForDrq(chan);
559                 retry = TRUE;
560             }
561             break;
562         }
563     }
564     if(i) {
565         KdPrint2((PRINT_PREFIX "AtapiSuckPortBuffer2: %#x words\n", i ));
566         if(i==Count) {
567             AtapiSuckPort2(chan);
568         }
569     }
570     return i;
571 } // AtapiSuckPortBuffer2()
572 
573 UCHAR
574 DDKFASTAPI
575 SelectDrive(
576     IN PHW_CHANNEL   chan,
577     IN ULONG         DeviceNumber
578     )
579 {
580     if(!chan) {
581         return 0;
582     }
583 /*
584     if(chan->lun[DeviceNumber] &&
585        (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_CHANGER)) {
586         KdPrint3(("  Select %d\n", DeviceNumber));
587     }
588 */
589     if(chan->last_devsel == DeviceNumber) {
590         //KdPrint3(("  Selected %d\n", DeviceNumber));
591         return 1;
592     }
593     AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1); \
594     chan->last_devsel = DeviceNumber ? 1 : 0;
595     if(!g_opt_DriveSelectNanoDelay) {
596         //KdPrint3(("  Select %d\n", DeviceNumber));
597         return 2;
598     }
599     //KdPrint3(("  Select %d (%d ns)\n", DeviceNumber, g_opt_DriveSelectNanoDelay));
600     UniataNanoSleep(g_opt_DriveSelectNanoDelay);
601     return 2;
602 } // end SelectDrive()
603 
604 UCHAR
605 DDKFASTAPI
606 WaitOnBusy(
607     IN PHW_CHANNEL   chan
608     )
609 {
610     ULONG i;
611     UCHAR Status;
612 
613     GetStatus(chan, Status);
614     for (i=0; i<g_opt_WaitBusyCount; i++) {
615         if (Status & IDE_STATUS_BUSY) {
616             AtapiStallExecution(g_opt_WaitBusyDelay);
617             GetStatus(chan, Status);
618             continue;
619         } else {
620             break;
621         }
622     }
623     return Status;
624 } // end WaitOnBusy()
625 
626 UCHAR
627 DDKFASTAPI
628 WaitOnBusyLong(
629     IN PHW_CHANNEL   chan
630     )
631 {
632     ULONG i;
633     UCHAR Status;
634 
635     Status = WaitOnBusy(chan);
636     if(!(Status & IDE_STATUS_BUSY))
637         return Status;
638     for (i=0; i<g_opt_WaitBusyLongCount; i++) {
639         GetStatus(chan, Status);
640         if (Status & IDE_STATUS_BUSY) {
641             AtapiStallExecution(g_opt_WaitBusyLongDelay);
642             continue;
643         } else {
644             break;
645         }
646     }
647     return Status;
648 } // end WaitOnBusyLong()
649 
650 UCHAR
651 DDKFASTAPI
652 WaitOnBaseBusy(
653     IN PHW_CHANNEL   chan
654     )
655 {
656     ULONG i;
657     UCHAR Status = IDE_STATUS_WRONG;
658     for (i=0; i<g_opt_WaitBusyCount; i++) {
659         GetBaseStatus(chan, Status);
660         if (Status & IDE_STATUS_BUSY) {
661             AtapiStallExecution(g_opt_WaitBusyDelay);
662             continue;
663         } else {
664             break;
665         }
666     }
667     return Status;
668 } // end WaitOnBaseBusy()
669 
670 UCHAR
671 DDKFASTAPI
672 WaitOnBaseBusyLong(
673     IN PHW_CHANNEL   chan
674     )
675 {
676     ULONG i;
677     UCHAR Status;
678 
679     Status = WaitOnBaseBusy(chan);
680     if(!(Status & IDE_STATUS_BUSY))
681         return Status;
682     for (i=0; i<2000; i++) {
683         GetBaseStatus(chan, Status);
684         if (Status & IDE_STATUS_BUSY) {
685             AtapiStallExecution(250);
686             continue;
687         } else {
688             break;
689         }
690     }
691     return Status;
692 } // end WaitOnBaseBusyLong()
693 
694 UCHAR
695 DDKFASTAPI
696 UniataIsIdle(
697     IN struct _HW_DEVICE_EXTENSION* deviceExtension,
698     IN UCHAR Status
699     )
700 {
701     UCHAR Status2;
702 
703     if(Status == IDE_STATUS_WRONG) {
704         return IDE_STATUS_WRONG;
705     }
706     if(Status & IDE_STATUS_BUSY) {
707         return Status;
708     }
709 //    if(deviceExtension->HwFlags & UNIATA_SATA) {
710     if(UniataIsSATARangeAvailable(deviceExtension, 0)) {
711         if(Status & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
712             return Status;
713         }
714     } else {
715         Status2 = Status & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX);
716         if ((Status & IDE_STATUS_BUSY) ||
717             (Status2 != IDE_STATUS_IDLE && Status2 != IDE_STATUS_DRDY)) {
718             return Status;
719         }
720     }
721     return IDE_STATUS_IDLE;
722 } // end UniataIsIdle()
723 
724 UCHAR
725 DDKFASTAPI
726 WaitForIdleLong(
727     IN PHW_CHANNEL   chan
728     )
729 {
730     ULONG i;
731     UCHAR Status;
732     UCHAR Status2;
733     for (i=0; i<20000; i++) {
734         GetStatus(chan, Status);
735         Status2 = UniataIsIdle(chan->DeviceExtension, Status);
736         if(Status2 == IDE_STATUS_WRONG) {
737             // no drive ?
738             break;
739         } else
740         if(Status2 & IDE_STATUS_BUSY) {
741             AtapiStallExecution(10);
742             continue;
743         } else {
744             break;
745         }
746     }
747     return Status;
748 } // end WaitForIdleLong()
749 
750 UCHAR
751 DDKFASTAPI
752 WaitForDrq(
753     IN PHW_CHANNEL   chan
754     )
755 {
756     ULONG i;
757     UCHAR Status;
758     for (i=0; i<1000; i++) {
759         GetStatus(chan, Status);
760         if (Status & IDE_STATUS_BUSY) {
761             AtapiStallExecution(g_opt_WaitDrqDelay);
762         } else if (Status & IDE_STATUS_DRQ) {
763             break;
764         } else {
765             AtapiStallExecution(g_opt_WaitDrqDelay*2);
766         }
767     }
768     return Status;
769 } // end WaitForDrq()
770 
771 UCHAR
772 DDKFASTAPI
773 WaitShortForDrq(
774     IN PHW_CHANNEL   chan
775     )
776 {
777     ULONG i;
778     UCHAR Status;
779     for (i=0; i<2; i++) {
780         GetStatus(chan, Status);
781         if (Status & IDE_STATUS_BUSY) {
782             AtapiStallExecution(g_opt_WaitDrqDelay);
783         } else if (Status & IDE_STATUS_DRQ) {
784             break;
785         } else {
786             AtapiStallExecution(g_opt_WaitDrqDelay);
787         }
788     }
789     return Status;
790 } // end WaitShortForDrq()
791 
792 VOID
793 DDKFASTAPI
794 AtapiSoftReset(
795     IN PHW_CHANNEL   chan,
796     IN ULONG         DeviceNumber
797     )
798 {
799     //ULONG c = chan->lChannel;
800     ULONG i = 30 * 1000;
801     UCHAR dma_status = 0;
802     KdPrint2((PRINT_PREFIX "AtapiSoftReset:\n"));
803     UCHAR statusByte0, statusByte2;
804 
805     if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
806         UniataAhciSoftReset(chan->DeviceExtension, chan->lChannel, DeviceNumber);
807         return;
808     }
809 
810     GetBaseStatus(chan, statusByte2);
811     KdPrint2((PRINT_PREFIX "  statusByte2 %x:\n", statusByte2));
812     SelectDrive(chan, DeviceNumber);
813     if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MANUAL_CHS) {
814         // For ESDI/MFM
815         KdPrint2((PRINT_PREFIX "  ESDI/MFM\n"));
816         AtapiStallExecution(10000);
817         for (i = 0; i < 1000; i++) {
818             AtapiStallExecution(999);
819         }
820 /*    } else
821     // Seems to be unnecessary, verified by KtP
822     if(!hasPCI) {
823         // original atapi.sys behavior for old ISA-only hardware
824         AtapiStallExecution(10000);
825         AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
826         for (i = 0; i < 1000; i++) {
827             AtapiStallExecution(999);
828         } */
829     } else {
830         AtapiStallExecution(500);
831         GetBaseStatus(chan, statusByte2);
832         statusByte0 = statusByte2;
833         AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
834 
835         // Do not wait for BUSY assertion if it was initially set, jump to
836         // BUSY release wait loop
837         if(!(statusByte0 & IDE_STATUS_BUSY)) {
838             // Wait for BUSY assertion, in some cases delay may occure
839             // 100ms should be enough
840             if(g_opt_VirtualMachine == VM_BOCHS) {
841                 i = 100;
842             } else {
843                 i = 10*1000;
844             }
845             statusByte2 = AtapiReadPort1(chan, IDX_IO1_i_Status);
846             while (!(statusByte2 & IDE_STATUS_BUSY) &&
847                    i--)
848             {
849                 if(!(statusByte0 & IDE_STATUS_ERROR) && (statusByte2 & IDE_STATUS_ERROR)) {
850                     KdPrint2((PRINT_PREFIX "  Command aborted, statusByte2 %x:\n", statusByte2));
851                     break;
852                 }
853                 AtapiStallExecution(10);
854             }
855         }
856 
857         i = 30 * 1000;
858         // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
859         // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
860         // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
861         // implementation. (which is around 1 second)
862         while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
863                i--)
864         {
865             AtapiStallExecution(30);
866         }
867         KdPrint2((PRINT_PREFIX " set DFLAGS_REINIT_DMA\n"));
868         chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_REINIT_DMA;
869     }
870 
871     chan->last_devsel = -1; // make sure proper drive would be selected
872     SelectDrive(chan, DeviceNumber);
873     WaitOnBusy(chan);
874     GetBaseStatus(chan, statusByte2);
875     AtapiStallExecution(500);
876 
877     GetBaseStatus(chan, statusByte2);
878     if(chan && chan->DeviceExtension) {
879         dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
880         KdPrint2((PRINT_PREFIX "  DMA status %#x\n", dma_status));
881     } else {
882         KdPrint2((PRINT_PREFIX "  can't get DMA status\n"));
883     }
884     if(dma_status & BM_STATUS_INTR) {
885         // bullshit, we have DMA interrupt, but had never initiate DMA operation
886         KdPrint2((PRINT_PREFIX "  clear unexpected DMA intr on ATAPI reset\n"));
887         AtapiDmaDone(chan->DeviceExtension, DeviceNumber, chan->lChannel, NULL);
888         GetBaseStatus(chan, statusByte2);
889     }
890     if(chan->DeviceExtension->HwFlags & UNIATA_SATA) {
891         UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, DeviceNumber);
892 /*        if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
893             UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1);
894         }*/
895     }
896     return;
897 
898 } // end AtapiSoftReset()
899 
900 VOID
901 DDKFASTAPI
902 AtapiHardReset(
903     IN struct _HW_CHANNEL*   chan,
904     IN BOOLEAN               DisableInterrupts,
905     IN ULONG                 Delay
906     )
907 {
908     KdPrint2((PRINT_PREFIX "AtapiHardReset: %d, dis=%d\n", Delay, DisableInterrupts));
909     AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_RESET_CONTROLLER |
910                               (DisableInterrupts ? IDE_DC_DISABLE_INTERRUPTS : 0));
911     chan->last_devsel = -1;
912     AtapiStallExecution(Delay);
913     AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_REENABLE_CONTROLLER);
914 } // end AtapiHardReset()
915 
916 /*
917     Send command to device.
918     Translate to 48-Lba form if required
919 */
920 UCHAR
921 NTAPI
922 AtaCommand48(
923     IN PHW_DEVICE_EXTENSION deviceExtension,
924     IN ULONG DeviceNumber,
925     IN ULONG lChannel,
926     IN UCHAR command,
927     IN ULONGLONG lba,
928     IN USHORT count,
929     IN USHORT feature,
930     IN ULONG wait_flags
931     )
932 {
933     PHW_CHANNEL          chan = &(deviceExtension->chan[lChannel]);
934     UCHAR                statusByte;
935     ULONG i;
936     PUCHAR plba;
937 
938     KdPrint2((PRINT_PREFIX "AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
939                  deviceExtension->DevIndex, deviceExtension->Channel, DeviceNumber, command, lba, count, feature ));
940 
941     if(deviceExtension->HwFlags & UNIATA_AHCI) {
942         //PIDE_AHCI_CMD  AHCI_CMD = &(chan->AhciCtlBlock->cmd);
943 
944         KdPrint3(("  (ahci)\n"));
945 
946         statusByte = UniataAhciSendPIOCommand(deviceExtension, lChannel, DeviceNumber,
947             (PSCSI_REQUEST_BLOCK)NULL,
948             NULL,
949             0,
950             command,
951             lba, count,
952             feature,
953             0 /* ahci flags */ ,
954             wait_flags,
955             1000 /* timeout 1 sec */
956             );
957 
958         return statusByte;
959     }
960 
961     SelectDrive(chan, DeviceNumber);
962 
963     statusByte = WaitOnBusy(chan);
964 
965     /* ready to issue command ? */
966     if (statusByte & IDE_STATUS_BUSY) {
967         KdPrint2((PRINT_PREFIX "  Returning BUSY status\n"));
968         return statusByte;
969     }
970     // !!! We should not check ERROR condition here
971     // ERROR bit may be asserted durring previous operation
972     // and not cleared after SELECT
973 
974     //>>>>>> NV: 2006/08/03
975     if(((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp|ATA_CMD_FLAG_FUA)) == ATA_CMD_FLAG_LBAIOsupp) &&
976        CheckIfBadBlock(chan->lun[DeviceNumber], lba, count)) {
977         KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count));
978         return IDE_STATUS_ERROR;
979         //return SRB_STATUS_ERROR;
980     }
981     //<<<<<< NV:  2006/08/03
982 
983     /* only use 48bit addressing if needed because of the overhead */
984     if (UniAta_need_lba48(command, lba, count,
985         chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48)) {
986 
987         KdPrint2((PRINT_PREFIX "  dev %#x USE_LBA_48\n", DeviceNumber ));
988         /* translate command into 48bit version */
989         if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) {
990             command = AtaCommands48[command];
991         } else {
992             KdPrint2((PRINT_PREFIX "  unhandled LBA48 command\n"));
993 			return (UCHAR)-1;
994         }
995 
996         chan->ChannelCtrlFlags |= CTRFLAGS_LBA48;
997         plba = (PUCHAR)&lba;
998 
999         AtapiWritePort1(chan, IDX_IO1_o_Feature,      (UCHAR)(feature>>8));
1000         AtapiWritePort1(chan, IDX_IO1_o_Feature,      (UCHAR)feature);
1001         AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   (UCHAR)(count>>8));
1002         AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   (UCHAR)count);
1003         AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  (UCHAR)(plba[3]));
1004         AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  (UCHAR)(plba[0]));
1005         AtapiWritePort1(chan, IDX_IO1_o_CylinderLow,  (UCHAR)(plba[4]));
1006         AtapiWritePort1(chan, IDX_IO1_o_CylinderLow,  (UCHAR)(plba[1]));
1007         AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[5]));
1008         AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[2]));
1009 
1010         //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber ));
1011         AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) );
1012     } else {
1013 
1014         plba = (PUCHAR)&lba; //ktp
1015         chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48;
1016 
1017         //if(feature ||
1018         //   (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
1019             AtapiWritePort1(chan, IDX_IO1_o_Feature,      (UCHAR)feature);
1020         //}
1021         AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   (UCHAR)count);
1022         AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  (UCHAR)plba[0]);
1023         AtapiWritePort1(chan, IDX_IO1_o_CylinderLow,  (UCHAR)plba[1]);
1024         AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)plba[2]);
1025         if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_LBA_ENABLED) {
1026             //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber ));
1027             AtapiWritePort1(chan, IDX_IO1_o_DriveSelect,  (UCHAR)(plba[3] & 0xf) | IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
1028         } else {
1029             //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber ));
1030             AtapiWritePort1(chan, IDX_IO1_o_DriveSelect,  (UCHAR)(plba[3] & 0xf) | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
1031         }
1032     }
1033 
1034     // write command code to device
1035     AtapiWritePort1(chan, IDX_IO1_o_Command, command);
1036 
1037     switch (wait_flags) {
1038     case ATA_WAIT_INTR:
1039 
1040         // caller requested wait for interrupt
1041         for(i=0;i<4;i++) {
1042             WaitOnBusy(chan);
1043             statusByte = WaitForDrq(chan);
1044             if (statusByte & IDE_STATUS_DRQ)
1045                 break;
1046             AtapiStallExecution(500);
1047             KdPrint2((PRINT_PREFIX "  retry waiting DRQ, status %#x\n", statusByte));
1048         }
1049 
1050         return statusByte;
1051 
1052     case ATA_WAIT_IDLE:
1053 
1054         // caller requested wait for entering Wait state
1055         for (i=0; i<30 * 1000; i++) {
1056 
1057             GetStatus(chan, statusByte);
1058             statusByte = UniataIsIdle(deviceExtension, statusByte);
1059             if(statusByte == IDE_STATUS_WRONG) {
1060                 // no drive ?
1061                 break;
1062             } else
1063             if(statusByte & IDE_STATUS_ERROR) {
1064                 break;
1065             } else
1066             if(statusByte & IDE_STATUS_BUSY) {
1067                 AtapiStallExecution(100);
1068                 continue;
1069             } else
1070             if((statusByte & ~IDE_STATUS_INDEX) == IDE_STATUS_IDLE) {
1071                 break;
1072             } else {
1073                 //if(deviceExtension->HwFlags & UNIATA_SATA) {
1074                 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1075                     break;
1076                 }
1077                 AtapiStallExecution(100);
1078             }
1079         }
1080         //statusByte |= IDE_STATUS_BUSY;
1081         break;
1082 
1083     case ATA_WAIT_READY:
1084         statusByte = WaitOnBusyLong(chan);
1085         break;
1086     case ATA_WAIT_BASE_READY:
1087         statusByte = WaitOnBaseBusyLong(chan);
1088         break;
1089     case ATA_IMMEDIATE:
1090         GetStatus(chan, statusByte);
1091         if (statusByte & IDE_STATUS_ERROR) {
1092             KdPrint2((PRINT_PREFIX "  Warning: Immed Status %#x :(\n", statusByte));
1093             if(statusByte == (IDE_STATUS_IDLE | IDE_STATUS_ERROR)) {
1094                 break;
1095             }
1096             KdPrint2((PRINT_PREFIX "  try to continue\n"));
1097             statusByte &= ~IDE_STATUS_ERROR;
1098 
1099         } else {
1100             //KdPrint2((PRINT_PREFIX "  send Status %#x\n", statusByte));
1101         }
1102         UniataExpectChannelInterrupt(chan, TRUE);
1103         // !!!!!
1104         InterlockedExchange(&(chan->CheckIntr),
1105                                       CHECK_INTR_IDLE);
1106 
1107         statusByte = IDE_STATUS_SUCCESS;
1108         break;
1109     }
1110 
1111     //KdPrint2((PRINT_PREFIX "  Status %#x\n", statusByte));
1112 
1113     return statusByte;
1114 } // end AtaCommand48()
1115 
1116 /*
1117     Send command to device.
1118     This is simply wrapper for AtaCommand48()
1119 */
1120 UCHAR
1121 NTAPI
1122 AtaCommand(
1123     IN PHW_DEVICE_EXTENSION deviceExtension,
1124     IN ULONG DeviceNumber,
1125     IN ULONG lChannel,
1126     IN UCHAR command,
1127     IN USHORT cylinder,
1128     IN UCHAR head,
1129     IN UCHAR sector,
1130     IN UCHAR count,
1131     IN UCHAR feature,
1132     IN ULONG wait_flags
1133     )
1134 {
1135     if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
1136         return AtaCommand48(deviceExtension, DeviceNumber, lChannel,
1137                             command,
1138                             (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
1139                             count, feature, wait_flags);
1140     } else {
1141         return UniataAhciSendPIOCommand(deviceExtension, lChannel, DeviceNumber,
1142             (PSCSI_REQUEST_BLOCK)NULL,
1143             NULL,
1144             0,
1145             command,
1146             (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
1147             count,
1148             feature,
1149             0 /* ahci flags */ ,
1150             wait_flags,
1151             1000 /* timeout 1 sec */
1152             );
1153 
1154     }
1155 } // end AtaCommand()
1156 
1157 LONG
1158 NTAPI
1159 AtaPio2Mode(LONG pio)
1160 {
1161     switch (pio) {
1162     default: return ATA_PIO;
1163     case 0: return ATA_PIO0;
1164     case 1: return ATA_PIO1;
1165     case 2: return ATA_PIO2;
1166     case 3: return ATA_PIO3;
1167     case 4: return ATA_PIO4;
1168     case 5: return ATA_PIO5;
1169     }
1170 } // end AtaPio2Mode()
1171 
1172 LONG
1173 NTAPI
1174 AtaPioMode(PIDENTIFY_DATA2 ident)
1175 {
1176     if (ident->PioTimingsValid) {
1177         if (ident->AdvancedPIOModes & AdvancedPIOModes_5)
1178             return 5;
1179         if (ident->AdvancedPIOModes & AdvancedPIOModes_4)
1180             return 4;
1181         if (ident->AdvancedPIOModes & AdvancedPIOModes_3)
1182             return 3;
1183     }
1184     if (ident->PioCycleTimingMode == 2)
1185         return 2;
1186     if (ident->PioCycleTimingMode == 1)
1187         return 1;
1188     if (ident->PioCycleTimingMode == 0)
1189         return 0;
1190     return IOMODE_NOT_SPECIFIED;
1191 } // end AtaPioMode()
1192 
1193 LONG
1194 NTAPI
1195 AtaWmode(PIDENTIFY_DATA2 ident)
1196 {
1197     if (ident->MultiWordDMASupport & 0x04)
1198         return 2;
1199     if (ident->MultiWordDMASupport & 0x02)
1200         return 1;
1201     if (ident->MultiWordDMASupport & 0x01)
1202         return 0;
1203     return IOMODE_NOT_SPECIFIED;
1204 } // end AtaWmode()
1205 
1206 LONG
1207 NTAPI
1208 AtaUmode(PIDENTIFY_DATA2 ident)
1209 {
1210     if (!ident->UdmaModesValid)
1211         return IOMODE_NOT_SPECIFIED;
1212     if (ident->UltraDMASupport & 0x40)
1213         return 6;
1214     if (ident->UltraDMASupport & 0x20)
1215         return 5;
1216     if (ident->UltraDMASupport & 0x10)
1217         return 4;
1218     if (ident->UltraDMASupport & 0x08)
1219         return 3;
1220     if (ident->UltraDMASupport & 0x04)
1221         return 2;
1222     if (ident->UltraDMASupport & 0x02)
1223         return 1;
1224     if (ident->UltraDMASupport & 0x01)
1225         return 0;
1226     return IOMODE_NOT_SPECIFIED;
1227 } // end AtaUmode()
1228 
1229 LONG
1230 NTAPI
1231 AtaSAmode(PIDENTIFY_DATA2 ident) {
1232     if(!ident->SataCapabilities ||
1233        ident->SataCapabilities == 0xffff) {
1234         return IOMODE_NOT_SPECIFIED;
1235     }
1236     if(ident->SataCapabilities & ATA_SATA_GEN3) {
1237         return ATA_SA600;
1238     } else
1239     if(ident->SataCapabilities & ATA_SATA_GEN2) {
1240         return ATA_SA300;
1241     } else
1242     if(ident->SataCapabilities & ATA_SATA_GEN1) {
1243         return ATA_SA150;
1244     }
1245     return IOMODE_NOT_SPECIFIED;
1246 } // end AtaSAmode()
1247 
1248 #ifndef UNIATA_CORE
1249 
1250 VOID
1251 NTAPI
1252 AtapiTimerDpc(
1253     IN PVOID HwDeviceExtension
1254     )
1255 {
1256     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1257     PHW_TIMER HwScsiTimer;
1258     LARGE_INTEGER time;
1259     ULONG MiniportTimerValue;
1260     BOOLEAN recall = FALSE;
1261     ULONG lChannel;
1262     PHW_CHANNEL chan;
1263 
1264     KdPrint2((PRINT_PREFIX "AtapiTimerDpc:\n"));
1265 
1266     lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
1267     if(lChannel == CHAN_NOT_SPECIFIED) {
1268         KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no items\n"));
1269         return;
1270     }
1271     chan = &(deviceExtension->chan[lChannel]);
1272 
1273     while(TRUE) {
1274 
1275         HwScsiTimer = chan->HwScsiTimer;
1276         chan->HwScsiTimer = NULL;
1277 
1278         deviceExtension->FirstDpcChan = chan->NextDpcChan;
1279         if(deviceExtension->FirstDpcChan != CHAN_NOT_SPECIFIED) {
1280             recall = TRUE;
1281         }
1282 
1283         HwScsiTimer(HwDeviceExtension);
1284 
1285         chan->NextDpcChan = CHAN_NOT_SPECIFIED;
1286 
1287         lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
1288         if(lChannel == CHAN_NOT_SPECIFIED) {
1289             KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no more items\n"));
1290             deviceExtension->FirstDpcChan =
1291             deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
1292             return;
1293         }
1294 
1295         KeQuerySystemTime(&time);
1296         KdPrint2((PRINT_PREFIX "AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
1297 
1298         chan = &deviceExtension->chan[lChannel];
1299         if(time.QuadPart >= chan->DpcTime - 10) {
1300             // call now
1301             KdPrint2((PRINT_PREFIX "AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1302                          (ULONG)(chan->DpcTime >> 32), (ULONG)(chan->DpcTime)));
1303             continue;
1304         }
1305         break;
1306     }
1307 
1308     if(recall) {
1309         deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
1310         MiniportTimerValue = (ULONG)(time.QuadPart - chan->DpcTime)/10;
1311         if(!MiniportTimerValue)
1312             MiniportTimerValue = 1;
1313 
1314         KdPrint2((PRINT_PREFIX "AtapiTimerDpc: recall AtapiTimerDpc\n"));
1315         ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
1316                              AtapiTimerDpc,
1317                              MiniportTimerValue
1318                              );
1319     }
1320     return;
1321 
1322 } // end AtapiTimerDpc()
1323 
1324 /*
1325     Wrapper for ScsiPort, that implements smart Dpc
1326     queueing. We need it to allow parallel functioning
1327     of IDE channels with shared interrupt. Standard Dpc mechanism
1328     cancels previous Dpc request (if any), but we need Dpc queue.
1329 */
1330 VOID
1331 NTAPI
1332 AtapiQueueTimerDpc(
1333     IN PVOID HwDeviceExtension,
1334     IN ULONG lChannel,
1335     IN PHW_TIMER HwScsiTimer,
1336     IN ULONG MiniportTimerValue
1337     )
1338 {
1339     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1340     LARGE_INTEGER time;
1341     LARGE_INTEGER time2;
1342     ULONG i;
1343     PHW_CHANNEL prev_chan;
1344     PHW_CHANNEL chan;
1345 //    BOOLEAN UseRequestTimerCall = TRUE;
1346 
1347     KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
1348     KeQuerySystemTime(&time);
1349     time2 = time;
1350     KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
1351     time.QuadPart += MiniportTimerValue*10;
1352     KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time.HighPart, time.LowPart));
1353 
1354     KdPrint2((PRINT_PREFIX "  ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension->ActiveDpcChan, deviceExtension->FirstDpcChan));
1355 
1356     i = deviceExtension->FirstDpcChan;
1357     chan = prev_chan = NULL;
1358     while(i != CHAN_NOT_SPECIFIED) {
1359         prev_chan = chan;
1360         chan = &(deviceExtension->chan[i]);
1361         if(chan->DpcTime > time.QuadPart) {
1362             break;
1363         }
1364         i = chan->NextDpcChan;
1365     }
1366     chan = &(deviceExtension->chan[lChannel]);
1367     if(!prev_chan) {
1368         deviceExtension->FirstDpcChan = lChannel;
1369     } else {
1370         prev_chan->NextDpcChan = lChannel;
1371     }
1372     chan->NextDpcChan = i;
1373     chan->HwScsiTimer = HwScsiTimer;
1374     chan->DpcTime     = time.QuadPart;
1375 
1376     KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2.HighPart, time2.LowPart));
1377     if(time.QuadPart <= time2.QuadPart) {
1378         MiniportTimerValue = 1;
1379     } else {
1380         MiniportTimerValue = (ULONG)((time.QuadPart - time2.QuadPart) / 10);
1381     }
1382 
1383     KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
1384     ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
1385                          AtapiTimerDpc,
1386                          MiniportTimerValue);
1387 
1388 } // end AtapiQueueTimerDpc()
1389 
1390 #endif //UNIATA_CORE
1391 
1392 #ifdef _DEBUG
1393 VOID
1394 NTAPI
1395 UniataDumpATARegs(
1396     IN PHW_CHANNEL chan
1397     )
1398 {
1399     ULONG                j;
1400     UCHAR                statusByteAlt;
1401 
1402     GetStatus(chan, statusByteAlt);
1403     KdPrint2((PRINT_PREFIX "  AltStatus (%#x)\n", statusByteAlt));
1404 
1405     for(j=1; j<IDX_IO1_SZ; j++) {
1406         statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1407         KdPrint2((PRINT_PREFIX
1408                    "  Reg_%#x (%#x) = %#x\n",
1409                    j,
1410                    chan->RegTranslation[IDX_IO1+j].Addr,
1411                    statusByteAlt));
1412     }
1413     if(!chan->RegTranslation[IDX_BM_IO].Addr) {
1414         return;
1415     }
1416     for(j=0; j<IDX_BM_IO_SZ-1; j++) {
1417         statusByteAlt = AtapiReadPort1(chan, IDX_BM_IO+j);
1418         KdPrint2((PRINT_PREFIX
1419                    "  BM_%#x (%#x) = %#x\n",
1420                    j,
1421                    chan->RegTranslation[IDX_BM_IO+j].Addr,
1422                    statusByteAlt));
1423     }
1424     return;
1425 } // end UniataDumpATARegs()
1426 #endif //_DEBUG
1427 
1428 VOID
1429 NTAPI
1430 UniataSnapAtaRegs(
1431     IN PHW_CHANNEL chan,
1432     IN ULONG DeviceNumber,
1433  IN OUT PIDEREGS_EX regs
1434     )
1435 {
1436     if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
1437         // AHCI
1438         UniataAhciSnapAtaRegs(chan, DeviceNumber, regs);
1439     } else {
1440         // SATA/PATA, assume drive is selected
1441         ULONG                j;
1442         UCHAR                statusByteAlt;
1443 
1444         if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) {
1445             for(j=IDX_IO1_i_Error; j<=IDX_IO1_i_Status; j++) {
1446                 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1447                 ((PUCHAR)regs)[j-1] = statusByteAlt;
1448             }
1449             regs->bOpFlags = 0;
1450         } else {
1451             regs->bDriveHeadReg    = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect);
1452             for(j=IDX_IO1_i_Error; j<IDX_IO1_i_DriveSelect; j++) {
1453                 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1454                 ((PUCHAR)regs)[j-1] = statusByteAlt;
1455                 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1456                 ((PUCHAR)regs)[j+8-1] = statusByteAlt;
1457             }
1458             regs->bCommandReg      = AtapiReadPort1(chan, IDX_IO1_i_Status);
1459         }
1460     }
1461     return;
1462 } // end UniataSnapAtaRegs()
1463 
1464 /*++
1465 
1466 Routine Description:
1467 
1468     Issue IDENTIFY command to a device.
1469 
1470 Arguments:
1471 
1472     HwDeviceExtension - HBA miniport driver's adapter data storage
1473     DeviceNumber - Indicates which device.
1474     Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1475 
1476 Return Value:
1477 
1478     TRUE if all goes well.
1479 
1480 --*/
1481 BOOLEAN
1482 NTAPI
1483 IssueIdentify(
1484     IN PVOID HwDeviceExtension,
1485     IN ULONG DeviceNumber,
1486     IN ULONG lChannel,
1487     IN UCHAR Command,
1488     IN BOOLEAN NoSetup
1489     )
1490 {
1491     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1492     PHW_CHANNEL          chan = &(deviceExtension->chan[lChannel]);
1493     ULONG                waitCount = 50000;
1494     ULONG                j;
1495     UCHAR                statusByte;
1496     //UCHAR                statusByte2;
1497     UCHAR                signatureLow,
1498                          signatureHigh;
1499     BOOLEAN              atapiDev = FALSE;
1500     BOOLEAN              use_ahci = FALSE;
1501     PHW_LU_EXTENSION     LunExt = chan->lun[DeviceNumber];
1502 
1503     use_ahci = UniataIsSATARangeAvailable(deviceExtension, lChannel) &&
1504         (deviceExtension->HwFlags & UNIATA_AHCI);
1505 
1506     if(chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) {
1507         if(chan->PmLunMap & (1 << DeviceNumber)) {
1508             // OK
1509         } else {
1510             KdPrint2((PRINT_PREFIX "IssueIdentify: PM empty port\n"));
1511             return FALSE;
1512         }
1513     } else
1514     if(DeviceNumber && (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
1515         KdPrint2((PRINT_PREFIX "IssueIdentify: NO SLAVE\n"));
1516         return FALSE;
1517     }
1518     if(LunExt->DeviceFlags & DFLAGS_HIDDEN) {
1519         KdPrint2((PRINT_PREFIX "IssueIdentify: HIDDEN\n"));
1520         return FALSE;
1521     }
1522 
1523     if(use_ahci) {
1524         statusByte = WaitOnBusyLong(chan);
1525 #ifdef _DEBUG
1526         if(!chan->AhciInternalAtaReq) {
1527             KdPrint2((PRINT_PREFIX "!AhciInternalAtaReq\n"));
1528         }
1529 #endif
1530     } else {
1531         SelectDrive(chan, DeviceNumber);
1532         AtapiStallExecution(10);
1533         statusByte = WaitOnBusyLong(chan);
1534         // Check that the status register makes sense.
1535         GetBaseStatus(chan, statusByte);
1536         /*
1537         // unnecessary
1538         if(!hasPCI) {
1539             // original atapi.sys behavior for old ISA-only hardware
1540             AtapiStallExecution(100);
1541         }
1542         */
1543     }
1544 
1545     if (Command == IDE_COMMAND_IDENTIFY) {
1546         // Mask status byte ERROR bits.
1547         statusByte = UniataIsIdle(deviceExtension, statusByte & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX));
1548         KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte));
1549         // Check if register value is reasonable.
1550 
1551         if(statusByte != IDE_STATUS_IDLE) {
1552 
1553             // No reset here !!!
1554             KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1555 
1556             //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1557             if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1558                 SelectDrive(chan, DeviceNumber);
1559                 WaitOnBusyLong(chan);
1560 
1561                 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1562                 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1563 
1564                 if (signatureLow == ATAPI_MAGIC_LSB &&
1565                     signatureHigh == ATAPI_MAGIC_MSB) {
1566                     // Device is Atapi.
1567                     KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber));
1568                     return FALSE;
1569                 }
1570 
1571                 // We really should wait up to 31 seconds
1572                 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1573                 // (30 seconds for device 1)
1574                 do {
1575                     // Wait for Busy to drop.
1576                     AtapiStallExecution(100);
1577                     GetStatus(chan, statusByte);
1578                     if(statusByte == IDE_STATUS_WRONG) {
1579                         KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_WRONG (dev %d)\n", DeviceNumber));
1580                         return FALSE;
1581                     }
1582 
1583                 } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
1584                 GetBaseStatus(chan, statusByte);
1585 
1586                 SelectDrive(chan, DeviceNumber);
1587             } else {
1588                 GetBaseStatus(chan, statusByte);
1589             }
1590             // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1591             // a soft reset.
1592             signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1593             signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1594 
1595             if (signatureLow == ATAPI_MAGIC_LSB &&
1596                 signatureHigh == ATAPI_MAGIC_MSB) {
1597                 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber));
1598                 // Device is Atapi.
1599                 return FALSE;
1600             }
1601 
1602             statusByte = UniataIsIdle(deviceExtension, statusByte) & ~IDE_STATUS_INDEX;
1603             if (statusByte != IDE_STATUS_IDLE) {
1604                 // Give up on this.
1605                 KdPrint2((PRINT_PREFIX "IssueIdentify: no dev (dev %d)\n", DeviceNumber));
1606                 return FALSE;
1607             }
1608         }
1609     } else {
1610         KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte));
1611         if(statusByte == IDE_STATUS_WRONG) {
1612             return FALSE;
1613         }
1614         //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1615         if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1616             statusByte = WaitForIdleLong(chan);
1617             KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte));
1618         }
1619         atapiDev = TRUE;
1620     }
1621 
1622 //    if(deviceExtension->HwFlags & UNIATA_SATA) {
1623     if(use_ahci) {
1624         statusByte = UniataAhciSendPIOCommand(HwDeviceExtension, lChannel, DeviceNumber,
1625             (PSCSI_REQUEST_BLOCK)NULL,
1626             (PUCHAR)(&deviceExtension->FullIdentifyData),
1627             DEV_BSIZE,
1628             Command,
1629             0, 0,
1630             0,
1631             0 /* ahci flags */ ,
1632             ATA_WAIT_INTR,
1633             1000 /* timeout 1 sec */
1634             );
1635         j = 9; // AHCI is rather different, skip loop at all
1636     } else
1637     if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) {
1638         j = 9; // don't send IDENTIFY, assume it is not supported
1639         KdPrint2((PRINT_PREFIX "IssueIdentify: Manual CHS\n"));
1640         RtlZeroMemory(&(deviceExtension->FullIdentifyData), sizeof(deviceExtension->FullIdentifyData));
1641         RtlCopyMemory(&(deviceExtension->FullIdentifyData), &(LunExt->IdentifyData), sizeof(LunExt->IdentifyData));
1642     } else
1643     if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1644         j = 4; // skip old-style checks
1645     } else {
1646         j = 0;
1647     }
1648     for (; j < 4*2; j++) {
1649         // Send IDENTIFY command.
1650 
1651         // Load CylinderHigh and CylinderLow with number bytes to transfer for old devices, use 0 for newer.
1652 
1653         statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, Command, (j < 4) ? DEV_BSIZE : 0 /* cyl */, 0, 0, 0, 0, ATA_WAIT_INTR);
1654         // Clear interrupt
1655 
1656         if (!statusByte) {
1657             KdPrint2((PRINT_PREFIX "IssueIdentify: 0-status, not present\n"));
1658             return FALSE;
1659         } else
1660         if (statusByte & IDE_STATUS_DRQ) {
1661             // Read status to acknowledge any interrupts generated.
1662             KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte));
1663             GetBaseStatus(chan, statusByte);
1664             // One last check for Atapi.
1665             if (Command == IDE_COMMAND_IDENTIFY) {
1666                 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1667                 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1668 
1669                 if (signatureLow == ATAPI_MAGIC_LSB &&
1670                     signatureHigh == ATAPI_MAGIC_MSB) {
1671                     KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber));
1672                     // Device is Atapi.
1673                     return FALSE;
1674                 }
1675             }
1676             break;
1677         } else {
1678             KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte));
1679             if (Command == IDE_COMMAND_IDENTIFY) {
1680                 // Check the signature. If DRQ didn't come up it's likely Atapi.
1681                 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1682                 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1683 
1684                 if (signatureLow == ATAPI_MAGIC_LSB &&
1685                     signatureHigh == ATAPI_MAGIC_MSB) {
1686                     // Device is Atapi.
1687                     KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber));
1688                     return FALSE;
1689                 }
1690             } else {
1691                 if(!(statusByte & IDE_STATUS_ERROR) && (statusByte & IDE_STATUS_BUSY)) {
1692                     KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n"));
1693                     break;
1694                 }
1695             }
1696             // Device didn't respond correctly. It will be given one more chance.
1697             KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1698                         statusByte, AtapiReadPort1(chan, IDX_IO1_i_Error)));
1699             GetBaseStatus(chan, statusByte);
1700             AtapiSoftReset(chan,DeviceNumber);
1701 
1702             AtapiDisableInterrupts(deviceExtension, lChannel);
1703             AtapiEnableInterrupts(deviceExtension, lChannel);
1704 
1705             GetBaseStatus(chan, statusByte);
1706             //GetStatus(chan, statusByte);
1707             KdPrint2((PRINT_PREFIX "IssueIdentify: Status after soft reset (%#x)\n", statusByte));
1708         }
1709     }
1710     // Check for error on really stupid master devices that assert random
1711     // patterns of bits in the status register at the slave address.
1712     if ((Command == IDE_COMMAND_IDENTIFY) && (statusByte & IDE_STATUS_ERROR)) {
1713         KdPrint2((PRINT_PREFIX "IssueIdentify: Exit on error (%#x)\n", statusByte));
1714         return FALSE;
1715     }
1716 
1717     if(use_ahci) {
1718         // everything should already be done by controller
1719     } else
1720     if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) {
1721         j = 9; // don't send IDENTIFY, assume it is not supported
1722         KdPrint2((PRINT_PREFIX "IssueIdentify: Manual CHS (2)\n"));
1723         statusByte = WaitForDrq(chan);
1724         statusByte = WaitOnBusyLong(chan);
1725             KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1726         GetBaseStatus(chan, statusByte);
1727     } else {
1728 
1729         KdPrint2((PRINT_PREFIX "IssueIdentify: Status before read words %#x\n", statusByte));
1730         // Suck out 256 words. After waiting for one model that asserts busy
1731         // after receiving the Packet Identify command.
1732         statusByte = WaitForDrq(chan);
1733         statusByte = WaitOnBusyLong(chan);
1734             KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1735 
1736         if (!(statusByte & IDE_STATUS_DRQ)) {
1737             KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte));
1738             GetBaseStatus(chan, statusByte);
1739             return FALSE;
1740         }
1741         GetBaseStatus(chan, statusByte);
1742         KdPrint2((PRINT_PREFIX "IssueIdentify: BASE statusByte %#x\n", statusByte));
1743 
1744 #ifdef _DEBUG
1745         if(atapiDev) {
1746           j = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
1747           KdPrint3((PRINT_PREFIX "IssueIdentify: iReason %x\n", j));
1748 
1749           j =
1750               AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
1751 
1752           j |=
1753               (USHORT)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8;
1754           KdPrint3((PRINT_PREFIX "IssueIdentify: wCount %x\n", j));
1755 
1756         }
1757 #endif //_DEBUG
1758 
1759         if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
1760 
1761             KdPrint2((PRINT_PREFIX "  use 16bit IO\n"));
1762             // ATI/SII chipsets with memory-mapped IO hangs when
1763             // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1764             // Unfortunately, I don't know yet how to workaround it except
1765             // spacifying manual delay in the way you see below.
1766             ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
1767 
1768             // Work around for some IDE and one model Atapi that will present more than
1769             // 256 bytes for the Identify data.
1770             KdPrint2((PRINT_PREFIX "IssueIdentify: suck data port\n", statusByte));
1771             statusByte = AtapiSuckPort2(chan);
1772         } else {
1773             KdPrint2((PRINT_PREFIX "  use 32bit IO\n"));
1774             ReadBuffer2(chan, (PULONG)&deviceExtension->FullIdentifyData, 256/2, PIO0_TIMING);
1775         }
1776 
1777         KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1778         statusByte = WaitForDrq(chan);
1779         KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1780         GetBaseStatus(chan, statusByte);
1781     }
1782     KdPrint2((PRINT_PREFIX "IssueIdentify: Status after read words %#x\n", statusByte));
1783 
1784     if(NoSetup) {
1785         KdPrint2((PRINT_PREFIX "IssueIdentify: no setup, exiting\n"));
1786         return TRUE;
1787     }
1788 
1789     KdPrint2((PRINT_PREFIX "Model: %20.20s\n", deviceExtension->FullIdentifyData.ModelNumber));
1790     KdPrint2((PRINT_PREFIX "FW:    %4.4s\n", deviceExtension->FullIdentifyData.FirmwareRevision));
1791     KdPrint2((PRINT_PREFIX "S/N:   %20.20s\n", deviceExtension->FullIdentifyData.SerialNumber));
1792     if(g_opt_VirtualMachine == VM_AUTO) {
1793         if((deviceExtension->FullIdentifyData.FirmwareRevision[0] == 0 ||
1794            deviceExtension->FullIdentifyData.FirmwareRevision[0] == ' ') &&
1795            (deviceExtension->FullIdentifyData.FirmwareRevision[1] == 0 ||
1796            deviceExtension->FullIdentifyData.FirmwareRevision[1] == ' ')) {
1797             // Check for BOCHS VM signature. If no additional PCI devices (e.g. VGA)
1798             // are declared BOCHS looks like regular PC
1799             if (!atapiDev && !AtapiStringCmp ((PCCHAR)(deviceExtension->FullIdentifyData.SerialNumber), "XBDH00", 6)) {
1800                 KdPrint2((PRINT_PREFIX "IssueIdentify: BOCHS HDD\n"));
1801                 g_opt_VirtualMachine = VM_BOCHS;
1802             } else
1803             if (atapiDev && !AtapiStringCmp ((PCCHAR)(deviceExtension->FullIdentifyData.SerialNumber), "XBDC00", 6)) {
1804                 KdPrint2((PRINT_PREFIX "IssueIdentify: BOCHS CD\n"));
1805                 g_opt_VirtualMachine = VM_BOCHS;
1806             }
1807         }
1808     }
1809 
1810     KdPrint2((PRINT_PREFIX "Pio:   %x\n", deviceExtension->FullIdentifyData.PioCycleTimingMode));
1811     if(deviceExtension->FullIdentifyData.PioTimingsValid) {
1812         KdPrint2((PRINT_PREFIX "APio:  %x\n", deviceExtension->FullIdentifyData.AdvancedPIOModes));
1813     }
1814     KdPrint2((PRINT_PREFIX "SWDMA: %x\n", deviceExtension->FullIdentifyData.SingleWordDMAActive));
1815     KdPrint2((PRINT_PREFIX "MWDMA: %x\n", deviceExtension->FullIdentifyData.MultiWordDMAActive));
1816     if(deviceExtension->FullIdentifyData.UdmaModesValid) {
1817         KdPrint2((PRINT_PREFIX "UDMA:  %x/%x\n", deviceExtension->FullIdentifyData.UltraDMAActive, deviceExtension->FullIdentifyData.UltraDMASupport));
1818     }
1819     KdPrint2((PRINT_PREFIX "SATA:  %x\n", deviceExtension->FullIdentifyData.SataEnable));
1820     KdPrint2((PRINT_PREFIX "SATA support: %x, CAPs %#x\n",
1821         deviceExtension->FullIdentifyData.SataSupport,
1822         deviceExtension->FullIdentifyData.SataCapabilities));
1823 
1824     LunExt->LimitedTransferMode =
1825     LunExt->OrigTransferMode =
1826         (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData), IDENT_MODE_MAX);
1827     LunExt->TransferMode =
1828         (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData), IDENT_MODE_ACTIVE);
1829 
1830     KdPrint2((PRINT_PREFIX "OrigTransferMode: %x, Active: %x\n", LunExt->OrigTransferMode, LunExt->TransferMode));
1831     KdPrint2((PRINT_PREFIX "Accoustic %d, cur %d\n",
1832         deviceExtension->FullIdentifyData.VendorAcoustic,
1833         deviceExtension->FullIdentifyData.CurrentAcoustic
1834         ));
1835     KdPrint2((PRINT_PREFIX "AdvPowerMode %d\n",
1836         deviceExtension->FullIdentifyData.CfAdvPowerMode
1837         ));
1838 
1839     KdPrint2((PRINT_PREFIX "PowerMngt %d/%d, APM %d/%d\n",
1840         deviceExtension->FullIdentifyData.FeaturesEnabled.PowerMngt,
1841         deviceExtension->FullIdentifyData.FeaturesSupport.PowerMngt,
1842         deviceExtension->FullIdentifyData.FeaturesEnabled.APM,
1843         deviceExtension->FullIdentifyData.FeaturesSupport.APM
1844         ));
1845 
1846     // Check out a few capabilities / limitations of the device.
1847     if (deviceExtension->FullIdentifyData.RemovableStatus & 1) {
1848         // Determine if this drive supports the MSN functions.
1849         KdPrint2((PRINT_PREFIX "IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1850                     DeviceNumber,
1851                     deviceExtension->FullIdentifyData.RemovableStatus));
1852         LunExt->DeviceFlags |= DFLAGS_REMOVABLE_DRIVE;
1853     }
1854     if(use_ahci) {
1855         // AHCI doesn't recommend using PIO and multiblock
1856         LunExt->MaximumBlockXfer = 0;
1857     } else
1858     if (deviceExtension->FullIdentifyData.MaximumBlockTransfer) {
1859         // Determine max. block transfer for this device.
1860         LunExt->MaximumBlockXfer =
1861             (UCHAR)(deviceExtension->FullIdentifyData.MaximumBlockTransfer & 0xFF);
1862     }
1863     LunExt->NumOfSectors = 0;
1864     if (Command == IDE_COMMAND_IDENTIFY) {
1865         ULONGLONG NumOfSectors=0;
1866         ULONGLONG NativeNumOfSectors=0;
1867         ULONGLONG cylinders=0;
1868         ULONGLONG tmp_cylinders=0;
1869 
1870         KdPrint2((PRINT_PREFIX "PhysLogSectorSize %#x, %#x, offset %#x\n",
1871                 deviceExtension->FullIdentifyData.PhysLogSectorSize,
1872                 deviceExtension->FullIdentifyData.LargeSectorSize,
1873                 deviceExtension->FullIdentifyData.LogicalSectorOffset
1874                 ));
1875 
1876         KdPrint2((PRINT_PREFIX "NV PM_Sup %d, PM_En %d, En %d, PM ver %#x ver %#x\n",
1877                 deviceExtension->FullIdentifyData.NVCache_PM_Supported,
1878                 deviceExtension->FullIdentifyData.NVCache_PM_Enabled,
1879                 deviceExtension->FullIdentifyData.NVCache_Enabled,
1880                 deviceExtension->FullIdentifyData.NVCache_PM_Version,
1881                 deviceExtension->FullIdentifyData.NVCache_Version
1882                 ));
1883 
1884         KdPrint2((PRINT_PREFIX "R-rate %d\n",
1885                 deviceExtension->FullIdentifyData.NominalMediaRotationRate
1886                 ));
1887         KdPrint2((PRINT_PREFIX "WC %d/%d, LA %d/%d, WB %d/%d, RB %d/%d, Q %d/%d\n",
1888                 deviceExtension->FullIdentifyData.FeaturesEnabled.WriteCache,
1889                 deviceExtension->FullIdentifyData.FeaturesSupport.WriteCache,
1890                 deviceExtension->FullIdentifyData.FeaturesEnabled.LookAhead,
1891                 deviceExtension->FullIdentifyData.FeaturesSupport.LookAhead,
1892                 deviceExtension->FullIdentifyData.FeaturesEnabled.WriteBuffer,
1893                 deviceExtension->FullIdentifyData.FeaturesSupport.WriteBuffer,
1894                 deviceExtension->FullIdentifyData.FeaturesEnabled.ReadBuffer,
1895                 deviceExtension->FullIdentifyData.FeaturesSupport.ReadBuffer,
1896                 deviceExtension->FullIdentifyData.FeaturesEnabled.Queued,
1897                 deviceExtension->FullIdentifyData.FeaturesSupport.Queued
1898                 ));
1899 
1900         KdPrint2((PRINT_PREFIX "Protected %d/%d status %#x, rev %#x\n",
1901                 deviceExtension->FullIdentifyData.FeaturesEnabled.Protected,
1902                 deviceExtension->FullIdentifyData.FeaturesSupport.Protected,
1903                 deviceExtension->FullIdentifyData.SecurityStatus,
1904                 deviceExtension->FullIdentifyData.MasterPasswdRevision
1905                 ));
1906 
1907         // Read very-old-style drive geometry
1908         KdPrint2((PRINT_PREFIX "CHS %#x:%#x:%#x\n",
1909                 deviceExtension->FullIdentifyData.NumberOfCylinders,
1910                 deviceExtension->FullIdentifyData.NumberOfHeads,
1911                 deviceExtension->FullIdentifyData.SectorsPerTrack
1912                 ));
1913         NumOfSectors = deviceExtension->FullIdentifyData.NumberOfCylinders *
1914                        deviceExtension->FullIdentifyData.NumberOfHeads *
1915                        deviceExtension->FullIdentifyData.SectorsPerTrack;
1916         KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
1917         // Check for HDDs > 8Gb
1918         if ((deviceExtension->FullIdentifyData.NumberOfCylinders == 0x3fff) &&
1919 /*            (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1920              deviceExtension->FullIdentifyData.NumberOfHeads &&
1921              deviceExtension->FullIdentifyData.SectorsPerTrack &&
1922             (NumOfSectors < deviceExtension->FullIdentifyData.UserAddressableSectors)) {
1923             KdPrint2((PRINT_PREFIX "NumberOfCylinders == 0x3fff\n"));
1924             cylinders =
1925                 (deviceExtension->FullIdentifyData.UserAddressableSectors /
1926                     (deviceExtension->FullIdentifyData.NumberOfHeads *
1927                        deviceExtension->FullIdentifyData.SectorsPerTrack));
1928 
1929             KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
1930 
1931             NumOfSectors = cylinders *
1932                            deviceExtension->FullIdentifyData.NumberOfHeads *
1933                            deviceExtension->FullIdentifyData.SectorsPerTrack;
1934 
1935             KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
1936         } else {
1937 
1938         }
1939         // Check for LBA mode
1940         KdPrint2((PRINT_PREFIX "SupportLba flag %#x\n", deviceExtension->FullIdentifyData.SupportLba));
1941         KdPrint2((PRINT_PREFIX "SupportDMA flag %#x\n", deviceExtension->FullIdentifyData.SupportDma));
1942         KdPrint2((PRINT_PREFIX "SoftReset %#x\n", deviceExtension->FullIdentifyData.SoftReset));
1943         KdPrint2((PRINT_PREFIX "SupportIordy %#x, DisableIordy %#x\n",
1944             deviceExtension->FullIdentifyData.SupportIordy,
1945             deviceExtension->FullIdentifyData.DisableIordy
1946             ));
1947         KdPrint2((PRINT_PREFIX "MajorRevision %#x\n", deviceExtension->FullIdentifyData.MajorRevision));
1948         KdPrint2((PRINT_PREFIX "UserAddressableSectors %#x\n", deviceExtension->FullIdentifyData.UserAddressableSectors));
1949         if ( deviceExtension->FullIdentifyData.SupportLba
1950                             ||
1951             (deviceExtension->FullIdentifyData.MajorRevision &&
1952 /*             deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1953              deviceExtension->FullIdentifyData.UserAddressableSectors)) {
1954             KdPrint2((PRINT_PREFIX "LBA mode\n"));
1955             LunExt->DeviceFlags |= DFLAGS_LBA_ENABLED;
1956         } else {
1957             KdPrint2((PRINT_PREFIX "Keep orig geometry\n"));
1958             LunExt->DeviceFlags |= DFLAGS_ORIG_GEOMETRY;
1959             goto skip_lba_staff;
1960         }
1961         // Check for LBA48 support
1962         if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
1963             if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48 &&
1964                deviceExtension->FullIdentifyData.FeaturesEnabled.Address48 &&
1965                deviceExtension->FullIdentifyData.NumberOfHeads &&
1966                deviceExtension->FullIdentifyData.SectorsPerTrack &&
1967                (deviceExtension->FullIdentifyData.UserAddressableSectors48 > NumOfSectors)
1968                ) {
1969                 KdPrint2((PRINT_PREFIX "LBA48\n"));
1970                 cylinders =
1971                     (deviceExtension->FullIdentifyData.UserAddressableSectors48 /
1972                         (deviceExtension->FullIdentifyData.NumberOfHeads *
1973                            deviceExtension->FullIdentifyData.SectorsPerTrack));
1974 
1975                 KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
1976 
1977                 NativeNumOfSectors = cylinders *
1978                                deviceExtension->FullIdentifyData.NumberOfHeads *
1979                                deviceExtension->FullIdentifyData.SectorsPerTrack;
1980 
1981                 KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
1982 
1983                 if(NativeNumOfSectors > NumOfSectors) {
1984                     KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
1985                     NumOfSectors = NativeNumOfSectors;
1986                 }
1987             }
1988 
1989             // Check drive capacity report for LBA48-capable drives.
1990             if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48) {
1991                 ULONG hNativeNumOfSectors;
1992                 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1993 
1994                 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
1995                              IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY);
1996 
1997                 if(!(statusByte & IDE_STATUS_ERROR)) {
1998                     if(use_ahci) {
1999                         NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
2000                     } else {
2001                         NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
2002                                             ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow)  << 8) |
2003                                             ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) ;
2004 
2005                         AtapiWritePort1(chan, IDX_IO2_o_Control,
2006                                                IDE_DC_USE_HOB );
2007 
2008                         KdPrint2((PRINT_PREFIX "Read high order bytes\n"));
2009                         NativeNumOfSectors |=
2010                                             (ULONG)((ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber)  << 24 );
2011                         hNativeNumOfSectors=
2012                                              (ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) |
2013                                             ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 8) ;
2014                         ((PULONG)&NativeNumOfSectors)[1] = hNativeNumOfSectors;
2015                     }
2016                     KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
2017 
2018                     // Some drives report LBA48 capability while has capacity below 128Gb
2019                     // Probably they support large block-counters.
2020                     // But the problem is that some of them reports higher part of Max LBA equal to lower part.
2021                     // Here we check this
2022                     if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
2023                         KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!!\n"));
2024 
2025                         statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
2026                                      IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY);
2027 
2028                         if(!(statusByte & IDE_STATUS_ERROR)) {
2029                             if(use_ahci) {
2030                                 NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
2031                             } else {
2032                                 NativeNumOfSectors = (ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
2033                                                 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber)  << 24) |
2034                                                 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow)  << 8 ) |
2035                                                 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow)  << 32) |
2036                                                 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
2037                                                 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 40)
2038                                                 ;
2039                             }
2040                         }
2041 
2042                         if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
2043                             KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!! (2)\n"));
2044                             NativeNumOfSectors = 0;
2045                         }
2046                     }
2047 
2048                     if(NumOfSectors <= ATA_MAX_LBA28 &&
2049                        NativeNumOfSectors > NumOfSectors) {
2050 
2051                         KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
2052                         KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
2053 
2054                         statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
2055                                      IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
2056                         if(!(statusByte & IDE_STATUS_ERROR)) {
2057                             NumOfSectors = NativeNumOfSectors;
2058                         }
2059                     }
2060                 } // !error
2061             }
2062 
2063             if(NumOfSectors < 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
2064                 // check for native LBA size
2065                 // some drives report ~32Gb in Identify Block
2066                 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
2067 
2068                 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_READ_NATIVE_SIZE,
2069                              0, IDE_USE_LBA, 0, 0, 0, ATA_WAIT_READY);
2070 
2071                 if(!(statusByte & IDE_STATUS_ERROR)) {
2072                     if(use_ahci) {
2073                         NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
2074                     } else {
2075                         NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
2076                                             ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
2077                                             ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
2078                                            (((ULONG)AtapiReadPort1(chan, IDX_IO1_i_DriveSelect) & 0xf) << 24);
2079                     }
2080                     KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
2081 
2082                     if(NativeNumOfSectors > NumOfSectors) {
2083 
2084                         KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
2085                         KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
2086 
2087                         statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
2088                                      IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
2089                         if(!(statusByte & IDE_STATUS_ERROR)) {
2090                             NumOfSectors = NativeNumOfSectors;
2091                         }
2092                     }
2093                 }
2094             }
2095 
2096             if(NumOfSectors > ATA_MAX_IOLBA28) {
2097               KdPrint2((PRINT_PREFIX "2TB threshold, force LBA64 WRITE requirement\n"));
2098               LunExt->DeviceFlags |= DFLAGS_LBA32plus;
2099             }
2100         } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
2101 
2102         // fill IdentifyData with bogus geometry
2103         KdPrint2((PRINT_PREFIX "requested LunExt->GeomType=%x\n", LunExt->opt_GeomType));
2104         if(deviceExtension->FullIdentifyData.CurrentSectorsPerTrack &&
2105            deviceExtension->FullIdentifyData.NumberOfCurrentHeads) {
2106           tmp_cylinders = NumOfSectors / (deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *
2107                                           deviceExtension->FullIdentifyData.NumberOfCurrentHeads);
2108         } else
2109         if(deviceExtension->FullIdentifyData.SectorsPerTrack &&
2110            deviceExtension->FullIdentifyData.NumberOfHeads) {
2111             KdPrint2((PRINT_PREFIX "Current C/H = %#I64x/%#I64x\n",
2112                 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack,
2113                 deviceExtension->FullIdentifyData.NumberOfCurrentHeads));
2114             tmp_cylinders = NumOfSectors / (deviceExtension->FullIdentifyData.SectorsPerTrack *
2115                                             deviceExtension->FullIdentifyData.NumberOfHeads);
2116         } else {
2117             tmp_cylinders = 0;
2118         }
2119         KdPrint2((PRINT_PREFIX "tmp_cylinders = %#I64x\n", tmp_cylinders));
2120         if((tmp_cylinders < 0xffff) || (LunExt->opt_GeomType == GEOM_ORIG)) {
2121             // ok, we can keep original values
2122             if(LunExt->opt_GeomType == GEOM_AUTO) {
2123                 LunExt->opt_GeomType = GEOM_ORIG;
2124             }
2125         } else {
2126             tmp_cylinders = NumOfSectors / (255*63);
2127             if(tmp_cylinders < 0xffff) {
2128                 // we can use generic values for H/S for generic geometry approach
2129                 if(LunExt->opt_GeomType == GEOM_AUTO) {
2130                     LunExt->opt_GeomType = GEOM_STD;
2131                 }
2132             } else {
2133                 // we should use UNIATA geometry approach
2134                 if(LunExt->opt_GeomType == GEOM_AUTO) {
2135                     LunExt->opt_GeomType = GEOM_UNIATA;
2136                 }
2137             }
2138         }
2139 
2140         if(!deviceExtension->FullIdentifyData.SectorsPerTrack ||
2141            !deviceExtension->FullIdentifyData.NumberOfHeads) {
2142             KdPrint2((PRINT_PREFIX "Zero S/H -> Force Use GEOM_STD\n"));
2143         }
2144 
2145         if(LunExt->opt_GeomType == GEOM_STD) {
2146             deviceExtension->FullIdentifyData.CurrentSectorsPerTrack =
2147             deviceExtension->FullIdentifyData.SectorsPerTrack = 63;
2148 
2149             deviceExtension->FullIdentifyData.NumberOfCurrentHeads =
2150             deviceExtension->FullIdentifyData.NumberOfHeads   = 255;
2151 
2152             cylinders = NumOfSectors / (255*63);
2153             KdPrint2((PRINT_PREFIX "Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders, 255, 63));
2154         } else
2155         if(LunExt->opt_GeomType == GEOM_UNIATA) {
2156             while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x80)) {
2157                 cylinders /= 2;
2158                 KdPrint2((PRINT_PREFIX "cylinders /= 2\n"));
2159                 deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
2160                 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
2161             }
2162             while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x80)) {
2163                 cylinders /= 2;
2164                 KdPrint2((PRINT_PREFIX "cylinders /= 2 (2)\n"));
2165                 deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
2166                 deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
2167             }
2168             while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x8000)) {
2169                 cylinders /= 2;
2170                 KdPrint2((PRINT_PREFIX "cylinders /= 2 (3)\n"));
2171                 deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
2172                 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
2173             }
2174             while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x8000)) {
2175                 cylinders /= 2;
2176                 KdPrint2((PRINT_PREFIX "cylinders /= 2 (4)\n"));
2177                 deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
2178                 deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
2179             }
2180             KdPrint2((PRINT_PREFIX "Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders,
2181                 deviceExtension->FullIdentifyData.NumberOfCurrentHeads,
2182                 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack));
2183         }
2184         if(!cylinders) {
2185             KdPrint2((PRINT_PREFIX "cylinders = tmp_cylinders (%x = %x)\n", cylinders, tmp_cylinders));
2186             cylinders = tmp_cylinders;
2187         }
2188         deviceExtension->FullIdentifyData.NumberOfCurrentCylinders =
2189         deviceExtension->FullIdentifyData.NumberOfCylinders = (USHORT)cylinders;
2190 
2191 skip_lba_staff:
2192 
2193         KdPrint2((PRINT_PREFIX "Geometry: C %#x (%#x)\n",
2194                   deviceExtension->FullIdentifyData.NumberOfCylinders,
2195                   deviceExtension->FullIdentifyData.NumberOfCurrentCylinders
2196                   ));
2197         KdPrint2((PRINT_PREFIX "Geometry: H %#x (%#x)\n",
2198                   deviceExtension->FullIdentifyData.NumberOfHeads,
2199                   deviceExtension->FullIdentifyData.NumberOfCurrentHeads
2200                   ));
2201         KdPrint2((PRINT_PREFIX "Geometry: S %#x (%#x)\n",
2202                   deviceExtension->FullIdentifyData.SectorsPerTrack,
2203                   deviceExtension->FullIdentifyData.CurrentSectorsPerTrack
2204                   ));
2205 
2206         if(NumOfSectors) {
2207             LunExt->NumOfSectors = NumOfSectors;
2208         }
2209         if(deviceExtension->FullIdentifyData.MajorRevision &&
2210            deviceExtension->FullIdentifyData.DoubleWordIo) {
2211             LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
2212             KdPrint2((PRINT_PREFIX "IssueIdentify: DWORDIO supported\n"));
2213         }
2214     } else {
2215         // ATAPI
2216         if(deviceExtension->FullIdentifyData.MajorRevision &&
2217            deviceExtension->FullIdentifyData.DoubleWordIo) {
2218             LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
2219             KdPrint2((PRINT_PREFIX "IssueIdentify: DFLAGS_DWORDIO_ENABLED.\n"));
2220         }
2221         if(deviceExtension->FullIdentifyData.AtapiDMA.DMADirRequired) {
2222             KdPrint2((PRINT_PREFIX "DMADirRequired.\n"));
2223         }
2224         if(deviceExtension->FullIdentifyData.AtapiByteCount0) {
2225             KdPrint2((PRINT_PREFIX "AtapiByteCount0=%x\n", deviceExtension->FullIdentifyData.AtapiByteCount0));
2226         }
2227     }
2228 
2229     ScsiPortMoveMemory(&LunExt->IdentifyData,
2230                        &deviceExtension->FullIdentifyData,sizeof(IDENTIFY_DATA2));
2231 
2232     InitBadBlocks(LunExt);
2233 
2234     if ((LunExt->IdentifyData.DrqType & ATAPI_DRQT_INTR) &&
2235         (Command != IDE_COMMAND_IDENTIFY)) {
2236 
2237         // This device interrupts with the assertion of DRQ after receiving
2238         // Atapi Packet Command
2239         LunExt->DeviceFlags |= DFLAGS_INT_DRQ;
2240         KdPrint2((PRINT_PREFIX "IssueIdentify: Device interrupts on assertion of DRQ.\n"));
2241 
2242     } else {
2243         KdPrint2((PRINT_PREFIX "IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
2244     }
2245 
2246     if(Command != IDE_COMMAND_IDENTIFY) {
2247         // ATAPI branch
2248         if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_TAPE) {
2249             // This is a tape.
2250             LunExt->DeviceFlags |= DFLAGS_TAPE_DEVICE;
2251             KdPrint2((PRINT_PREFIX "IssueIdentify: Device is a tape drive.\n"));
2252         } else
2253         if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM ||
2254             LunExt->IdentifyData.DeviceType == ATAPI_TYPE_OPTICAL) {
2255             KdPrint2((PRINT_PREFIX "IssueIdentify: Device is CD/Optical drive.\n"));
2256             // set CD default costs
2257             LunExt->RwSwitchCost  = REORDER_COST_SWITCH_RW_CD;
2258             LunExt->RwSwitchMCost = REORDER_MCOST_SWITCH_RW_CD;
2259             LunExt->SeekBackMCost = REORDER_MCOST_SEEK_BACK_CD;
2260             statusByte = WaitForDrq(chan);
2261         } else {
2262             KdPrint2((PRINT_PREFIX "IssueIdentify: ATAPI drive type %#x.\n",
2263                 LunExt->IdentifyData.DeviceType));
2264         }
2265         KdPrint2((PRINT_PREFIX "IssueIdentify: AtapiCmdSize %#x\n", deviceExtension->FullIdentifyData.AtapiCmdSize));
2266     } else {
2267         KdPrint2((PRINT_PREFIX "IssueIdentify: hard drive.\n"));
2268     }
2269 
2270     GetBaseStatus(chan, statusByte);
2271     KdPrint2((PRINT_PREFIX "IssueIdentify: final Status on exit (%#x)\n", statusByte));
2272     return TRUE;
2273 
2274 } // end IssueIdentify()
2275 
2276 
2277 /*++
2278 
2279 Routine Description:
2280     Set drive parameters using the IDENTIFY data.
2281 
2282 Arguments:
2283     HwDeviceExtension - HBA miniport driver's adapter data storage
2284     DeviceNumber - Indicates which device.
2285 
2286 Return Value:
2287     TRUE if all goes well.
2288 
2289 --*/
2290 BOOLEAN
2291 NTAPI
2292 SetDriveParameters(
2293     IN PVOID HwDeviceExtension,
2294     IN ULONG DeviceNumber,
2295     IN ULONG lChannel
2296     )
2297 {
2298     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2299     PIDENTIFY_DATA2      identifyData;
2300     PHW_LU_EXTENSION     LunExt;
2301 //    ULONG i;
2302     UCHAR statusByte;
2303     UCHAR errorByte;
2304 
2305     LunExt = deviceExtension->chan[lChannel].lun[DeviceNumber];
2306     identifyData = &(LunExt->IdentifyData);
2307 
2308     if(LunExt->DeviceFlags &
2309           (DFLAGS_LBA_ENABLED | DFLAGS_ORIG_GEOMETRY))
2310        return TRUE;
2311 
2312     KdPrint2((PRINT_PREFIX "SetDriveParameters: Number of heads %#x\n", identifyData->NumberOfHeads));
2313     KdPrint2((PRINT_PREFIX "SetDriveParameters: Sectors per track %#x\n", identifyData->SectorsPerTrack));
2314 
2315     // Send SET PARAMETER command.
2316     statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
2317                             IDE_COMMAND_SET_DRIVE_PARAMETERS, 0,
2318                             (identifyData->NumberOfHeads - 1), 0,
2319                             (UCHAR)identifyData->SectorsPerTrack, 0, ATA_WAIT_IDLE);
2320 
2321     statusByte = UniataIsIdle(deviceExtension, statusByte);
2322     if(statusByte & IDE_STATUS_ERROR) {
2323         errorByte = AtapiReadPort1(&deviceExtension->chan[lChannel], IDX_IO1_i_Error);
2324         KdPrint2((PRINT_PREFIX "SetDriveParameters: Error bit set. Status %#x, error %#x\n",
2325                     errorByte, statusByte));
2326         return FALSE;
2327     }
2328 
2329     if(statusByte == IDE_STATUS_IDLE) {
2330         return TRUE;
2331     }
2332 
2333     return FALSE;
2334 
2335 } // end SetDriveParameters()
2336 
2337 VOID
2338 NTAPI
2339 UniataForgetDevice(
2340     PHW_LU_EXTENSION   LunExt
2341     )
2342 {
2343     // keep only DFLAGS_HIDDEN flag
2344     LunExt->DeviceFlags &= DFLAGS_HIDDEN;
2345     LunExt->AtapiReadyWaitDelay = 0;
2346 } // end UniataForgetDevice()
2347 
2348 
2349 /*++
2350 
2351 Routine Description:
2352     Reset IDE controller and/or Atapi device.
2353     ->HwResetBus
2354 
2355 Arguments:
2356     HwDeviceExtension - HBA miniport driver's adapter data storage
2357 
2358 Return Value:
2359     Nothing.
2360 
2361 
2362 --*/
2363 BOOLEAN
2364 NTAPI
2365 AtapiResetController(
2366     IN PVOID HwDeviceExtension,
2367     IN ULONG PathId
2368     )
2369 {
2370     KdPrint2((PRINT_PREFIX "AtapiResetController(%x)\n", PathId));
2371     return AtapiResetController__(HwDeviceExtension, PathId, RESET_COMPLETE_ALL);
2372 } // end AtapiResetController()
2373 
2374 BOOLEAN
2375 NTAPI
2376 AtapiResetController__(
2377     IN PVOID HwDeviceExtension,
2378     IN ULONG PathId,
2379     IN BOOLEAN CompleteType
2380     )
2381 {
2382     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2383     ULONG                numberChannels  = deviceExtension->NumberChannels;
2384     PHW_CHANNEL          chan = NULL;
2385     ULONG i,j;
2386     ULONG MaxLuns;
2387     UCHAR statusByte;
2388     PSCSI_REQUEST_BLOCK CurSrb;
2389     ULONG ChannelCtrlFlags;
2390     UCHAR dma_status = 0;
2391 
2392     ULONG slotNumber = deviceExtension->slotNumber;
2393     ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
2394     ULONG VendorID =  deviceExtension->DevID        & 0xffff;
2395 #ifdef _DEBUG
2396     ULONG DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
2397 #endif
2398     //ULONG RevID    =  deviceExtension->RevID;
2399     ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
2400     //UCHAR tmp8;
2401     USHORT tmp16;
2402 
2403     KdPrint2((PRINT_PREFIX "AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID, DeviceID, slotNumber));
2404     KdPrint2((PRINT_PREFIX "simplexOnly %d, VM %x\n", deviceExtension->simplexOnly, g_opt_VirtualMachine));
2405 
2406     if(!deviceExtension->simplexOnly && (PathId != CHAN_NOT_SPECIFIED)) {
2407         // we shall reset both channels on SimplexOnly devices,
2408         // It's not worth doing so on normal controllers
2409         j = PathId;
2410         numberChannels = min(j+1, deviceExtension->NumberChannels);
2411     } else {
2412         j=0;
2413         numberChannels = deviceExtension->NumberChannels;
2414     }
2415 
2416     for (; j < numberChannels; j++) {
2417 
2418         KdPrint2((PRINT_PREFIX "AtapiResetController: Reset lchannel %d[%d]\n", j, deviceExtension->Channel));
2419         chan = &(deviceExtension->chan[j]);
2420         MaxLuns = chan->NumberLuns;
2421         // Save control flags
2422         ChannelCtrlFlags = chan->ChannelCtrlFlags;
2423         KdPrint2((PRINT_PREFIX "  CompleteType %#x, Luns %d, chan %#x, sptr %#x, flags %#x\n", CompleteType, MaxLuns, chan, &chan, ChannelCtrlFlags));
2424         //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
2425         if(CompleteType != RESET_COMPLETE_NONE) {
2426 #ifndef UNIATA_CORE
2427             while((CurSrb = UniataGetCurRequest(chan))) {
2428 
2429                 PHW_LU_EXTENSION     LunExt;
2430                 PATA_REQ AtaReq = (PATA_REQ)(CurSrb->SrbExtension);
2431 
2432                 i = GET_CDEV(CurSrb);
2433                 KdPrint2((PRINT_PREFIX "  Lun %x\n", i));
2434                 LunExt = chan->lun[i];
2435 
2436                 KdPrint2((PRINT_PREFIX "AtapiResetController: pending SRB %#x, chan %#x\n", CurSrb, chan));
2437                 if(CurSrb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
2438                     KdPrint2((PRINT_PREFIX "  was MechStatus\n"));
2439 
2440                     if(!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)) {
2441                         LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED;
2442                         KdPrint2((PRINT_PREFIX "  set DFLAGS_CHANGER_INITED\n"));
2443                     }
2444                 }
2445                 // Check and see if we are processing an internal srb
2446                 if (AtaReq->OriginalSrb) {
2447                     KdPrint2((PRINT_PREFIX "  restore original SRB %#x\n", AtaReq->OriginalSrb));
2448                     AtaReq->Srb = AtaReq->OriginalSrb;
2449                     CurSrb->SrbExtension = NULL;
2450                     AtaReq->OriginalSrb = NULL;
2451                     // NOTE: internal SRB doesn't get to SRB queue !!!
2452                     CurSrb = AtaReq->Srb;
2453                 }
2454 
2455                 // Remove current request from queue
2456                 UniataRemoveRequest(chan, CurSrb);
2457 
2458                 // Check if request is in progress.
2459                 ASSERT(AtaReq->Srb == CurSrb);
2460                 if (CurSrb) {
2461                     // Complete outstanding request with SRB_STATUS_BUS_RESET.
2462                     UCHAR CurPathId = CurSrb->PathId;
2463                     UCHAR TargetId = CurSrb->TargetId;
2464                     UCHAR Lun = CurSrb->Lun;
2465 
2466                     CurSrb->SrbStatus = ((CompleteType == RESET_COMPLETE_ALL) ? SRB_STATUS_BUS_RESET : SRB_STATUS_ABORTED) | SRB_STATUS_AUTOSENSE_VALID;
2467                     CurSrb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
2468 
2469                     if (CurSrb->SenseInfoBuffer) {
2470 
2471                         PSENSE_DATA  senseBuffer = (PSENSE_DATA)CurSrb->SenseInfoBuffer;
2472                         KdPrint2((PRINT_PREFIX "  senseBuffer %#x, chan %#x, ReqFlags %#x\n", senseBuffer, chan, AtaReq->Flags));
2473 
2474                         senseBuffer->ErrorCode = 0x70;
2475                         senseBuffer->Valid     = 1;
2476                         senseBuffer->AdditionalSenseLength = 0xb;
2477                         if(CompleteType == RESET_COMPLETE_ALL) {
2478                             KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
2479                             senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
2480                             senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_BUS_RESET;
2481                             senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_SCSI_BUS;
2482                         } else {
2483                             KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
2484                             senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
2485                             senseBuffer->AdditionalSenseCode = 0;
2486                             senseBuffer->AdditionalSenseCodeQualifier = 0;
2487                         }
2488                     }
2489 
2490                     if(!ATAPI_DEVICE(chan, i) && AtaReq->bcount && AtaReq->retry < MAX_RETRIES) {
2491                         KdPrint2((PRINT_PREFIX "Save IDE retry status %d\n", AtaReq->retry));
2492                         LunExt->errLastLba = AtaReq->lba;
2493                         LunExt->errBCount = AtaReq->bcount;
2494                         LunExt->errRetry = AtaReq->retry+1;
2495                         //KdPrint2((PRINT_PREFIX "AtaReq->Flags & REQ_FLAG_RW_MASK = %x (%x)\n", (AtaReq->Flags & REQ_FLAG_RW_MASK), REQ_FLAG_READ));
2496                         //KdPrint2((PRINT_PREFIX "ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION = %x (%x)\n", ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE, CTRFLAGS_DMA_OPERATION));
2497                         //KdPrint2((PRINT_PREFIX "g_opt_VirtualMachine = %x (%x)\n", g_opt_VirtualMachine, VM_BOCHS));
2498                         if(((AtaReq->Flags & REQ_FLAG_RW_MASK) == REQ_FLAG_READ) &&
2499                            (ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) &&
2500                            (g_opt_VirtualMachine == VM_BOCHS)) {
2501                             KdPrint2((PRINT_PREFIX "set CTRFLAGS_DMA_BEFORE_R on BOCHS\n"));
2502                             g_opt_BochsDmaReadWorkaround = TRUE;
2503                             g_opt_AtapiNoDma = TRUE;
2504                         } else {
2505                             KdPrint2((PRINT_PREFIX "do nothing\n"));
2506                         }
2507                     } else
2508                     if(ATAPI_DEVICE(chan, i) && AtaReq->bcount && !AtaReq->retry) {
2509                         KdPrint2((PRINT_PREFIX "Save ATAPI retry status %d\n", AtaReq->retry));
2510                         LunExt->errLastLba = AtaReq->lba;
2511                         LunExt->errBCount = AtaReq->bcount;
2512                         LunExt->errRetry = AtaReq->retry+1;
2513                         if(((AtaReq->Flags & REQ_FLAG_RW_MASK) == REQ_FLAG_READ) &&
2514                            (ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) &&
2515                            (g_opt_VirtualMachine == VM_BOCHS)) {
2516                             KdPrint2((PRINT_PREFIX "set CTRFLAGS_DMA_BEFORE_R on BOCHS ATAPI\n"));
2517                             //g_opt_BochsDmaReadWorkaround = TRUE;
2518                             g_opt_AtapiNoDma = TRUE;
2519                         } else {
2520                             KdPrint2((PRINT_PREFIX "do nothing\n"));
2521                         }
2522                     } else {
2523                         LunExt->errRetry = 0;
2524                     }
2525 
2526                     // Clear request tracking fields.
2527                     AtaReq->WordsLeft = 0;
2528                     AtaReq->DataBuffer = NULL;
2529                     AtaReq->TransferLength = 0;
2530                     KdPrint2((PRINT_PREFIX "chan %#x\n", chan));
2531 
2532                     ScsiPortNotification(RequestComplete,
2533                                          deviceExtension,
2534                                          CurSrb);
2535 
2536                     // Indicate ready for next request.
2537                     ScsiPortNotification(NextLuRequest,
2538                                          deviceExtension,
2539                                          CurPathId,
2540                                          TargetId,
2541                                          Lun);
2542                 }
2543                 if(CompleteType != RESET_COMPLETE_ALL)
2544                     break;
2545             } // end while()
2546 #endif //UNIATA_CORE
2547         } // end if (!CompleteType != RESET_COMPLETE_NONE)
2548 
2549         // Clear expecting interrupt flag.
2550         UniataExpectChannelInterrupt(chan, FALSE);
2551         chan->RDP = FALSE;
2552         chan->ChannelCtrlFlags = ChannelCtrlFlags & CTRFLAGS_PERMANENT;
2553         InterlockedExchange(&(chan->CheckIntr),
2554                                       CHECK_INTR_IDLE);
2555 
2556         for (i = 0; i < MaxLuns; i++) {
2557             chan->lun[i]->PowerState = 0;
2558         }
2559         // Reset controller
2560         if(ChipFlags & UNIATA_AHCI) {
2561             KdPrint2((PRINT_PREFIX "  AHCI path\n"));
2562             if(UniataAhciChanImplemented(deviceExtension, j)) {
2563 #ifdef _DEBUG
2564                 UniataDumpAhciPortRegs(chan);
2565 #endif
2566                 AtapiDisableInterrupts(deviceExtension, j);
2567                 UniataAhciReset(HwDeviceExtension, j);
2568             } else {
2569                 KdPrint2((PRINT_PREFIX "  skip not implemented\n"));
2570                 continue;
2571             }
2572         } else {
2573             KdPrint2((PRINT_PREFIX "  ATA path, chan %#x\n", chan));
2574             KdPrint2((PRINT_PREFIX "  disable intr (0)\n"));
2575             AtapiDisableInterrupts(deviceExtension, j);
2576             KdPrint2((PRINT_PREFIX "  done\n"));
2577             switch(VendorID) {
2578             case ATA_INTEL_ID: {
2579                 ULONG mask;
2580                 ULONG pshift;
2581                 ULONG timeout;
2582                 if(!(ChipFlags & UNIATA_SATA)) {
2583                     goto default_reset;
2584                 }
2585                 if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
2586                     goto default_reset;
2587                 }
2588 
2589 #if 0
2590                 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2591                 if(ChipFlags & UNIATA_AHCI) {
2592                     mask = 0x0005 << j;
2593                 } else {
2594                     /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2595                     GetPciConfig1(0x90, tmp8);
2596                     if(tmp8 & 0x04) {
2597                         mask = 0x0003;
2598                     } else {
2599                         mask = 0x0001 << j;
2600                     }
2601                 }
2602 #else
2603                 mask = 1 << chan->lun[0]->SATA_lun_map;
2604                 if (MaxLuns > 1) {
2605                     mask |= (1 << chan->lun[1]->SATA_lun_map);
2606                 }
2607 #endif
2608                 ChangePciConfig2(0x92, a & ~mask);
2609                 AtapiStallExecution(10);
2610                 ChangePciConfig2(0x92, a | mask);
2611                 timeout = 100;
2612 
2613                 /* Wait up to 1 sec for "connect well". */
2614                 if (ChipFlags & (I6CH | I6CH2)) {
2615                     pshift = 8;
2616                 } else {
2617                     pshift = 4;
2618                 }
2619                 while (timeout--) {
2620                     GetPciConfig2(0x92, tmp16);
2621                     if (((tmp16 >> pshift) & mask) == mask) {
2622                         GetBaseStatus(chan, statusByte);
2623                         if(statusByte != IDE_STATUS_WRONG) {
2624                             break;
2625                         }
2626                     }
2627                     AtapiStallExecution(10000);
2628                 }
2629                 break; }
2630             case ATA_SIS_ID: {
2631                 KdPrint2((PRINT_PREFIX "  SIS\n"));
2632                 if(!(ChipFlags & UNIATA_SATA))
2633                     goto default_reset;
2634                 break; }
2635 #if 0
2636             case ATA_NVIDIA_ID: {
2637                 KdPrint2((PRINT_PREFIX "  nVidia\n"));
2638                 if(!(ChipFlags & UNIATA_SATA))
2639                     goto default_reset;
2640                 break; }
2641 #else
2642             case ATA_NVIDIA_ID: {
2643                 ULONG offs;
2644                 ULONG Channel = deviceExtension->Channel + j;
2645                 KdPrint2((PRINT_PREFIX "  nVidia\n"));
2646                 if(!(ChipFlags & UNIATA_SATA)) {
2647                     goto default_reset;
2648                 }
2649                 offs = (ChipFlags & NV4OFF) ? 0x0440 : 0x0010;
2650 
2651                 KdPrint2((PRINT_PREFIX "  disable Phy intr, offs %#x, c %u\n", offs, Channel));
2652                 /* disable device and PHY state change interrupts */
2653                 if(ChipFlags & NVQ) {
2654                     KdPrint2((PRINT_PREFIX "  NVQ, 32bits reg\n"));
2655                     AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4,
2656                         AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4) & ((~(ULONG)0x0000000d) << (!Channel*16)) );
2657                 } else {
2658                     AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1,
2659                         AtapiReadPortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1) & ((~(UCHAR)0x0d) << (!Channel*4)) );
2660                 }
2661                 tmp16 = UniataSataPhyEnable(HwDeviceExtension, j, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE);
2662 
2663                 KdPrint2((PRINT_PREFIX "  enable Phy intr, offs %#x\n", offs));
2664                 /* enable device and PHY state change interrupts */
2665                 if(ChipFlags & NVQ) {
2666                     AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4,
2667                         AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4) | (((ULONG)0x0000000d) << (!Channel*16)) );
2668                 } else {
2669                     AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1,
2670                         AtapiReadPortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1) | (((UCHAR)0x0d) << (!Channel*4)) );
2671                 }
2672 
2673                 KdPrint2((PRINT_PREFIX "  dev status %#x\n", tmp16));
2674                 if(tmp16 != IDE_STATUS_WRONG) {
2675                     goto default_reset;
2676                 }
2677                 break; }
2678 #endif //0
2679             case ATA_SILICON_IMAGE_ID: {
2680                 ULONG offset;
2681                 ULONG Channel = deviceExtension->Channel + j;
2682                 if(!(ChipFlags & UNIATA_SATA))
2683                     goto default_reset;
2684                 offset = ((Channel & 1) << 7) + ((Channel & 2) << 8);
2685                 /* disable PHY state change interrupt */
2686                 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + offset, 0);
2687 
2688                 UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0);
2689 
2690                 /* reset controller part for this channel */
2691                 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
2692                      AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) | (0xc0 >> Channel));
2693                 AtapiStallExecution(1000);
2694                 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
2695                      AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) & ~(0xc0 >> Channel));
2696 
2697 
2698                 break; }
2699             case ATA_PROMISE_ID: {
2700                 break; }
2701             default:
2702                 if(ChipFlags & UNIATA_SATA) {
2703                     KdPrint2((PRINT_PREFIX "  SATA generic reset\n"));
2704                     UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0);
2705                 }
2706 default_reset:
2707 /*
2708                 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS |
2709                                                                         IDE_DC_RESET_CONTROLLER );
2710                 chan->last_devsel = -1;
2711                 KdPrint2((PRINT_PREFIX "  wait a little\n"));
2712                 AtapiStallExecution(10000);
2713                 // Disable interrupts
2714                 KdPrint2((PRINT_PREFIX "  disable intr\n"));
2715                 AtapiDisableInterrupts(deviceExtension, j);
2716                 AtapiStallExecution(100);
2717                 KdPrint2((PRINT_PREFIX "  re-enable intr\n"));
2718                 AtapiEnableInterrupts(deviceExtension, j);
2719                 KdPrint2((PRINT_PREFIX "  wait a little (2)\n"));
2720                 AtapiStallExecution(100000);
2721 */
2722                 AtapiHardReset(chan, TRUE, 100000);
2723                 KdPrint2((PRINT_PREFIX "  disable intr\n"));
2724                 AtapiDisableInterrupts(deviceExtension, j);
2725                 AtapiStallExecution(100);
2726                 KdPrint2((PRINT_PREFIX "  re-enable intr\n"));
2727                 AtapiEnableInterrupts(deviceExtension, j);
2728                 KdPrint2((PRINT_PREFIX "  done\n"));
2729 
2730                 break;
2731             } // end switch()
2732 
2733             //if(!(ChipFlags & UNIATA_SATA)) {}
2734             if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
2735                 // Reset DMA engine if active
2736                 KdPrint2((PRINT_PREFIX "  check DMA engine\n"));
2737                 dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
2738                 KdPrint2((PRINT_PREFIX "  DMA status %#x\n", dma_status));
2739                 if((ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
2740                    (dma_status & BM_STATUS_INTR)) {
2741                     AtapiDmaDone(HwDeviceExtension, 0, j, NULL);
2742                 }
2743             }
2744         } // ATA vs AHCI
2745 
2746         // all these shall be performed inside AtapiHwInitialize__() ?
2747 #if 1
2748         KdPrint2((PRINT_PREFIX "  process connected devices 0 - %d\n", MaxLuns-1));
2749         // Do special processing for ATAPI and IDE disk devices.
2750         for (i = 0; i < MaxLuns; i++) {
2751 
2752             // Check if device present.
2753             KdPrint2((PRINT_PREFIX "  Chan %#x\n", chan));
2754             KdPrint2((PRINT_PREFIX "  Lun %#x\n", i));
2755             KdPrint2((PRINT_PREFIX "  Lun ptr %#x\n", chan->lun[i]));
2756             if (!(chan->lun[i]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
2757                 if(ChipFlags & UNIATA_AHCI) {
2758                     // everything is done in UniataAhciReset()
2759                     KdPrint2((PRINT_PREFIX "  device have gone\n"));
2760                     continue;
2761                 }
2762 #ifdef NAVO_TEST
2763                 continue;
2764 #else //NAVO_TEST
2765                 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2766                 if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
2767                     continue;
2768                 }
2769                 if(!CheckDevice(HwDeviceExtension, j, i, TRUE)) {
2770                     continue;
2771                 }
2772             } else {
2773                 if(ChipFlags & UNIATA_AHCI) {
2774                     // everything is done in UniataAhciReset()
2775                     KdPrint2((PRINT_PREFIX "  found some device\n"));
2776 
2777                     if(!IssueIdentify(HwDeviceExtension,
2778                                   i, j,
2779                              ATAPI_DEVICE(chan, i) ?
2780                                   IDE_COMMAND_ATAPI_IDENTIFY : IDE_COMMAND_IDENTIFY,
2781                                   FALSE)) {
2782                         KdPrint2((PRINT_PREFIX "  identify failed !\n"));
2783                         UniataForgetDevice(chan->lun[i]);
2784                     }
2785                     continue;
2786                 }
2787                 if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
2788                     KdPrint2((PRINT_PREFIX "  device have gone\n"));
2789                     UniataForgetDevice(chan->lun[i]);
2790                 }
2791 #endif //NAVO_TEST
2792             }
2793 
2794             SelectDrive(chan, i);
2795             AtapiStallExecution(10);
2796             statusByte = WaitOnBusyLong(chan);
2797             statusByte = UniataIsIdle(deviceExtension, statusByte);
2798             if(statusByte == IDE_STATUS_WRONG) {
2799                 KdPrint2((PRINT_PREFIX
2800                            "no drive, status %#x\n",
2801                            statusByte));
2802                 UniataForgetDevice(chan->lun[i]);
2803             } else
2804             // Check for ATAPI disk.
2805             if (ATAPI_DEVICE(chan, i)) {
2806                 // Issue soft reset and issue identify.
2807                 GetStatus(chan, statusByte);
2808                 KdPrint2((PRINT_PREFIX "AtapiResetController: Status before Atapi reset (%#x).\n",
2809                             statusByte));
2810 
2811                 AtapiDisableInterrupts(deviceExtension, j);
2812                 AtapiSoftReset(chan, i);
2813                 AtapiEnableInterrupts(deviceExtension, j);
2814 
2815                 GetStatus(chan, statusByte);
2816 
2817                 if(statusByte != IDE_STATUS_SUCCESS) {
2818                     ULONG k;
2819                     k = UniataAnybodyHome(deviceExtension, j, i);
2820                     if(k == ATA_AT_HOME_HDD) {
2821                         // device reset in progress, perform additional wait
2822                         KdPrint2((PRINT_PREFIX "  long reset, wait up to 4.5 s\n"));
2823                         k = 30 * 1000;
2824                         while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
2825                                k--)
2826                         {
2827                             AtapiStallExecution(150);
2828                         }
2829                         KdPrint2((PRINT_PREFIX " exit after %u loops\n", k));
2830                         GetStatus(chan, statusByte);
2831                     }
2832                 }
2833                 if(statusByte == IDE_STATUS_SUCCESS) {
2834 
2835                     IssueIdentify(HwDeviceExtension,
2836                                   i, j,
2837                                   IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
2838                 } else {
2839 
2840                     KdPrint2((PRINT_PREFIX
2841                                "AtapiResetController: Status after soft reset %#x\n",
2842                                statusByte));
2843                 }
2844                 GetBaseStatus(chan, statusByte);
2845 
2846             } else {
2847                 // Issue identify and reinit after channel reset.
2848 
2849                 if (statusByte != IDE_STATUS_IDLE &&
2850                     statusByte != IDE_STATUS_SUCCESS &&
2851                     statusByte != IDE_STATUS_DRDY) {
2852 //                    result2 = FALSE;
2853                     KdPrint2((PRINT_PREFIX "AtapiResetController: IdeHardReset failed\n"));
2854                 } else
2855                 if(!IssueIdentify(HwDeviceExtension,
2856                                   i, j,
2857                                   IDE_COMMAND_IDENTIFY, FALSE)) {
2858 //                    result2 = FALSE;
2859                     KdPrint2((PRINT_PREFIX "AtapiResetController: IDE IssueIdentify failed\n"));
2860                 } else
2861                 // Set disk geometry parameters.
2862                 if (!SetDriveParameters(HwDeviceExtension, i, j)) {
2863                     KdPrint2((PRINT_PREFIX "AtapiResetController: SetDriveParameters failed\n"));
2864                 }
2865                 GetBaseStatus(chan, statusByte);
2866             }
2867             // force DMA mode reinit
2868             KdPrint2((PRINT_PREFIX " set DFLAGS_REINIT_DMA\n"));
2869             chan->lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
2870         }
2871 #endif //0
2872 
2873         // Enable interrupts, note, we can have here recursive disable
2874         AtapiStallExecution(10);
2875         KdPrint2((PRINT_PREFIX "AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2876             j,
2877             chan->DisableIntr));
2878         AtapiEnableInterrupts(deviceExtension, j);
2879 
2880         // Call the HwInitialize routine to setup multi-block.
2881         AtapiHwInitialize__(deviceExtension, j);
2882     } // for(channel)
2883     ScsiPortNotification(NextRequest, deviceExtension, NULL);
2884 
2885     return TRUE;
2886 
2887 } // end AtapiResetController__()
2888 
2889 
2890 /*++
2891 
2892 Routine Description:
2893     This routine maps ATAPI and IDE errors to specific SRB statuses.
2894 
2895 Arguments:
2896     HwDeviceExtension - HBA miniport driver's adapter data storage
2897     Srb - IO request packet
2898 
2899 Return Value:
2900     SRB status
2901 
2902 --*/
2903 ULONG
2904 NTAPI
2905 MapError(
2906     IN PVOID HwDeviceExtension,
2907     IN PSCSI_REQUEST_BLOCK Srb
2908     )
2909 {
2910     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2911     ULONG lChannel = GET_CHANNEL(Srb);
2912     PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
2913 //    ULONG i;
2914     UCHAR errorByte = 0;
2915     UCHAR srbStatus = SRB_STATUS_SUCCESS;
2916     UCHAR scsiStatus;
2917     ULONG DeviceNumber = GET_CDEV(Srb);
2918     PHW_LU_EXTENSION     LunExt = chan->lun[DeviceNumber];
2919 
2920     // Read the error register.
2921 
2922     if(deviceExtension->HwFlags & UNIATA_AHCI) {
2923         PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
2924         if(AtaReq) {
2925             errorByte = AtaReq->ahci.in_error;
2926         } else {
2927         }
2928     } else {
2929         errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
2930     }
2931     KdPrint2((PRINT_PREFIX
2932                "MapError: Error register is %#x\n",
2933                errorByte));
2934 
2935     if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2936 
2937         switch (errorByte >> 4) {
2938         case SCSI_SENSE_NO_SENSE:
2939 
2940             KdPrint2((PRINT_PREFIX
2941                        "ATAPI: No sense information\n"));
2942             scsiStatus = SCSISTAT_CHECK_CONDITION;
2943             srbStatus = SRB_STATUS_ERROR;
2944             break;
2945 
2946         case SCSI_SENSE_RECOVERED_ERROR:
2947 
2948             KdPrint2((PRINT_PREFIX
2949                        "ATAPI: Recovered error\n"));
2950             scsiStatus = 0;
2951             srbStatus = SRB_STATUS_SUCCESS;
2952             break;
2953 
2954         case SCSI_SENSE_NOT_READY:
2955 
2956             KdPrint2((PRINT_PREFIX
2957                        "ATAPI: Device not ready\n"));
2958             scsiStatus = SCSISTAT_CHECK_CONDITION;
2959             srbStatus = SRB_STATUS_ERROR;
2960             break;
2961 
2962         case SCSI_SENSE_MEDIUM_ERROR:
2963 
2964             KdPrint2((PRINT_PREFIX
2965                        "ATAPI: Media error\n"));
2966             scsiStatus = SCSISTAT_CHECK_CONDITION;
2967             srbStatus = SRB_STATUS_ERROR;
2968             break;
2969 
2970         case SCSI_SENSE_HARDWARE_ERROR:
2971 
2972             KdPrint2((PRINT_PREFIX
2973                        "ATAPI: Hardware error\n"));
2974             scsiStatus = SCSISTAT_CHECK_CONDITION;
2975             srbStatus = SRB_STATUS_ERROR;
2976             break;
2977 
2978         case SCSI_SENSE_ILLEGAL_REQUEST:
2979 
2980             KdPrint2((PRINT_PREFIX
2981                        "ATAPI: Illegal request\n"));
2982             scsiStatus = SCSISTAT_CHECK_CONDITION;
2983             srbStatus = SRB_STATUS_ERROR;
2984             break;
2985 
2986         case SCSI_SENSE_UNIT_ATTENTION:
2987 
2988             KdPrint2((PRINT_PREFIX
2989                        "ATAPI: Unit attention\n"));
2990             scsiStatus = SCSISTAT_CHECK_CONDITION;
2991             srbStatus = SRB_STATUS_ERROR;
2992             break;
2993 
2994         case SCSI_SENSE_DATA_PROTECT:
2995 
2996             KdPrint2((PRINT_PREFIX
2997                        "ATAPI: Data protect\n"));
2998             scsiStatus = SCSISTAT_CHECK_CONDITION;
2999             srbStatus = SRB_STATUS_ERROR;
3000             break;
3001 
3002         case SCSI_SENSE_BLANK_CHECK:
3003 
3004             KdPrint2((PRINT_PREFIX
3005                        "ATAPI: Blank check\n"));
3006             scsiStatus = SCSISTAT_CHECK_CONDITION;
3007             srbStatus = SRB_STATUS_ERROR;
3008             break;
3009 
3010         case SCSI_SENSE_ABORTED_COMMAND:
3011             KdPrint2((PRINT_PREFIX
3012                         "Atapi: Command Aborted\n"));
3013             scsiStatus = SCSISTAT_CHECK_CONDITION;
3014             srbStatus = SRB_STATUS_ERROR;
3015             break;
3016 
3017         default:
3018 
3019             KdPrint2((PRINT_PREFIX
3020                        "ATAPI: Invalid sense information\n"));
3021             scsiStatus = 0;
3022             srbStatus = SRB_STATUS_ERROR;
3023             break;
3024         }
3025 
3026     } else {
3027 
3028         scsiStatus = 0;
3029 
3030         // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
3031         chan->ReturningMediaStatus = errorByte;
3032 
3033         if (errorByte & IDE_ERROR_MEDIA_CHANGE_REQ) {
3034             KdPrint2((PRINT_PREFIX
3035                        "IDE: Media change\n"));
3036             scsiStatus = SCSISTAT_CHECK_CONDITION;
3037             srbStatus = SRB_STATUS_ERROR;
3038 
3039             if (Srb->SenseInfoBuffer) {
3040 
3041                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3042 
3043                 senseBuffer->ErrorCode = 0x70;
3044                 senseBuffer->Valid     = 1;
3045                 senseBuffer->AdditionalSenseLength = 0xb;
3046                 senseBuffer->SenseKey =  SCSI_SENSE_UNIT_ATTENTION;
3047                 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
3048                 senseBuffer->AdditionalSenseCodeQualifier = 0;
3049 
3050                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3051             }
3052 
3053         } else if (errorByte & IDE_ERROR_COMMAND_ABORTED) {
3054             KdPrint2((PRINT_PREFIX
3055                        "IDE: Command abort\n"));
3056             srbStatus = SRB_STATUS_ABORTED;
3057             scsiStatus = SCSISTAT_CHECK_CONDITION;
3058 
3059             if (Srb->SenseInfoBuffer) {
3060 
3061                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3062 
3063                 senseBuffer->ErrorCode = 0x70;
3064                 senseBuffer->Valid     = 1;
3065                 senseBuffer->AdditionalSenseLength = 0xb;
3066                 senseBuffer->SenseKey =  SCSI_SENSE_ABORTED_COMMAND;
3067                 senseBuffer->AdditionalSenseCode = 0;
3068                 senseBuffer->AdditionalSenseCodeQualifier = 0;
3069 
3070                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3071             }
3072 
3073             LunExt->ErrorCount++;
3074 
3075         } else if (errorByte & IDE_ERROR_END_OF_MEDIA) {
3076 
3077             KdPrint2((PRINT_PREFIX
3078                        "IDE: End of media\n"));
3079             scsiStatus = SCSISTAT_CHECK_CONDITION;
3080             srbStatus = SRB_STATUS_ERROR;
3081 
3082             if (Srb->SenseInfoBuffer) {
3083 
3084                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3085 
3086                 senseBuffer->ErrorCode = 0x70;
3087                 senseBuffer->Valid     = 1;
3088                 senseBuffer->AdditionalSenseLength = 0xb;
3089                 senseBuffer->SenseKey =  SCSI_SENSE_UNIT_ATTENTION;
3090                 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIA_STATE;
3091                 senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_END_OF_MEDIUM;
3092                 senseBuffer->EndOfMedia = 1;
3093 
3094                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3095             }
3096 
3097             if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
3098                 LunExt->ErrorCount++;
3099             }
3100 
3101         } else if (errorByte & IDE_ERROR_ILLEGAL_LENGTH) {
3102 
3103             KdPrint2((PRINT_PREFIX
3104                        "IDE: Illegal length\n"));
3105             srbStatus = SRB_STATUS_INVALID_REQUEST;
3106 
3107             if (Srb->SenseInfoBuffer) {
3108 
3109                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3110 
3111                 senseBuffer->ErrorCode = 0x70;
3112                 senseBuffer->Valid     = 1;
3113                 senseBuffer->AdditionalSenseLength = 0xb;
3114                 senseBuffer->SenseKey =  SCSI_SENSE_ILLEGAL_REQUEST;
3115                 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_VALUE;
3116                 senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_PARAM_INVALID_VALUE;
3117                 senseBuffer->IncorrectLength = 1;
3118 
3119                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3120             }
3121 
3122         } else if (errorByte & IDE_ERROR_BAD_BLOCK) {
3123 
3124             KdPrint2((PRINT_PREFIX
3125                        "IDE: Bad block\n"));
3126             srbStatus = SRB_STATUS_ERROR;
3127             scsiStatus = SCSISTAT_CHECK_CONDITION;
3128             if (Srb->SenseInfoBuffer) {
3129 
3130                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3131 
3132                 senseBuffer->ErrorCode = 0x70;
3133                 senseBuffer->Valid     = 1;
3134                 senseBuffer->AdditionalSenseLength = 0xb;
3135                 senseBuffer->SenseKey =  SCSI_SENSE_MEDIUM_ERROR;
3136                 senseBuffer->AdditionalSenseCode = 0;
3137                 senseBuffer->AdditionalSenseCodeQualifier = 0;
3138 
3139                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3140             }
3141 
3142         } else if (errorByte & IDE_ERROR_ID_NOT_FOUND) {
3143 
3144             KdPrint2((PRINT_PREFIX
3145                        "IDE: Id not found\n"));
3146             srbStatus = SRB_STATUS_ERROR;
3147             scsiStatus = SCSISTAT_CHECK_CONDITION;
3148 
3149             if (Srb->SenseInfoBuffer) {
3150 
3151                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3152 
3153                 senseBuffer->ErrorCode = 0x70;
3154                 senseBuffer->Valid     = 1;
3155                 senseBuffer->AdditionalSenseLength = 0xb;
3156                 senseBuffer->SenseKey =  SCSI_SENSE_MEDIUM_ERROR;
3157                 senseBuffer->AdditionalSenseCode = 0;
3158                 senseBuffer->AdditionalSenseCodeQualifier = 0;
3159 
3160                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3161             }
3162 
3163             LunExt->ErrorCount++;
3164 
3165         } else if (errorByte & IDE_ERROR_MEDIA_CHANGE) {
3166 
3167             KdPrint2((PRINT_PREFIX
3168                        "IDE: Media change\n"));
3169             scsiStatus = SCSISTAT_CHECK_CONDITION;
3170             srbStatus = SRB_STATUS_ERROR;
3171 
3172             if (Srb->SenseInfoBuffer) {
3173 
3174                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3175 
3176                 senseBuffer->ErrorCode = 0x70;
3177                 senseBuffer->Valid     = 1;
3178                 senseBuffer->AdditionalSenseLength = 0xb;
3179                 senseBuffer->SenseKey =  SCSI_SENSE_UNIT_ATTENTION;
3180                 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
3181                 senseBuffer->AdditionalSenseCodeQualifier = 0;
3182 
3183                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3184             }
3185 
3186         } else if (errorByte & IDE_ERROR_DATA_ERROR) {
3187 
3188             KdPrint2((PRINT_PREFIX
3189                    "IDE: Data error\n"));
3190             scsiStatus = SCSISTAT_CHECK_CONDITION;
3191             srbStatus = SRB_STATUS_ERROR;
3192 
3193             if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
3194                 LunExt->ErrorCount++;
3195             }
3196 
3197             // Build sense buffer
3198             if (Srb->SenseInfoBuffer) {
3199 
3200                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
3201 
3202                 senseBuffer->ErrorCode = 0x70;
3203                 senseBuffer->Valid     = 1;
3204                 senseBuffer->AdditionalSenseLength = 0xb;
3205                 senseBuffer->SenseKey =  SCSI_SENSE_MEDIUM_ERROR;
3206                 senseBuffer->AdditionalSenseCode = 0;
3207                 senseBuffer->AdditionalSenseCodeQualifier = 0;
3208 
3209                 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3210             }
3211         }
3212 
3213         if (LunExt->ErrorCount >= MAX_ERRORS) {
3214 //            deviceExtension->DWordIO = FALSE;
3215 
3216             KdPrint2((PRINT_PREFIX
3217                         "MapError: ErrorCount >= MAX_ERRORS\n"));
3218 
3219             LunExt->DeviceFlags &= ~DFLAGS_DWORDIO_ENABLED;
3220             LunExt->MaximumBlockXfer = 0;
3221             BrutePoint();
3222 
3223             KdPrint2((PRINT_PREFIX
3224                         "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
3225 
3226             // Log the error.
3227             KdPrint2((PRINT_PREFIX
3228                         "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
3229                               HwDeviceExtension,
3230                               Srb,
3231                               Srb->PathId,
3232                               Srb->TargetId,
3233                               Srb->Lun,
3234                               SP_BAD_FW_WARNING,
3235                               4
3236                         ));
3237             ScsiPortLogError( HwDeviceExtension,
3238                               Srb,
3239                               Srb->PathId,
3240                               Srb->TargetId,
3241                               Srb->Lun,
3242                               SP_BAD_FW_WARNING,
3243                               4);
3244 
3245             // Reprogram to not use Multi-sector.
3246             UCHAR statusByte;
3247 
3248             if (LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT &&
3249                  !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_MANUAL_CHS))) {
3250 
3251                 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY);
3252 
3253                 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
3254                 // command was aborted.
3255                 if (statusByte & IDE_STATUS_ERROR) {
3256 
3257                     // Read the error register.
3258                     errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
3259 
3260                     KdPrint2((PRINT_PREFIX "MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
3261                                 statusByte,
3262                                 errorByte));
3263 
3264                     // Adjust the devExt. value, if necessary.
3265                     LunExt->MaximumBlockXfer = 0;
3266                     BrutePoint();
3267 
3268                 }
3269             }
3270         }
3271     }
3272 
3273     // Set SCSI status to indicate a check condition.
3274     Srb->ScsiStatus = scsiStatus;
3275 
3276     return srbStatus;
3277 
3278 } // end MapError()
3279 
3280 
3281 /*++
3282 
3283 Routine Description:
3284 
3285 Arguments:
3286     HwDeviceExtension - HBA miniport driver's adapter data storage
3287     ->HwInitialize
3288 
3289 Return Value:
3290     TRUE - if initialization successful.
3291     FALSE - if initialization unsuccessful.
3292 
3293 --*/
3294 BOOLEAN
3295 NTAPI
3296 AtapiHwInitialize(
3297     IN PVOID HwDeviceExtension
3298     )
3299 {
3300     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3301     ULONG                numberChannels  = deviceExtension->NumberChannels;
3302     ULONG c;
3303 
3304     KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base)\n"));
3305 
3306     if(WinVer_WDM_Model) {
3307         AtapiResetController__(HwDeviceExtension, CHAN_NOT_SPECIFIED, RESET_COMPLETE_ALL);
3308     }
3309     if(deviceExtension->MasterDev) {
3310         KdPrint2((PRINT_PREFIX "  mark chan %d of master controller [%x] as inited\n",
3311             deviceExtension->Channel, deviceExtension->DevIndex));
3312         BMList[deviceExtension->DevIndex].ChanInitOk |= 0x01 << deviceExtension->Channel;
3313     }
3314 
3315     /* do extra chipset specific setups */
3316     AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
3317 /*
3318     if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
3319         KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
3320         BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
3321     }
3322 */
3323     for (c = 0; c < numberChannels; c++) {
3324         AtapiHwInitialize__(deviceExtension, c);
3325     }
3326     KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base) done\n"));
3327     return TRUE;
3328 } // end AtapiHwInitialize()
3329 
3330 VOID
3331 NTAPI
3332 AtapiHwInitialize__(
3333     IN PHW_DEVICE_EXTENSION deviceExtension,
3334     IN ULONG lChannel
3335     )
3336 {
3337     ULONG i;
3338     UCHAR statusByte, errorByte;
3339     PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
3340     PHW_LU_EXTENSION     LunExt;
3341 //    ULONG tmp32;
3342     ULONG PreferedMode = 0xffffffff;
3343 
3344     if((deviceExtension->HwFlags & UNIATA_AHCI) &&
3345        !UniataAhciChanImplemented(deviceExtension, lChannel)) {
3346         return;
3347     }
3348 
3349     AtapiChipInit(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel);
3350     FindDevices(deviceExtension, 0, lChannel);
3351 
3352     for (i = 0; i < chan->NumberLuns; i++) {
3353 
3354         KdPrint3((PRINT_PREFIX "AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel, i));
3355 
3356         LunExt = chan->lun[i];
3357         // skip empty slots
3358         if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
3359             continue;
3360         }
3361 
3362         AtapiDisableInterrupts(deviceExtension, lChannel);
3363         AtapiStallExecution(1);
3364 
3365         if (!(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_MANUAL_CHS))) {
3366 
3367             KdPrint2((PRINT_PREFIX "AtapiHwInitialize: IDE branch\n"));
3368             // Enable media status notification
3369             IdeMediaStatus(TRUE,deviceExtension,lChannel,(UCHAR)i);
3370 
3371             // If supported, setup Multi-block transfers.
3372             statusByte = AtaCommand(deviceExtension, i, lChannel,
3373                                 IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
3374                                 LunExt->MaximumBlockXfer, 0, ATA_WAIT_BASE_READY);
3375 
3376             // Check for errors. Reset the value to 0 (disable MultiBlock) if the
3377             // command was aborted.
3378             if (statusByte & IDE_STATUS_ERROR) {
3379 
3380                 // Read the error register.
3381                 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
3382 
3383                 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
3384                             statusByte,
3385                             errorByte));
3386 
3387                 statusByte = AtaCommand(deviceExtension, i, lChannel,
3388                                     IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
3389                                     0, 0, ATA_WAIT_BASE_READY);
3390 
3391                 if (statusByte & IDE_STATUS_ERROR) {
3392                     // Read the error register.
3393                     errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
3394 
3395                     KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
3396                                 statusByte,
3397                                 errorByte));
3398                 }
3399                 // Adjust the devExt. value, if necessary.
3400                 LunExt->MaximumBlockXfer = 0;
3401 
3402             } else {
3403                 KdPrint2((PRINT_PREFIX
3404                             "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
3405                             i,
3406                             LunExt->MaximumBlockXfer));
3407             }
3408 
3409             if(LunExt->IdentifyData.MajorRevision) {
3410 
3411                 if(LunExt->opt_ReadCacheEnable) {
3412                     KdPrint2((PRINT_PREFIX "  Try Enable Read Cache\n"));
3413                     // If supported, setup read/write cacheing
3414                     statusByte = AtaCommand(deviceExtension, i, lChannel,
3415                                         IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3416                                         0, ATA_C_F_ENAB_RCACHE, ATA_WAIT_BASE_READY);
3417 
3418                     // Check for errors.
3419                     if (statusByte & IDE_STATUS_ERROR) {
3420                         KdPrint2((PRINT_PREFIX
3421                                     "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
3422                                     i));
3423                         LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
3424                     } else {
3425                         LunExt->DeviceFlags |= DFLAGS_RCACHE_ENABLED;
3426                     }
3427                 } else {
3428                     KdPrint2((PRINT_PREFIX "  Disable Read Cache\n"));
3429                     statusByte = AtaCommand(deviceExtension, i, lChannel,
3430                                         IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3431                                         0, ATA_C_F_DIS_RCACHE, ATA_WAIT_BASE_READY);
3432                     LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
3433                 }
3434                 if(LunExt->IdentifyData.FeaturesSupport.WriteCache) {
3435                     if(LunExt->opt_WriteCacheEnable) {
3436                         KdPrint2((PRINT_PREFIX "  Try Enable Write Cache\n"));
3437                         // If supported & allowed, setup write cacheing
3438                         statusByte = AtaCommand(deviceExtension, i, lChannel,
3439                                             IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3440                                             0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
3441                         // Check for errors.
3442                         if (statusByte & IDE_STATUS_ERROR) {
3443                             KdPrint2((PRINT_PREFIX
3444                                         "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
3445                                         i));
3446                             LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
3447                         } else {
3448                             LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED;
3449                         }
3450                     } else {
3451                         KdPrint2((PRINT_PREFIX "  Disable Write Cache\n"));
3452                         statusByte = AtaCommand(deviceExtension, i, lChannel,
3453                                             IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3454                                             0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY);
3455                         LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
3456                     }
3457                 }
3458 
3459                 if(/*LunExt->IdentifyData.FeaturesSupport.PowerMngt ||*/
3460                    LunExt->IdentifyData.FeaturesSupport.APM) {
3461 
3462                     if(LunExt->opt_AdvPowerMode) {
3463                         KdPrint2((PRINT_PREFIX "  Try Enable Adv. Power Mgmt\n"));
3464                         // setup APM
3465                         statusByte = AtaCommand(deviceExtension, i, lChannel,
3466                                             IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3467                                             LunExt->opt_AdvPowerMode, ATA_C_F_ENAB_APM, ATA_WAIT_BASE_READY);
3468                         // Check for errors.
3469                         if (statusByte & IDE_STATUS_ERROR) {
3470                             KdPrint2((PRINT_PREFIX
3471                                         "AtapiHwInitialize: Enable APM on Device %d failed\n",
3472                                         i));
3473                         }
3474                     } else {
3475                         KdPrint2((PRINT_PREFIX "  Disable Adv. Power Mgmt\n"));
3476                         statusByte = AtaCommand(deviceExtension, i, lChannel,
3477                                             IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3478                                             0, ATA_C_F_DIS_APM, ATA_WAIT_BASE_READY);
3479                     }
3480                 }
3481                 if(LunExt->IdentifyData.FeaturesSupport.AutoAcoustic) {
3482                     if(LunExt->opt_AcousticMode) {
3483                         KdPrint2((PRINT_PREFIX "  Try Enable Acoustic Mgmt\n"));
3484                         // setup acoustic mgmt
3485                         statusByte = AtaCommand(deviceExtension, i, lChannel,
3486                                             IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3487                                             LunExt->opt_AcousticMode, ATA_C_F_ENAB_ACOUSTIC, ATA_WAIT_BASE_READY);
3488                         // Check for errors.
3489                         if (statusByte & IDE_STATUS_ERROR) {
3490                             KdPrint2((PRINT_PREFIX
3491                                         "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n",
3492                                         i));
3493                         }
3494                     } else {
3495                         KdPrint2((PRINT_PREFIX "  Disable Acoustic Mgmt\n"));
3496                         statusByte = AtaCommand(deviceExtension, i, lChannel,
3497                                             IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3498                                             0, ATA_C_F_DIS_ACOUSTIC, ATA_WAIT_BASE_READY);
3499                     }
3500                 }
3501                 if(LunExt->IdentifyData.FeaturesSupport.Standby) {
3502                     KdPrint2((PRINT_PREFIX "  Try init standby timer: %d\n"));
3503                     // setup standby timer
3504                     statusByte = AtaCommand(deviceExtension, i, lChannel,
3505                                         IDE_COMMAND_IDLE, 0, 0, 0,
3506                                         LunExt->opt_StandbyTimer, 0, ATA_WAIT_BASE_READY);
3507                     // Check for errors.
3508                     if (statusByte & IDE_STATUS_ERROR) {
3509                         KdPrint2((PRINT_PREFIX
3510                                     "AtapiHwInitialize: standby timer on Device %d failed\n",
3511                                     i));
3512                     }
3513                 }
3514             }
3515 
3516         } else if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)){
3517 
3518             ULONG j;
3519             //BOOLEAN isSanyo = FALSE;
3520             CCHAR vendorId[26];
3521 
3522             KdPrint2((PRINT_PREFIX "AtapiHwInitialize: ATAPI/Changer branch\n"));
3523 
3524             // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
3525             for (j = 0; j < 26; j += 2) {
3526 
3527                 // Build a buffer based on the identify data.
3528                 MOV_DW_SWP(vendorId[j], ((PUCHAR)LunExt->IdentifyData.ModelNumber)[j]);
3529             }
3530 
3531             if (!AtapiStringCmp (vendorId, "CD-ROM  CDR", 11)) {
3532 
3533                 // Inquiry string for older model had a '-', newer is '_'
3534                 if (vendorId[12] == 'C') {
3535 
3536                     // Torisan changer. Set the bit. This will be used in several places
3537                     // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
3538                     LunExt->DeviceFlags |= (DFLAGS_CHANGER_INITED | DFLAGS_SANYO_ATAPI_CHANGER);
3539                     LunExt->DiscsPresent = 3;
3540                     //isSanyo = TRUE;
3541                 }
3542             }
3543         }
3544 
3545         PreferedMode = LunExt->opt_MaxTransferMode;
3546         if((PreferedMode == 0xffffffff) || (PreferedMode > chan->MaxTransferMode)) {
3547             KdPrint2((PRINT_PREFIX "MaxTransferMode (overriden): %#x\n", chan->MaxTransferMode));
3548             PreferedMode = chan->MaxTransferMode;
3549         }
3550 
3551         if(LunExt->opt_PreferedTransferMode != 0xffffffff) {
3552             KdPrint2((PRINT_PREFIX "PreferedTransferMode: %#x\n", PreferedMode));
3553             PreferedMode = min(LunExt->opt_PreferedTransferMode, PreferedMode);
3554         }
3555 
3556         KdPrint2((PRINT_PREFIX "  try mode %#x\n", PreferedMode));
3557         LunExt->LimitedTransferMode =
3558         LunExt->TransferMode =
3559             (CHAR)PreferedMode;
3560 
3561         AtapiDmaInit__(deviceExtension, LunExt);
3562 
3563         LunExt->LimitedTransferMode =
3564             LunExt->TransferMode;
3565         KdPrint2((PRINT_PREFIX "Using %#x mode\n", LunExt->TransferMode));
3566 
3567         // We need to get our device ready for action before
3568         // returning from this function
3569 
3570         // According to the atapi spec 2.5 or 2.6, an atapi device
3571         // clears its status BSY bit when it is ready for atapi commands.
3572         // However, some devices (Panasonic SQ-TC500N) are still
3573         // not ready even when the status BSY is clear.  They don't react
3574         // to atapi commands.
3575         //
3576         // Since there is really no other indication that tells us
3577         // the drive is really ready for action.  We are going to check BSY
3578         // is clear and then just wait for an arbitrary amount of time!
3579         //
3580         if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
3581             ULONG waitCount;
3582 
3583             // have to get out of the loop sometime!
3584             // 10000 * 100us = 1000,000us = 1000ms = 1s
3585             waitCount = 10000;
3586             GetStatus(chan, statusByte);
3587             if(statusByte == IDE_STATUS_WRONG) {
3588                 waitCount = 0;
3589             }
3590             while ((statusByte & IDE_STATUS_BUSY) && waitCount) {
3591 
3592                 KdPrint2((PRINT_PREFIX "Wait for ATAPI (status %x)\n", statusByte));
3593                 // Wait for Busy to drop.
3594                 AtapiStallExecution(100);
3595                 GetStatus(chan, statusByte);
3596                 waitCount--;
3597             }
3598 
3599             // 5000 * 100us = 500,000us = 500ms = 0.5s
3600             if(statusByte != IDE_STATUS_WRONG) {
3601                 waitCount = 5000;
3602                 do {
3603                     AtapiStallExecution(100);
3604                 } while (waitCount--);
3605             }
3606         }
3607         GetBaseStatus(chan, statusByte);
3608         AtapiEnableInterrupts(deviceExtension, lChannel);
3609         AtapiStallExecution(10);
3610     }
3611 
3612     return;
3613 
3614 } // end AtapiHwInitialize__()
3615 
3616 
3617 #ifndef UNIATA_CORE
3618 
3619 VOID
3620 NTAPI
3621 AtapiHwInitializeChanger(
3622     IN PVOID HwDeviceExtension,
3623     IN PSCSI_REQUEST_BLOCK Srb,
3624     IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus)
3625 {
3626     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3627     ULONG lChannel = GET_CHANNEL(Srb);
3628     PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
3629     ULONG DeviceNumber = GET_CDEV(Srb);
3630     PHW_LU_EXTENSION     LunExt = chan->lun[DeviceNumber];
3631 
3632     if (MechanismStatus) {
3633         LunExt->DiscsPresent = MechanismStatus->NumberAvailableSlots;
3634         if (LunExt->DiscsPresent > 1) {
3635             LunExt->DeviceFlags |= DFLAGS_ATAPI_CHANGER;
3636         }
3637     }
3638     return;
3639 } // end AtapiHwInitializeChanger()
3640 
3641 
3642 /*++
3643 
3644 Routine Description:
3645     This routine will parse the string for a match on the keyword, then
3646     calculate the value for the keyword and return it to the caller.
3647 
3648 Arguments:
3649     String - The ASCII string to parse.
3650     KeyWord - The keyword for the value desired.
3651 
3652 Return Values:
3653     Zero if value not found
3654     Value converted from ASCII to binary.
3655 
3656 --*/
3657 ULONG
3658 NTAPI
3659 AtapiParseArgumentString(
3660     IN PCCH String,
3661     IN PCCH KeyWord
3662     )
3663 {
3664     PCCH cptr;
3665     PCCH kptr;
3666     ULONG value;
3667     ULONG stringLength = 0;
3668     ULONG keyWordLength = 0;
3669     ULONG index;
3670 
3671     if (!String) {
3672         return 0;
3673     }
3674     if (!KeyWord) {
3675         return 0;
3676     }
3677 
3678     // Calculate the string length and lower case all characters.
3679     cptr = String;
3680     while (*cptr++) {
3681         stringLength++;
3682     }
3683 
3684     // Calculate the keyword length.
3685     kptr = KeyWord;
3686     while (*kptr++) {
3687         keyWordLength++;
3688     }
3689 
3690     if (keyWordLength > stringLength) {
3691 
3692         // Can't possibly have a match.
3693         return 0;
3694     }
3695 
3696     // Now setup and start the compare.
3697     cptr = String;
3698 
3699 ContinueSearch:
3700 
3701     // The input string may start with white space.  Skip it.
3702     while (*cptr == ' ' || *cptr == '\t') {
3703         cptr++;
3704     }
3705 
3706     if (*cptr == '\0') {
3707         // end of string.
3708         return 0;
3709     }
3710 
3711     kptr = KeyWord;
3712     while ((*cptr == *kptr) ||
3713            (*cptr >= 'A' && *cptr <= 'Z' && *cptr + ('a' - 'A') == *kptr) ||
3714            (*cptr >= 'a' && *cptr <= 'z' && *cptr - ('a' - 'A') == *kptr)) {
3715         cptr++;
3716         kptr++;
3717 
3718         if (*cptr == '\0') {
3719             // end of string
3720             return 0;
3721         }
3722     }
3723 
3724     if (*kptr == '\0') {
3725 
3726         // May have a match backup and check for blank or equals.
3727         while (*cptr == ' ' || *cptr == '\t') {
3728             cptr++;
3729         }
3730 
3731         // Found a match.  Make sure there is an equals.
3732         if (*cptr != '=') {
3733 
3734             // Not a match so move to the next semicolon.
3735             while (*cptr) {
3736                 if (*cptr++ == ';') {
3737                     goto ContinueSearch;
3738                 }
3739             }
3740             return 0;
3741         }
3742         // Skip the equals sign.
3743         cptr++;
3744 
3745         // Skip white space.
3746         while ((*cptr == ' ') || (*cptr == '\t')) {
3747             cptr++;
3748         }
3749 
3750         if (*cptr == '\0') {
3751             // Early end of string, return not found
3752             return 0;
3753         }
3754 
3755         if (*cptr == ';') {
3756             // This isn't it either.
3757             cptr++;
3758             goto ContinueSearch;
3759         }
3760 
3761         value = 0;
3762         if ((*cptr == '0') && ((*(cptr + 1) == 'x') || (*(cptr + 1) == 'X'))) {
3763             // Value is in Hex.  Skip the "0x"
3764             cptr += 2;
3765             for (index = 0; *(cptr + index); index++) {
3766 
3767                 if (*(cptr + index) == ' ' ||
3768                     *(cptr + index) == '\t' ||
3769                     *(cptr + index) == ';') {
3770                      break;
3771                 }
3772 
3773                 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
3774                     value = (16 * value) + (*(cptr + index) - '0');
3775                 } else {
3776                     if ((*(cptr + index) >= 'a') && (*(cptr + index) <= 'f')) {
3777                         value = (16 * value) + (*(cptr + index) - 'a' + 10);
3778                     } else if ((*(cptr + index) >= 'A') && (*(cptr + index) <= 'F')) {
3779                         value = (16 * value) + (*(cptr + index) - 'A' + 10);
3780                     } else {
3781                         // Syntax error, return not found.
3782                         return 0;
3783                     }
3784                 }
3785             }
3786         } else {
3787 
3788             // Value is in Decimal.
3789             for (index = 0; *(cptr + index); index++) {
3790 
3791                 if (*(cptr + index) == ' ' ||
3792                     *(cptr + index) == '\t' ||
3793                     *(cptr + index) == ';') {
3794                      break;
3795                 }
3796 
3797                 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
3798                     value = (10 * value) + (*(cptr + index) - '0');
3799                 } else {
3800 
3801                     // Syntax error return not found.
3802                     return 0;
3803                 }
3804             }
3805         }
3806 
3807         return value;
3808     } else {
3809 
3810         // Not a match check for ';' to continue search.
3811         while (*cptr) {
3812             if (*cptr++ == ';') {
3813                 goto ContinueSearch;
3814             }
3815         }
3816 
3817         return 0;
3818     }
3819 } // end AtapiParseArgumentString()_
3820 
3821 /*
3822     Timer callback
3823 */
3824 VOID
3825 NTAPI
3826 AtapiCallBack__(
3827     IN PVOID HwDeviceExtension,
3828     IN UCHAR lChannel
3829     )
3830 {
3831 
3832     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3833     PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
3834     ULONG c, _c;
3835 
3836     PSCSI_REQUEST_BLOCK  srb = UniataGetCurRequest(chan);
3837     UCHAR statusByte;
3838 
3839     KdPrint2((PRINT_PREFIX "AtapiCallBack:\n"));
3840     // If the last command was DSC restrictive, see if it's set. If so, the device is
3841     // ready for a new request. Otherwise, reset the timer and come back to here later.
3842 
3843     // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3844     // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3845     // we shall have no problem with interrupt handler.
3846     if (!srb || chan->ExpectingInterrupt) {
3847         KdPrint2((PRINT_PREFIX "AtapiCallBack: Calling ISR directly due to BUSY\n"));
3848         chan->DpcState = DPC_STATE_TIMER;
3849         if(!AtapiInterrupt__(HwDeviceExtension, lChannel)) {
3850             InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
3851             KdPrint2((PRINT_PREFIX "AtapiCallBack: What's fucking this ???\n"));
3852         }
3853         goto ReturnCallback;
3854     }
3855 
3856 #ifdef _DEBUG
3857     if (!IS_RDP((srb->Cdb[0]))) {
3858         KdPrint2((PRINT_PREFIX "AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb->Cdb[0]));
3859     }
3860 #endif
3861     if(!(chan->RDP)) {
3862         goto ReturnEnableIntr;
3863     }
3864     GetStatus(chan, statusByte);
3865     if (statusByte & IDE_STATUS_DSC) {
3866 
3867         UCHAR PathId   = srb->PathId;
3868         UCHAR TargetId = srb->TargetId;
3869         UCHAR Lun      = srb->Lun;
3870 
3871         KdPrint2((PRINT_PREFIX "AtapiCallBack: Found DSC for RDP - %#x\n", srb->Cdb[0]));
3872         AtapiDmaDBSync(chan, srb);
3873         UniataRemoveRequest(chan, srb);
3874         ScsiPortNotification(RequestComplete, deviceExtension, srb);
3875         // Clear current SRB.
3876         if(!deviceExtension->simplexOnly) {
3877             srb = UniataGetCurRequest(chan);
3878         } else {
3879             srb = NULL;
3880         }
3881         chan->RDP = FALSE;
3882 
3883         // Ask for next request.
3884         ScsiPortNotification(NextLuRequest,
3885                              deviceExtension,
3886                              PathId,
3887                              TargetId,
3888                              Lun);
3889         ScsiPortNotification(NextRequest, deviceExtension, NULL);
3890 
3891         if(srb) {
3892             AtapiStartIo__(HwDeviceExtension, srb, FALSE);
3893         }
3894 
3895     } else {
3896         KdPrint2((PRINT_PREFIX "AtapiCallBack: Requesting another timer for Op %#x\n",
3897                     srb->Cdb[0]));
3898 
3899         AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
3900                              AtapiCallBack_X,
3901                              1000);
3902 
3903         goto ReturnCallback;
3904     }
3905 
3906 ReturnEnableIntr:
3907 
3908     if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) {
3909         KdPrint2((PRINT_PREFIX "AtapiCallBack: CallDisableInterrupts\n"));
3910         //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3911 #ifdef UNIATA_USE_XXableInterrupts
3912         chan->ChannelCtrlFlags |= CTRFLAGS_ENABLE_INTR_REQ;
3913         // must be called on DISPATCH_LEVEL
3914         ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension,
3915                              AtapiEnableInterrupts__);
3916 #else
3917         AtapiEnableInterrupts(HwDeviceExtension, lChannel);
3918         InterlockedExchange(&(chan->CheckIntr),
3919                                       CHECK_INTR_IDLE);
3920         // Will raise IRQL to DIRQL
3921         AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
3922                              AtapiEnableInterrupts__,
3923                              1);
3924         KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
3925 #endif // UNIATA_USE_XXableInterrupts
3926     } else {
3927         //ASSERT(!deviceExtension->simplexOnly);
3928     }
3929 
3930 ReturnCallback:
3931 
3932     // Check other channel
3933     // In simplex mode no interrupts must appear on other channels
3934     for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
3935         c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
3936 
3937         if(c == lChannel) {
3938             continue;
3939         }
3940 
3941         chan = &(deviceExtension->chan[c]);
3942 
3943         if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr),
3944                                       CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
3945                                       CRNT_ILK_TYPE CHECK_INTR_DETECTED) == CHECK_INTR_DETECTED)
3946         {
3947             //ASSERT(!deviceExtension->simplexOnly);
3948             chan->DpcState = DPC_STATE_ISR;
3949             if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
3950                 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
3951             }
3952         }
3953     }
3954     KdPrint2((PRINT_PREFIX "AtapiCallBack: return\n"));
3955     return;
3956 
3957 } // end AtapiCallBack__()
3958 
3959 VOID
3960 NTAPI
3961 AtapiCallBack_X(
3962     IN PVOID HwDeviceExtension
3963     )
3964 {
3965     AtapiCallBack__(HwDeviceExtension, (UCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->ActiveDpcChan);
3966 } // end AtapiCallBack_X()
3967 
3968 #endif //UNIATA_CORE
3969 
3970 /*++
3971 
3972 Routine Description:
3973 
3974     This is the interrupt service routine for ATAPI IDE miniport driver.
3975 
3976 Arguments:
3977 
3978     HwDeviceExtension - HBA miniport driver's adapter data storage
3979 
3980 Return Value:
3981 
3982     TRUE if expecting an interrupt.
3983 
3984 --*/
3985 BOOLEAN
3986 NTAPI
3987 AtapiInterrupt(
3988     IN PVOID HwDeviceExtension
3989     )
3990 {
3991     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3992     ULONG c, _c;
3993     BOOLEAN status = FALSE;
3994     ULONG c_state;
3995     ULONG i_res = 0;
3996     ULONG pass;
3997     //BOOLEAN checked[AHCI_MAX_PORT];
3998     ULONG hIS;
3999     ULONG checked;
4000 
4001     KdPrint2((PRINT_PREFIX "Intr: DeviceID+VendorID/Rev %#x/%#x (ex %d)\n",
4002         deviceExtension->DevID, deviceExtension->RevID, deviceExtension->ExpectingInterrupt ));
4003 
4004     if(deviceExtension->HwFlags & UNIATA_AHCI) {
4005         // AHCI may generate state change notification, never skip this check
4006         hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
4007         KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
4008         if(!hIS) {
4009             return FALSE;
4010         }
4011         // assume all non-interrupted ports to be already checked
4012         checked = ~hIS;
4013         // assume all not implemented ports to be already checked
4014         checked |= ~deviceExtension->AHCI_PI;
4015     } else {
4016         checked = 0; // assume all ports are not checked
4017     }
4018 
4019     if(!deviceExtension->ExpectingInterrupt) {
4020         // if we do not expect interrupt, exit now,
4021         // but keep in mind that it can be unexpected one
4022         // Note: this is just a hint, not exact counter
4023         KdPrint2((PRINT_PREFIX "unexpected, 1st chance\n"));
4024         //deviceExtension->ExpectingInterrupt++;
4025         //return FALSE;
4026     }
4027     // clear this flag now, it can be set again in sub-calls
4028     deviceExtension->ExpectingInterrupt=0;
4029 
4030 
4031 //    for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
4032 //        checked[_c] = (UCHAR)((hIS >> _c) & 0x01);
4033 //    }
4034 
4035 //    fc =
4036     for(pass=0; pass<2; pass++) {
4037         //KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): pass %d\n", pass));
4038         if(status && pass) {
4039             // we catched some expected interrupts now.
4040             // do not touch unexpected until next ISR call
4041             break;
4042         }
4043         for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
4044 
4045             c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
4046 
4047             if((checked>>c) & 0x01)
4048                 continue;
4049 
4050             // check non-empty and expecting interrupt channels first
4051             if(!pass && !deviceExtension->chan[c].ExpectingInterrupt)
4052                 continue;
4053 
4054             checked |= (ULONG)1 << c;
4055 
4056             KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
4057 
4058             if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
4059                 // we get here on idle channels or when ISR is posted to DPC
4060                 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): disabled INTR on ch %d\n", c));
4061                 continue;
4062             }
4063             // lock channel. Wait, while 2nd ISR checks interrupt on this channel
4064             do {
4065                 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): try lock\n"));
4066                 // c_state = deviceExtension->chan[c].CheckIntr;
4067                 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
4068                 //     deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
4069                 // }
4070                 c_state =
4071                     (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
4072                                               CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
4073                                               CRNT_ILK_TYPE CHECK_INTR_DETECTED);
4074                 if(c_state == CHECK_INTR_IDLE) {
4075                     // c_state = deviceExtension->chan[c].CheckIntr;
4076                     // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
4077                     //     deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
4078                     // }
4079                     c_state =
4080                         (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
4081                                                   CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
4082                                                   CRNT_ILK_TYPE CHECK_INTR_IDLE);
4083                 }
4084             } while(c_state == CHECK_INTR_CHECK);
4085             KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): locked\n"));
4086             // check if already serviced
4087             if(c_state == CHECK_INTR_ACTIVE) {
4088                 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
4089                 continue;
4090             }
4091 
4092             if((c_state == CHECK_INTR_DETECTED) ||
4093                (i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
4094 
4095                 if(i_res == INTERRUPT_REASON_UNEXPECTED) {
4096                     KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): Catch unexpected\n"));
4097                     InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4098                     //return TRUE;
4099                     status = TRUE;
4100                     continue;
4101                 }
4102                 // disable interrupts on other channel of legacy mode
4103                 // ISA-bridged onboard controller
4104                 if(deviceExtension->simplexOnly /*||
4105                    ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
4106                     AtapiDisableInterrupts(deviceExtension, !c);
4107                 }
4108 
4109                 deviceExtension->chan[c].DpcState = DPC_STATE_ISR;
4110                 if(AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
4111                     deviceExtension->LastInterruptedChannel = (UCHAR)c;
4112                     KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): return status TRUE\n"));
4113                     status = TRUE;
4114                 } else {
4115                     KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
4116                     InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4117                 }
4118 
4119                 // re-enable interrupts on other channel
4120                 if(deviceExtension->simplexOnly /*||
4121                    ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
4122                     AtapiEnableInterrupts(deviceExtension, !c);
4123                 }
4124 
4125             } else {
4126                 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
4127                 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4128             }
4129 
4130         }
4131     }
4132     KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): exit with status %#x\n", status));
4133     if(status) {
4134         deviceExtension->FirstChannelToCheck++;
4135         if(deviceExtension->FirstChannelToCheck >= deviceExtension->NumberChannels)
4136             deviceExtension->FirstChannelToCheck = 0;
4137     }
4138     return status;
4139 } // end AtapiInterrupt()
4140 
4141 //ULONG i2c = 0;
4142 #ifndef UNIATA_CORE
4143 
4144 BOOLEAN
4145 NTAPI
4146 AtapiInterrupt2(
4147     IN PKINTERRUPT Interrupt,
4148     IN PVOID Isr2HwDeviceExtension
4149     )
4150 {
4151     // This ISR is intended to catch interrupts when we are already in other ISR instance
4152     // for the same device. This may happen when we have multiple channels,
4153     // especially on SMP machines
4154 
4155     PISR2_DEVICE_EXTENSION Isr2DeviceExtension = (PISR2_DEVICE_EXTENSION)Isr2HwDeviceExtension;
4156     PHW_DEVICE_EXTENSION deviceExtension = Isr2DeviceExtension->HwDeviceExtension;
4157     ULONG c;
4158     BOOLEAN status = FALSE;
4159     ULONG c_count = 0;
4160     ULONG i_res;
4161     ULONG hIS;
4162     ULONG checked;
4163 
4164     // we should never get here for ISA/MCA
4165     if(!BMList[deviceExtension->DevIndex].Isr2Enable) {
4166         KdPrint2((PRINT_PREFIX "AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension->DevIndex, deviceExtension->Channel));
4167         return FALSE;
4168     }
4169 
4170     if(deviceExtension->HwFlags & UNIATA_AHCI) {
4171         // AHCI may generate state change notification, never skip this check
4172         hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
4173         KdPrint2((PRINT_PREFIX "AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
4174         if(!hIS) {
4175             return FALSE;
4176         }
4177         // assume all non-interrupted ports to be already checked
4178         checked = ~hIS;
4179         // assume all not implemented ports to be already checked
4180         checked |= ~deviceExtension->AHCI_PI;
4181 
4182     } else {
4183         checked = 0; // assume all ports are not checked
4184     }
4185     if(!deviceExtension->ExpectingInterrupt) {
4186         KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !deviceExtension->ExpectingInterrupt\n"));
4187         deviceExtension->ExpectingInterrupt++;
4188         return FALSE;
4189     }
4190     //deviceExtension->ExpectingInterrupt = 0;
4191 
4192     for(c=0; c<deviceExtension->NumberChannels; c++) {
4193         KdPrint2((PRINT_PREFIX "AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
4194 
4195         if((checked>>c) & 0x01)
4196             continue;
4197 
4198         checked |= (ULONG)1 << c;
4199 
4200         if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
4201             KdPrint2((PRINT_PREFIX "AtapiInterrupt2: disabled INTR\n"));
4202             continue;
4203         }
4204 
4205         if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
4206                                       CRNT_ILK_TYPE CHECK_INTR_CHECK,
4207                                       CRNT_ILK_TYPE CHECK_INTR_IDLE) != CHECK_INTR_IDLE)
4208         {
4209             KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
4210             // hunt on unexpected intr (Some devices generate double interrupts,
4211             // some controllers (at least CMD649) interrupt twice with small delay.
4212             // If interrupts are disabled, they queue interrupt and re-issue it later,
4213             // when we do not expect it.
4214             continue;
4215         }
4216 
4217         c_count++;
4218         if((i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
4219 
4220             KdPrint2((PRINT_PREFIX "AtapiInterrupt2: intr\n"));
4221             if(i_res == INTERRUPT_REASON_UNEXPECTED) {
4222                 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: Catch unexpected\n"));
4223                 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4224                 return TRUE;
4225             }
4226 
4227             status = TRUE;
4228             InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_DETECTED);
4229         } else {
4230             InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4231         }
4232     }
4233     KdPrint2((PRINT_PREFIX "AtapiInterrupt2: status %d, c_count %d\n", status, c_count));
4234     if(status && (c_count != deviceExtension->NumberChannels)) {
4235         // there is an active ISR/DPC for one channel, but
4236         // we have an interrupt from another one
4237         // Lets inform current ISR/DPC about new interrupt
4238         InterlockedExchange(&(deviceExtension->ReCheckIntr), CHECK_INTR_DETECTED);
4239     } else {
4240         status = FALSE;
4241     }
4242     KdPrint2((PRINT_PREFIX "AtapiInterrupt2: return %d\n", status));
4243     return status;
4244 
4245 } // end AtapiInterrupt2()
4246 
4247 RETTYPE_XXableInterrupts
4248 NTAPI
4249 AtapiInterruptDpc(
4250     IN PVOID HwDeviceExtension
4251     )
4252 {
4253     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4254     ULONG c;
4255 
4256     for(c=0; c<deviceExtension->NumberChannels; c++) {
4257         KdPrint2((PRINT_PREFIX "AtapiInterruptDpc: %#x\n",c));
4258 
4259         if(!(deviceExtension->chan[c].ChannelCtrlFlags & CTRFLAGS_DPC_REQ)) {
4260 
4261             if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
4262                                           CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
4263                                           CRNT_ILK_TYPE CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED)
4264             {
4265                 continue;
4266             }
4267 
4268         } else {
4269             deviceExtension->chan[c].ChannelCtrlFlags &= ~CTRFLAGS_DPC_REQ;
4270         }
4271 /*
4272         if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
4273             AtapiDisableInterrupts(deviceExtension, lChannel);
4274         }
4275 */
4276         deviceExtension->chan[c].DpcState = DPC_STATE_DPC;
4277         if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
4278             InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4279         }
4280     }
4281     return RETVAL_XXableInterrupts;
4282 } // end AtapiInterruptDpc()
4283 
4284 
4285 RETTYPE_XXableInterrupts
4286 NTAPI
4287 AtapiEnableInterrupts__(
4288     IN PVOID HwDeviceExtension
4289     )
4290 {
4291     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4292     KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__():\n"));
4293     ULONG c;
4294     PHW_CHANNEL chan = NULL;
4295 
4296     for(c=0; c<deviceExtension->NumberChannels; c++) {
4297         KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__(2): %#x\n",c));
4298         chan = &(deviceExtension->chan[c]);
4299 
4300         if(chan->ChannelCtrlFlags & CTRFLAGS_ENABLE_INTR_REQ) {
4301             // enable intrs on requested channel
4302             chan->ChannelCtrlFlags &= ~CTRFLAGS_ENABLE_INTR_REQ;
4303             AtapiEnableInterrupts(HwDeviceExtension, c);
4304             InterlockedExchange(&(chan->CheckIntr),
4305                                           CHECK_INTR_IDLE);
4306 
4307             // check if current or other channel(s) interrupted
4308             //AtapiInterrupt(HwDeviceExtension);
4309 
4310             if(deviceExtension->simplexOnly) {
4311                 break;
4312             }
4313         } else {
4314             // check if other channel(s) interrupted
4315             // must do nothing in simplex mode
4316             if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr),
4317                                           CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
4318                                           CRNT_ILK_TYPE CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED) {
4319                 continue;
4320             }
4321             //ASSERT(!deviceExtension->simplexOnly);
4322             chan->DpcState = DPC_STATE_ISR;
4323             if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
4324                 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
4325             }
4326         }
4327     }
4328     // In simplex mode next command must be sent to device here
4329     if(deviceExtension->simplexOnly && chan) {
4330         PSCSI_REQUEST_BLOCK srb;
4331         chan = UniataGetNextChannel(chan);
4332         if(chan) {
4333             srb = UniataGetCurRequest(chan);
4334         } else {
4335             srb = NULL;
4336         }
4337         if(srb) {
4338             AtapiStartIo__(HwDeviceExtension, srb, FALSE);
4339         }
4340     }
4341 
4342     return RETVAL_XXableInterrupts;
4343 
4344 } // end AtapiEnableInterrupts__()
4345 
4346 #endif //UNIATA_CORE
4347 
4348 
4349 VOID
4350 NTAPI
4351 AtapiEnableInterrupts(
4352     IN PVOID HwDeviceExtension,
4353     IN ULONG c
4354     )
4355 {
4356     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4357     PHW_CHANNEL chan;
4358     //UCHAR statusByte;
4359 
4360     if(c >= deviceExtension->NumberChannels) {
4361         KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c));
4362         return;
4363     }
4364     if((deviceExtension->HwFlags & UNIATA_AHCI) &&
4365        !UniataAhciChanImplemented(deviceExtension, c)) {
4366         KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c));
4367         return;
4368     }
4369 
4370     chan = &(deviceExtension->chan[c]);
4371     KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: %d\n",c, chan->DisableIntr));
4372     if(!InterlockedDecrement(&chan->DisableIntr)) {
4373         if(deviceExtension->HwFlags & UNIATA_AHCI) {
4374             UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE,
4375                 (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF |
4376                  ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_INF | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF |
4377                  ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC : 0) |
4378                  ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC | /* DEBUG */
4379                  ATA_AHCI_P_IX_DI |
4380                  ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB |
4381                  ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR)
4382                 );
4383         } else {
4384             //SelectDrive(chan, 0);
4385             //GetBaseStatus(chan, statusByte);
4386             AtapiWritePort1(chan, IDX_IO2_o_Control,
4387                                    0 | IDE_DC_A_4BIT );
4388             //if(chan->NumberLuns) {
4389             //    SelectDrive(chan, 1);
4390             //    GetBaseStatus(chan, statusByte);
4391             //    AtapiWritePort1(chan, IDX_IO2_o_Control,
4392             //                           IDE_DC_A_4BIT );
4393             //    SelectDrive(chan, chan->cur_cdev);
4394             //}
4395         }
4396         chan->ChannelCtrlFlags &= ~CTRFLAGS_INTR_DISABLED;
4397     } else {
4398         if(deviceExtension->HwFlags & UNIATA_AHCI) {
4399             // keep interrupts disabled
4400             UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
4401         } else {
4402             AtapiWritePort1(chan, IDX_IO2_o_Control,
4403                                IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4404         }
4405     }
4406     return;
4407 } // end AtapiEnableInterrupts()
4408 
4409 VOID
4410 NTAPI
4411 AtapiDisableInterrupts(
4412     IN PVOID HwDeviceExtension,
4413     IN ULONG c
4414     )
4415 {
4416     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4417     PHW_CHANNEL chan;
4418     if(c >= deviceExtension->NumberChannels) {
4419         KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c));
4420         return;
4421     }
4422     chan = &(deviceExtension->chan[c]);
4423     KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: %d\n",c, chan->DisableIntr));
4424     // mark channel as busy
4425     if(InterlockedIncrement(&chan->DisableIntr)) {
4426         if(deviceExtension->HwFlags & UNIATA_AHCI) {
4427             UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
4428         } else {
4429             //SelectDrive(chan, 0);
4430             AtapiWritePort1(chan, IDX_IO2_o_Control,
4431                                    IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4432             //if(chan->NumberLuns) {
4433             //    SelectDrive(chan, 1);
4434             //    AtapiWritePort1(chan, IDX_IO2_o_Control,
4435             //                           IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4436             //    SelectDrive(chan, chan->cur_cdev);
4437             //}
4438         }
4439         chan->ChannelCtrlFlags |= CTRFLAGS_INTR_DISABLED;
4440     }
4441 
4442     return;
4443 } // end AtapiDisableInterrupts()
4444 
4445 VOID
4446 UniataExpectChannelInterrupt(
4447     IN struct _HW_CHANNEL* chan,
4448     IN BOOLEAN Expecting
4449     )
4450 {
4451     chan->ExpectingInterrupt = Expecting;
4452     if(Expecting) {
4453         chan->DeviceExtension->ExpectingInterrupt++;
4454     } else
4455     if(chan->DeviceExtension->ExpectingInterrupt) {
4456         chan->DeviceExtension->ExpectingInterrupt--;
4457     }
4458     return;
4459 } // end UniataExpectChannelInterrupt()
4460 
4461 /*
4462     Check hardware for interrupt state
4463  */
4464 BOOLEAN
4465 NTAPI
4466 AtapiCheckInterrupt__(
4467     IN PVOID HwDeviceExtension,
4468     IN UCHAR c // logical channel
4469     )
4470 {
4471     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4472     PHW_CHANNEL chan = &(deviceExtension->chan[c]);
4473     PHW_LU_EXTENSION LunExt;
4474 
4475     ULONG VendorID  = deviceExtension->DevID & 0xffff;
4476     ULONG ChipType  = deviceExtension->HwFlags & CHIPTYPE_MASK;
4477 
4478     ULONG status;
4479     ULONG pr_status = 0;
4480     UCHAR dma_status = 0;
4481     UCHAR reg8 = 0;
4482     ULONG reg32 = 0;
4483     UCHAR statusByte = 0;
4484     ULONG slotNumber = deviceExtension->slotNumber;
4485     ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
4486     ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
4487     UCHAR Channel;
4488     UCHAR lChannel;
4489     BOOLEAN DmaTransfer = FALSE;
4490     BOOLEAN OurInterrupt = FALSE;
4491     BOOLEAN StatusValid = FALSE;
4492 //    ULONG k;
4493     UCHAR interruptReason;
4494     BOOLEAN EarlyIntr = FALSE;
4495     BOOLEAN SingleBlockIntr = FALSE;
4496 
4497     KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__:\n"));
4498 
4499     lChannel = c;
4500     Channel = (UCHAR)(deviceExtension->Channel + lChannel);
4501     LunExt = chan->lun[chan->cur_cdev];
4502 
4503     //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ chan %#x:\n", chan));
4504     //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ (%d/%d):\n", Channel, chan->cur_cdev));
4505 
4506     if((ChipFlags & UNIATA_AHCI) &&
4507         UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
4508 
4509         if(!UniataAhciChanImplemented(deviceExtension, lChannel)) {
4510             return OurInterrupt;
4511         }
4512 
4513         OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED);
4514         if((OurInterrupt == INTERRUPT_REASON_UNEXPECTED) &&
4515            (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
4516             UniataAhciWaitCommandReady(chan, 2 /* ms */ );
4517             statusByte = (UCHAR)UniataAhciWaitReady(chan, 0 /* immediate */);
4518             if(!(statusByte & (IDE_STATUS_BUSY)) ) {
4519                 KdPrint2((PRINT_PREFIX "ATAPI special case READY\n"));
4520                 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
4521                 OurInterrupt = INTERRUPT_REASON_OUR;
4522             } else
4523             if((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRDY)) == (IDE_STATUS_BUSY | IDE_STATUS_DRDY) ) {
4524                 KdPrint2((PRINT_PREFIX "ATAPI special case pre ERR-READY\n"));
4525                 OurInterrupt = INTERRUPT_REASON_OUR;
4526             } else
4527             if(statusByte & IDE_STATUS_ERROR) {
4528                 KdPrint2((PRINT_PREFIX "ATAPI special case ERR-READY\n"));
4529                 OurInterrupt = INTERRUPT_REASON_OUR;
4530             } else {
4531                 KdPrint2((PRINT_PREFIX "ATAPI special case ? %x\n", statusByte));
4532                 OurInterrupt = INTERRUPT_REASON_OUR;
4533             }
4534         }
4535         return OurInterrupt;
4536     }
4537 
4538     if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) {
4539         DmaTransfer = TRUE;
4540         KdPrint2((PRINT_PREFIX "  cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension->DevIndex,
4541             deviceExtension->Channel + c, c));
4542     } else {
4543         KdPrint2((PRINT_PREFIX "  cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension->DevIndex,
4544             deviceExtension->Channel + c, c));
4545         dma_status = GetDmaStatus(deviceExtension, lChannel);
4546         KdPrint2((PRINT_PREFIX "  DMA status %#x\n", dma_status));
4547     }
4548 
4549     // do controller-specific interrupt servicing staff
4550     if(deviceExtension->UnknownDev) {
4551         KdPrint2((PRINT_PREFIX "  UnknownDev\n"));
4552         goto check_unknown;
4553     }
4554 
4555     // Attention !
4556     // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
4557     // Such behavior was observed with Intel ICH-xxx chips
4558     // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
4559 
4560     switch(VendorID) {
4561 
4562     case ATA_PROMISE_ID: {
4563         switch(ChipType) {
4564         case PROLD:
4565         case PRNEW:
4566             status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x1c);
4567             if (!DmaTransfer)
4568                 break;
4569             if (!(status &
4570                   ((Channel) ? 0x00004000 : 0x00000400))) {
4571                 KdPrint2((PRINT_PREFIX "  Promise old/new unexpected\n"));
4572                 return INTERRUPT_REASON_IGNORE;
4573             }
4574             break;
4575         case PRTX:
4576             AtapiWritePort1(chan, IDX_BM_DeviceSpecific0, 0x0b);
4577             status = AtapiReadPort1(chan, IDX_BM_DeviceSpecific1);
4578             if (!DmaTransfer)
4579                 break;
4580             if(!(status & 0x20)) {
4581                 KdPrint2((PRINT_PREFIX "  Promise tx unexpected\n"));
4582                 return INTERRUPT_REASON_IGNORE;
4583             }
4584             break;
4585         case PRMIO: {
4586             ULONG stat_reg = (ChipFlags & PRG2) ? 0x60 : 0x6c;
4587             status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x40);
4588             AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x40, status);
4589 
4590             if(status & (1 << (Channel+1))) {
4591                 // our
4592             } else {
4593                 KdPrint2((PRINT_PREFIX "  Promise mio unexpected\n"));
4594                 return INTERRUPT_REASON_IGNORE;
4595             }
4596 
4597             if(!(ChipFlags & UNIATA_SATA))
4598                 break;
4599 
4600             pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),stat_reg);
4601             AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),stat_reg, (pr_status & (0x11 << Channel)));
4602             if(pr_status & (0x11 << Channel)) {
4603                 // TODO: reset channel
4604                 KdPrint2((PRINT_PREFIX "  Promise mio unexpected + reset req\n"));
4605                 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, 0);
4606             }
4607             if(!(status & (0x01 << Channel))) {
4608                 // Connect event
4609                 KdPrint2((PRINT_PREFIX "  Promise mio unexpected attach\n"));
4610                 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, 0);
4611             }
4612             if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
4613                 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4614             } else {
4615                 return INTERRUPT_REASON_IGNORE;
4616             }
4617 
4618             AtapiWritePort4(chan, IDX_BM_DeviceSpecific0, 0x00000001);
4619             break; }
4620         }
4621         break; }
4622     case ATA_NVIDIA_ID: {
4623         if(!(ChipFlags & UNIATA_SATA) || (ChipFlags & NVGEN))
4624             break;
4625 
4626         KdPrint2((PRINT_PREFIX "NVIDIA\n"));
4627 
4628         ULONG offs = (ChipFlags & NV4OFF) ? 0x0440 : 0x0010;
4629         ULONG shift = Channel * ((ChipFlags & NVQ) ? 4 : 16);
4630 
4631         /* get and clear interrupt status */
4632         if(ChipFlags & NVQ) {
4633             pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs);
4634             AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0fUL << shift) | 0x00f000f0);
4635         } else {
4636             pr_status = AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs);
4637             AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0f << shift));
4638         }
4639         KdPrint2((PRINT_PREFIX "  pr_status %x, shift %x\n", pr_status, shift));
4640 
4641         /* check for and handle connect events */
4642         if(((pr_status & (0x0cUL << shift)) == (0x04UL << shift)) ) {
4643             UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, 0);
4644         }
4645         /* check for and handle disconnect events */
4646         if((pr_status & (0x08UL << shift)) &&
4647             !((pr_status & (0x04UL << shift) &&
4648             UniataSataReadPort4(chan, IDX_SATA_SStatus, 0))) ) {
4649             UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, 0);
4650         }
4651         /* do we have any device action ? */
4652         if(!(pr_status & (0x01UL << shift))) {
4653             KdPrint2((PRINT_PREFIX "  nVidia unexpected\n"));
4654             if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
4655                 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4656             } else {
4657                 return INTERRUPT_REASON_IGNORE;
4658             }
4659         }
4660 
4661         break; }
4662     case ATA_ATI_ID:
4663         KdPrint2((PRINT_PREFIX "ATI\n"));
4664         if(ChipType == SIIMIO) {
4665             // fall to SiI
4666         } else {
4667             break;
4668         }
4669     case ATA_SILICON_IMAGE_ID:
4670 
4671         if(ChipType == SIIMIO) {
4672 
4673             reg32 = AtapiReadPort4(chan, IDX_BM_DeviceSpecific0);
4674             KdPrint2((PRINT_PREFIX "  Sii DS0 %x\n", reg32));
4675             if(reg32 == 0xffffffff) {
4676                 KdPrint2((PRINT_PREFIX "  Sii mio unexpected\n"));
4677                 return INTERRUPT_REASON_IGNORE;
4678             }
4679             if(!(reg32 & (BM_DS0_SII_DMA_SATA_IRQ | BM_DS0_SII_DMA_COMPLETE | BM_DS0_SII_IRQ | BM_DS0_SII_DMA_ENABLE | BM_DS0_SII_DMA_ERROR))) {
4680                 KdPrint2((PRINT_PREFIX "  Sii mio unexpected (2)\n"));
4681                 return INTERRUPT_REASON_IGNORE;
4682             }
4683 
4684             if(ChipFlags & UNIATA_SATA) {
4685                 if(reg32 & (BM_DS0_SII_DMA_SATA_IRQ | BM_DS0_SII_IRQ)) {
4686 
4687                     /* SIEN doesn't mask SATA IRQs on some 3112s.  Those
4688                     * controllers continue to assert IRQ as long as
4689                     * SError bits are pending.  Clear SError immediately.
4690                     */
4691                     if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
4692                         OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4693                     }
4694                 }
4695             }
4696 
4697             if (!DmaTransfer)
4698                 break;
4699             if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
4700                 KdPrint2((PRINT_PREFIX "  Sii mio unexpected (3)\n"));
4701                 return OurInterrupt;
4702             }
4703             AtapiWritePort1(chan, IDX_BM_Status, dma_status & ~BM_STATUS_ERR);
4704             goto skip_dma_stat_check;
4705 
4706         } else {
4707             if(!(deviceExtension->HwFlags & SIIINTR))
4708                 break;
4709             GetPciConfig1(0x71, reg8);
4710             KdPrint2((PRINT_PREFIX "  0x71 = %#x\n", reg8));
4711             if (!(reg8 &
4712                   (Channel ? 0x08 : 0x04))) {
4713                 return INTERRUPT_REASON_IGNORE;
4714             }
4715             if (!DmaTransfer) {
4716                 KdPrint2((PRINT_PREFIX "  cmd our\n"));
4717                 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4718             }
4719             SetPciConfig1(0x71, (Channel ? 0x08 : 0x04));
4720         }
4721         break;
4722 
4723     case ATA_ACARD_ID:
4724         if (!DmaTransfer)
4725             break;
4726         //dma_status = GetDmaStatus(deviceExtension, lChannel);
4727         if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
4728             KdPrint2((PRINT_PREFIX "  Acard unexpected\n"));
4729             return INTERRUPT_REASON_IGNORE;
4730         }
4731         AtapiWritePort1(chan, IDX_BM_Status, dma_status | BM_STATUS_INTR);
4732         AtapiStallExecution(1);
4733         AtapiWritePort1(chan, IDX_BM_Command,
4734             AtapiReadPort1(chan, IDX_BM_Command) & ~BM_COMMAND_START_STOP);
4735         goto skip_dma_stat_check;
4736     case ATA_INTEL_ID:
4737         if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
4738             if(ChipFlags & UNIATA_AHCI) {
4739                 // Do nothing here
4740             } else
4741             if(ChipFlags & UNIATA_SATA) {
4742                 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
4743                     OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4744                 }
4745                 if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
4746                     if(UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1)) {
4747                         OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4748                     }
4749                 }
4750             }
4751         }
4752         break;
4753     default:
4754         if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
4755             if(ChipFlags & UNIATA_AHCI) {
4756                 // Do nothing here
4757             } else
4758             if(ChipFlags & UNIATA_SATA) {
4759                 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
4760                     OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4761                 }
4762             }
4763         }
4764     }
4765 check_unknown:
4766     KdPrint2((PRINT_PREFIX "  perform generic check\n"));
4767     if (DmaTransfer) {
4768         if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
4769             KdPrint2((PRINT_PREFIX "  DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status));
4770             if(dma_status & BM_STATUS_ERR) {
4771                 KdPrint2((PRINT_PREFIX "  DmaTransfer + BM_STATUS_ERR -> our\n"));
4772                 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4773             } else {
4774                 KdPrint2((PRINT_PREFIX "  getting status...\n"));
4775                 GetStatus(chan, statusByte);
4776                 StatusValid = 1;
4777                 KdPrint2((PRINT_PREFIX "  status %#x\n", statusByte));
4778                 if(statusByte & IDE_STATUS_ERROR) {
4779                     KdPrint2((PRINT_PREFIX "  IDE_STATUS_ERROR -> our\n", statusByte));
4780                     OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4781                 } else
4782                 if ((statusByte & IDE_STATUS_DSC) &&
4783                     (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
4784                     (dma_status == BM_STATUS_ACTIVE)) {
4785                     KdPrint2((PRINT_PREFIX "  special case DMA + ATAPI + IDE_STATUS_DSC -> our\n", statusByte));
4786                     // some devices interrupts on each block transfer even in DMA mode
4787                     if(LunExt->TransferMode >= ATA_SDMA && LunExt->TransferMode <= ATA_WDMA2) {
4788                         KdPrint2((PRINT_PREFIX "  wait for completion\n"));
4789                         ///* clear interrupt and get status */
4790                         //GetBaseStatus(chan, statusByte);
4791                         //return INTERRUPT_REASON_IGNORE;
4792                         SingleBlockIntr = TRUE;
4793                     }
4794                 } else {
4795                     return INTERRUPT_REASON_IGNORE;
4796                 }
4797             }
4798         }
4799     } else {
4800         if(dma_status & BM_STATUS_INTR) {
4801             // bullshit, we have DMA interrupt, but had never initiate DMA operation
4802             KdPrint2((PRINT_PREFIX "  clear unexpected DMA intr\n"));
4803             AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL);
4804             // catch it !
4805             OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4806         }
4807     }
4808 skip_dma_stat_check:
4809     if(!(ChipFlags & UNIATA_SATA) && chan->ExpectingInterrupt) {
4810         AtapiStallExecution(1);
4811     }
4812 
4813     /* if drive is busy it didn't interrupt */
4814     /* the exception is DCS + BSY state of ATAPI devices */
4815     if(!StatusValid) {
4816         KdPrint2((PRINT_PREFIX "  getting status...\n"));
4817         GetStatus(chan, statusByte);
4818     }
4819     if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
4820         KdPrint3((PRINT_PREFIX "  ATAPI status %#x\n", statusByte));
4821     } else {
4822         KdPrint2((PRINT_PREFIX "  IDE status %#x\n", statusByte));
4823     }
4824     if (statusByte == IDE_STATUS_WRONG) {
4825         // interrupt from empty controller ?
4826     } else
4827     if (statusByte & IDE_STATUS_BUSY) {
4828         if(!chan->ExpectingInterrupt) {
4829             KdPrint3((PRINT_PREFIX "  unexpected intr + BUSY\n"));
4830             return OurInterrupt;
4831         }
4832 
4833         if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
4834             KdPrint2((PRINT_PREFIX "  ATAPI additional check\n"));
4835         } else {
4836             KdPrint2((PRINT_PREFIX "  expecting intr + BUSY (3), non ATAPI\n"));
4837             return INTERRUPT_REASON_IGNORE;
4838         }
4839         if((statusByte & ~(IDE_STATUS_DRQ | IDE_STATUS_INDEX)) !=
4840            (IDE_STATUS_BUSY | IDE_STATUS_DRDY | IDE_STATUS_DSC)) {
4841             KdPrint3((PRINT_PREFIX "  unexpected status, seems it is not our\n"));
4842             return INTERRUPT_REASON_IGNORE;
4843         }
4844         if(!(LunExt->DeviceFlags & DFLAGS_INT_DRQ) && (statusByte & IDE_STATUS_DRQ)) {
4845             KdPrint3((PRINT_PREFIX "  unexpected DRQ, seems it is not our\n"));
4846             return INTERRUPT_REASON_IGNORE;
4847         }
4848 
4849         EarlyIntr = TRUE;
4850 
4851         if(dma_status & BM_STATUS_INTR) {
4852             KdPrint3((PRINT_PREFIX "  our interrupt with BSY set, try wait in ISR or post to DPC\n"));
4853             /* clear interrupt and get status */
4854             GetBaseStatus(chan, statusByte);
4855             if(!(dma_status & BM_STATUS_ACTIVE)) {
4856                 AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL);
4857             }
4858             KdPrint3((PRINT_PREFIX "  base status %#x (+BM_STATUS_INTR)\n", statusByte));
4859             return INTERRUPT_REASON_OUR;
4860         }
4861 
4862         if(g_WaitBusyInISR) {
4863             GetStatus(chan, statusByte);
4864             KdPrint2((PRINT_PREFIX "  status re-check %#x\n", statusByte));
4865             reg8 = AtapiReadPort1(chan, IDX_IO1_i_Error);
4866             KdPrint2((PRINT_PREFIX "  Error reg (%#x)\n", reg8));
4867             if (!(statusByte & IDE_STATUS_BUSY)) {
4868                 KdPrint2((PRINT_PREFIX "  expecting intr + cleared BUSY\n"));
4869             }
4870             if (statusByte & IDE_STATUS_BUSY) {
4871                 KdPrint2((PRINT_PREFIX "  still BUSY, seems it is not our\n"));
4872                 return INTERRUPT_REASON_IGNORE;
4873             }
4874         }
4875 
4876     }
4877 
4878     /* clear interrupt and get status */
4879     GetBaseStatus(chan, statusByte);
4880     KdPrint2((PRINT_PREFIX "  base status %#x\n", statusByte));
4881     if (statusByte == IDE_STATUS_WRONG) {
4882         // interrupt from empty controller ?
4883     } else
4884     if(!(statusByte & (IDE_STATUS_DRQ | IDE_STATUS_DRDY))) {
4885         KdPrint2((PRINT_PREFIX "  no DRQ/DRDY set\n"));
4886         return OurInterrupt;
4887     }
4888 
4889 #ifndef UNIATA_PIO_ONLY
4890     if(DmaTransfer) {
4891         if(!SingleBlockIntr && (!EarlyIntr || g_WaitBusyInISR)) {
4892             dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
4893         } else {
4894             PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
4895             PATA_REQ AtaReq = srb ? (PATA_REQ)(srb->SrbExtension) : NULL;
4896 
4897             //ASSERT(AtaReq);
4898 
4899             if(SingleBlockIntr) {
4900                 KdPrint2((PRINT_PREFIX "  set REQ_STATE_ATAPI_EXPECTING_DATA_INTR2.\n"));
4901             } else {
4902                 KdPrint2((PRINT_PREFIX "  set REQ_STATE_EARLY_INTR.\n"));
4903             }
4904             if(AtaReq) {
4905                 AtaReq->ReqState = SingleBlockIntr ? REQ_STATE_ATAPI_EXPECTING_DATA_INTR2 : REQ_STATE_EARLY_INTR;
4906             }
4907         }
4908     }
4909 #endif //
4910 
4911     if (!(chan->ExpectingInterrupt)) {
4912 
4913         KdPrint2((PRINT_PREFIX "  Unexpected interrupt.\n"));
4914 
4915         if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
4916             KdPrint2((PRINT_PREFIX "  ATAPI additional check\n"));
4917         } else {
4918             KdPrint2((PRINT_PREFIX "  OurInterrupt = %d\n", OurInterrupt));
4919             return OurInterrupt;
4920         }
4921         interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
4922         KdPrint3((PRINT_PREFIX "AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason));
4923         return OurInterrupt;
4924     }
4925     //ASSERT(!chan->queue_depth || chan->cur_req);
4926 
4927     KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__: exit with TRUE\n"));
4928     return INTERRUPT_REASON_OUR;
4929 
4930 } // end AtapiCheckInterrupt__()
4931 
4932 
4933 BOOLEAN
4934 NTAPI
4935 AtapiInterrupt__(
4936     IN PVOID HwDeviceExtension,
4937     IN UCHAR c
4938     )
4939 {
4940     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4941     PHW_CHANNEL chan = &(deviceExtension->chan[c]);
4942     // Get current Srb
4943     PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
4944     PATA_REQ AtaReq = srb ? (PATA_REQ)(srb->SrbExtension) : NULL;
4945 
4946     ULONG wordCount = 0, wordsThisInterrupt = DEV_BSIZE/2;
4947     ULONG status = SRB_STATUS_SUCCESS;
4948     UCHAR dma_status = 0;
4949     ULONG i;
4950     ULONG k;
4951     UCHAR statusByte = 0,interruptReason;
4952 
4953     BOOLEAN atapiDev = FALSE;
4954 
4955 #ifdef _DEBUG
4956     UCHAR Channel;
4957 #endif //_DEBUG
4958     UCHAR lChannel;
4959     UCHAR DeviceNumber;
4960     BOOLEAN DmaTransfer = FALSE;
4961     UCHAR error = 0;
4962     ULONG TimerValue = 1000;
4963     ULONG TotalTimerValue = 0;
4964 #ifdef UNIATA_USE_XXableInterrupts
4965     BOOLEAN InDpc = (KeGetCurrentIrql() == DISPATCH_LEVEL);
4966 #else
4967     BOOLEAN InDpc = (chan->DpcState != DPC_STATE_ISR);
4968 #endif // UNIATA_USE_XXableInterrupts
4969     BOOLEAN UseDpc = deviceExtension->UseDpc;
4970 //    BOOLEAN RestoreUseDpc = FALSE;
4971     BOOLEAN DataOverrun = FALSE;
4972     BOOLEAN NoStartIo = TRUE;
4973     BOOLEAN NoRetry = FALSE;
4974 
4975     KdPrint2((PRINT_PREFIX "AtapiInterrupt:\n"));
4976     if(InDpc) {
4977         KdPrint2((PRINT_PREFIX "  InDpc = TRUE\n"));
4978         //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
4979     }
4980 
4981     UCHAR PathId;
4982     UCHAR TargetId;
4983     UCHAR Lun;
4984     UCHAR OldReqState = REQ_STATE_NONE;
4985     //ULONG ldev;
4986     PHW_LU_EXTENSION LunExt;
4987 
4988     lChannel = c;
4989 
4990 #ifdef _DEBUG
4991     Channel = (UCHAR)(deviceExtension->Channel + lChannel);
4992 
4993     KdPrint2((PRINT_PREFIX "  cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension->DevIndex, Channel, KeGetCurrentIrql(), c));
4994 #endif //_DEBUG
4995 
4996     if((chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
4997        (AtaReq && (AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) ||
4998        (deviceExtension->HwFlags & UNIATA_AHCI)) {
4999         DmaTransfer = TRUE;
5000         KdPrint2((PRINT_PREFIX "  DmaTransfer = TRUE\n"));
5001     }
5002 
5003     if (srb) {
5004         PathId   = srb->PathId;
5005         TargetId = srb->TargetId;
5006         Lun      = srb->Lun;
5007     } else {
5008         PathId = (UCHAR)c;
5009         TargetId =
5010         Lun      = 0;
5011         goto enqueue_next_req;
5012     }
5013 
5014     //ldev = GET_LDEV2(PathId, TargetId, Lun);
5015     DeviceNumber = (UCHAR)(TargetId);
5016     LunExt = chan->lun[DeviceNumber];
5017     atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
5018     KdPrint2((PRINT_PREFIX "  dev_type %s\n", atapiDev ? "ATAPI" : "IDE"));
5019 
5020     // check if we are in ISR DPC
5021     if(InDpc) {
5022         KdPrint2((PRINT_PREFIX "  InDpc -> CTRFLAGS_INTR_DISABLED\n"));
5023         goto ServiceInterrupt;
5024     }
5025 
5026     if (DmaTransfer) {
5027         dma_status = GetDmaStatus(deviceExtension, lChannel);
5028     }
5029 
5030     if (!(chan->ExpectingInterrupt)) {
5031 
5032         KdPrint2((PRINT_PREFIX "  Unexpected interrupt for this channel.\n"));
5033         return FALSE;
5034     }
5035 
5036     // change request state
5037     if(AtaReq) {
5038         OldReqState = AtaReq->ReqState;
5039         AtaReq->ReqState = REQ_STATE_PROCESSING_INTR;
5040         KdPrint2((PRINT_PREFIX "  OldReqState = %x\n", OldReqState));
5041     }
5042 
5043     // We don't want using DPC for fast operations, like
5044     // DMA completion, sending CDB, short ATAPI transfers, etc.
5045     // !!!! BUT !!!!
5046     // We MUST use DPC, because of interprocessor synchronization
5047     // on multiprocessor platforms
5048 
5049     if(DmaTransfer)
5050         goto ServiceInterrupt;
5051 
5052     switch(OldReqState) {
5053     case REQ_STATE_ATAPI_EXPECTING_CMD_INTR:
5054         KdPrint3((PRINT_PREFIX "  EXPECTING_CMD_INTR\n"));
5055     case REQ_STATE_ATAPI_EXPECTING_DATA_INTR:
5056     case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2:
5057     case REQ_STATE_DPC_WAIT_BUSY0:
5058     case REQ_STATE_DPC_WAIT_BUSY1:
5059         KdPrint2((PRINT_PREFIX "  continue service interrupt\n"));
5060         goto ServiceInterrupt;
5061     case REQ_STATE_ATAPI_DO_NOTHING_INTR:
5062         KdPrint2((PRINT_PREFIX "  do nothing on interrupt\n"));
5063         return TRUE;
5064     }
5065 
5066     if((!DmaTransfer && !atapiDev) || deviceExtension->DriverMustPoll) {
5067         KdPrint2((PRINT_PREFIX "  service PIO HDD\n"));
5068         UseDpc = FALSE;
5069     }
5070 
5071 #ifndef UNIATA_CORE
5072 
5073     if(!UseDpc)
5074         goto ServiceInterrupt;
5075 
5076 #ifdef UNIATA_USE_XXableInterrupts
5077     if(InDpc) {
5078         KdPrint2((PRINT_PREFIX "  Unexpected InDpc\n"));
5079         ASSERT(FALSE);
5080         // shall never get here
5081         TimerValue = 1;
5082         goto CallTimerDpc;
5083     }
5084 
5085     KdPrint2((PRINT_PREFIX "  this is direct DPC call on DRQL\n"));
5086     if(AtaReq) {
5087         AtaReq->ReqState = REQ_STATE_DPC_INTR_REQ;
5088         KdPrint2((PRINT_PREFIX "  ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
5089     } else {
5090         KdPrint2((PRINT_PREFIX "  DPC without AtaReq!!!\n"));
5091     }
5092 #else
5093     KdPrint2((PRINT_PREFIX "call service interrupt\n"));
5094     goto ServiceInterrupt;
5095 #endif // UNIATA_USE_XXableInterrupts
5096 
5097 PostToDpc:
5098 
5099     // Attention !!!
5100     // AtapiInterruptDpc() is called on DISPATCH_LEVEL
5101     // We always get here when are called from timer callback, which is invoked on DRQL.
5102     // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
5103 
5104     KdPrint2((PRINT_PREFIX "AtapiInterrupt: start DPC init...\n"));
5105     // disable interrupts for this channel,
5106     // but avoid recursion and double-disable
5107     if(OldReqState != REQ_STATE_DPC_WAIT_BUSY1) {
5108         UniataExpectChannelInterrupt(chan, FALSE);
5109         AtapiDisableInterrupts(deviceExtension, lChannel);
5110     }
5111     // go to ISR DPC
5112     chan->ChannelCtrlFlags |= CTRFLAGS_DPC_REQ;
5113 
5114 #ifdef UNIATA_USE_XXableInterrupts
5115     // Will lower IRQL to DISPATCH_LEVEL
5116     ScsiPortNotification(CallEnableInterrupts, HwDeviceExtension,
5117                          /*c ?*/ AtapiInterruptDpc/*_1 : AtapiInterruptDpc_0*/);
5118     KdPrint2((PRINT_PREFIX "AtapiInterrupt: DPC inited\n"));
5119 #else
5120     // Will raise IRQL to DIRQL
5121     AtapiQueueTimerDpc(HwDeviceExtension, c,
5122                          AtapiInterruptDpc,
5123                          TimerValue);
5124     KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
5125 #endif // UNIATA_USE_XXableInterrupts
5126     return TRUE;
5127 
5128 #ifndef UNIATA_CORE
5129 CallTimerDpc:
5130     AtaReq->ReqState = REQ_STATE_PROCESSING_INTR;
5131 CallTimerDpc2:
5132     if(!InDpc && OldReqState != REQ_STATE_DPC_WAIT_BUSY1) {
5133         // we must block interrupts from this channel
5134         // If device generate new interrupt before we get to DPC,
5135         // ISR will assume, that it is NOT our interrupt
5136         AtapiDisableInterrupts(deviceExtension, lChannel);
5137         // We should not clean ExpectingInterrupt flag on channel, since it is used in DPC
5138     }
5139     // Will raise IRQL to DIRQL
5140     AtapiQueueTimerDpc(HwDeviceExtension, c,
5141                          AtapiCallBack_X,
5142                          TimerValue);
5143     return TRUE;
5144 #endif //UNIATA_CORE
5145 
5146 ServiceInterrupt:
5147 
5148     if(AtaReq && InDpc) {
5149         switch(AtaReq->ReqState) {
5150         case REQ_STATE_DPC_WAIT_DRQ0:
5151             goto PIO_wait_DRQ0;
5152         case REQ_STATE_DPC_WAIT_BUSY:
5153             goto PIO_wait_busy;
5154         case REQ_STATE_DPC_WAIT_DRQ:
5155             goto PIO_wait_DRQ;
5156         case REQ_STATE_DPC_WAIT_DRQ_ERR:
5157             goto continue_err;
5158         case REQ_STATE_DPC_WAIT_BUSY0:
5159         case REQ_STATE_DPC_WAIT_BUSY1:
5160             // continue normal execution
5161             break;
5162         }
5163     }
5164 #else
5165 ServiceInterrupt:
5166 #endif //UNIATA_CORE
5167 /*
5168     // make additional delay for old devices (if we are not in DPC)
5169     if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
5170              &&
5171        !InDpc &&
5172        !atapiDev &&
5173        !(deviceExtension->HwFlags & UNIATA_SATA)
5174        ) {
5175         KdPrint2((PRINT_PREFIX "  additional delay 10us for old devices\n"));
5176         AtapiStallExecution(10);
5177     }
5178 */
5179 
5180     /* clear interrupt and get status */
5181     if(deviceExtension->HwFlags & UNIATA_AHCI) {
5182         UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, srb);
5183         statusByte = (UCHAR)(AtaReq->ahci.in_status & IDE_STATUS_MASK);
5184 
5185         if(chan->AhciLastIS & ~(ATA_AHCI_P_IX_DHR | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_SDB)) {
5186             KdPrint3((PRINT_PREFIX "Err intr (%#x), SE (%#x)\n",
5187                 chan->AhciLastIS & ~(ATA_AHCI_P_IX_DHR | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_SDB),
5188                 chan->AhciLastSError));
5189             if(chan->AhciLastIS & ~ATA_AHCI_P_IX_OF) {
5190 
5191                 if((chan->AhciLastIS == ATA_AHCI_P_IX_INF) &&
5192                    !(statusByte & IDE_STATUS_ERROR) &&
5193                    !chan->AhciLastSError &&
5194                    srb && (srb->SrbFlags & SRB_FLAGS_DATA_IN)
5195                    ) {
5196                   KdPrint3((PRINT_PREFIX "ATA_AHCI_P_IX_INF on READ, assume underflow\n"));
5197                   // continue processing in regular way
5198                 } else {
5199 
5200                   //KdPrint3((PRINT_PREFIX "Err mask (%#x)\n", chan->AhciLastIS & ~ATA_AHCI_P_IX_OF));
5201                   // We have some other error except Overflow
5202                   // Just signal ERROR, operation will be aborted in ERROR branch.
5203                   statusByte |= IDE_STATUS_ERROR;
5204                   AtaReq->ahci.in_serror = chan->AhciLastSError;
5205                   if(chan->AhciLastSError & (ATA_SE_HANDSHAKE_ERR | ATA_SE_LINKSEQ_ERR | ATA_SE_TRANSPORT_ERR | ATA_SE_UNKNOWN_FIS)) {
5206                       KdPrint2((PRINT_PREFIX "Unrecoverable\n"));
5207                       NoRetry = TRUE;
5208                   }
5209                 }
5210             } else {
5211                 // We have only Overflow. Abort operation and continue
5212 #ifdef _DEBUG
5213                 UniataDumpAhciPortRegs(chan);
5214 #endif
5215                 if(!UniataAhciAbortOperation(chan)) {
5216                     KdPrint2((PRINT_PREFIX "need UniataAhciReset\n"));
5217                 }
5218 #ifdef _DEBUG
5219                 UniataDumpAhciPortRegs(chan);
5220 #endif
5221                 UniataAhciWaitCommandReady(chan, 10);
5222             }
5223         }
5224 
5225     } else {
5226         GetBaseStatus(chan, statusByte);
5227     }
5228     if(atapiDev) {
5229         KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte));
5230     } else {
5231         KdPrint2((PRINT_PREFIX "AtapiInterrupt: Entered with status (%#x)\n", statusByte));
5232     }
5233 
5234     if(!UseDpc) {
5235         KdPrint2((PRINT_PREFIX "  operate like in DPC\n"));
5236         InDpc = TRUE;
5237     }
5238 
5239     if (!atapiDev) {
5240         // IDE
5241         if(deviceExtension->HwFlags & UNIATA_AHCI) {
5242             KdPrint3((PRINT_PREFIX "  AHCI branch (IDE)\n"));
5243         } else
5244         if (statusByte & IDE_STATUS_BUSY) {
5245             if (deviceExtension->DriverMustPoll) {
5246                 // Crashdump is polling and we got caught with busy asserted.
5247                 // Just go away, and we will be polled again shortly.
5248                 KdPrint2((PRINT_PREFIX "  Hit BUSY while polling during crashdump.\n"));
5249                 goto ReturnEnableIntr;
5250             }
5251 try_dpc_wait:
5252             // Ensure BUSY is non-asserted.
5253             // make a very small idle before falling to DPC
5254             k = (InDpc && UseDpc) ? 1000 : 2;
5255 
5256             for (i = 0; i < k; i++) {
5257 
5258                 GetBaseStatus(chan, statusByte);
5259                 if (!(statusByte & IDE_STATUS_BUSY)) {
5260                     break;
5261                 }
5262                 AtapiStallExecution(10);
5263             }
5264 
5265             if (!InDpc && UseDpc && i == 2) {
5266 
5267                 KdPrint2((PRINT_PREFIX "  BUSY on entry. Status %#x, Base IO %#x\n", statusByte));
5268 
5269                 TimerValue = 50;
5270                 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
5271 
5272 #ifndef UNIATA_CORE
5273                 goto PostToDpc;
5274 #else //UNIATA_CORE
5275                 AtapiStallExecution(TimerValue);
5276                 goto ServiceInterrupt;
5277 #endif //UNIATA_CORE
5278             } else
5279             if (InDpc && i == k) {
5280                 // reset the controller.
5281                 KdPrint2((PRINT_PREFIX
5282                             "  Resetting due to BUSY on entry - %#x.\n",
5283                             statusByte));
5284                 goto IntrPrepareResetController;
5285             }
5286         }
5287     } else {
5288         // ATAPI
5289         if(!LunExt->IdentifyData.MajorRevision &&
5290             InDpc &&
5291             /*!atapiDev &&*/
5292             !(deviceExtension->HwFlags & UNIATA_SATA)
5293             ) {
5294             //KdPrint2((PRINT_PREFIX "  additional delay 10us for old devices (2)\n"));
5295             //AtapiStallExecution(10);
5296         }
5297         if(deviceExtension->HwFlags & UNIATA_AHCI) {
5298             KdPrint3((PRINT_PREFIX "  AHCI branch (ATAPI)\n"));
5299         } else {
5300             interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
5301             KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
5302         }
5303 
5304         if (statusByte & IDE_STATUS_BUSY) {
5305         //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
5306 /*
5307 #ifndef UNIATA_CORE
5308             // This is just workaround
5309             // We should DISABLE interrupts before entering WAIT state
5310             UniataExpectChannelInterrupt(chan, TRUE);
5311 #endif //UNIATA_CORE
5312 */
5313             KdPrint3((PRINT_PREFIX "  BUSY on ATAPI device, waiting %d us\n", LunExt->AtapiReadyWaitDelay));
5314 #ifndef UNIATA_CORE
5315             if(LunExt->AtapiReadyWaitDelay && (LunExt->AtapiReadyWaitDelay > g_opt_MaxIsrWait) && !InDpc && UseDpc) {
5316                 TimerValue = LunExt->AtapiReadyWaitDelay;
5317                 KdPrint2((PRINT_PREFIX "  too long wait: ISR -> DPC (0)\n"));
5318                 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
5319                 goto CallTimerDpc2;
5320             }
5321 #endif //UNIATA_CORE
5322             TimerValue = 10;
5323             for(k=20; k; k--) {
5324                 GetBaseStatus(chan, statusByte);
5325                 KdPrint3((PRINT_PREFIX "  status re-check %#x\n", statusByte));
5326                 KdPrint3((PRINT_PREFIX "  Error reg (%#x)\n",
5327                             AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Error)));
5328                 if (!(statusByte & IDE_STATUS_BUSY)) {
5329                     KdPrint2((PRINT_PREFIX "  expecting intr + cleared BUSY\n"));
5330                     break;
5331                 }
5332                 TotalTimerValue += TimerValue;
5333                 if(k <= 1) {
5334                     KdPrint3((PRINT_PREFIX "  too long wait -> DPC\n"));
5335                     if(!InDpc) {
5336                         KdPrint2((PRINT_PREFIX "  too long wait: ISR -> DPC\n"));
5337                         TimerValue = 100;
5338                         AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
5339                     } else {
5340                         KdPrint2((PRINT_PREFIX "  too long wait: DPC -> DPC\n"));
5341                         TimerValue = 1000;
5342                         AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY1;
5343                     }
5344 #ifndef UNIATA_CORE
5345                     if(UseDpc) {
5346                         if(!LunExt->AtapiReadyWaitDelay) {
5347                             LunExt->AtapiReadyWaitDelay = TotalTimerValue*2/3;
5348                         }
5349                         goto CallTimerDpc2;
5350                     }
5351 #endif //UNIATA_CORE
5352                 }
5353 
5354                 AtapiStallExecution(TimerValue);
5355                 TimerValue += 10;
5356             }
5357             if(!LunExt->AtapiReadyWaitDelay) {
5358                 LunExt->AtapiReadyWaitDelay = TotalTimerValue*2/3;
5359                 KdPrint2((PRINT_PREFIX "  store AtapiReadyWaitDelay: %d\n", LunExt->AtapiReadyWaitDelay));
5360             }
5361             if (statusByte & IDE_STATUS_BUSY) {
5362                 KdPrint3((PRINT_PREFIX "  expecting intr + BUSY (2), try DPC wait\n"));
5363                 goto try_dpc_wait;
5364             }
5365         }
5366     }
5367 
5368     if(AtaReq && DmaTransfer && !(deviceExtension->HwFlags & UNIATA_AHCI)) {
5369         switch(OldReqState) {
5370         case REQ_STATE_EARLY_INTR:
5371         case REQ_STATE_DPC_WAIT_BUSY0:
5372 
5373             if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) {
5374                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: DMA still active\n"));
5375                 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
5376             }
5377             break;
5378         }
5379     }
5380 
5381 //retry_check:
5382     // Check for error conditions.
5383     if ((statusByte & IDE_STATUS_ERROR) ||
5384         (dma_status & BM_STATUS_ERR)) {
5385 
5386         if(deviceExtension->HwFlags & UNIATA_AHCI) {
5387             error = AtaReq->ahci.in_error;
5388             // wait ready
5389 #ifdef _DEBUG
5390             UniataDumpAhciPortRegs(chan);
5391 #endif
5392             if(!UniataAhciAbortOperation(chan)) {
5393                 KdPrint2((PRINT_PREFIX "need UniataAhciReset\n"));
5394             }
5395             // clear interrupts again
5396             UniataAhciWaitCommandReady(chan, 10);
5397 #ifdef _DEBUG
5398             UniataDumpAhciPortRegs(chan);
5399 #endif
5400             UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED);
5401             if(NoRetry) {
5402                 AtaReq->retry += MAX_RETRIES;
5403                 if(!error && (statusByte & IDE_STATUS_ERROR)) {
5404                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: force error status\n"));
5405                     error |= IDE_STATUS_ERROR;
5406                 }
5407             }
5408 #ifdef _DEBUG
5409             UniataDumpAhciPortRegs(chan);
5410 #endif
5411         } else {
5412             error = AtapiReadPort1(chan, IDX_IO1_i_Error);
5413         }
5414         KdPrint2((PRINT_PREFIX "AtapiInterrupt: Error %#x\n", error));
5415 /*
5416         if(error & IDE_STATUS_CORRECTED_ERROR) {
5417             KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
5418             statusByte &= ~IDE_STATUS_ERROR;
5419             goto retry_check;
5420         }
5421 */
5422         if(AtaReq) {
5423             KdPrint2((PRINT_PREFIX "  Bad Lba %#I64x\n", AtaReq->lba));
5424         } else {
5425             KdPrint2((PRINT_PREFIX "  Bad Lba unknown\n"));
5426         }
5427 
5428         if(deviceExtension->HwFlags & UNIATA_AHCI) {
5429             KdPrint2((PRINT_PREFIX "  no wait ready after error\n"));
5430         } else
5431         if(!atapiDev) {
5432             KdPrint2((PRINT_PREFIX "  wait 100 ready after IDE error\n"));
5433             AtapiStallExecution(100);
5434         } else {
5435             KdPrint2((PRINT_PREFIX "  wait 10 ready after ATAPI error\n"));
5436             AtapiStallExecution(10);
5437         }
5438 continue_err:
5439 
5440         KdPrint3((PRINT_PREFIX "  Intr on DRQ %x\n",
5441             LunExt->DeviceFlags & DFLAGS_INT_DRQ));
5442 
5443         for (k = atapiDev ? 0 : 200; k; k--) {
5444             GetBaseStatus(chan, statusByte);
5445             if (!(statusByte & IDE_STATUS_DRQ)) {
5446                 AtapiStallExecution(50);
5447             } else {
5448                 break;
5449             }
5450         }
5451 
5452         if (!atapiDev) {
5453             /* if this is a UDMA CRC error, reinject request */
5454 
5455             AtaReq->retry++;
5456             if(AtaReq->retry < MAX_RETRIES) {
5457 #ifdef IO_STATISTICS
5458                 chan->lun[DeviceNumber]->ModeErrorCount[AtaReq->retry]++;
5459 #endif //IO_STATISTICS
5460                 if(DmaTransfer /*&&
5461                    (error & IDE_ERROR_ICRC)*/) {
5462                     KdPrint2((PRINT_PREFIX "Errors in DMA mode\n"));
5463                     if(AtaReq->retry < MAX_RETRIES) {
5464 //fallback_pio:
5465                         if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
5466                             //AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
5467                             // Downrate will happen in AtapiDmaReinit(), try UDMA-2 for HDD only
5468                             AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
5469                         }
5470                         AtaReq->ReqState = REQ_STATE_QUEUED;
5471                         goto reenqueue_req;
5472                     }
5473                 } else {
5474                     if(!(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE)) {
5475                         AtaReq->retry++;
5476                     }
5477                     KdPrint2((PRINT_PREFIX "Errors in PIO mode\n"));
5478                 }
5479             }
5480         } else {
5481             interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
5482             KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason));
5483 
5484             if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
5485                 if(deviceExtension->HwFlags & UNIATA_AHCI) {
5486                     // Do nothing here
5487                 } else
5488                 if(deviceExtension->HwFlags & UNIATA_SATA) {
5489                     UniataSataClearErr(HwDeviceExtension, lChannel, UNIATA_SATA_IGNORE_CONNECT, 0);
5490                 }
5491             }
5492 
5493             if(DmaTransfer && (chan->lun[DeviceNumber]->TransferMode > ATA_UDMA2) &&
5494                ((error >> 4) == SCSI_SENSE_HARDWARE_ERROR)) {
5495                 if(AtaReq->retry < MAX_RETRIES) {
5496 //fallback_pio:
5497                     // Downrate will happen in AtapiDmaReinit(), use PIO immediately for ATAPI
5498                     AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
5499                     AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
5500 //                        LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5501                     AtaReq->ReqState = REQ_STATE_QUEUED;
5502                     goto reenqueue_req;
5503                 }
5504             } else {
5505                 if(!(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE)) {
5506                     AtaReq->retry++;
5507                 }
5508                 KdPrint3((PRINT_PREFIX "Errors in PIO mode\n"));
5509             }
5510         }
5511 
5512         KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error\n"));
5513         if (srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
5514             // Fail this request.
5515             status = SRB_STATUS_ERROR;
5516             goto CompleteRequest;
5517         } else {
5518             KdPrint2((PRINT_PREFIX "  continue with SCSIOP_REQUEST_SENSE\n"));
5519         }
5520     } else
5521     if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE_LBA48) {
5522         KdPrint2((PRINT_PREFIX "DMA doesn't work right with LBA48\n"));
5523         deviceExtension->HbaCtrlFlags |= HBAFLAGS_DMA_DISABLED_LBA48;
5524     } else
5525     if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE) {
5526 #ifdef IO_STATISTICS
5527         KdPrint2((PRINT_PREFIX "Some higher mode doesn't work right :((\n"));
5528         KdPrint2((PRINT_PREFIX "Recovery stats[%d]: %d vs %d\n",
5529               AtaReq->retry,
5530               LunExt->RecoverCount[AtaReq->retry],
5531               LunExt->BlockIoCount
5532               ));
5533         LunExt->RecoverCount[AtaReq->retry]++;
5534         if(LunExt->RecoverCount[AtaReq->retry] >= LunExt->BlockIoCount/3 ||
5535            (deviceExtension->HwFlags & UNIATA_NO80CHK)
5536            ) {
5537 #else
5538         if(deviceExtension->HwFlags & UNIATA_NO80CHK) {
5539 #endif //IO_STATISTICS
5540             KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", LunExt->TransferMode));
5541             LunExt->LimitedTransferMode =
5542                 LunExt->TransferMode;
5543         }
5544     }
5545 #ifdef IO_STATISTICS
5546     if(AtaReq->bcount) {
5547         // we need stats for Read/Write operations
5548         LunExt->BlockIoCount++;
5549     }
5550     LunExt->IoCount++;
5551 #endif //IO_STATISTICS
5552 
5553 continue_PIO:
5554 
5555     // check reason for this interrupt.
5556     if (atapiDev) {
5557 
5558         KdPrint2((PRINT_PREFIX "AtapiInterrupt: ATAPI branch\n"));
5559         // ATAPI branch
5560 
5561         interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
5562         KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
5563         if(DmaTransfer) {
5564             wordsThisInterrupt = DEV_BSIZE/2*512;
5565         } else {
5566             wordsThisInterrupt = DEV_BSIZE/2;
5567         }
5568 
5569     } else {
5570 
5571         // ATA branch
5572 
5573         if(DmaTransfer) {
5574             // simulate DRQ for DMA transfers
5575             statusByte |= IDE_STATUS_DRQ;
5576         }
5577         if (statusByte & IDE_STATUS_DRQ) {
5578 
5579             if(DmaTransfer) {
5580                 wordsThisInterrupt = DEV_BSIZE/2*512;
5581             } else
5582             if (LunExt->MaximumBlockXfer) {
5583                 wordsThisInterrupt = DEV_BSIZE/2 * LunExt->MaximumBlockXfer;
5584             }
5585 
5586             if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
5587 
5588                 interruptReason = ATAPI_IR_IO_toHost;
5589 
5590             } else if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
5591                 interruptReason = ATAPI_IR_IO_toDev;
5592 
5593             } else {
5594                 status = SRB_STATUS_ERROR;
5595                 goto CompleteRequest;
5596             }
5597 
5598         } else if (statusByte & IDE_STATUS_BUSY) {
5599 
5600             //AtapiEnableInterrupts(deviceExtension, lChannel);
5601             KdPrint2((PRINT_PREFIX "AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
5602             return FALSE;
5603 
5604         } else {
5605 
5606             KdPrint2((PRINT_PREFIX "AtapiInterrupt: !DRQ, !BUSY, WordsLeft %#x\n", AtaReq->WordsLeft));
5607             if (AtaReq->WordsLeft) {
5608 
5609                 // Funky behaviour seen with PCI IDE (not all, just one).
5610 PIO_wait_DRQ0:
5611                 // The ISR hits with DRQ low, but comes up later.
5612                 for (k = 0; k < 5000; k++) {
5613                     GetBaseStatus(chan, statusByte);
5614                     if (statusByte & IDE_STATUS_DRQ) {
5615                         break;
5616                     }
5617                     if(!InDpc) {
5618                         // goto DPC
5619                         AtaReq->ReqState = REQ_STATE_DPC_WAIT_DRQ0;
5620                         TimerValue = 100;
5621                         KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (drq0)\n"));
5622 #ifndef UNIATA_CORE
5623                         goto PostToDpc;
5624 #else //UNIATA_CORE
5625                         AtapiStallExecution(TimerValue);
5626                         goto ServiceInterrupt;
5627 #endif //UNIATA_CORE
5628                     }
5629                     AtapiStallExecution(100);
5630                 }
5631                 if (k == 5000) {
5632                     // reset the controller.
5633                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
5634                                 statusByte));
5635 IntrPrepareResetController:
5636                     AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_CURRENT);
5637                     goto ReturnEnableIntr;
5638 
5639                 } else {
5640                     interruptReason = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ? ATAPI_IR_IO_toHost : ATAPI_IR_IO_toDev;
5641                 }
5642 
5643             } else {
5644                 // Command complete - verify, write, or the SMART enable/disable.
5645                 // Also get_media_status
5646                 interruptReason = ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd;
5647             }
5648         }
5649     }
5650 
5651     KdPrint2((PRINT_PREFIX "AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason, statusByte));
5652     if(deviceExtension->HwFlags & UNIATA_AHCI) {
5653         KdPrint2((PRINT_PREFIX "  AHCI path, WordsTransfered %x, WordsLeft %x\n", AtaReq->WordsTransfered, AtaReq->WordsLeft));
5654 /*        if(chan->AhciLastIS & ATA_AHCI_P_IX_OF) {
5655             //status = SRB_STATUS_DATA_OVERRUN;
5656             DataOverrun = TRUE;
5657         } else {
5658             status = SRB_STATUS_SUCCESS;
5659         }*/
5660         if(AtaReq->WordsTransfered >= AtaReq->WordsLeft) {
5661             AtaReq->WordsLeft = 0;
5662         } else {
5663             AtaReq->WordsLeft -= AtaReq->WordsTransfered;
5664         }
5665         //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
5666         //    status = SRB_STATUS_DATA_OVERRUN;
5667         //}
5668         status = SRB_STATUS_SUCCESS;
5669         chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
5670         goto CompleteRequest;
5671     } else
5672     if ((interruptReason == ATAPI_IR_COD_Cmd) && (statusByte & IDE_STATUS_DRQ)) {
5673         if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
5674             AtapiDmaDBPreSync(HwDeviceExtension, chan, srb);
5675         }
5676         // Write the packet.
5677         KdPrint3((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n"));
5678         // Send CDB to device.
5679         WriteBuffer(chan, (PUSHORT)srb->Cdb,
5680                           LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
5681                           /*0*/ PIO0_TIMING);
5682         AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
5683 
5684         if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
5685             KdPrint2((PRINT_PREFIX "AtapiInterrupt: AtapiDmaStart().\n"));
5686             AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, srb);
5687         }
5688 
5689         goto ReturnEnableIntr;
5690 
5691     } else if ((interruptReason == ATAPI_IR_IO_toDev) && (statusByte & IDE_STATUS_DRQ)) {
5692 
5693         // Write the data.
5694         if (atapiDev) {
5695 
5696             // Pick up bytes to transfer and convert to words.
5697             wordCount =
5698                 AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
5699 
5700             wordCount |=
5701                 (USHORT)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8;
5702 
5703             // Covert bytes to words.
5704             wordCount >>= 1;
5705             KdPrint2((PRINT_PREFIX "AtapiInterrupt: get W wordCount %#x\n", wordCount));
5706 
5707             if (wordCount != AtaReq->WordsLeft) {
5708                 KdPrint2((PRINT_PREFIX
5709                            "AtapiInterrupt: %d words requested; %d words xferred\n",
5710                            AtaReq->WordsLeft,
5711                            wordCount));
5712             }
5713 
5714             // Verify this makes sense.
5715             if (wordCount > AtaReq->WordsLeft) {
5716                 wordCount = AtaReq->WordsLeft;
5717                 KdPrint2((PRINT_PREFIX
5718                            "AtapiInterrupt: Write underrun\n"));
5719                 DataOverrun = TRUE;
5720             }
5721 
5722         } else {
5723 
5724             // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
5725             if (AtaReq->WordsLeft < wordsThisInterrupt) {
5726                // Transfer only words requested.
5727                wordCount = AtaReq->WordsLeft;
5728             } else {
5729                // Transfer next block.
5730                wordCount = wordsThisInterrupt;
5731             }
5732         }
5733 
5734         if (DmaTransfer &&
5735             (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
5736             //ASSERT(AtaReq->WordsLeft == wordCount);
5737             if(AtaReq->ReqState == REQ_STATE_ATAPI_EXPECTING_DATA_INTR2) {
5738                 KdPrint2((PRINT_PREFIX
5739                           "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount));
5740                 if(AtaReq->WordsLeft > wordCount) {
5741                     AtaReq->WordsLeft -= wordCount;
5742                     AtaReq->WordsTransfered += wordCount;
5743                     AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
5744                     goto ReturnEnableIntr;
5745                 }
5746                 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
5747             }
5748             AtaReq->WordsTransfered = AtaReq->WordsLeft;
5749             AtaReq->WordsLeft = 0;
5750             status = SRB_STATUS_SUCCESS;
5751             chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
5752             goto CompleteRequest;
5753         }
5754 
5755         // Ensure that this is a write command.
5756         if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
5757 
5758            KdPrint2((PRINT_PREFIX
5759                       "AtapiInterrupt: Write interrupt\n"));
5760 
5761            statusByte = WaitOnBusy(chan);
5762 
5763             if (/*atapiDev || */ !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/
5764                 || (wordCount & 1)) {
5765 
5766                WriteBuffer(chan,
5767                            AtaReq->DataBuffer,
5768                            wordCount,
5769                            UniataGetPioTiming(LunExt));
5770            } else {
5771 
5772                WriteBuffer2(chan,
5773                            (PULONG)(AtaReq->DataBuffer),
5774                            wordCount / 2,
5775                            UniataGetPioTiming(LunExt));
5776            }
5777         } else {
5778 
5779             KdPrint3((PRINT_PREFIX
5780                         "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5781                         interruptReason,
5782                         srb));
5783 
5784             // Fail this request.
5785             status = SRB_STATUS_ERROR;
5786             if(!wordCount && atapiDev && (srb->Cdb[0] != SCSIOP_REQUEST_SENSE)) {
5787                 // some devices feel bad after incorrect commands and may need reset
5788                 KdPrint2((PRINT_PREFIX
5789                           "AtapiInterrupt: Try ATAPI reset\n"));
5790 
5791                 AtapiDisableInterrupts(deviceExtension, lChannel);
5792                 AtapiSoftReset(chan, DeviceNumber);
5793                 AtapiEnableInterrupts(deviceExtension, lChannel);
5794                 status = SRB_STATUS_BUS_RESET;
5795                 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
5796 
5797 //                goto IntrPrepareResetController;
5798             }
5799             goto CompleteRequest;
5800         }
5801         // Advance data buffer pointer and bytes left.
5802         AtaReq->DataBuffer += wordCount;
5803         AtaReq->WordsLeft -= wordCount;
5804         AtaReq->WordsTransfered += wordCount;
5805 
5806         if (atapiDev) {
5807             AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
5808         }
5809 
5810         goto ReturnEnableIntr;
5811 
5812     } else if (interruptReason == ATAPI_IR_IO_toHost && (statusByte & IDE_STATUS_DRQ)) {
5813 
5814 continue_read_drq:
5815 
5816         if (atapiDev) {
5817 
5818             // Pick up bytes to transfer and convert to words.
5819             wordCount =
5820                 (ULONG)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow) |
5821                 ((ULONG)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8);
5822 
5823             // Convert bytes to words.
5824             KdPrint2((PRINT_PREFIX "AtapiInterrupt: get R byteCount %#x\n", wordCount));
5825             wordCount >>= 1;
5826             /*
5827                 When ATAPI 64k PIO read is requested we may have 0xfffe byte
5828                 count reported for 0x10000 bytes in single interrupt.
5829                 It is not allowed to read entire 64k block with DwordIo intead of
5830                 wait for last word.
5831             */
5832             if (wordCount != AtaReq->WordsLeft) {
5833                 KdPrint2((PRINT_PREFIX
5834                            "AtapiInterrupt: %d words requested; %d words xferred\n",
5835                            AtaReq->WordsLeft,
5836                            wordCount));
5837             }
5838 
5839             // Verify this makes sense.
5840             if (wordCount > AtaReq->WordsLeft) {
5841                 wordCount = AtaReq->WordsLeft;
5842                 DataOverrun = TRUE;
5843             }
5844 
5845         } else {
5846 
5847             // Check if words left is at least 256.
5848             if (AtaReq->WordsLeft < wordsThisInterrupt) {
5849                // Transfer only words requested.
5850                wordCount = AtaReq->WordsLeft;
5851             } else {
5852                // Transfer next block.
5853                wordCount = wordsThisInterrupt;
5854             }
5855         }
5856 
5857         if(DmaTransfer &&
5858            (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
5859             if(AtaReq->ReqState == REQ_STATE_ATAPI_EXPECTING_DATA_INTR2) {
5860                 KdPrint2((PRINT_PREFIX
5861                           "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount));
5862                 if(AtaReq->WordsLeft > wordCount) {
5863                     AtaReq->WordsLeft -= wordCount;
5864                     AtaReq->WordsTransfered += wordCount;
5865                     AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
5866                     goto ReturnEnableIntr;
5867                 }
5868                 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
5869             }
5870             //ASSERT(AtaReq->WordsLeft == wordCount);
5871             AtaReq->WordsTransfered = AtaReq->WordsLeft;
5872             AtaReq->WordsLeft = 0;
5873             status = SRB_STATUS_SUCCESS;
5874             chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
5875             goto CompleteRequest;
5876         }
5877         // Ensure that this is a read command.
5878         if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
5879 
5880 /*           KdPrint2((
5881                       "AtapiInterrupt: Read interrupt\n"));*/
5882 
5883             statusByte = WaitOnBusy(chan);
5884 
5885             if(wordCount&1 && atapiDev && (g_opt_VirtualMachine == VM_BOCHS)) {
5886                 KdPrint2((PRINT_PREFIX
5887                           "IdeIntr: unaligned ATAPI %#x Words\n", wordCount));
5888             } else
5889             if(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) {
5890                 KdPrint2((PRINT_PREFIX
5891                           "IdeIntr: pre-Read %#x Dwords\n", wordCount/2));
5892 
5893                 ReadBuffer2(chan,
5894                            (PULONG)(AtaReq->DataBuffer),
5895                            wordCount / 2,
5896                            UniataGetPioTiming(LunExt));
5897                 // Advance data buffer pointer and bytes left.
5898                 AtaReq->DataBuffer += wordCount & ~1;
5899                 AtaReq->WordsLeft -= wordCount & ~1;
5900                 AtaReq->WordsTransfered += wordCount & ~1;
5901                 wordCount &= 1;
5902             }
5903             if (wordCount) {
5904                 KdPrint2((PRINT_PREFIX
5905                            "IdeIntr: Read %#x words\n", wordCount));
5906 
5907                 ReadBuffer(chan,
5908                           AtaReq->DataBuffer,
5909                           wordCount,
5910                           UniataGetPioTiming(LunExt));
5911             }
5912 
5913             KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)-1) ));
5914             //KdDump(AtaReq->DataBuffer, wordCount*2);
5915             if(srb && atapiDev && srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
5916                 KdDump(AtaReq->DataBuffer, wordCount*2);
5917             }
5918 
5919             GetBaseStatus(chan, statusByte);
5920             KdPrint2((PRINT_PREFIX "  status re-check %#x\n", statusByte));
5921 
5922             if(DataOverrun) {
5923                 KdPrint2((PRINT_PREFIX "  DataOverrun\n"));
5924                 AtapiSuckPort2(chan);
5925                 GetBaseStatus(chan, statusByte);
5926             }
5927 
5928             if(statusByte & IDE_STATUS_BUSY) {
5929                 for (i = 0; i < 2; i++) {
5930                     AtapiStallExecution(10);
5931                     GetBaseStatus(chan, statusByte);
5932                     if (!(statusByte & IDE_STATUS_BUSY)) {
5933                         break;
5934                     }
5935                 }
5936             }
5937 
5938         } else {
5939 
5940             KdPrint3((PRINT_PREFIX
5941                         "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5942                         interruptReason,
5943                         srb));
5944 
5945             // Fail this request.
5946             status = SRB_STATUS_ERROR;
5947             goto CompleteRequest;
5948         }
5949 //continue_atapi_pio_read:
5950         // Advance data buffer pointer and bytes left.
5951         AtaReq->DataBuffer += wordCount;
5952         AtaReq->WordsLeft -= wordCount;
5953         AtaReq->WordsTransfered += wordCount;
5954 
5955         // Check for read command complete.
5956         if (AtaReq->WordsLeft == 0) {
5957 
5958             KdPrint2((PRINT_PREFIX "AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
5959             if (atapiDev) {
5960 
5961                 if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM) {
5962 
5963                     // Work around to make many atapi devices return correct sector size
5964                     // of 2048. Also certain devices will have sector count == 0x00, check
5965                     // for that also.
5966                     if (srb->Cdb[0] == SCSIOP_READ_CAPACITY) {
5967 
5968                         AtaReq->DataBuffer -= AtaReq->WordsTransfered;
5969                         if (AtaReq->DataBuffer[0] == 0x00) {
5970                             *((ULONG *) &(AtaReq->DataBuffer[0])) = 0xFFFFFF7F;
5971                         }
5972 
5973                         *((ULONG *) &(AtaReq->DataBuffer[2])) = 0x00080000;
5974                         AtaReq->DataBuffer += AtaReq->WordsTransfered;
5975                     }
5976 #ifndef UNIATA_INIT_CHANGERS
5977                     else
5978                     if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
5979 
5980                         KdPrint3((PRINT_PREFIX "AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status));
5981                         // Bingo!!
5982                         AtapiHwInitializeChanger (HwDeviceExtension,
5983                                                   srb,
5984                                                   (PMECHANICAL_STATUS_INFORMATION_HEADER) srb->DataBuffer);
5985                         LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED;
5986                         KdPrint2((PRINT_PREFIX "  set DFLAGS_CHANGER_INITED\n"));
5987                     }
5988 #endif // UNIATA_INIT_CHANGERS
5989                 }
5990                 GetStatus(chan, statusByte);
5991                 if(!(statusByte & IDE_STATUS_BUSY)) {
5992                     // Assume command is completed if BUSY is cleared
5993                     // and all data read
5994                     // Optionally, we may receive COMPLETE interrupt later and
5995                     // treat it as unexpected
5996                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: early complete ? status %x\n", statusByte));
5997 
5998                     status = SRB_STATUS_SUCCESS;
5999                     goto CompleteRequest;
6000                 }
6001 
6002             } else {
6003 
6004             /*
6005                 // Completion for IDE drives.
6006                 if (AtaReq->WordsLeft) {
6007                     status = SRB_STATUS_DATA_OVERRUN;
6008                 } else {
6009                     status = SRB_STATUS_SUCCESS;
6010                 }
6011 
6012                 goto CompleteRequest;
6013             */
6014                 status = SRB_STATUS_SUCCESS;
6015                 goto CompleteRequest;
6016 
6017             }
6018         } else {
6019             if (atapiDev) {
6020                 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
6021                 GetStatus(chan, statusByte);
6022                 if(!(statusByte & IDE_STATUS_BUSY)) {
6023                     // Assume command is completed if BUSY is cleared
6024                     // even if NOT all data read
6025                     // Optionally, we may receive COMPLETE interrupt later and
6026                     // treat it as unexpected
6027                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: early complete + underrun ? status %x\n", statusByte));
6028 
6029                     status = SRB_STATUS_SUCCESS;
6030                     goto CompleteRequest;
6031                 }
6032             } else {
6033                 if(!atapiDev && !DataOverrun && (srb->SrbFlags & SRB_FLAGS_DATA_IN) &&
6034                     ((statusByte & ~IDE_STATUS_INDEX) == (IDE_STATUS_IDLE | IDE_STATUS_DRQ))) {
6035                     KdPrint2((PRINT_PREFIX "  HDD read data ready \n"));
6036                     goto continue_read_drq;
6037                 }
6038             }
6039         }
6040 
6041         goto ReturnEnableIntr;
6042 
6043     } else if (interruptReason == (ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd) && !(statusByte & IDE_STATUS_DRQ)) {
6044 
6045         KdPrint2((PRINT_PREFIX "AtapiInterrupt: interruptReason = CompleteRequest\n"));
6046         // Command complete. We exactly know this because of IReason.
6047 
6048         if(DmaTransfer) {
6049             KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
6050             AtaReq->WordsTransfered += AtaReq->WordsLeft;
6051             AtaReq->WordsLeft = 0;
6052         } else {
6053             KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was PIO\n"));
6054 
6055             wordCount = AtaReq->WordsLeft;
6056             // Advance data buffer pointer and bytes left.
6057             AtaReq->DataBuffer += wordCount;
6058             AtaReq->WordsLeft -= wordCount;
6059             AtaReq->WordsTransfered += wordCount;
6060 
6061             KdPrint2((PRINT_PREFIX "AtapiInterrupt: wordCount %#x, WordsTransfered %#x\n", wordCount, AtaReq->WordsTransfered));
6062 
6063         }
6064         //if (AtaReq->WordsLeft) {
6065         //    status = SRB_STATUS_DATA_OVERRUN;
6066         //} else {
6067             status = SRB_STATUS_SUCCESS;
6068         //}
6069 
6070 #ifdef UNIATA_DUMP_ATAPI
6071         if(srb &&
6072            srb->SrbFlags & SRB_FLAGS_DATA_IN) {
6073             UCHAR                   ScsiCommand;
6074             PCDB                    Cdb;
6075             PCHAR                   CdbData;
6076             PCHAR                   ModeSelectData;
6077             ULONG                   CdbDataLen;
6078             PSCSI_REQUEST_BLOCK     Srb = srb;
6079 
6080             Cdb = (PCDB)(Srb->Cdb);
6081             ScsiCommand = Cdb->CDB6.OperationCode;
6082             CdbData = (PCHAR)(Srb->DataBuffer);
6083             CdbDataLen = Srb->DataTransferLength;
6084 
6085             if(CdbDataLen > 0x1000) {
6086                 CdbDataLen = 0x1000;
6087             }
6088 
6089             KdPrint(("--\n"));
6090             KdPrint2(("DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
6091             KdPrint2(("P:T:D=%d:%d:%d\n",
6092                                       Srb->PathId,
6093                                       Srb->TargetId,
6094                                       Srb->Lun));
6095             KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand));
6096             KdDump(Cdb, 16);
6097 
6098             if(ScsiCommand == SCSIOP_MODE_SENSE) {
6099                 KdPrint(("ModeSense 6\n"));
6100                 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
6101                 ModeSelectData = CdbData+4;
6102                 KdDump(CdbData, CdbDataLen);
6103             } else
6104             if(ScsiCommand == SCSIOP_MODE_SENSE10) {
6105                 KdPrint(("ModeSense 10\n"));
6106                 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
6107                 ModeSelectData = CdbData+8;
6108                 KdDump(CdbData, CdbDataLen);
6109             } else {
6110                 if(srb->SrbFlags & SRB_FLAGS_DATA_IN) {
6111                     KdPrint(("Read buffer from device:\n"));
6112                     KdDump(CdbData, CdbDataLen);
6113                 }
6114             }
6115             KdPrint(("--\n"));
6116         }
6117 #endif //UNIATA_DUMP_ATAPI
6118 
6119 CompleteRequest:
6120 
6121         KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, srbstatus %x\n", status));
6122         // Check and see if we are processing our secret (mechanism status/request sense) srb
6123 
6124         if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
6125             KdPrint2((PRINT_PREFIX "WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq->WordsLeft));
6126             status = SRB_STATUS_DATA_OVERRUN;
6127         }
6128 
6129         if (AtaReq->OriginalSrb) {
6130 
6131             ULONG srbStatus;
6132 
6133             KdPrint2((PRINT_PREFIX "AtapiInterrupt: OriginalSrb != NULL\n"));
6134             if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
6135 #ifdef UNIATA_INIT_CHANGERS
6136                 // We can get here only when UNIATA_INIT_CHANGERS is defined
6137                 KdPrint3((PRINT_PREFIX "AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status));
6138                 if (status == SRB_STATUS_SUCCESS) {
6139                     // Bingo!!
6140                     AtapiHwInitializeChanger (HwDeviceExtension,
6141                                               srb,
6142                                               (PMECHANICAL_STATUS_INFORMATION_HEADER) srb->DataBuffer);
6143 
6144                     // Get ready to issue the original srb
6145                     srb = AtaReq->Srb = AtaReq->OriginalSrb;
6146                     AtaReq->OriginalSrb = NULL;
6147 
6148                 } else {
6149                     // failed!  Get the sense key and maybe try again
6150                     srb = AtaReq->Srb = BuildRequestSenseSrb (
6151                                                           HwDeviceExtension,
6152                                                           AtaReq->OriginalSrb);
6153                 }
6154 /*
6155                 // do not enable interrupts in DPC, do not waste time, do it now!
6156                 if(UseDpc && chan->DisableIntr) {
6157                     AtapiEnableInterrupts(HwDeviceExtension, c);
6158                     UseDpc = FALSE;
6159                     RestoreUseDpc = TRUE;
6160                 }
6161 */
6162                 srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL);
6163 
6164                 KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt));
6165 
6166                 if (srbStatus == SRB_STATUS_PENDING) {
6167                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
6168                     goto ReturnEnableIntr;
6169                 }
6170 /*
6171                 if(RestoreUseDpc) {
6172                     // restore state on error
6173                     UseDpc = TRUE;
6174                     AtapiDisableInterrupts(HwDeviceExtension, c);
6175                 }
6176 */
6177 #else
6178                 KdPrint((PRINT_PREFIX "AtapiInterrupt: ERROR: internal SCSIOP_MECHANISM_STATUS !!!!\n"));
6179                 ASSERT(FALSE);
6180 #endif // UNIATA_INIT_CHANGERS
6181             } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
6182 
6183                 PSENSE_DATA senseData = (PSENSE_DATA) srb->DataBuffer;
6184 #ifdef __REACTOS__
6185                 (void)senseData;
6186 #endif
6187                 KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI command status %#x\n", status));
6188                 if (status == SRB_STATUS_DATA_OVERRUN) {
6189                     // Check to see if we at least get mininum number of bytes
6190                     if ((srb->DataTransferLength - AtaReq->WordsLeft) >
6191                         (FIELD_OFFSET (SENSE_DATA, AdditionalSenseLength) + sizeof(senseData->AdditionalSenseLength))) {
6192                         status = SRB_STATUS_SUCCESS;
6193                     }
6194                 }
6195 
6196                 if (status == SRB_STATUS_SUCCESS) {
6197 #ifndef UNIATA_CORE
6198 #ifdef UNIATA_INIT_CHANGERS
6199                     if ((senseData->SenseKey != SCSI_SENSE_ILLEGAL_REQUEST) &&
6200                         FALSE &&
6201                         chan->MechStatusRetryCount) {
6202 
6203                         KdPrint3((PRINT_PREFIX "AtapiInterrupt: MechStatusRetryCount %#x\n", chan->MechStatusRetryCount));
6204                         // The sense key doesn't say the last request is illegal, so try again
6205                         chan->MechStatusRetryCount--;
6206                         srb = AtaReq->Srb = BuildMechanismStatusSrb (
6207                                                               HwDeviceExtension,
6208                                                               AtaReq->OriginalSrb);
6209                     } else
6210 #endif // UNIATA_INIT_CHANGERS
6211                     {
6212                         // Get ready to issue the original srb
6213                         srb = AtaReq->Srb = AtaReq->OriginalSrb;
6214                         AtaReq->OriginalSrb = NULL;
6215                     }
6216 #endif //UNIATA_CORE
6217 /*
6218                     // do not enable interrupts in DPC, do not waste time, do it now!
6219                     if(UseDpc && chan->DisableIntr) {
6220                         AtapiEnableInterrupts(HwDeviceExtension, c);
6221                         UseDpc = FALSE;
6222                         RestoreUseDpc = TRUE;
6223                     }
6224 */
6225                     srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL);
6226 
6227                     KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan->ExpectingInterrupt));
6228 
6229                     if (srbStatus == SRB_STATUS_PENDING) {
6230                         KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
6231                         goto ReturnEnableIntr;
6232                     }
6233 /*
6234                     if(RestoreUseDpc) {
6235                         // restore state on error
6236                         UseDpc = TRUE;
6237                         AtapiDisableInterrupts(HwDeviceExtension, c);
6238                     }
6239 */
6240                 }
6241             }
6242 
6243             // If we get here, it means AtapiSendCommand() has failed
6244             // Can't recover.  Pretend the original srb has failed and complete it.
6245 
6246             KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. complete OriginalSrb\n"));
6247 
6248             if (AtaReq->OriginalSrb) {
6249                 srb = AtaReq->Srb = AtaReq->OriginalSrb;
6250                 AtaReq->OriginalSrb = NULL;
6251             }
6252 
6253             KdPrint2((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan->ExpectingInterrupt));
6254 
6255             // fake an error and read no data
6256             status = SRB_STATUS_ERROR;
6257             srb->ScsiStatus = 0;
6258             AtaReq->DataBuffer = (PUSHORT)(srb->DataBuffer);
6259             AtaReq->WordsLeft = srb->DataTransferLength;
6260             chan->RDP = FALSE;
6261 
6262         } else if (status == SRB_STATUS_ERROR) {
6263 
6264             // Map error to specific SRB status and handle request sense.
6265             KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. Begin mapping...\n"));
6266             status = MapError(deviceExtension,
6267                               srb);
6268 
6269             chan->RDP = FALSE;
6270 
6271         } else if(!DmaTransfer) {
6272 
6273             KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion\n"));
6274             // Command complete.
6275 PIO_wait_busy:
6276             KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion, wait BUSY\n"));
6277             // Wait for busy to drop.
6278             for (i = 0; i < 5*30; i++) {
6279                 GetBaseStatus(chan, statusByte);
6280                 if (!(statusByte & IDE_STATUS_BUSY)) {
6281                     break;
6282                 }
6283                 if(!InDpc) {
6284                     // goto DPC
6285                     AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY;
6286                     TimerValue = 200;
6287                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (busy)\n"));
6288 #ifndef UNIATA_CORE
6289                     goto PostToDpc;
6290 #else //UNIATA_CORE
6291                     AtapiStallExecution(TimerValue);
6292                     goto ServiceInterrupt;
6293 #endif //UNIATA_CORE
6294                 }
6295                 AtapiStallExecution(100);
6296             }
6297 
6298             if (i == 5*30) {
6299 
6300                 // reset the controller.
6301                 KdPrint2((PRINT_PREFIX
6302                             "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
6303                             statusByte));
6304                 goto IntrPrepareResetController;
6305             }
6306             // Check to see if DRQ is still up.
6307             if(statusByte & IDE_STATUS_DRQ) {
6308                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: DRQ...\n"));
6309                 if(srb) {
6310                     if(srb->SrbFlags & SRB_FLAGS_DATA_IN) {
6311                         KdPrint2((PRINT_PREFIX "srb %x data in\n", srb));
6312                     } else {
6313                         KdPrint2((PRINT_PREFIX "srb %x data out\n", srb));
6314                     }
6315                 } else {
6316                     KdPrint2((PRINT_PREFIX "srb NULL\n"));
6317                 }
6318                 if(AtaReq) {
6319                     KdPrint2((PRINT_PREFIX "AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq, AtaReq->WordsLeft));
6320                 } else {
6321                     KdPrint2((PRINT_PREFIX "AtaReq NULL\n"));
6322                 }
6323                 if(AtaReq && AtaReq->WordsLeft /*&&
6324                    !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
6325                     KdPrint2((PRINT_PREFIX "DRQ+AtaReq->WordsLeft -> next portion\n"));
6326                     goto continue_PIO;
6327                 }
6328             }
6329             //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
6330             //if ((statusByte & IDE_STATUS_DRQ)) {}
6331             if((statusByte & IDE_STATUS_DRQ) &&
6332                (LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED)) ) {
6333 
6334 PIO_wait_DRQ:
6335                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO_wait_DRQ\n"));
6336                 for (i = 0; i < 200; i++) {
6337                     GetBaseStatus(chan, statusByte);
6338                     if (!(statusByte & IDE_STATUS_DRQ)) {
6339                         break;
6340                     }
6341                     if(!InDpc) {
6342                         // goto DPC
6343                         KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (drq)\n"));
6344                         AtaReq->ReqState = REQ_STATE_DPC_WAIT_DRQ;
6345                         TimerValue = 100;
6346 #ifndef UNIATA_CORE
6347                         goto PostToDpc;
6348 #else //UNIATA_CORE
6349                         AtapiStallExecution(TimerValue);
6350                         goto ServiceInterrupt;
6351 #endif //UNIATA_CORE
6352                     }
6353                     AtapiStallExecution(100);
6354                 }
6355 
6356                 if (i == 200) {
6357                     // reset the controller.
6358                     KdPrint2((PRINT_PREFIX   "AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
6359                                 statusByte));
6360                     goto IntrPrepareResetController;
6361                 }
6362             }
6363             if(atapiDev) {
6364                 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
6365                      AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)(-1)), srb->DataTransferLength ));
6366                 //KdDump(srb->DataBuffer, srb->DataTransferLength);
6367             }
6368             if(!AtapiDmaPioSync(HwDeviceExtension, srb, (PUCHAR)(srb->DataBuffer), srb->DataTransferLength)) {
6369                 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
6370             }
6371         }
6372 
6373         // Clear interrupt expecting flag.
6374         UniataExpectChannelInterrupt(chan, FALSE);
6375         // clear this flag now, it can be set again in sub-calls
6376         InterlockedExchange(&(chan->CheckIntr),
6377                                       CHECK_INTR_IDLE);
6378 
6379         // Sanity check that there is a current request.
6380         if(srb != NULL) {
6381             // Set status in SRB.
6382             srb->SrbStatus = (UCHAR)status;
6383 
6384             // Check for underflow.
6385             if(AtaReq->WordsLeft) {
6386 
6387                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq->WordsLeft));
6388                 // Subtract out residual words and update if filemark hit,
6389                 // setmark hit , end of data, end of media...
6390                 if (!(LunExt->DeviceFlags & DFLAGS_TAPE_DEVICE)) {
6391                     if (status == SRB_STATUS_DATA_OVERRUN) {
6392                         srb->DataTransferLength -= AtaReq->WordsLeft*2;
6393                     } else {
6394                         srb->DataTransferLength = 0;
6395                     }
6396                 } else {
6397                     srb->DataTransferLength -= AtaReq->WordsLeft*2;
6398                 }
6399             }
6400             if(status == SRB_STATUS_SUCCESS) {
6401                 //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) {
6402                 //    // This should be set in UniataAhciEndTransaction() for AHCI
6403                 //    AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
6404                 //}
6405                 if(!atapiDev &&
6406                    AtaReq->WordsTransfered*2 < AtaReq->TransferLength) {
6407                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
6408                          AtaReq->WordsTransfered*2, AtaReq->TransferLength));
6409                     AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
6410                     AtaReq->ReqState = REQ_STATE_PREPARE_TO_NEXT;
6411                     goto reenqueue_req;
6412                 } else {
6413                     KdPrint2((PRINT_PREFIX "   Transfered %x, full size %x\n",
6414                         AtaReq->WordsTransfered*2, AtaReq->TransferLength));
6415                 }
6416             }
6417 
6418             if (srb->Function != SRB_FUNCTION_IO_CONTROL) {
6419 
6420 CompleteRDP:
6421                 // Indicate command complete.
6422                 if (!(chan->RDP)) {
6423                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete\n"));
6424 IntrCompleteReq:
6425 
6426                     if (status == SRB_STATUS_SUCCESS &&
6427                         srb->SenseInfoBuffer &&
6428                         srb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) {
6429 
6430                         PSENSE_DATA  senseBuffer = (PSENSE_DATA)srb->SenseInfoBuffer;
6431 
6432                         KdPrint2((PRINT_PREFIX "AtapiInterrupt: set AutoSense\n"));
6433                         senseBuffer->ErrorCode = 0;
6434                         senseBuffer->Valid     = 1;
6435                         senseBuffer->AdditionalSenseLength = 0xb;
6436                         senseBuffer->SenseKey =  0;
6437                         senseBuffer->AdditionalSenseCode = 0;
6438                         senseBuffer->AdditionalSenseCodeQualifier = 0;
6439 
6440                         srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
6441                     }
6442                     AtapiDmaDBSync(chan, srb);
6443                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove srb %#x, status %x\n", srb, status));
6444                     UniataRemoveRequest(chan, srb);
6445                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete, srb %#x\n", srb));
6446                     ScsiPortNotification(RequestComplete,
6447                                          deviceExtension,
6448                                          srb);
6449                 }
6450             } else {
6451 
6452                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: IOCTL completion\n"));
6453 
6454                 if (status != SRB_STATUS_SUCCESS) {
6455                     error = AtapiReadPort1(chan, IDX_IO1_i_Error);
6456                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: error %#x\n", error));
6457                 }
6458 
6459                 if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
6460 
6461                     PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
6462                     // Build the SMART status block depending upon the completion status.
6463                     cmdOutParameters->cBufferSize = wordCount;
6464                     cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0;
6465                     cmdOutParameters->DriverStatus.bIDEError = error;
6466 
6467                     // If the sub-command is return smart status, jam the value from cylinder low and high, into the
6468                     // data buffer.
6469                     if (chan->SmartCommand == RETURN_SMART_STATUS) {
6470                         PIDEREGS_EX regs = (PIDEREGS_EX)&(cmdOutParameters->bBuffer);
6471 
6472                         regs->bOpFlags = 0;
6473                         UniataSnapAtaRegs(chan, 0, regs);
6474 
6475                         regs->bCommandReg = SMART_CMD;
6476                         regs->bFeaturesReg = RETURN_SMART_STATUS;
6477 
6478                         cmdOutParameters->cBufferSize = 8;
6479                     }
6480                     chan->SmartCommand = 0; // cleanup after execution
6481                 }
6482                 // Indicate command complete.
6483                 goto IntrCompleteReq;
6484             }
6485 
6486         } else {
6487 
6488             KdPrint2((PRINT_PREFIX "AtapiInterrupt: No SRB!\n"));
6489         }
6490 
6491         if (chan->RDP) {
6492             // Check DSC
6493             for (i = 0; i < 5; i++) {
6494                 GetBaseStatus(chan, statusByte);
6495                 if(!(statusByte & IDE_STATUS_BUSY)) {
6496                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: RDP + cleared BUSY\n"));
6497                     chan->RDP = FALSE;
6498                     goto CompleteRDP;
6499                 } else
6500                 if (statusByte & IDE_STATUS_DSC) {
6501                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: Clear RDP\n"));
6502                     chan->RDP = FALSE;
6503                     goto CompleteRDP;
6504                 }
6505                 AtapiStallExecution(50);
6506             }
6507         }
6508         // RDP can be cleared since previous check
6509         if (chan->RDP) {
6510             KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestTimerCall 2000\n"));
6511 
6512             TimerValue = 2000;
6513 #ifndef UNIATA_CORE
6514             goto CallTimerDpc;
6515 #else //UNIATA_CORE
6516             AtapiStallExecution(TimerValue);
6517             goto ServiceInterrupt;
6518 #endif //UNIATA_CORE
6519         }
6520 
6521 //            ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
6522 enqueue_next_req:
6523         // Get next request
6524         srb = UniataGetCurRequest(chan);
6525 
6526 reenqueue_req:
6527 
6528 #ifndef UNIATA_CORE
6529         KdPrint2((PRINT_PREFIX "AtapiInterrupt: NextRequest, srb=%#x\n",srb));
6530         if(!srb) {
6531             ScsiPortNotification(NextRequest,
6532                                  deviceExtension,
6533                                  NULL);
6534         } else {
6535             ScsiPortNotification(NextLuRequest,
6536                                  deviceExtension,
6537                                  PathId,
6538                                  TargetId,
6539                                  Lun);
6540             // in simplex mode next command must NOT be sent here
6541             if(!deviceExtension->simplexOnly) {
6542                 AtapiStartIo__(HwDeviceExtension, srb, FALSE);
6543             }
6544         }
6545         // Try to get SRB fron any non-empty queue (later)
6546         if(deviceExtension->simplexOnly) {
6547             NoStartIo = FALSE;
6548         }
6549 #endif //UNIATA_CORE
6550 
6551         goto ReturnEnableIntr;
6552 
6553     } else {
6554 
6555         // Unexpected int. Catch it
6556         KdPrint2((PRINT_PREFIX "AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
6557                     interruptReason,
6558                     statusByte));
6559 
6560         if(g_opt_VirtualMachine == VM_QEMU) {
6561             if(interruptReason == ATAPI_IR_IO_toDev && !(statusByte & IDE_STATUS_DRQ) && !DmaTransfer) {
6562                 statusByte = WaitForDrq(chan);
6563                 if(statusByte & IDE_STATUS_DRQ) {
6564                     goto continue_PIO;
6565                 }
6566             }
6567         }
6568 
6569         if(OldReqState == REQ_STATE_DPC_WAIT_BUSY0 &&
6570            AtaReq->WordsLeft == 0) {
6571             KdPrint2((PRINT_PREFIX "AtapiInterrupt: pending WAIT_BUSY0. Complete.\n"));
6572             status = SRB_STATUS_SUCCESS;
6573             chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
6574             goto CompleteRequest;
6575         }
6576     }
6577 
6578 ReturnEnableIntr:
6579 
6580     KdPrint2((PRINT_PREFIX "AtapiInterrupt: ReturnEnableIntr\n",srb));
6581     //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6582     deviceExtension->ExpectingInterrupt = TRUE;
6583     if(UseDpc) {
6584         if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) {
6585             KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
6586 #ifdef UNIATA_USE_XXableInterrupts
6587             //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
6588             chan->ChannelCtrlFlags |= CTRFLAGS_ENABLE_INTR_REQ;
6589             // must be called on DISPATCH_LEVEL
6590             ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension,
6591                                  AtapiEnableInterrupts__);
6592 #else
6593             AtapiEnableInterrupts(HwDeviceExtension, c);
6594             InterlockedExchange(&(chan->CheckIntr),
6595                                           CHECK_INTR_IDLE);
6596             // Will raise IRQL to DIRQL
6597 #ifndef UNIATA_CORE
6598             AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
6599                                  AtapiEnableInterrupts__,
6600                                  1);
6601 #endif // UNIATA_CORE
6602             KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
6603 #endif // UNIATA_USE_XXableInterrupts
6604         }
6605     }
6606 
6607     InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
6608     // in simplex mode next command must be sent here if
6609     // DPC is not used
6610     KdPrint2((PRINT_PREFIX "AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc, NoStartIo));
6611 
6612 #ifndef UNIATA_CORE
6613     if(!UseDpc && /*deviceExtension->simplexOnly &&*/ !NoStartIo) {
6614         chan = UniataGetNextChannel(chan);
6615         if(chan) {
6616             srb = UniataGetCurRequest(chan);
6617         } else {
6618             srb = NULL;
6619         }
6620         KdPrint2((PRINT_PREFIX "AtapiInterrupt: run srb %x\n", srb));
6621         if(srb) {
6622             AtapiStartIo__(HwDeviceExtension, srb, FALSE);
6623         }
6624     }
6625 #endif //UNIATA_CORE
6626     return TRUE;
6627 
6628 } // end AtapiInterrupt__()
6629 
6630 #ifndef UNIATA_CORE
6631 
6632 /*++
6633 
6634 Routine Description:
6635 
6636     This routine handles SMART enable, disable, read attributes and threshold commands.
6637 
6638 Arguments:
6639 
6640     HwDeviceExtension - HBA miniport driver's adapter data storage
6641     Srb - IO request packet
6642 
6643 Return Value:
6644 
6645     SRB status
6646 
6647 --*/
6648 ULONG
6649 NTAPI
6650 IdeSendSmartCommand(
6651     IN PVOID HwDeviceExtension,
6652     IN PSCSI_REQUEST_BLOCK Srb,
6653     IN ULONG targetId // assume it is always valid
6654     )
6655 {
6656     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
6657     ULONG                c               ; // = GET_CHANNEL(Srb); may be invalid
6658     PHW_CHANNEL          chan            ; // = &(deviceExtension->chan[c]);
6659     PATA_REQ             AtaReq          = (PATA_REQ)(Srb->SrbExtension);
6660     PSENDCMDOUTPARAMS    cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
6661     SENDCMDINPARAMS      cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
6662     PIDEREGS             regs            = &cmdInParameters.irDriveRegs;
6663 //    ULONG                i;
6664     UCHAR                statusByte;
6665     ULONG DeviceNumber;
6666 
6667     if (regs->bCommandReg != SMART_CMD) {
6668         KdPrint2((PRINT_PREFIX
6669                     "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
6670         return SRB_STATUS_INVALID_REQUEST;
6671     }
6672 
6673     c = targetId / deviceExtension->NumberLuns;
6674     DeviceNumber = targetId % deviceExtension->NumberLuns;
6675     KdPrint2((PRINT_PREFIX "  c %d, dev %d\n", c, DeviceNumber));
6676 
6677     chan = &(deviceExtension->chan[c]);
6678 
6679     chan->SmartCommand = regs->bFeaturesReg;
6680 
6681     // Determine which of the commands to carry out.
6682     switch(regs->bFeaturesReg) {
6683     case READ_ATTRIBUTES:
6684     case READ_THRESHOLDS:
6685     case READ_LOG_SECTOR:
6686     case WRITE_LOG_SECTOR:
6687 
6688         if(Srb->DataTransferLength < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1) {
6689             KdPrint2((PRINT_PREFIX
6690                         "IdeSendSmartCommand: wrong buffer size\n"));
6691             return SRB_STATUS_DATA_OVERRUN;
6692         }
6693 
6694         statusByte = WaitOnBusy(chan);
6695 
6696         if (statusByte & IDE_STATUS_BUSY) {
6697             KdPrint2((PRINT_PREFIX
6698                         "IdeSendSmartCommand: Returning BUSY status\n"));
6699             return SRB_STATUS_BUSY;
6700         }
6701 
6702         // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6703         RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1);
6704 
6705         // Set data buffer pointer and words left.
6706         AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
6707         AtaReq->WordsLeft = READ_ATTRIBUTE_BUFFER_SIZE / 2;
6708 
6709         statusByte = AtaCommand(deviceExtension, DeviceNumber, c,
6710                    regs->bCommandReg,
6711                    (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
6712                    0,
6713                    regs->bSectorNumberReg,
6714                    regs->bSectorCountReg,
6715                    regs->bFeaturesReg,
6716                    ATA_IMMEDIATE);
6717 
6718         if(!(statusByte & IDE_STATUS_ERROR)) {
6719             // Wait for interrupt.
6720             return SRB_STATUS_PENDING;
6721         }
6722         return SRB_STATUS_ERROR;
6723 
6724     case ENABLE_SMART:
6725     case DISABLE_SMART:
6726     case RETURN_SMART_STATUS:
6727     case ENABLE_DISABLE_AUTOSAVE:
6728     case EXECUTE_OFFLINE_DIAGS:
6729     case SAVE_ATTRIBUTE_VALUES:
6730     case AUTO_OFFLINE:
6731 
6732         statusByte = WaitOnBusy(chan);
6733 
6734         if (statusByte & IDE_STATUS_BUSY) {
6735             KdPrint2((PRINT_PREFIX
6736                         "IdeSendSmartCommand: Returning BUSY status\n"));
6737             return SRB_STATUS_BUSY;
6738         }
6739 
6740         // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6741         RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) - 1);
6742 
6743         // Set data buffer pointer and indicate no data transfer.
6744         AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
6745         AtaReq->WordsLeft = 0;
6746 
6747         statusByte = AtaCommand(deviceExtension, DeviceNumber, c,
6748                    regs->bCommandReg,
6749                    (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
6750                    0,
6751                    regs->bSectorNumberReg,
6752                    regs->bSectorCountReg,
6753                    regs->bFeaturesReg,
6754                    ATA_IMMEDIATE);
6755 
6756         if(!(statusByte & IDE_STATUS_ERROR)) {
6757             // Wait for interrupt.
6758             UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6759             return SRB_STATUS_PENDING;
6760         }
6761         return SRB_STATUS_ERROR;
6762     } // end switch(regs->bFeaturesReg)
6763 
6764     return SRB_STATUS_INVALID_REQUEST;
6765 
6766 } // end IdeSendSmartCommand()
6767 
6768 #endif //UNIATA_CORE
6769 
6770 ULONGLONG
6771 NTAPI
6772 UniAtaCalculateLBARegs(
6773     PHW_LU_EXTENSION     LunExt,
6774     ULONGLONG            startingSector,
6775     PULONG               max_bcount
6776     )
6777 {
6778     UCHAR                drvSelect,sectorNumber;
6779     USHORT               cylinder;
6780     ULONG                tmp;
6781 
6782     if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
6783         (*max_bcount) = 0;
6784         if(LunExt->LimitedTransferMode >= ATA_DMA) {
6785             if(LunExt->DeviceExtension) {
6786                 (*max_bcount) = LunExt->DeviceExtension->MaximumDmaTransferLength / DEV_BSIZE;
6787             }
6788         }
6789         return startingSector;
6790     }
6791     tmp = LunExt->IdentifyData.SectorsPerTrack *
6792                        LunExt->IdentifyData.NumberOfHeads;
6793     if(!tmp) {
6794         KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: 0-sized\n"));
6795         cylinder     = 0;
6796         drvSelect    = 0;
6797         sectorNumber = 1;
6798         (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack;
6799     } else {
6800         cylinder =    (USHORT)(startingSector / tmp);
6801         drvSelect =   (UCHAR)((startingSector % tmp) / LunExt->IdentifyData.SectorsPerTrack);
6802         sectorNumber = (UCHAR)(startingSector % LunExt->IdentifyData.SectorsPerTrack) + 1;
6803         (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack - sectorNumber + 1;
6804         KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
6805             cylinder, drvSelect, sectorNumber, (*max_bcount)));
6806     }
6807 
6808     return (ULONG)(sectorNumber&0xff) | (((ULONG)cylinder&0xffff)<<8) | (((ULONG)drvSelect&0xf)<<24);
6809 } // end UniAtaCalculateLBARegs()
6810 
6811 ULONGLONG
6812 NTAPI
6813 UniAtaCalculateLBARegsBack(
6814     PHW_LU_EXTENSION     LunExt,
6815     ULONGLONG            lba
6816     )
6817 {
6818     ULONG                drvSelect,sectorNumber;
6819     ULONG                cylinder;
6820     ULONG                tmp;
6821 
6822     if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
6823         return lba;
6824     }
6825     tmp = LunExt->IdentifyData.SectorsPerTrack *
6826                        LunExt->IdentifyData.NumberOfHeads;
6827 
6828     cylinder     = (USHORT)((lba >> 8) & 0xffff);
6829     drvSelect    = (UCHAR)((lba >> 24) & 0xf);
6830     sectorNumber = (UCHAR)(lba & 0xff);
6831 
6832     lba = sectorNumber-1 +
6833           (drvSelect*LunExt->IdentifyData.SectorsPerTrack) +
6834           (cylinder*tmp);
6835 
6836     return lba;
6837 } // end UniAtaCalculateLBARegsBack()
6838 
6839 
6840 /*++
6841 
6842 Routine Description:
6843 
6844     This routine handles IDE read and writes.
6845 
6846 Arguments:
6847 
6848     HwDeviceExtension - HBA miniport driver's adapter data storage
6849     Srb - IO request packet
6850 
6851 Return Value:
6852 
6853     SRB status
6854 
6855 --*/
6856 ULONG
6857 NTAPI
6858 IdeReadWrite(
6859     IN PVOID HwDeviceExtension,
6860     IN PSCSI_REQUEST_BLOCK Srb,
6861     IN ULONG CmdAction
6862     )
6863 {
6864     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
6865     UCHAR                lChannel = GET_CHANNEL(Srb);
6866     PHW_CHANNEL          chan = &(deviceExtension->chan[lChannel]);
6867     PHW_LU_EXTENSION     LunExt;
6868     PATA_REQ             AtaReq = (PATA_REQ)(Srb->SrbExtension);
6869     //ULONG                ldev = GET_LDEV(Srb);
6870     UCHAR                DeviceNumber = GET_CDEV(Srb);;
6871     ULONGLONG            startingSector=0;
6872     ULONG                max_bcount = 0;
6873     ULONG                wordCount = 0;
6874     UCHAR                statusByte,statusByte2;
6875     UCHAR                cmd;
6876     ULONGLONG            lba;
6877     BOOLEAN              use_dma = FALSE;
6878     ULONG                fis_size;
6879 
6880     AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD;
6881     LunExt = chan->lun[DeviceNumber];
6882 
6883     if((CmdAction & CMD_ACTION_PREPARE) &&
6884        (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
6885 
6886         if(LunExt->opt_ReadOnly &&
6887            (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) {
6888             if(LunExt->opt_ReadOnly == 1) {
6889                 KdPrint2((PRINT_PREFIX "Abort WRITE (Soft R/O)\n"));
6890                 return SRB_STATUS_ERROR;
6891             } else {
6892                 KdPrint2((PRINT_PREFIX "Ignore WRITE (Soft R/O)\n"));
6893                 return SRB_STATUS_SUCCESS;
6894             }
6895         }
6896 
6897         // Set data buffer pointer and words left.
6898         AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
6899 
6900         if(AtaReq->WordsTransfered) {
6901             AtaReq->DataBuffer = ((PUSHORT)(Srb->DataBuffer)) + AtaReq->WordsTransfered;
6902             startingSector = (UniAtaCalculateLBARegsBack(LunExt, AtaReq->lba)) /* latest lba */ + AtaReq->bcount /* previous bcount */;
6903             AtaReq->bcount = (AtaReq->TransferLength - AtaReq->WordsTransfered*2 + DEV_BSIZE-1) / DEV_BSIZE;
6904             KdPrint2((PRINT_PREFIX "IdeReadWrite (Chained REQ): Starting sector %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
6905                        startingSector,
6906                        AtaReq->TransferLength/2,
6907                        AtaReq->WordsTransfered,
6908                        AtaReq->bcount));
6909         } else {
6910             AtaReq->DataBuffer = (PUSHORT)(Srb->DataBuffer);
6911             AtaReq->TransferLength = Srb->DataTransferLength;
6912             // Set up 1st block.
6913             switch(Srb->Cdb[0]) {
6914             case SCSIOP_WRITE:
6915                 if(LunExt->DeviceFlags & DFLAGS_LBA32plus) {
6916                   KdPrint2((PRINT_PREFIX "Attention: SCSIOP_WRITE on 2TB\n"));
6917                   //return SRB_STATUS_ERROR;
6918                 }
6919                 // FALLTHROUGH
6920             case SCSIOP_READ:
6921                 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA);
6922                 MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
6923                 break;
6924             case SCSIOP_WRITE12:
6925                 if(LunExt->DeviceFlags & DFLAGS_LBA32plus) {
6926                   KdPrint2((PRINT_PREFIX "Attention: SCSIOP_WRITE12 on 2TB\n"));
6927                   //return SRB_STATUS_ERROR;
6928                 }
6929                 // FALLTHROUGH
6930             case SCSIOP_READ12:
6931                 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB12READWRITE.LBA);
6932                 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks);
6933                 break;
6934             case SCSIOP_READ16:
6935             case SCSIOP_WRITE16:
6936                 MOV_QD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA);
6937                 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks);
6938                 break;
6939             }
6940             KdPrint2((PRINT_PREFIX "IdeReadWrite (Orig REQ): Starting sector %I64x, OrigWordsRequested %#x, DevSize %#x\n",
6941                        startingSector,
6942                        AtaReq->TransferLength/2,
6943                        AtaReq->bcount));
6944         }
6945         lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount);
6946 
6947         if(max_bcount) {
6948             AtaReq->bcount = min(AtaReq->bcount, max_bcount);
6949         }
6950         AtaReq->WordsLeft = min(AtaReq->TransferLength - AtaReq->WordsTransfered*2,
6951                                 AtaReq->bcount * DEV_BSIZE) / 2;
6952 
6953         KdPrint2((PRINT_PREFIX "IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n",
6954                    startingSector,
6955                    AtaReq->WordsLeft,
6956                    AtaReq->bcount));
6957 
6958         AtaReq->lba = lba;
6959         if(LunExt->errRetry &&
6960            lba == LunExt->errLastLba &&
6961            /* AtaReq->bcount && */ // errRetry can be set only for non-zero bcount
6962            AtaReq->bcount == LunExt->errBCount) {
6963             KdPrint3((PRINT_PREFIX "IdeReadWrite: Retry after BUS_RESET %d @%#I64x (%#x)\n",
6964                 LunExt->errRetry, LunExt->errLastLba, LunExt->errBCount));
6965             if(AtaReq->retry < MAX_RETRIES) {
6966                 AtaReq->retry = LunExt->errRetry;
6967                 AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
6968             }
6969             LunExt->errRetry = 0;
6970         }
6971 
6972         // assume best case here
6973         // we cannot reinit Dma until previous request is completed
6974         if(deviceExtension->HwFlags & UNIATA_AHCI) {
6975             UniataAhciSetupCmdPtr(AtaReq);
6976             if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
6977                           (PUCHAR)(AtaReq->DataBuffer),
6978                           AtaReq->bcount * DEV_BSIZE)) {
6979                 KdPrint3((PRINT_PREFIX "IdeReadWrite: AHCI !DMA\n"));
6980                 return SRB_STATUS_ERROR;
6981             }
6982         } else
6983         if ((LunExt->LimitedTransferMode >= ATA_DMA)) {
6984             use_dma = TRUE;
6985             // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6986             if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
6987                           (PUCHAR)(AtaReq->DataBuffer),
6988                           AtaReq->bcount * DEV_BSIZE)) {
6989                 use_dma = FALSE;
6990             }
6991         }
6992 
6993         if(deviceExtension->HwFlags & UNIATA_AHCI) {
6994             KdPrint2((PRINT_PREFIX "IdeReadWrite: setup AHCI FIS\n"));
6995             RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
6996 
6997             fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
6998                    &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]),
6999                     (AtaReq->Flags & REQ_FLAG_READ) ? IDE_COMMAND_READ_DMA : IDE_COMMAND_WRITE_DMA,
7000                     lba,
7001                      (USHORT)(AtaReq->bcount),
7002                     0
7003                     /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/
7004                     );
7005 
7006             if(!fis_size) {
7007                 KdPrint3((PRINT_PREFIX "IdeReadWrite: AHCI !FIS\n"));
7008                 return SRB_STATUS_ERROR;
7009             }
7010 
7011             AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0, (AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE, fis_size, DeviceNumber);
7012             KdPrint2((PRINT_PREFIX "IdeReadWrite ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags));
7013         }
7014 
7015         AtaReq->ReqState = REQ_STATE_READY_TO_TRANSFER;
7016 
7017     } else { // exec_only
7018         KdPrint2((PRINT_PREFIX "IdeReadWrite (ExecOnly): \n"));
7019         lba = AtaReq->lba;
7020 
7021         if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
7022             use_dma = TRUE;
7023         }
7024     }
7025     if(!(CmdAction & CMD_ACTION_EXEC)) {
7026 
7027         return SRB_STATUS_PENDING;
7028     }
7029 
7030     // if this is queued request, reinit DMA and check
7031     // if DMA mode is still available
7032     AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7033     if (/*EnableDma &&*/
7034         (LunExt->TransferMode >= ATA_DMA)) {
7035         use_dma = TRUE;
7036     } else {
7037         AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7038         use_dma = FALSE;
7039     }
7040 
7041     // Check if write request.
7042     if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
7043 
7044         // Prepare read command.
7045         if(use_dma) {
7046             cmd = IDE_COMMAND_READ_DMA;
7047         } else
7048         if(LunExt->MaximumBlockXfer) {
7049             cmd = IDE_COMMAND_READ_MULTIPLE;
7050         } else {
7051             cmd = IDE_COMMAND_READ;
7052         }
7053     } else {
7054 
7055         // Prepare write command.
7056         if (use_dma) {
7057             wordCount = AtaReq->bcount*DEV_BSIZE/2;
7058             cmd = IDE_COMMAND_WRITE_DMA;
7059         } else
7060         if (LunExt->MaximumBlockXfer) {
7061             wordCount = DEV_BSIZE/2 * LunExt->MaximumBlockXfer;
7062 
7063             if (AtaReq->WordsLeft < wordCount) {
7064                // Transfer only words requested.
7065                wordCount = AtaReq->WordsLeft;
7066             }
7067             cmd = IDE_COMMAND_WRITE_MULTIPLE;
7068 
7069         } else {
7070             wordCount = DEV_BSIZE/2;
7071             cmd = IDE_COMMAND_WRITE;
7072         }
7073     }
7074 
7075     // Send IO command.
7076     KdPrint2((PRINT_PREFIX "IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba, ((Srb->DataTransferLength + 0x1FF) / 0x200),
7077                                                            ((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE)));
7078     if(use_dma) {
7079         chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
7080     } else {
7081         chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
7082     }
7083 
7084     if(deviceExtension->HwFlags & UNIATA_AHCI) {
7085         // AHCI doesn't distinguish DMA and PIO
7086         //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
7087         UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
7088         UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
7089         InterlockedExchange(&(chan->CheckIntr),
7090                                       CHECK_INTR_IDLE);
7091         return SRB_STATUS_PENDING;
7092     }
7093 
7094     if ((Srb->SrbFlags & SRB_FLAGS_DATA_IN) ||
7095         use_dma) {
7096         if(use_dma) {
7097             AtapiDmaDBPreSync(HwDeviceExtension, chan, Srb);
7098             if(g_opt_BochsDmaReadWorkaround &&
7099                (Srb->SrbFlags & SRB_FLAGS_DATA_IN)) {
7100                 KdPrint2((PRINT_PREFIX "CTRFLAGS_DMA_BEFORE_R on BOCHS\n"));
7101                 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
7102             }
7103         }
7104         statusByte2 = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
7105                      cmd, lba,
7106                      (USHORT)(AtaReq->bcount),
7107 //                     (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
7108                      0, ATA_IMMEDIATE);
7109 /*        if(statusByte2 != IDE_STATUS_WRONG) {
7110             GetStatus(chan, statusByte2);
7111         }*/
7112         if(statusByte2 & IDE_STATUS_ERROR) {
7113             // Unfortunately, we cannot handle errors in such a way in real life (except known bad blocks).
7114             // Because some devices doesn't reset ERR from previous command immediately after getting new one.
7115             // On the other hand we cannot wait here because of possible timeout condition
7116             statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7117             KdPrint2((PRINT_PREFIX "IdeReadWrite: status %#x, error %#x\n", statusByte2, statusByte));
7118             return SRB_STATUS_ERROR;
7119         }
7120         if(use_dma) {
7121            if(!g_opt_BochsDmaReadWorkaround ||
7122               !(Srb->SrbFlags & SRB_FLAGS_DATA_IN)) {
7123                 //GetStatus(chan, statusByte2);
7124                 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
7125             }
7126         }
7127         return SRB_STATUS_PENDING;
7128     }
7129 
7130     statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
7131                  cmd, lba,
7132                  (USHORT)(AtaReq->bcount),
7133 //                 (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
7134                  0, ATA_WAIT_INTR);
7135 
7136     if (!(statusByte & IDE_STATUS_DRQ) ||
7137         statusByte == IDE_STATUS_WRONG) {
7138 
7139         if(statusByte == IDE_STATUS_WRONG) {
7140             KdPrint2((PRINT_PREFIX
7141                        "IdeReadWrite: error sending command (%#x)\n",
7142                        statusByte));
7143         } else {
7144             KdPrint2((PRINT_PREFIX
7145                        "IdeReadWrite: DRQ never asserted (%#x)\n",
7146                        statusByte));
7147         }
7148 
7149         AtaReq->WordsLeft = 0;
7150 
7151         // Clear interrupt expecting flag.
7152         UniataExpectChannelInterrupt(chan, FALSE);
7153         InterlockedExchange(&(chan->CheckIntr),
7154                                       CHECK_INTR_IDLE);
7155 
7156         // Clear current SRB.
7157         UniataRemoveRequest(chan, Srb);
7158 
7159         return (statusByte == IDE_STATUS_WRONG) ? SRB_STATUS_ERROR : SRB_STATUS_TIMEOUT;
7160     }
7161 
7162     UniataExpectChannelInterrupt(chan, TRUE);
7163     InterlockedExchange(&(chan->CheckIntr),
7164                                   CHECK_INTR_IDLE);
7165 
7166     // Write next DEV_BSIZE/2*N words.
7167     if (!(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) || (wordCount & 1)) {
7168         KdPrint2((PRINT_PREFIX
7169                    "IdeReadWrite: Write %#x words\n", wordCount));
7170 
7171         WriteBuffer(chan,
7172                   AtaReq->DataBuffer,
7173                   wordCount,
7174                   UniataGetPioTiming(LunExt));
7175 
7176     } else {
7177 
7178         KdPrint2((PRINT_PREFIX
7179                    "IdeReadWrite: Write %#x Dwords\n", wordCount/2));
7180 
7181         WriteBuffer2(chan,
7182                    (PULONG)(AtaReq->DataBuffer),
7183                    wordCount / 2,
7184                    UniataGetPioTiming(LunExt));
7185     }
7186 
7187     // Adjust buffer address and words left count.
7188     AtaReq->WordsLeft -= wordCount;
7189     AtaReq->DataBuffer += wordCount;
7190     AtaReq->WordsTransfered += wordCount;
7191 
7192     // Wait for interrupt.
7193     return SRB_STATUS_PENDING;
7194 
7195 } // end IdeReadWrite()
7196 
7197 #ifndef UNIATA_CORE
7198 
7199 /*++
7200 
7201 Routine Description:
7202     This routine handles IDE Verify.
7203 
7204 Arguments:
7205     HwDeviceExtension - HBA miniport driver's adapter data storage
7206     Srb - IO request packet
7207     `
7208 Return Value:
7209     SRB status
7210 
7211 --*/
7212 ULONG
7213 NTAPI
7214 IdeVerify(
7215     IN PVOID HwDeviceExtension,
7216     IN PSCSI_REQUEST_BLOCK Srb
7217     )
7218 {
7219     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
7220     UCHAR                lChannel = GET_CHANNEL(Srb);
7221     PHW_CHANNEL          chan = &(deviceExtension->chan[lChannel]);
7222     PATA_REQ             AtaReq = (PATA_REQ)(Srb->SrbExtension);
7223     PHW_LU_EXTENSION     LunExt;
7224     //ULONG                ldev = GET_LDEV(Srb);
7225     ULONG                DeviceNumber = GET_CDEV(Srb);
7226     UCHAR                statusByte;
7227     ULONGLONG            startingSector=0;
7228     ULONG                max_bcount;
7229     ULONGLONG            sectors;
7230     ULONGLONG            endSector;
7231     ULONG                sectorCount=0;
7232     ULONGLONG            lba;
7233 
7234     LunExt = chan->lun[DeviceNumber];
7235     // Drive has these number sectors.
7236     if(!(sectors = (ULONG)(LunExt->NumOfSectors))) {
7237         sectors = LunExt->IdentifyData.SectorsPerTrack *
7238                   LunExt->IdentifyData.NumberOfHeads *
7239                   LunExt->IdentifyData.NumberOfCylinders;
7240     }
7241 
7242     KdPrint2((PRINT_PREFIX
7243                 "IdeVerify: Total sectors %#I64x\n",
7244                 sectors));
7245 
7246     // Get starting sector number from CDB.
7247     switch(Srb->Cdb[0]) {
7248     case SCSIOP_VERIFY:
7249         MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA);
7250         MOV_SWP_DW2DD(sectorCount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
7251         break;
7252     case SCSIOP_VERIFY12:
7253         MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB12READWRITE.LBA);
7254         MOV_DD_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks);
7255         break;
7256     case SCSIOP_VERIFY16:
7257         MOV_QD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA);
7258         MOV_DD_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks);
7259         break;
7260     }
7261 
7262     KdPrint2((PRINT_PREFIX
7263                 "IdeVerify: Starting sector %#I64x. Number of blocks %#x\n",
7264                 startingSector,
7265                 sectorCount));
7266 
7267     endSector = startingSector + sectorCount;
7268 
7269     KdPrint2((PRINT_PREFIX
7270                 "IdeVerify: Ending sector %#I64x\n",
7271                 endSector));
7272 
7273     if (endSector > sectors) {
7274 
7275         // Too big, round down.
7276         KdPrint2((PRINT_PREFIX
7277                     "IdeVerify: Truncating request to %#x blocks\n",
7278                     sectors - startingSector - 1));
7279 
7280         sectorCount = (ULONG)(sectors - startingSector - 1);
7281 
7282     } else {
7283 
7284         // Set up sector count register. Round up to next block.
7285         if (sectorCount > 0xFF) {
7286             sectorCount = (USHORT)0xFF;
7287         }
7288     }
7289 
7290     // Set data buffer pointer and words left.
7291     AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
7292     AtaReq->WordsLeft = Srb->DataTransferLength / 2;
7293 
7294     // Indicate expecting an interrupt.
7295     InterlockedExchange(&(chan->CheckIntr),
7296                                   CHECK_INTR_IDLE);
7297 
7298     lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount);
7299 
7300     statusByte = AtaCommand48(deviceExtension, LunExt->Lun, GET_CHANNEL(Srb),
7301                  IDE_COMMAND_VERIFY, lba,
7302                  (USHORT)sectorCount,
7303                  0, ATA_IMMEDIATE);
7304 
7305     if(!(statusByte & IDE_STATUS_ERROR)) {
7306         // Wait for interrupt.
7307         UniataExpectChannelInterrupt(chan, TRUE);
7308         return SRB_STATUS_PENDING;
7309     }
7310     return SRB_STATUS_ERROR;
7311 
7312 } // end IdeVerify()
7313 
7314 #endif //UNIATA_CORE
7315 
7316 /*++
7317 
7318 Routine Description:
7319     Send ATAPI packet command to device.
7320 
7321 Arguments:
7322     HwDeviceExtension - HBA miniport driver's adapter data storage
7323     Srb - IO request packet
7324 
7325 Return Value:
7326 
7327 --*/
7328 ULONG
7329 NTAPI
7330 AtapiSendCommand(
7331     IN PVOID HwDeviceExtension,
7332     IN PSCSI_REQUEST_BLOCK Srb,
7333     IN ULONG CmdAction
7334     )
7335 {
7336     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
7337     UCHAR                lChannel = GET_CHANNEL(Srb);
7338     PHW_CHANNEL          chan = &(deviceExtension->chan[lChannel]);
7339     PATA_REQ             AtaReq = (PATA_REQ)(Srb->SrbExtension);
7340     PHW_LU_EXTENSION     LunExt;
7341     //ULONG                ldev = GET_LDEV(Srb);
7342     ULONG                DeviceNumber = GET_CDEV(Srb);
7343     ULONG flags;
7344     UCHAR statusByte,statusByte0,byteCountLow,byteCountHigh;
7345     UCHAR interruptReason;
7346     BOOLEAN use_dma = FALSE;
7347     BOOLEAN dma_reinited = FALSE;
7348     BOOLEAN retried = FALSE;
7349     ULONG                fis_size, i;
7350     UCHAR FeatureReg=0;
7351 
7352     LunExt = chan->lun[DeviceNumber];
7353 
7354     KdPrint3((PRINT_PREFIX "AtapiSendCommand: req state %#x, Action %x\n", AtaReq->ReqState, CmdAction));
7355     if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
7356         AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER;
7357 
7358 
7359 #ifdef UNIATA_DUMP_ATAPI
7360     if(CmdAction & CMD_ACTION_PREPARE) {
7361         UCHAR                   ScsiCommand;
7362         PCDB                    Cdb;
7363         PCHAR                   CdbData;
7364         PCHAR                   ModeSelectData;
7365         ULONG                   CdbDataLen;
7366 
7367         Cdb = (PCDB)(Srb->Cdb);
7368         ScsiCommand = Cdb->CDB6.OperationCode;
7369         CdbData = (PCHAR)(Srb->DataBuffer);
7370         CdbDataLen = Srb->DataTransferLength;
7371 
7372         if(CdbDataLen > 0x1000) {
7373             CdbDataLen = 0x1000;
7374         }
7375 
7376         KdPrint(("--\n"));
7377         KdPrint2(("DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
7378         KdPrint2(("P:T:D=%d:%d:%d\n",
7379                                   Srb->PathId,
7380                                   Srb->TargetId,
7381                                   Srb->Lun));
7382         KdPrint(("SCSI Command %2.2x\n", ScsiCommand));
7383         KdDump(Cdb, 16);
7384 
7385         if(ScsiCommand == SCSIOP_WRITE_CD) {
7386             KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
7387                      Cdb->WRITE_CD.LBA[0],
7388                      Cdb->WRITE_CD.LBA[1],
7389                      Cdb->WRITE_CD.LBA[2],
7390                      Cdb->WRITE_CD.LBA[3]
7391                      ));
7392         } else
7393         if(ScsiCommand == SCSIOP_WRITE12) {
7394             KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
7395                      Cdb->CDB12READWRITE.LBA[0],
7396                      Cdb->CDB12READWRITE.LBA[1],
7397                      Cdb->CDB12READWRITE.LBA[2],
7398                      Cdb->CDB12READWRITE.LBA[3]
7399                      ));
7400         } else
7401         if(ScsiCommand == SCSIOP_WRITE16) {
7402             KdPrint(("Write16, LBA %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
7403                      Cdb->CDB16READWRITE.LBA[0],
7404                      Cdb->CDB16READWRITE.LBA[1],
7405                      Cdb->CDB16READWRITE.LBA[2],
7406                      Cdb->CDB16READWRITE.LBA[3],
7407                      Cdb->CDB16READWRITE.LBA[4],
7408                      Cdb->CDB16READWRITE.LBA[5],
7409                      Cdb->CDB16READWRITE.LBA[6],
7410                      Cdb->CDB16READWRITE.LBA[7]
7411                      ));
7412         } else
7413         if(ScsiCommand == SCSIOP_MODE_SELECT) {
7414             KdPrint(("ModeSelect 6\n"));
7415             PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
7416             ModeSelectData = CdbData+4;
7417             KdDump(CdbData, CdbDataLen);
7418         } else
7419         if(ScsiCommand == SCSIOP_MODE_SELECT10) {
7420             KdPrint(("ModeSelect 10\n"));
7421             PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
7422             ModeSelectData = CdbData+8;
7423             KdDump(CdbData, CdbDataLen);
7424         } else {
7425             if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
7426                 KdPrint(("Send buffer to device:\n"));
7427                 KdDump(CdbData, CdbDataLen);
7428             }
7429         }
7430         KdPrint(("--\n"));
7431     }
7432 #endif //UNIATA_DUMP_ATAPI
7433 
7434 
7435     if(CmdAction == CMD_ACTION_PREPARE) {
7436         KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb->Cdb)));
7437 
7438         switch (Srb->Cdb[0]) {
7439         case SCSIOP_RECEIVE:
7440         case SCSIOP_SEND:
7441         case SCSIOP_READ:
7442         case SCSIOP_WRITE:
7443         case SCSIOP_READ12:
7444         case SCSIOP_WRITE12:
7445         case SCSIOP_READ16:
7446         case SCSIOP_WRITE16:
7447             // all right
7448             break;
7449         case SCSIOP_READ_CD:
7450         case SCSIOP_READ_CD_MSF:
7451             if(deviceExtension->opt_AtapiDmaRawRead) {
7452                 // all right
7453                 break;
7454             }
7455             /* FALL THROUGH */
7456         default:
7457             KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY\n"));
7458             return SRB_STATUS_BUSY;
7459         }
7460         //
7461 #ifdef UNIATA_INIT_CHANGERS
7462         if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
7463             !AtaReq->OriginalSrb) {
7464             KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
7465             return SRB_STATUS_BUSY;
7466         }
7467 #endif // UNIATA_INIT_CHANGERS
7468     }
7469 
7470 #ifndef UNIATA_CORE
7471     // standard atapi.sys claims:
7472 
7473     // We need to know how many platters our atapi cd-rom device might have.
7474     // Before anyone tries to send a srb to our target for the first time,
7475     // we must "secretly" send down a separate mechanism status srb in order to
7476     // initialize our device extension changer data.  That's how we know how
7477     // many platters our target has.
7478 
7479     // BUT!
7480     // some devices freeze (sometimes) forever on this command
7481     // Let CD-ROM driver send this command itself, if it find it necessary
7482     // We shall just parse output (if any)
7483 
7484 #ifdef UNIATA_INIT_CHANGERS
7485     if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
7486         !AtaReq->OriginalSrb) {
7487 
7488         ULONG srbStatus;
7489 
7490         KdPrint3((PRINT_PREFIX "AtapiSendCommand: BuildMechanismStatusSrb()\n"));
7491         // Set this flag now. If the device hangs on the mech. status
7492         // command, we will not have the chance to set it.
7493         LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED;
7494 
7495         chan->MechStatusRetryCount = 3;
7496         AtaReq->OriginalSrb = Srb;
7497         AtaReq->Srb = BuildMechanismStatusSrb (
7498                                         HwDeviceExtension,
7499                                         Srb);
7500 
7501         KdPrint3((PRINT_PREFIX "AtapiSendCommand: AtapiSendCommand recursive\n"));
7502         srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL);
7503         if (srbStatus == SRB_STATUS_PENDING) {
7504             KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
7505             return srbStatus;
7506         } else {
7507 
7508             // failed!  Get the sense key and maybe try again
7509             AtaReq->Srb = BuildRequestSenseSrb (  HwDeviceExtension,
7510                                                   AtaReq->OriginalSrb);
7511 
7512             srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL);
7513 
7514             KdPrint3((PRINT_PREFIX "AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt));
7515 
7516             if (srbStatus == SRB_STATUS_PENDING) {
7517                 KdPrint2((PRINT_PREFIX "AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n"));
7518                 return srbStatus;
7519             }
7520 
7521             // failed again ? should not get here
7522             AtaReq->Srb = AtaReq->OriginalSrb;
7523             AtaReq->OriginalSrb = NULL;
7524             // fall out
7525         }
7526     }
7527 #endif // UNIATA_INIT_CHANGERS
7528 #endif //UNIATA_CORE
7529 
7530     if((CmdAction & CMD_ACTION_PREPARE) &&
7531        (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
7532 
7533         KdPrint2((PRINT_PREFIX "AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb->Cdb[0], &(Srb->Cdb)));
7534 
7535         if(!LunExt->IdentifyData.AtapiCmdSize &&
7536             (Srb->CdbLength > 12)) {
7537             KdPrint2((PRINT_PREFIX "Cdb16 not supported\n"));
7538             return SRB_STATUS_INVALID_REQUEST;
7539         }
7540 
7541         // Set data buffer pointer and words left.
7542         AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
7543         AtaReq->WordsLeft = Srb->DataTransferLength / 2;
7544         AtaReq->TransferLength = Srb->DataTransferLength;
7545         AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7546         // reset this to force PRD init. May be already setup by recursive SRB
7547         AtaReq->dma_entries = 0;
7548 
7549         // check if reorderable
7550         switch(Srb->Cdb[0]) {
7551         case SCSIOP_READ16:
7552         case SCSIOP_WRITE16:
7553 
7554             MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks);
7555             MOV_QD_SWP(AtaReq->lba, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA);
7556             goto GetLba2;
7557 
7558         case SCSIOP_READ12:
7559         case SCSIOP_WRITE12:
7560 
7561             MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks);
7562             goto GetLba;
7563 
7564         case SCSIOP_READ:
7565         case SCSIOP_WRITE:
7566 
7567             MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
7568 GetLba:
7569             MOV_DD_SWP(AtaReq->lba, ((PCDB)Srb->Cdb)->CDB10.LBA);
7570 GetLba2:
7571             AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD;
7572             AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
7573             AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE ||
7574                               Srb->Cdb[0] == SCSIOP_WRITE12 ||
7575                               Srb->Cdb[0] == SCSIOP_WRITE16) ?
7576                               REQ_FLAG_WRITE : REQ_FLAG_READ;
7577             break;
7578         default:
7579             AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
7580             if(!AtaReq->TransferLength) {
7581                 KdPrint(("  assume 0-transfer\n"));
7582             } else
7583             if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
7584                 KdPrint(("  assume OUT\n"));
7585                 AtaReq->Flags |= REQ_FLAG_WRITE;
7586             } else
7587             if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
7588                 KdPrint(("  assume IN\n"));
7589                 AtaReq->Flags |= REQ_FLAG_READ;
7590             }
7591             break;
7592         }
7593 
7594         // check if DMA read/write
7595         if(g_opt_AtapiNoDma) {
7596             KdPrint2((PRINT_PREFIX "AtapiSendCommand: CTRFLAGS_DMA_BEFORE_R => no dma\n"));
7597             use_dma = FALSE;
7598         } else
7599         if(deviceExtension->HwFlags & UNIATA_AHCI) {
7600             KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (ahci)\n"));
7601             use_dma = TRUE;
7602             goto setup_dma;
7603         } else
7604 /*        if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) {
7605             KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n"));
7606             use_dma = TRUE;
7607             goto setup_dma;
7608         } else*/
7609         if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
7610             KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
7611         } else
7612         if(AtaReq->TransferLength && !(AtaReq->TransferLength & 0x0f)) {
7613             KdPrint2((PRINT_PREFIX "AtapiSendCommand: try DMA setup\n"));
7614             // try use DMA if TransferLength is 16-byte aligned
7615             switch(Srb->Cdb[0]) {
7616             case SCSIOP_WRITE:
7617             case SCSIOP_WRITE12:
7618             case SCSIOP_WRITE16:
7619             case SCSIOP_SEND:
7620                 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO)
7621                     break;
7622                 /* FALLTHROUGH */
7623             case SCSIOP_RECEIVE:
7624             case SCSIOP_READ:
7625             case SCSIOP_READ12:
7626             case SCSIOP_READ16:
7627 
7628                 if(deviceExtension->opt_AtapiDmaReadWrite) {
7629 call_dma_setup:
7630                     if(deviceExtension->HwFlags & UNIATA_AHCI) {
7631                         KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n"));
7632                         use_dma = TRUE;
7633                     } else
7634                     if(AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
7635                                   (PUCHAR)(AtaReq->DataBuffer),
7636                                   Srb->DataTransferLength
7637                                   /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
7638                                   )) {
7639                         KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n"));
7640                         use_dma = TRUE;
7641                     }
7642                 }
7643                 break;
7644             case SCSIOP_READ_CD:
7645             case SCSIOP_READ_CD_MSF:
7646                 if(deviceExtension->opt_AtapiDmaRawRead)
7647                     goto call_dma_setup;
7648                 break;
7649             default:
7650 
7651                 if(deviceExtension->opt_AtapiDmaControlCmd) {
7652                     if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
7653                         // read operation
7654                         use_dma = TRUE;
7655                     } else {
7656                         // write operation
7657                         if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO) {
7658                             KdPrint2((PRINT_PREFIX "dma RO\n"));
7659                             use_dma = FALSE;
7660                         } else {
7661                             use_dma = TRUE;
7662                         }
7663                     }
7664                 }
7665                 break;
7666             }
7667             // try setup DMA
7668 setup_dma:
7669             if(use_dma) {
7670                 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7671                     KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n"));
7672                     //use_dma = TRUE;
7673                 } else
7674                 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
7675                               (PUCHAR)(AtaReq->DataBuffer),
7676                               Srb->DataTransferLength)) {
7677                     KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma\n"));
7678                     use_dma = FALSE;
7679                 } else {
7680                     KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n"));
7681                 }
7682             }
7683         } else {
7684             KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero/unaligned transfer %x, no DMA setup\n", AtaReq->TransferLength));
7685         }
7686 
7687 
7688         if(deviceExtension->HwFlags & UNIATA_AHCI) {
7689 
7690             UniataAhciSetupCmdPtr(AtaReq);
7691 
7692             if(!Srb->DataTransferLength) {
7693                 KdPrint2((PRINT_PREFIX "zero-transfer\n"));
7694                 use_dma = FALSE;
7695             } else
7696             if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
7697                           (PUCHAR)(AtaReq->DataBuffer),
7698                           Srb->DataTransferLength)) {
7699                 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no AHCI dma!\n"));
7700                 return SRB_STATUS_ERROR;
7701             }
7702             if(!use_dma) {
7703                 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7704             } else {
7705                 FeatureReg |= ATA_F_DMA;
7706                 if(LunExt->IdentifyData.AtapiDMA.DMADirRequired) {
7707                     if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
7708                         KdPrint2((PRINT_PREFIX "Set DMADir.\n"));
7709                         FeatureReg |= ATA_F_DMAREAD;
7710                     }
7711                 }
7712             }
7713 
7714             KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n"));
7715             // this is done in UniataAhciSetupFIS_H2D()
7716             //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
7717             RtlCopyMemory(&(AtaReq->ahci.ahci_cmd_ptr->acmd), Srb->Cdb, Srb->CdbLength);
7718 
7719             fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
7720                    &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]),
7721                     IDE_COMMAND_ATAPI_PACKET /* command */,
7722                     0 /* lba */,
7723                     (Srb->DataTransferLength >= 0x10000) ? (USHORT)(0xffff) : (USHORT)(Srb->DataTransferLength),
7724                     FeatureReg/* feature */
7725                     );
7726 
7727             if(!fis_size) {
7728                 KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n"));
7729                 return SRB_STATUS_ERROR;
7730             }
7731 
7732             AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0,
7733                 ((Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) ? ATA_AHCI_CMD_WRITE : 0) |
7734                 (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH),
7735                 fis_size, DeviceNumber);
7736 
7737             KdPrint2((PRINT_PREFIX "AtapiSendCommand ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags));
7738         }
7739 
7740     } else {
7741         if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
7742             // if this is queued request, reinit DMA and check
7743             // if DMA mode is still available
7744             KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit()  (1)\n"));
7745             AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7746             if (/*EnableDma &&*/
7747                 (LunExt->TransferMode >= ATA_DMA)) {
7748                 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (2)\n"));
7749                 use_dma = TRUE;
7750             } else {
7751                 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7752                 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma (2)\n"));
7753                 use_dma = FALSE;
7754             }
7755             dma_reinited = TRUE;
7756         }
7757     }
7758 
7759     if(!(CmdAction & CMD_ACTION_EXEC)) {
7760         KdPrint2((PRINT_PREFIX "AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
7761         return SRB_STATUS_PENDING;
7762     }
7763     KdPrint3((PRINT_PREFIX "AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma, Srb->Cdb[0]));
7764     if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
7765         KdPrint2((PRINT_PREFIX "  REQ_FLAG_DMA_OPERATION\n"));
7766     }
7767 
7768     if((Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) && !(deviceExtension->HwFlags & UNIATA_SATA)) {
7769         KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
7770         use_dma = FALSE;
7771         AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7772         AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7773     } if(AtaReq->TransferLength) {
7774         if(!dma_reinited) {
7775             KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit()\n"));
7776             AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7777             if (/*EnableDma &&*/
7778                 (LunExt->TransferMode >= ATA_DMA)) {
7779                 use_dma = TRUE;
7780             } else {
7781                 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7782                 use_dma = FALSE;
7783             }
7784         }
7785     } else {
7786         KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer\n"));
7787         use_dma = FALSE;
7788         AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7789         if(!deviceExtension->opt_AtapiDmaZeroTransfer && !(deviceExtension->HwFlags & UNIATA_SATA)) {
7790             KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
7791             AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7792         }
7793     }
7794     KdPrint2((PRINT_PREFIX "AtapiSendCommand: use_dma=%d\n", use_dma));
7795     if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
7796         KdPrint2((PRINT_PREFIX "  REQ_FLAG_DMA_OPERATION\n"));
7797     }
7798 
7799     KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_EXEC\n"));
7800 
7801     KdPrint3((PRINT_PREFIX "AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
7802                &(Srb->Cdb), Srb->Cdb[0], Srb->TargetId, Srb->Lun));
7803 
7804     // Make sure command is to ATAPI device.
7805     flags = LunExt->DeviceFlags;
7806     if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
7807         if((Srb->Lun) > (LunExt->DiscsPresent - 1)) {
7808 
7809             // Indicate no device found at this address.
7810             AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7811             return SRB_STATUS_SELECTION_TIMEOUT;
7812         }
7813     } else if(Srb->Lun > 0) {
7814         AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7815         return SRB_STATUS_SELECTION_TIMEOUT;
7816     }
7817 
7818     if(!(flags & DFLAGS_ATAPI_DEVICE)) {
7819         AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7820         return SRB_STATUS_SELECTION_TIMEOUT;
7821     }
7822 retry:
7823     // Select device 0 or 1. Or more for PM
7824     SelectDrive(chan, DeviceNumber);
7825 
7826     // Verify that controller is ready for next command.
7827     GetStatus(chan, statusByte);
7828     KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status %#x\n", statusByte));
7829 
7830     if(statusByte == IDE_STATUS_WRONG) {
7831         KdPrint2((PRINT_PREFIX "AtapiSendCommand: bad status 0xff on entry\n"));
7832         goto make_reset;
7833     }
7834     if(statusByte & IDE_STATUS_BUSY) {
7835         if(statusByte & IDE_STATUS_DSC) {
7836             KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte));
7837         } else {
7838             KdPrint2((PRINT_PREFIX "AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte));
7839             // We have to make reset here, since we are expecting device to be available
7840             //return SRB_STATUS_BUSY; // this cause queue freeze
7841             goto make_reset;
7842         }
7843     }
7844     if(deviceExtension->HwFlags & UNIATA_AHCI) {
7845         ULONG CI;
7846         // Check if command list is free
7847         CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
7848         if(CI) {
7849             // controller is busy, however we expect it to be free
7850             KdPrint2((PRINT_PREFIX "AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI));
7851             goto make_reset;
7852         }
7853     }
7854     if(statusByte & IDE_STATUS_ERROR) {
7855         if (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
7856 
7857             KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on entry: (%#x)\n", statusByte));
7858             // Read the error reg. to clear it and fail this request.
7859             AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7860             return MapError(deviceExtension, Srb);
7861         } else {
7862             KdPrint2((PRINT_PREFIX "  continue with SCSIOP_REQUEST_SENSE\n", statusByte));
7863         }
7864     }
7865     // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
7866     // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
7867     if((!(statusByte & IDE_STATUS_DSC)) &&
7868           (flags & (DFLAGS_TAPE_DEVICE | DFLAGS_ATAPI_DEVICE)) && chan->RDP) {
7869 
7870         AtapiStallExecution(200);
7871         KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte));
7872         AtaReq->ReqState = REQ_STATE_QUEUED;
7873         return SRB_STATUS_PENDING;
7874     }
7875 
7876     if(IS_RDP(Srb->Cdb[0])) {
7877         chan->RDP = TRUE;
7878         KdPrint2((PRINT_PREFIX "AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb->Cdb[0]));
7879     } else {
7880         chan->RDP = FALSE;
7881     }
7882     if(statusByte & IDE_STATUS_DRQ) {
7883 
7884         KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
7885                     statusByte));
7886         // Try to drain the data that one preliminary device thinks that it has
7887         // to transfer. Hopefully this random assertion of DRQ will not be present
7888         // in production devices.
7889         statusByte = AtapiSuckPort2(chan);
7890 /*
7891         for (i = 0; i < 0x10000; i++) {
7892             GetStatus(chan, statusByte);
7893             if(statusByte & IDE_STATUS_DRQ) {
7894                 AtapiReadPort2(chan, IDX_IO1_i_Data);
7895             } else {
7896                 break;
7897             }
7898         }
7899 */
7900         if (statusByte & IDE_STATUS_DRQ) {
7901             KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted. Status (%#x)\n", statusByte));
7902 make_reset:
7903             AtapiDisableInterrupts(deviceExtension, lChannel);
7904 
7905             AtapiSoftReset(chan, DeviceNumber);
7906 
7907             KdPrint2((PRINT_PREFIX "AtapiSendCommand: Issued soft reset to Atapi device. \n"));
7908             // Re-initialize Atapi device.
7909             CheckDevice(HwDeviceExtension, GET_CHANNEL(Srb), DeviceNumber, TRUE);
7910 /*
7911             IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
7912                           IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
7913 */
7914             // Inform the port driver that the bus has been reset.
7915             ScsiPortNotification(ResetDetected, HwDeviceExtension, 0);
7916             // Clean up device extension fields that AtapiStartIo won't.
7917             UniataExpectChannelInterrupt(chan, FALSE);
7918             chan->RDP = FALSE;
7919             InterlockedExchange(&(deviceExtension->chan[GET_CHANNEL(Srb)].CheckIntr),
7920                                           CHECK_INTR_IDLE);
7921 
7922             AtapiEnableInterrupts(deviceExtension, lChannel);
7923 /*
7924             AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7925             return SRB_STATUS_BUS_RESET;
7926 */
7927             if(!retried) {
7928                 KdPrint3((PRINT_PREFIX "AtapiSendCommand: retry after reset.\n"));
7929                 retried = TRUE;
7930                 goto retry;
7931             }
7932             KdPrint3((PRINT_PREFIX "AtapiSendCommand: selection timeout.\n"));
7933             AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7934             return SRB_STATUS_SELECTION_TIMEOUT;
7935         }
7936     }
7937 
7938     if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
7939         // As the cdrom driver sets the LUN field in the cdb, it must be removed.
7940         Srb->Cdb[1] &= ~0xE0;
7941         if((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY) && (flags & DFLAGS_SANYO_ATAPI_CHANGER)) {
7942             // Torisan changer. TUR's are overloaded to be platter switches.
7943             Srb->Cdb[7] = Srb->Lun;
7944         }
7945     }
7946 
7947     // SETUP DMA !!!!!
7948 
7949     if(use_dma) {
7950         chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
7951     } else {
7952         chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
7953     }
7954 
7955     if(deviceExtension->HwFlags & UNIATA_AHCI) {
7956         KdPrint2((PRINT_PREFIX "AtapiSendCommand: AHCI, begin transaction\n"));
7957         //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
7958         UniataExpectChannelInterrupt(chan, TRUE);
7959         UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
7960         return SRB_STATUS_PENDING;
7961     }
7962 
7963     statusByte = WaitOnBusy(chan);
7964     KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entry Status (%#x)\n",
7965                statusByte));
7966 
7967     if(use_dma) {
7968         FeatureReg |= ATA_F_DMA;
7969         if(LunExt->IdentifyData.AtapiDMA.DMADirRequired) {
7970             if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
7971                 FeatureReg |= ATA_F_DMAREAD;
7972             }
7973         }
7974     }
7975 
7976     // Write transfer byte count to registers.
7977     if (Srb->DataTransferLength >= 0x10000) {
7978         byteCountLow = byteCountHigh = 0xFF;
7979     } else {
7980         byteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF);
7981         byteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8);
7982     }
7983 
7984     KdPrint3((PRINT_PREFIX "AtapiSendCommand: F:%#x, CntHL:%#x:%#x.\n", FeatureReg, byteCountHigh, byteCountLow));
7985 
7986     if (flags & DFLAGS_INT_DRQ) {
7987         // This device interrupts when ready to receive the packet.
7988         KdPrint3((PRINT_PREFIX "AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
7989                    statusByte));
7990 
7991         UniataExpectChannelInterrupt(chan, TRUE);
7992         AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_CMD_INTR;
7993         InterlockedExchange(&(chan->CheckIntr),
7994                                       CHECK_INTR_IDLE);
7995         // inform driver that packet command must be sent in ISR
7996         flags |= DFLAGS_INT_DRQ;
7997     } else {
7998         // This device quickly sets DRQ when ready to receive the packet.
7999         KdPrint2((PRINT_PREFIX "AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
8000                    statusByte));
8001 
8002         UniataExpectChannelInterrupt(chan, TRUE);
8003         AtaReq->ReqState = REQ_STATE_ATAPI_DO_NOTHING_INTR;
8004         InterlockedExchange(&(chan->CheckIntr),
8005                                       CHECK_INTR_IDLE);
8006 
8007         if(g_opt_AtapiSendDisableIntr) {
8008             AtapiDisableInterrupts(deviceExtension, lChannel);
8009         }
8010         // remember status. Later we may check if error appeared after cmd packet
8011         statusByte0 = statusByte;
8012     }
8013 
8014     // must be already selected, experimental for ROS BUG-9119
8015     //AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) );
8016     AtapiWritePort1(chan, IDX_IO2_o_Control , 0);
8017     AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Feature /*IDX_IO1_o_Feature*/, FeatureReg);
8018     //AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Unused0, 0);  // experimental for ROS BUG-9119
8019     //AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Unused1, 0);  // experimental for ROS BUG-9119
8020     AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountLow, byteCountLow);
8021     AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh, byteCountHigh);
8022     // Write ATAPI packet command.
8023     AtapiWritePort1(chan, IDX_ATAPI_IO1_o_Command /*IDX_IO1_o_Command*/, IDE_COMMAND_ATAPI_PACKET);
8024 
8025     if (flags & DFLAGS_INT_DRQ) {
8026         // Wait for interrupt and send PACKET there
8027         KdPrint3((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
8028         return SRB_STATUS_PENDING;
8029     }
8030 
8031     WaitOnBusy(chan);
8032 /*
8033     // Wait for DRQ.
8034     statusByte = WaitForDrq(chan);
8035 
8036     // Need to read status register and clear interrupt (if any)
8037     GetBaseStatus(chan, statusByte);
8038 
8039     if (!(statusByte & IDE_STATUS_DRQ)) {
8040         if(g_opt_AtapiSendDisableIntr) {
8041             AtapiEnableInterrupts(deviceExtension, lChannel);
8042         }
8043         KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte));
8044         AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
8045         return SRB_STATUS_ERROR;
8046     }
8047 */
8048     GetStatus(chan, statusByte);
8049     KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte));
8050 
8051     //statusByte = WaitOnBaseBusy(chan);
8052 
8053     // Indicate expecting an interrupt and wait for it.
8054     UniataExpectChannelInterrupt(chan, TRUE);
8055 
8056     for(i=0; i<5000; i++) {
8057         if(g_opt_AtapiSendDisableIntr) {
8058             GetStatus(chan, statusByte);
8059         } else {
8060             GetBaseStatus(chan, statusByte);
8061         }
8062         interruptReason = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason);
8063         //KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x (%d)\n", interruptReason, i));
8064         if(((interruptReason & ATAPI_IR_COD) == ATAPI_IR_COD_Cmd) &&
8065            (((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)) == IDE_STATUS_DRQ))) {
8066             break;
8067         }
8068         AtapiStallExecution(g_opt_WaitDrqDelay*2);
8069 #ifdef _DEBUG
8070 //        KdPrint3((PRINT_PREFIX "AtapiSendCommand: wait CoD, status (%#x)\n", interruptReason));
8071 #endif // _DEBUG
8072     }
8073     if(((interruptReason & ATAPI_IR_COD) != ATAPI_IR_COD_Cmd) ||
8074        (((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)) != IDE_STATUS_DRQ)) ) {
8075         KdPrint3((PRINT_PREFIX "AtapiSendCommand: no CoD raised, abort cmd\n"));
8076         KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x (%d)\n", interruptReason, i));
8077         KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte));
8078         if(g_opt_AtapiSendDisableIntr) {
8079             AtapiEnableInterrupts(deviceExtension, lChannel);
8080         }
8081         KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ+CoD never asserted\n"));
8082         statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
8083         KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte));
8084         if(statusByte >> 4) {
8085             GetBaseStatus(chan, statusByte);
8086             AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
8087             return MapError(deviceExtension, Srb);
8088         }
8089         goto make_reset;
8090 //        AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
8091 //        return SRB_STATUS_ERROR;
8092     } else {
8093         KdPrint3((PRINT_PREFIX "AtapiSendCommand: ready for packet, status %#x, i=%d\n", interruptReason, i));
8094     }
8095     // clear interrupt
8096     GetBaseStatus(chan, statusByte);
8097 
8098     if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
8099         AtapiDmaDBPreSync(HwDeviceExtension, chan, Srb);
8100     }
8101     if(g_opt_AtapiSendDisableIntr) {
8102         AtapiEnableInterrupts(deviceExtension, lChannel);
8103     }
8104 
8105     // Send CDB to device.
8106     WriteBuffer(chan,
8107                 (PUSHORT)Srb->Cdb,
8108                 LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
8109                 /*0*/ PIO0_TIMING);
8110 
8111     GetStatus(chan, statusByte);
8112     KdPrint3((PRINT_PREFIX "AtapiSendCommand: cmd status (%#x)\n", statusByte));
8113 
8114     // When we operate in DMA mode, we should not start transfer when there is an error on entry
8115     // Interrupt may never come in such case.
8116     if(statusByte & IDE_STATUS_ERROR) {
8117 
8118         GetBaseStatus(chan, statusByte);
8119         KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on cmd: (%#x)\n", statusByte));
8120 
8121         interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
8122         KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x\n", interruptReason));
8123 
8124         // TODO:  we should check interruptReason and decide what to do now
8125 
8126         // Read the error reg. to clear it and fail this request.
8127         AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
8128         return MapError(deviceExtension, Srb);
8129     }
8130     if(statusByte & IDE_STATUS_DRQ) {
8131         // Some devices require this. If error condition is not checked in such a way,
8132         // device may not operate correctly and would be treated as failed
8133         // (and finally invisible for OS)
8134         KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ on cmd: (%#x)\n", statusByte));
8135         // Read the error reg. to clear it and fail this request.
8136         statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
8137         KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte));
8138         if(statusByte >> 4) {
8139             GetBaseStatus(chan, statusByte);
8140             AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
8141             return MapError(deviceExtension, Srb);
8142         }
8143     }
8144 
8145     if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
8146         AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
8147     }
8148 
8149     InterlockedExchange(&(chan->CheckIntr),
8150                                   CHECK_INTR_IDLE);
8151     AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
8152 
8153     KdPrint3((PRINT_PREFIX "AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan->ExpectingInterrupt));
8154 
8155     KdPrint2((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
8156     return SRB_STATUS_PENDING;
8157 
8158 } // end AtapiSendCommand()
8159 
8160 
8161 #ifndef UNIATA_CORE
8162 
8163 /*++
8164 
8165 Routine Description:
8166     Program ATA registers for IDE disk transfer.
8167 
8168 Arguments:
8169     HwDeviceExtension - ATAPI driver storage.
8170     Srb - System request block.
8171 
8172 Return Value:
8173     SRB status (pending if all goes well).
8174 
8175 --*/
8176 
8177 #ifdef _DEBUG
8178 ULONG check_point = 0;
8179 #define SetCheckPoint(cp)  { check_point = (cp) ; }
8180 #else
8181 #define SetCheckPoint(cp)
8182 #endif
8183 
8184 ULONG
8185 NTAPI
8186 IdeSendCommand(
8187     IN PVOID HwDeviceExtension,
8188     IN PSCSI_REQUEST_BLOCK Srb,
8189     IN ULONG CmdAction
8190     )
8191 {
8192     SetCheckPoint(1);
8193     KdPrint2((PRINT_PREFIX "** Ide: Command: entryway\n"));
8194     SetCheckPoint(2);
8195 
8196     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
8197     SetCheckPoint(3);
8198     UCHAR                lChannel;
8199     PHW_CHANNEL          chan;
8200     PCDB cdb;
8201     PHW_LU_EXTENSION     LunExt;
8202 
8203     SetCheckPoint(4);
8204 
8205     UCHAR statusByte,errorByte;
8206     ULONG status = SRB_STATUS_INVALID_REQUEST;
8207     ULONG i;
8208     ULONGLONG lba;
8209     PMODE_PARAMETER_HEADER   modeData;
8210     //ULONG ldev;
8211     ULONG DeviceNumber;
8212     PATA_REQ AtaReq;
8213     UCHAR command;
8214 
8215     SetCheckPoint(5);
8216     //ULONG __ebp__ = 0;
8217 
8218     SetCheckPoint(0x20);
8219     KdPrint2((PRINT_PREFIX "** Ide: Command:\n\n"));
8220 /*    __asm {
8221         mov eax,ebp
8222         mov __ebp__, eax
8223     }*/
8224     /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
8225         __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
8226     KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
8227         (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
8228     KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
8229         Srb));
8230     KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
8231         Srb->SrbExtension));
8232     KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
8233         Srb->TargetId));*/
8234 
8235     SetCheckPoint(0x30);
8236     AtaReq = (PATA_REQ)(Srb->SrbExtension);
8237 
8238     KdPrint2((PRINT_PREFIX "** Ide: Command &AtaReq %#x\n",
8239         &AtaReq));
8240     KdPrint2((PRINT_PREFIX "** Ide: Command AtaReq %#x\n",
8241         AtaReq));
8242     KdPrint2((PRINT_PREFIX "** --- **\n"));
8243 
8244     lChannel = GET_CHANNEL(Srb);
8245     chan = &(deviceExtension->chan[lChannel]);
8246     //ldev = GET_LDEV(Srb);
8247     DeviceNumber = GET_CDEV(Srb);
8248     LunExt = chan->lun[DeviceNumber];
8249 
8250     SetCheckPoint(0x40);
8251     if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
8252         AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER;
8253 
8254     cdb = (PCDB)(Srb->Cdb);
8255 
8256     if(CmdAction == CMD_ACTION_PREPARE) {
8257         switch (Srb->Cdb[0]) {
8258         case SCSIOP_SERVICE_ACTION16:
8259             if( cdb->SERVICE_ACTION16.ServiceAction==SCSIOP_SA_READ_CAPACITY16 ) {
8260                 // ok
8261             } else {
8262                 goto default_no_prep;
8263             }
8264 #ifdef NAVO_TEST
8265         case SCSIOP_INQUIRY: // now it requires device access
8266 #endif //NAVO_TEST
8267         case SCSIOP_READ_CAPACITY:
8268         case SCSIOP_READ:
8269         case SCSIOP_WRITE:
8270         case SCSIOP_READ12:
8271         case SCSIOP_WRITE12:
8272         case SCSIOP_READ16:
8273         case SCSIOP_WRITE16:
8274         case SCSIOP_REQUEST_SENSE:
8275             // all right
8276             KdPrint2((PRINT_PREFIX "** Ide: Command continue prep\n"));
8277             SetCheckPoint(50);
8278             break;
8279         default:
8280 default_no_prep:
8281             SetCheckPoint(0);
8282             KdPrint2((PRINT_PREFIX "** Ide: Command break prep\n"));
8283             return SRB_STATUS_BUSY;
8284         }
8285     }
8286 
8287     SetCheckPoint(0x100 | Srb->Cdb[0]);
8288     switch (Srb->Cdb[0]) {
8289     case SCSIOP_INQUIRY:
8290 
8291         KdPrint2((PRINT_PREFIX
8292                    "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
8293                    Srb->PathId, Srb->Lun, Srb->TargetId));
8294         // Filter out wrong TIDs.
8295         if ((Srb->Lun != 0) ||
8296             (Srb->PathId >= deviceExtension->NumberChannels) ||
8297             (Srb->TargetId >= deviceExtension->NumberLuns)) {
8298 
8299             KdPrint2((PRINT_PREFIX
8300                        "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
8301             // Indicate no device found at this address.
8302             status = SRB_STATUS_SELECTION_TIMEOUT;
8303             break;
8304 
8305         } else {
8306 
8307             KdPrint2((PRINT_PREFIX
8308                        "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
8309             PINQUIRYDATA    inquiryData  = (PINQUIRYDATA)(Srb->DataBuffer);
8310             PIDENTIFY_DATA2 identifyData = &(LunExt->IdentifyData);
8311 
8312             if (!(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
8313 
8314                 if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8315                     KdPrint2((PRINT_PREFIX
8316                                "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
8317                     // Indicate no device found at this address.
8318 #ifndef NAVO_TEST
8319                     status = SRB_STATUS_SELECTION_TIMEOUT;
8320                     break;
8321                 }
8322             } else {
8323                 if(!UniataAnybodyHome(HwDeviceExtension, lChannel, DeviceNumber)) {
8324                     KdPrint2((PRINT_PREFIX
8325                                "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
8326                     // Indicate no device found at this address.
8327                     UniataForgetDevice(chan->lun[DeviceNumber]);
8328 #endif //NAVO_TEST
8329                     status = SRB_STATUS_SELECTION_TIMEOUT;
8330                     break;
8331                 }
8332             }
8333 
8334             // Zero INQUIRY data structure.
8335             RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength);
8336 
8337             // Standard IDE interface only supports disks.
8338             inquiryData->DeviceType = DIRECT_ACCESS_DEVICE;
8339 
8340             // Set the removable bit, if applicable.
8341             if (LunExt->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) {
8342                 KdPrint2((PRINT_PREFIX
8343                            "RemovableMedia\n"));
8344                 inquiryData->RemovableMedia = 1;
8345             }
8346             // Set the Relative Addressing (LBA) bit, if applicable.
8347             if (LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
8348                 inquiryData->RelativeAddressing = 1;
8349                 KdPrint2((PRINT_PREFIX
8350                            "RelativeAddressing\n"));
8351             }
8352             // Set the CommandQueue bit
8353             inquiryData->CommandQueue = 1;
8354 
8355             // Fill in vendor identification fields.
8356             for (i = 0; i < 24; i += 2) {
8357                 MOV_DW_SWP(inquiryData->DeviceIdentificationString[i], ((PUCHAR)identifyData->ModelNumber)[i]);
8358             }
8359 /*
8360             // Initialize unused portion of product id.
8361             for (i = 0; i < 4; i++) {
8362                 inquiryData->ProductId[12+i] = ' ';
8363             }
8364 */
8365             // Move firmware revision from IDENTIFY data to
8366             // product revision in INQUIRY data.
8367             for (i = 0; i < 4; i += 2) {
8368                 MOV_DW_SWP(inquiryData->ProductRevisionLevel[i], ((PUCHAR)identifyData->FirmwareRevision)[i]);
8369             }
8370 
8371             status = SRB_STATUS_SUCCESS;
8372         }
8373 
8374         break;
8375 
8376     case SCSIOP_REPORT_LUNS: {
8377 
8378         ULONG alen;
8379         PREPORT_LUNS_INFO_HDR LunInfo;
8380 
8381         KdPrint2((PRINT_PREFIX
8382                    "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
8383                    Srb->PathId, Srb->Lun, Srb->TargetId));
8384 
8385         MOV_DD_SWP(alen, cdb->REPORT_LUNS.AllocationLength);
8386 
8387         if(alen < 16) {
8388             goto invalid_cdb;
8389         }
8390         alen = 8;
8391 
8392         LunInfo = (PREPORT_LUNS_INFO_HDR)(Srb->DataBuffer);
8393         RtlZeroMemory(LunInfo, 16);
8394 
8395         MOV_DD_SWP( LunInfo->ListLength, alen );
8396         Srb->DataTransferLength = 16;
8397         status = SRB_STATUS_SUCCESS;
8398 
8399         break; }
8400 
8401     case SCSIOP_MODE_SENSE:
8402 
8403         KdPrint2((PRINT_PREFIX
8404                    "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8405                    Srb->PathId, Srb->Lun, Srb->TargetId));
8406 
8407         if(cdb->MODE_SENSE.PageCode == MODE_PAGE_POWER_CONDITION) {
8408             PMODE_POWER_CONDITION_PAGE modeData;
8409 
8410             KdPrint2((PRINT_PREFIX "MODE_PAGE_POWER_CONDITION\n"));
8411             modeData = (PMODE_POWER_CONDITION_PAGE)(Srb->DataBuffer);
8412             if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_POWER_CONDITION_PAGE)) {
8413                 status = SRB_STATUS_DATA_OVERRUN;
8414             } else {
8415                 RtlZeroMemory(modeData, sizeof(MODE_POWER_CONDITION_PAGE));
8416                 modeData->PageCode = MODE_PAGE_POWER_CONDITION;
8417 #ifdef __REACTOS__
8418                 modeData->PageLength = sizeof(MODE_POWER_CONDITION_PAGE)-sizeof(MODE_PARAMETER_HEADER);
8419 #else
8420                 modeData->PageLength = sizeof(MODE_PAGE_POWER_CONDITION)-sizeof(MODE_PARAMETER_HEADER);
8421 #endif
8422                 modeData->Byte3.Fields.Idle = LunExt->PowerState <= StartStop_Power_Idle;
8423                 modeData->Byte3.Fields.Standby = LunExt->PowerState == StartStop_Power_Standby;
8424                 Srb->DataTransferLength = sizeof(MODE_POWER_CONDITION_PAGE);
8425                 status = SRB_STATUS_SUCCESS;
8426             }
8427         } else
8428         if(cdb->MODE_SENSE.PageCode == MODE_PAGE_CACHING) {
8429             PMODE_CACHING_PAGE modeData;
8430 
8431             KdPrint2((PRINT_PREFIX "MODE_PAGE_CACHING\n"));
8432             modeData = (PMODE_CACHING_PAGE)(Srb->DataBuffer);
8433             if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_CACHING_PAGE)) {
8434                 status = SRB_STATUS_DATA_OVERRUN;
8435             } else {
8436                 RtlZeroMemory(modeData, sizeof(MODE_CACHING_PAGE));
8437                 modeData->PageCode = MODE_PAGE_CACHING;
8438                 modeData->PageLength = sizeof(MODE_CACHING_PAGE)-sizeof(MODE_PARAMETER_HEADER);
8439                 modeData->ReadDisableCache = (LunExt->DeviceFlags & DFLAGS_RCACHE_ENABLED) ? 0 : 1;
8440                 modeData->WriteCacheEnable = (LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) ? 1 : 0;
8441                 Srb->DataTransferLength = sizeof(MODE_CACHING_PAGE);
8442                 status = SRB_STATUS_SUCCESS;
8443             }
8444         } else
8445         if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
8446 
8447             // This is used to determine if the media is write-protected.
8448             // Since IDE does not support mode sense then we will modify just the portion we need
8449             // so the higher level driver can determine if media is protected.
8450 
8451             //SelectDrive(chan, DeviceNumber);
8452             //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
8453             //statusByte = WaitOnBusy(chan);
8454             statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY);
8455 
8456             if (!(statusByte & IDE_STATUS_ERROR)) {
8457 
8458                 // no error occured return success, media is not protected
8459                 UniataExpectChannelInterrupt(chan, FALSE);
8460                 InterlockedExchange(&(chan->CheckIntr),
8461                                               CHECK_INTR_IDLE);
8462                 status = SRB_STATUS_SUCCESS;
8463 
8464             } else {
8465 
8466                 // error occured, handle it locally, clear interrupt
8467                 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
8468 
8469                 GetBaseStatus(chan, statusByte);
8470                 UniataExpectChannelInterrupt(chan, FALSE);
8471                 InterlockedExchange(&(chan->CheckIntr),
8472                                               CHECK_INTR_IDLE);
8473                 status = SRB_STATUS_SUCCESS;
8474 
8475                 if (errorByte & IDE_ERROR_DATA_ERROR) {
8476 
8477                     //media is write-protected, set bit in mode sense buffer
8478                     modeData = (PMODE_PARAMETER_HEADER)Srb->DataBuffer;
8479 
8480                     Srb->DataTransferLength = sizeof(MODE_PARAMETER_HEADER);
8481                     modeData->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
8482                 }
8483             }
8484             status = SRB_STATUS_SUCCESS;
8485         } else {
8486             status = SRB_STATUS_INVALID_REQUEST;
8487         }
8488         break;
8489 
8490     case SCSIOP_TEST_UNIT_READY:
8491 
8492         KdPrint2((PRINT_PREFIX
8493                    "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
8494                    Srb->PathId, Srb->Lun, Srb->TargetId));
8495         if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
8496 
8497             // Select device 0 or 1.
8498             //SelectDrive(chan, DeviceNumber);
8499             //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
8500             // Wait for busy. If media has not changed, return success
8501             //statusByte = WaitOnBusy(chan);
8502             statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY);
8503 
8504             if (!(statusByte & IDE_STATUS_ERROR)){
8505                 UniataExpectChannelInterrupt(chan, FALSE);
8506                 InterlockedExchange(&(chan->CheckIntr),
8507                                               CHECK_INTR_IDLE);
8508                 status = SRB_STATUS_SUCCESS;
8509             } else {
8510                 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
8511                 if (errorByte == IDE_ERROR_DATA_ERROR){
8512 
8513                     // Special case: If current media is write-protected,
8514                     // the 0xDA command will always fail since the write-protect bit
8515                     // is sticky,so we can ignore this error
8516                     GetBaseStatus(chan, statusByte);
8517                     UniataExpectChannelInterrupt(chan, FALSE);
8518                     InterlockedExchange(&(chan->CheckIntr),
8519                                                   CHECK_INTR_IDLE);
8520                     status = SRB_STATUS_SUCCESS;
8521 
8522                 } else {
8523 
8524                     // Request sense buffer to be build
8525                     UniataExpectChannelInterrupt(chan, TRUE);
8526                     InterlockedExchange(&(chan->CheckIntr),
8527                                                   CHECK_INTR_IDLE);
8528                     status = SRB_STATUS_PENDING;
8529                }
8530             }
8531         } else {
8532             status = SRB_STATUS_SUCCESS;
8533         }
8534 
8535         break;
8536 
8537     case SCSIOP_READ_CAPACITY:
8538 
8539         KdPrint2((PRINT_PREFIX
8540                    "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
8541                    Srb->PathId, Srb->Lun, Srb->TargetId));
8542         // Claim 512 byte blocks (big-endian).
8543         //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
8544         i = DEV_BSIZE;
8545         RtlZeroMemory(Srb->DataBuffer, sizeof(READ_CAPACITY_DATA));
8546         MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock, i );
8547 
8548         // Calculate last sector.
8549         if(!(i = (ULONG)LunExt->NumOfSectors)) {
8550             i = LunExt->IdentifyData.SectorsPerTrack *
8551                 LunExt->IdentifyData.NumberOfHeads *
8552                 LunExt->IdentifyData.NumberOfCylinders;
8553         }
8554         i--;
8555 
8556         //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
8557         //    (((PUCHAR)&i)[0] << 24) |  (((PUCHAR)&i)[1] << 16) |
8558         //    (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
8559 
8560         MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress, i );
8561 
8562         KdPrint2((PRINT_PREFIX
8563                    "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
8564                    Srb->TargetId,
8565                    LunExt->IdentifyData.SectorsPerTrack,
8566                    LunExt->IdentifyData.NumberOfHeads,
8567                    LunExt->IdentifyData.NumberOfCylinders));
8568 
8569 
8570         status = SRB_STATUS_SUCCESS;
8571         break;
8572 
8573     case SCSIOP_SERVICE_ACTION16:
8574 
8575         if( cdb->SERVICE_ACTION16.ServiceAction==SCSIOP_SA_READ_CAPACITY16 ) {
8576             KdPrint2((PRINT_PREFIX
8577                        "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
8578                        Srb->PathId, Srb->Lun, Srb->TargetId));
8579             // Claim 512 byte blocks (big-endian).
8580             //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
8581             i = DEV_BSIZE;
8582             RtlZeroMemory(Srb->DataBuffer, sizeof(READ_CAPACITY16_DATA));
8583             MOV_DD_SWP( ((PREAD_CAPACITY16_DATA)Srb->DataBuffer)->BytesPerBlock, i );
8584 
8585             // Calculate last sector.
8586             if(!(lba = LunExt->NumOfSectors)) {
8587                 lba = LunExt->IdentifyData.SectorsPerTrack *
8588                     LunExt->IdentifyData.NumberOfHeads *
8589                     LunExt->IdentifyData.NumberOfCylinders;
8590             }
8591             lba--;
8592             MOV_QD_SWP( ((PREAD_CAPACITY16_DATA)Srb->DataBuffer)->LogicalBlockAddress, lba );
8593 
8594             KdPrint2((PRINT_PREFIX
8595                        "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n",
8596                        Srb->TargetId,
8597                        LunExt->IdentifyData.SectorsPerTrack,
8598                        LunExt->IdentifyData.NumberOfHeads,
8599                        LunExt->IdentifyData.NumberOfCylinders));
8600 
8601             status = SRB_STATUS_SUCCESS;
8602         } else {
8603             goto default_abort;
8604         }
8605         break;
8606 
8607     case SCSIOP_VERIFY:
8608     case SCSIOP_VERIFY12:
8609     case SCSIOP_VERIFY16:
8610 
8611         KdPrint2((PRINT_PREFIX
8612                    "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
8613                    Srb->PathId, Srb->Lun, Srb->TargetId));
8614         status = IdeVerify(HwDeviceExtension,Srb);
8615 
8616         break;
8617 
8618     case SCSIOP_READ:
8619     case SCSIOP_WRITE:
8620     case SCSIOP_READ12:
8621     case SCSIOP_WRITE12:
8622     case SCSIOP_READ16:
8623     case SCSIOP_WRITE16:
8624 
8625         KdPrint2((PRINT_PREFIX
8626                    "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
8627                    (Srb->Cdb[0] == SCSIOP_WRITE) ? "WRITE" : "READ",
8628                    Srb->PathId, Srb->Lun, Srb->TargetId));
8629         AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
8630         AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE ||
8631                           Srb->Cdb[0] == SCSIOP_WRITE12 ||
8632                           Srb->Cdb[0] == SCSIOP_WRITE16) ? REQ_FLAG_WRITE : REQ_FLAG_READ;
8633         status = IdeReadWrite(HwDeviceExtension,
8634                               Srb, CmdAction);
8635         break;
8636 
8637     case SCSIOP_START_STOP_UNIT:
8638 
8639         KdPrint2((PRINT_PREFIX
8640                    "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
8641                    cdb->START_STOP.Immediate, Srb->PathId, Srb->Lun, Srb->TargetId));
8642         //Determine what type of operation we should perform
8643 
8644         command = 0;
8645 
8646         if(cdb->START_STOP.FL ||
8647            cdb->START_STOP.FormatLayerNumber ||
8648            cdb->START_STOP.Reserved2 ||
8649            cdb->START_STOP.Reserved2_2 ||
8650            cdb->START_STOP.Reserved3 ||
8651            FALSE) {
8652             goto invalid_cdb;
8653         }
8654 
8655         if (cdb->START_STOP.PowerConditions) {
8656             KdPrint2((PRINT_PREFIX "START_STOP Power %d\n", cdb->START_STOP.PowerConditions));
8657             switch(cdb->START_STOP.PowerConditions) {
8658             case StartStop_Power_Idle:
8659                 command = IDE_COMMAND_IDLE_IMMED;
8660                 break;
8661             case StartStop_Power_Standby:
8662                 command = IDE_COMMAND_STANDBY_IMMED;
8663                 break;
8664             case StartStop_Power_Sleep:
8665                 // TODO: we should save power state in order to know
8666                 // that RESET sould be issued to revert device into
8667                 // operable state
8668 
8669                 command = IDE_COMMAND_SLEEP;
8670                 break;
8671             default:
8672                 goto invalid_cdb;
8673             }
8674             LunExt->PowerState = cdb->START_STOP.PowerConditions;
8675         } else
8676         if (cdb->START_STOP.LoadEject == 1) {
8677             KdPrint2((PRINT_PREFIX "START_STOP eject\n"));
8678             // Eject media,
8679             // first select device 0 or 1.
8680             //SelectDrive(chan, DeviceNumber);
8681             //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
8682             command = IDE_COMMAND_MEDIA_EJECT;
8683         } else
8684         if (cdb->START_STOP.Start == 0) {
8685             KdPrint2((PRINT_PREFIX "START_STOP standby\n"));
8686             command = IDE_COMMAND_STANDBY_IMMED;
8687         } else {
8688             // TODO: we may need to perform hard reset (after sleep) or
8689             // issue IDE_COMMAND_IDLE_IMMED in order to activate device
8690             KdPrint2((PRINT_PREFIX "START_STOP activate\n"));
8691 
8692             if(LunExt->PowerState == StartStop_Power_Sleep) {
8693                 UniataUserDeviceReset(deviceExtension, LunExt, lChannel);
8694                 status = SRB_STATUS_SUCCESS;
8695                 break;
8696             } else
8697             if(LunExt->PowerState > StartStop_Power_Idle) {
8698                 KdPrint2((PRINT_PREFIX "  issue IDLE\n"));
8699                 command = IDE_COMMAND_IDLE_IMMED;
8700             } else {
8701                 KdPrint2((PRINT_PREFIX "  do nothing\n"));
8702                 status = SRB_STATUS_SUCCESS;
8703                 break;
8704             }
8705         }
8706         if(command) {
8707             statusByte = WaitOnBaseBusy(chan);
8708             statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, command, 0, 0, 0, 0, 0,
8709                 cdb->START_STOP.Immediate ? ATA_IMMEDIATE : ATA_WAIT_READY);
8710             status = (statusByte & IDE_STATUS_ERROR) ? SRB_STATUS_ERROR : SRB_STATUS_SUCCESS;
8711             //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
8712 
8713         } else {
8714 invalid_cdb:
8715             KdPrint2((PRINT_PREFIX "START_STOP invalid\n"));
8716             if (Srb->SenseInfoBuffer) {
8717 
8718                 PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
8719 
8720                 senseBuffer->ErrorCode = 0x70;
8721                 senseBuffer->Valid     = 1;
8722                 senseBuffer->AdditionalSenseLength = 0xb;
8723                 senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST;
8724                 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_CDB;
8725                 senseBuffer->AdditionalSenseCodeQualifier = 0;
8726 
8727                 Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID;
8728                 Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
8729             }
8730             status = SRB_STATUS_ERROR;
8731         }
8732         break;
8733 
8734     case SCSIOP_MEDIUM_REMOVAL:
8735 
8736         cdb = (PCDB)Srb->Cdb;
8737 
8738         if(LunExt->IdentifyData.Removable) {
8739             statusByte = WaitOnBaseBusy(chan);
8740 
8741             //SelectDrive(chan, DeviceNumber);
8742             if (cdb->MEDIA_REMOVAL.Prevent == TRUE) {
8743                 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
8744                 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_LOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
8745             } else {
8746                 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
8747                 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_UNLOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
8748             }
8749             status = SRB_STATUS_SUCCESS;
8750         } else {
8751             status = SRB_STATUS_INVALID_REQUEST;
8752         }
8753         break;
8754 
8755 #if 0
8756     // Note: I don't implement this, because NTFS driver too often issues this command
8757     // It causes awful performance degrade. However, if somebody wants, I will implement
8758     // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
8759     case SCSIOP_FLUSH_BUFFER:
8760     case SCSIOP_SYNCHRONIZE_CACHE:
8761 
8762         SelectDrive(chan, DeviceNumber);
8763         AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_FLUSH_CACHE);
8764         status = SRB_STATUS_SUCCESS;
8765 //        status = SRB_STATUS_PENDING;
8766         statusByte = WaitOnBusy(chan);
8767         break;
8768 #endif
8769 
8770     case SCSIOP_REQUEST_SENSE:
8771         // this function makes sense buffers to report the results
8772         // of the original GET_MEDIA_STATUS command
8773 
8774         KdPrint2((PRINT_PREFIX
8775                    "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8776                    Srb->PathId, Srb->Lun, Srb->TargetId));
8777         if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
8778             status = IdeBuildSenseBuffer(HwDeviceExtension,Srb);
8779             break;
8780         }
8781         status = SRB_STATUS_INVALID_REQUEST;
8782         break;
8783 
8784     // ATA_PASSTHORUGH
8785     case SCSIOP_ATA_PASSTHROUGH:
8786     {
8787         PIDEREGS_EX regs;
8788         BOOLEAN use_dma = FALSE;
8789         ULONG to_lim;
8790 
8791         regs = (PIDEREGS_EX) &(Srb->Cdb[2]);
8792 
8793         if(chan->DeviceExtension->HwFlags & UNIATA_SATA) {
8794             //lChannel = Srb->TargetId >> 1;
8795         } else {
8796             DeviceNumber = max(DeviceNumber, 1);
8797             regs->bDriveHeadReg &= 0x0f;
8798             regs->bDriveHeadReg |= (UCHAR) (((DeviceNumber & 0x1) << 4) | 0xA0);
8799         }
8800 
8801         if((regs->bOpFlags & 1) == 0) {      // execute ATA command
8802 
8803             KdPrint2((PRINT_PREFIX
8804                        "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
8805                        Srb->PathId, Srb->Lun, Srb->TargetId));
8806 
8807             if((regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) == UNIATA_SPTI_EX_SPEC_TO) {
8808                 to_lim = Srb->TimeOutValue;
8809             } else {
8810                 if(Srb->TimeOutValue <= 2) {
8811                     to_lim = Srb->TimeOutValue*900;
8812                 } else {
8813                     to_lim = (Srb->TimeOutValue*999) - 500;
8814                 }
8815             }
8816 
8817             AtapiDisableInterrupts(deviceExtension, lChannel);
8818 
8819             if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
8820                 // AHCI
8821                 statusByte = UniataAhciSendPIOCommandDirect(
8822                         deviceExtension,
8823                         lChannel,
8824                         DeviceNumber,
8825                         Srb,
8826                         regs,
8827                         ATA_WAIT_INTR,
8828                         to_lim
8829                         );
8830                 if(statusByte == IDE_STATUS_WRONG) {
8831                     goto passthrough_err;
8832                 }
8833                 if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
8834                     UniataAhciAbortOperation(chan);
8835                     goto passthrough_err;
8836                 }
8837                 goto passthrough_done;
8838             }
8839 
8840             // SATA/PATA
8841             if((AtaCommandFlags[regs->bCommandReg] & ATA_CMD_FLAG_DMA) || (regs->bOpFlags & UNIATA_SPTI_EX_USE_DMA)) {
8842                 if((chan->lun[DeviceNumber]->LimitedTransferMode >= ATA_DMA)) {
8843                     use_dma = TRUE;
8844                     // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
8845                     if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
8846                                   (PUCHAR)(Srb->DataBuffer),
8847                                   ((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1)))) {
8848                         use_dma = FALSE;
8849                     }
8850                 }
8851             }
8852 
8853             AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, regs->bDriveHeadReg);
8854             AtapiStallExecution(10);
8855             if(use_dma) {
8856                 AtapiDmaDBPreSync(HwDeviceExtension, chan, Srb);
8857             }
8858 
8859             if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) {      // execute ATA command
8860                 AtapiWritePort1(chan, IDX_IO1_o_Feature,      regs->bFeaturesReg);
8861                 AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   regs->bSectorCountReg);
8862                 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  regs->bSectorNumberReg);
8863                 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow,  regs->bCylLowReg);
8864                 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg);
8865             } else {
8866                 AtapiWritePort1(chan, IDX_IO1_o_Feature,      regs->bFeaturesRegH);
8867                 AtapiWritePort1(chan, IDX_IO1_o_Feature,      regs->bFeaturesReg);
8868                 AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   regs->bSectorCountRegH);
8869                 AtapiWritePort1(chan, IDX_IO1_o_BlockCount,   regs->bSectorCountReg);
8870                 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  regs->bSectorNumberRegH);
8871                 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber,  regs->bSectorNumberReg);
8872                 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow,  regs->bCylLowRegH);
8873                 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow,  regs->bCylLowReg);
8874                 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighRegH);
8875                 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg);
8876             }
8877             AtapiWritePort1(chan, IDX_IO1_o_Command,      regs->bCommandReg);
8878 
8879             if(use_dma) {
8880                 GetBaseStatus(chan, statusByte);
8881                 if(statusByte & IDE_STATUS_ERROR) {
8882                     goto passthrough_err;
8883                 }
8884                 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
8885             }
8886 
8887             ScsiPortStallExecution(1);                  // wait for busy to be set
8888 
8889             for(i=0; i<to_lim;i+=2) {      // 2 msec from WaitOnBaseBusy()
8890                 statusByte = WaitOnBaseBusy(chan);      // wait for busy to be clear, up to 2 msec
8891                 GetBaseStatus(chan, statusByte);
8892                 if(statusByte & IDE_STATUS_ERROR) {
8893                     break;
8894                 }
8895                 if(!(statusByte & IDE_STATUS_BUSY)) {
8896                     break;
8897                 }
8898             }
8899             if(i >= to_lim) {
8900                 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
8901                 //}
8902                 AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_NONE);
8903                 goto passthrough_err;
8904             }
8905 
8906             if(use_dma) {
8907                 AtapiCheckInterrupt__(deviceExtension, (UCHAR)lChannel);
8908             }
8909             AtapiDmaDone(deviceExtension, DeviceNumber, lChannel, NULL);
8910             GetBaseStatus(chan, statusByte);
8911 
8912             if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
8913                 AtapiSuckPort2(chan);
8914 passthrough_err:
8915                 if (Srb->SenseInfoBuffer) {
8916 
8917                     PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
8918 
8919                     senseBuffer->ErrorCode = 0x70;
8920                     senseBuffer->Valid     = 1;
8921                     senseBuffer->AdditionalSenseLength = 0xb;
8922                     senseBuffer->SenseKey =  SCSI_SENSE_ABORTED_COMMAND;
8923                     senseBuffer->AdditionalSenseCode = 0;
8924                     senseBuffer->AdditionalSenseCodeQualifier = 0;
8925 
8926                     Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID;
8927                     Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
8928                 }
8929                 status = SRB_STATUS_ERROR;
8930             } else {
8931 
8932                 if(!use_dma) {
8933                     if (statusByte & IDE_STATUS_DRQ) {
8934                         if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
8935                             ReadBuffer(chan,
8936                                        (PUSHORT) Srb->DataBuffer,
8937                                        Srb->DataTransferLength / 2,
8938                                        0);
8939                         } else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
8940                             WriteBuffer(chan,
8941                                         (PUSHORT) Srb->DataBuffer,
8942                                         Srb->DataTransferLength / 2,
8943                                         0);
8944                         }
8945                     }
8946                 }
8947                 status = SRB_STATUS_SUCCESS;
8948             }
8949 passthrough_done:;
8950             AtapiEnableInterrupts(deviceExtension, lChannel);
8951 
8952         } else { // read task register
8953 
8954             BOOLEAN use48;
8955             regs = (PIDEREGS_EX) Srb->DataBuffer;
8956 
8957             KdPrint2((PRINT_PREFIX
8958                        "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
8959                        Srb->PathId, Srb->Lun, Srb->TargetId));
8960 
8961             if((Srb->DataTransferLength >= sizeof(IDEREGS_EX)) &&
8962                (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND)) {
8963                 use48 = TRUE;
8964             } else
8965             if(Srb->DataTransferLength >= sizeof(IDEREGS)) {
8966                 use48 = FALSE;
8967             } else {
8968                 KdPrint2((PRINT_PREFIX " buffer too small \n"));
8969                 status = SRB_STATUS_DATA_OVERRUN;
8970                 break;
8971             }
8972             RtlZeroMemory(regs, use48 ? sizeof(IDEREGS_EX) : sizeof(IDEREGS));
8973             regs->bOpFlags = use48 ? ATA_FLAGS_48BIT_COMMAND : 0;
8974             UniataSnapAtaRegs(chan, 0, regs);
8975 
8976             status = SRB_STATUS_SUCCESS;
8977         }
8978         break;
8979     }
8980 
8981     default:
8982 default_abort:
8983         KdPrint2((PRINT_PREFIX
8984                    "IdeSendCommand: Unsupported command %#x\n",
8985                    Srb->Cdb[0]));
8986 
8987         status = SRB_STATUS_INVALID_REQUEST;
8988 
8989     } // end switch
8990 
8991     if(status == SRB_STATUS_PENDING) {
8992         KdPrint2((PRINT_PREFIX "IdeSendCommand: SRB_STATUS_PENDING\n"));
8993         if(CmdAction & CMD_ACTION_EXEC) {
8994             KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
8995             AtaReq->ReqState = REQ_STATE_EXPECTING_INTR;
8996         }
8997     } else {
8998         KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
8999         AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
9000     }
9001 
9002     return status;
9003 
9004 } // end IdeSendCommand()
9005 
9006 
9007 /*++
9008 
9009 Routine Description:
9010     Enables disables media status notification
9011 
9012 Arguments:
9013     HwDeviceExtension - ATAPI driver storage.
9014 
9015 --*/
9016 VOID
9017 NTAPI
9018 IdeMediaStatus(
9019     BOOLEAN EnableMSN,
9020     IN PVOID HwDeviceExtension,
9021     IN ULONG lChannel,
9022     IN ULONG DeviceNumber
9023     )
9024 {
9025     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
9026     PHW_CHANNEL          chan;
9027     UCHAR statusByte,errorByte;
9028 
9029     chan = &(deviceExtension->chan[lChannel]);
9030     SelectDrive(chan, DeviceNumber);
9031 
9032     if (EnableMSN == TRUE){
9033 
9034         // If supported enable Media Status Notification support
9035         if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_REMOVABLE_DRIVE)) {
9036 
9037             // enable
9038             statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
9039                                 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
9040                                 0, ATA_C_F_ENAB_MEDIASTAT, ATA_WAIT_BASE_READY);
9041 
9042             if (statusByte & IDE_STATUS_ERROR) {
9043                 // Read the error register.
9044                 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
9045 
9046                 KdPrint2((PRINT_PREFIX
9047                             "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
9048                              statusByte,
9049                              errorByte));
9050             } else {
9051                 chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_MEDIA_STATUS_ENABLED;
9052                 KdPrint2((PRINT_PREFIX "IdeMediaStatus: Media Status Notification Supported\n"));
9053                 chan->ReturningMediaStatus = 0;
9054 
9055             }
9056 
9057         }
9058     } else { // end if EnableMSN == TRUE
9059 
9060         // disable if previously enabled
9061         if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)) {
9062 
9063             statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
9064                                 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
9065                                 0, ATA_C_F_DIS_MEDIASTAT, ATA_WAIT_BASE_READY);
9066             chan->lun[DeviceNumber]->DeviceFlags &= ~DFLAGS_MEDIA_STATUS_ENABLED;
9067         }
9068 
9069 
9070     }
9071 
9072 
9073 } // end IdeMediaStatus()
9074 
9075 
9076 /*++
9077 
9078 Routine Description:
9079 
9080     Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
9081     command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
9082 Arguments:
9083 
9084     HwDeviceExtension - ATAPI driver storage.
9085     Srb - System request block.
9086 
9087 Return Value:
9088 
9089     SRB status (ALWAYS SUCCESS).
9090 
9091 --*/
9092 ULONG
9093 NTAPI
9094 IdeBuildSenseBuffer(
9095     IN PVOID HwDeviceExtension,
9096     IN PSCSI_REQUEST_BLOCK Srb
9097     )
9098 {
9099     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
9100 //    ULONG status;
9101     PSENSE_DATA  senseBuffer = (PSENSE_DATA)Srb->DataBuffer;
9102     UCHAR ReturningMediaStatus = deviceExtension->chan[GET_CHANNEL(Srb)].ReturningMediaStatus;
9103 
9104     if (senseBuffer){
9105 
9106         if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE) {
9107 
9108             senseBuffer->ErrorCode = 0x70;
9109             senseBuffer->Valid     = 1;
9110             senseBuffer->AdditionalSenseLength = 0xb;
9111             senseBuffer->SenseKey =  SCSI_SENSE_UNIT_ATTENTION;
9112             senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
9113             senseBuffer->AdditionalSenseCodeQualifier = 0;
9114         } else if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE_REQ) {
9115 
9116             senseBuffer->ErrorCode = 0x70;
9117             senseBuffer->Valid     = 1;
9118             senseBuffer->AdditionalSenseLength = 0xb;
9119             senseBuffer->SenseKey =  SCSI_SENSE_UNIT_ATTENTION;
9120             senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
9121             senseBuffer->AdditionalSenseCodeQualifier = 0;
9122         } else if(ReturningMediaStatus & IDE_ERROR_END_OF_MEDIA) {
9123 
9124             senseBuffer->ErrorCode = 0x70;
9125             senseBuffer->Valid     = 1;
9126             senseBuffer->AdditionalSenseLength = 0xb;
9127             senseBuffer->SenseKey =  SCSI_SENSE_NOT_READY;
9128             senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
9129             senseBuffer->AdditionalSenseCodeQualifier = 0;
9130         } else if(ReturningMediaStatus & IDE_ERROR_DATA_ERROR) {
9131 
9132             senseBuffer->ErrorCode = 0x70;
9133             senseBuffer->Valid     = 1;
9134             senseBuffer->AdditionalSenseLength = 0xb;
9135             senseBuffer->SenseKey =  SCSI_SENSE_DATA_PROTECT;
9136             senseBuffer->AdditionalSenseCode = 0;
9137             senseBuffer->AdditionalSenseCodeQualifier = 0;
9138         }
9139         return SRB_STATUS_SUCCESS;
9140     }
9141     return SRB_STATUS_ERROR;
9142 
9143 }// End of IdeBuildSenseBuffer
9144 
9145 VOID
9146 NTAPI
9147 UniataUserDeviceReset(
9148     PHW_DEVICE_EXTENSION deviceExtension,
9149     PHW_LU_EXTENSION LunExt,
9150     ULONG lChannel
9151     )
9152 {
9153     ULONG i;
9154     AtapiDisableInterrupts(deviceExtension, lChannel);
9155     if ((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
9156         (LunExt->PowerState != StartStop_Power_Sleep)) {
9157         KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset ATAPI\n"));
9158         AtapiSoftReset(&(deviceExtension->chan[lChannel]), LunExt->Lun);
9159     } else {
9160         KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
9161         AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_NONE);
9162         for(i=0; i<deviceExtension->NumberLuns; i++) {
9163             deviceExtension->chan[lChannel].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
9164         }
9165     }
9166     LunExt->DeviceFlags |= DFLAGS_REINIT_DMA;  // force PIO/DMA reinit
9167     AtapiEnableInterrupts(deviceExtension, lChannel);
9168     return;
9169 } // end UniataUserDeviceReset()
9170 
9171 BOOLEAN
9172 NTAPI
9173 UniataNeedQueueing(
9174     PHW_DEVICE_EXTENSION deviceExtension,
9175     PHW_CHANNEL          chan,
9176     BOOLEAN              TopLevel
9177     )
9178 {
9179     BOOLEAN PostReq = FALSE;
9180     if(TopLevel) {
9181         KdPrint3((PRINT_PREFIX "UniataNeedQueueing: TopLevel, qd=%x\n", chan->queue_depth));
9182         if(chan->queue_depth > 0) {
9183 #if 0
9184             if(atapiDev &&
9185                ((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY)/* ||
9186                 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
9187                 KdPrint2((PRINT_PREFIX "spec: SCSIOP_TEST_UNIT_READY\n"));
9188                 //PostReq = FALSE;
9189                 status = SRB_STATUS_BUSY;
9190                 goto skip_exec;
9191             } else {
9192                 PostReq = TRUE;
9193             }
9194 #else
9195             PostReq = TRUE;
9196 #endif
9197         } else
9198         if(deviceExtension->simplexOnly && deviceExtension->queue_depth > 0) {
9199             PostReq = TRUE;
9200         }
9201     } else {
9202         KdPrint3((PRINT_PREFIX "UniataNeedQueueing: qd=%x\n", chan->queue_depth));
9203     }
9204     return PostReq;
9205 } // end UniataNeedQueueing()
9206 
9207 /*++
9208 
9209 Routine Description:
9210 
9211     This routine is called from the SCSI port driver synchronized
9212     with the kernel to start an IO request.
9213     ->HwStartIo
9214 
9215 Arguments:
9216 
9217     HwDeviceExtension - HBA miniport driver's adapter data storage
9218     Srb - IO request packet
9219 
9220 Return Value:
9221 
9222     TRUE
9223 
9224 --*/
9225 BOOLEAN
9226 NTAPI
9227 AtapiStartIo(
9228     IN PVOID HwDeviceExtension,
9229     IN PSCSI_REQUEST_BLOCK Srb
9230     )
9231 {
9232     return AtapiStartIo__(HwDeviceExtension, Srb, TRUE);
9233 } // end AtapiStartIo()
9234 
9235 BOOLEAN
9236 NTAPI
9237 AtapiStartIo__(
9238     IN PVOID HwDeviceExtension,
9239     IN PSCSI_REQUEST_BLOCK Srb,
9240     IN BOOLEAN TopLevel
9241     )
9242 {
9243     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
9244     UCHAR                lChannel;
9245     PHW_CHANNEL          chan;
9246     PHW_LU_EXTENSION     LunExt;
9247     ULONG status;
9248     //ULONG ldev;
9249     ULONG DeviceNumber;
9250     UCHAR PathId;
9251     UCHAR TargetId;
9252     UCHAR Lun;
9253     PATA_REQ AtaReq;
9254     PSCSI_REQUEST_BLOCK tmpSrb;
9255     BOOLEAN PostReq = FALSE;
9256     BOOLEAN atapiDev;
9257     BOOLEAN commPort = FALSE;
9258 
9259     // deviceExtension->Isr2DevObj must always be NULL for non-PCI
9260     if(deviceExtension->Isr2DevObj && !BMList[deviceExtension->DevIndex].Isr2Enable) {
9261         KdPrint2((PRINT_PREFIX "Isr2Enable -> 1\n"));
9262         BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
9263     }
9264 //    deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
9265 
9266 /*                KeBugCheckEx(0xc000000e,
9267                              (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
9268                              Srb->Function,
9269                              TopLevel, 0x80000001);
9270 */
9271     if(TopLevel && Srb && Srb->SrbExtension) {
9272         KdPrint2((PRINT_PREFIX "TopLevel\n"));
9273         //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
9274         UniAtaClearAtaReq(Srb->SrbExtension);
9275     }
9276 
9277     do { // fetch all queued commands for the channel (if valid)
9278 
9279         lChannel = GET_CHANNEL(Srb);
9280         //ldev = GET_LDEV(Srb);
9281         chan = NULL;
9282         LunExt = NULL;
9283         DeviceNumber = GET_CDEV(Srb);
9284         commPort = FALSE;
9285 
9286         //ASSERT(deviceExtension);
9287         //ASSERT(chan);
9288 
9289         KdPrint2((PRINT_PREFIX
9290                    "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
9291                    Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId));
9292         KdPrint2((PRINT_PREFIX "   DeviceID+VendorID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
9293 
9294         if(lChannel == deviceExtension->NumberChannels &&
9295            !Srb->Lun && !Srb->TargetId &&
9296            ((Srb->Function == SRB_FUNCTION_IO_CONTROL) ||
9297             (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI && Srb->Cdb[0] == SCSIOP_INQUIRY))
9298            ) {
9299             // This is our virtual device
9300             KdPrint2((PRINT_PREFIX
9301                        "AtapiStartIo: Communication port\n"));
9302             if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
9303 
9304                 if(Srb->DataTransferLength < sizeof(PINQUIRYDATA)) {
9305                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", Srb->DataTransferLength,
9306                         sizeof(PINQUIRYDATA) ));
9307 wrong_buffer_size:
9308                     status = SRB_STATUS_DATA_OVERRUN;
9309                     goto complete_req;
9310                 }
9311 
9312                 PINQUIRYDATA    inquiryData  = (PINQUIRYDATA)(Srb->DataBuffer);
9313 
9314                 KdPrint2((PRINT_PREFIX
9315                            "  INQUIRY\n"));
9316                 // Zero INQUIRY data structure.
9317                 RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength);
9318 
9319                 inquiryData->DeviceType = COMMUNICATION_DEVICE;
9320 
9321                 // Fill in vendor identification fields.
9322                 RtlCopyMemory(&inquiryData->VendorId, &uniata_comm_name, 28);
9323 
9324                 status = SRB_STATUS_SUCCESS;
9325                 goto complete_req;
9326             }
9327             commPort = TRUE;
9328             /* Pass IOCTL request down */
9329         } else
9330         if(lChannel >= deviceExtension->NumberChannels ||
9331             Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns ||
9332             Srb->Lun) {
9333 
9334             if(lChannel >= deviceExtension->NumberChannels) {
9335                 chan = NULL;
9336             }
9337 
9338 reject_srb:
9339             //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
9340             KdPrint3((PRINT_PREFIX
9341                            "AtapiStartIo: SRB rejected\n"));
9342             // Indicate no device found at this address.
9343             KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
9344             status = SRB_STATUS_SELECTION_TIMEOUT;
9345             goto complete_req;
9346             //}
9347         } else
9348         if((deviceExtension->HwFlags & UNIATA_AHCI) &&
9349            !UniataAhciChanImplemented(deviceExtension, lChannel)) {
9350             chan = NULL;
9351         }
9352 
9353         if(!commPort) {
9354             chan = &(deviceExtension->chan[lChannel]);
9355             LunExt = chan->lun[DeviceNumber];
9356             if(!LunExt) {
9357                 goto reject_srb;
9358             }
9359             atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
9360         } else {
9361             atapiDev = FALSE;
9362         }
9363 
9364 #ifdef _DEBUG
9365         if(!commPort && !LunExt) {
9366 #if 0
9367             PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
9368                 deviceExtension,
9369                 chan, DeviceNumber,
9370                 deviceExtension->NumberChannels);
9371             PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
9372                 lChannel, GET_CDEV(Srb), deviceExtension->chan[0].lun[0]);
9373             PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
9374                        Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId);
9375 #endif //0
9376 /*
9377             int i;
9378             for(i=0; i<1000; i++) {
9379                 AtapiStallExecution(3*1000);
9380             }
9381 */
9382             goto reject_srb;
9383         }
9384 #endif //_DEBUG
9385 
9386         // Determine which function.
9387         switch (Srb->Function) {
9388 
9389         case SRB_FUNCTION_EXECUTE_SCSI:
9390 
9391             if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
9392                 if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) {
9393                     // let passthrough go
9394                 } else
9395                 if(Srb->Cdb[0] == SCSIOP_INQUIRY) {
9396                     // let INQUIRY go
9397                 } else {
9398 
9399                 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
9400                     KdPrint2((PRINT_PREFIX
9401                                "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
9402                     // Indicate no device found at this address.
9403                     KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
9404                     status = SRB_STATUS_SELECTION_TIMEOUT;
9405                     break;
9406                 //}
9407                 }
9408             } else {
9409                 KdPrint2((PRINT_PREFIX
9410                            "  SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb, &(Srb->Cdb), Srb->SrbExtension, Srb->Cdb[0]));
9411             }
9412 /*
9413             __try {
9414                 if(Srb->DataTransferLength) {
9415                     UCHAR a;
9416                     a = ((PUCHAR)(Srb->DataBuffer))[0];
9417                     g_foo += a;
9418                 }
9419             } __except(EXCEPTION_EXECUTE_HANDLER) {
9420                 KdPrint3((PRINT_PREFIX
9421                            "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
9422                 // Indicate no device found at this address.
9423                 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
9424                 status = SRB_STATUS_ERROR;
9425                 KdPrint2((PRINT_PREFIX "  *** Exception...\n"));
9426                 ASSERT(FALSE);
9427                 break;
9428             }
9429 */
9430             PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
9431 
9432             if(PostReq) {
9433 
9434                 KdPrint3((PRINT_PREFIX "Non-empty queue\n"));
9435                 if (atapiDev &&
9436                     (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) {
9437                     KdPrint3((PRINT_PREFIX "Try ATAPI prepare\n"));
9438 
9439                     status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE);
9440                 } else {
9441                     KdPrint2((PRINT_PREFIX "Try IDE prepare\n"));
9442                     status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE);
9443                 }
9444                 /*KeBugCheckEx(0xc000000e,
9445                              (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
9446                              Srb->Function,
9447                              status, 0x80000001);*/
9448                 if(status == SRB_STATUS_BUSY)
9449                     status = SRB_STATUS_PENDING;
9450                 // Insert requests AFTER they have been initialized on
9451                 // CMD_ACTION_PREPARE stage
9452                 // we should not check TopLevel here (it is always TRUE)
9453                 //ASSERT(chan->lun[GET_CDEV(Srb)]);
9454                 UniataQueueRequest(chan, Srb);
9455 
9456                 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
9457 
9458             } else {
9459 
9460                 // Send command to device.
9461                 KdPrint2((PRINT_PREFIX "Send to device %x\n", Srb->Cdb[0]));
9462                 if(TopLevel) {
9463                     KdPrint2((PRINT_PREFIX "TopLevel (2), srb %#x\n", Srb));
9464                     AtaReq = (PATA_REQ)(Srb->SrbExtension);
9465                     KdPrint2((PRINT_PREFIX "TopLevel (3), AtaReq %#x\n", AtaReq));
9466                     //ASSERT(!AtaReq->Flags);
9467                     //ASSERT(chan->lun[GET_CDEV(Srb)]);
9468                     UniataQueueRequest(chan, Srb);
9469 //                    AtaReq = (PATA_REQ)(Srb->SrbExtension);
9470                     //ASSERT(!AtaReq->Flags);
9471                     AtaReq->ReqState = REQ_STATE_QUEUED;
9472                     //ASSERT(!AtaReq->Flags);
9473                 }
9474 
9475 #ifndef NAVO_TEST
9476                 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
9477                     if(!LunExt) {
9478                         goto reject_srb;
9479                     }
9480                     if(Srb->Cdb[0] == SCSIOP_INQUIRY) {
9481                         if(UniataAnybodyHome(deviceExtension, chan->lChannel, DeviceNumber)) {
9482                             if(!CheckDevice(HwDeviceExtension, chan->lChannel, DeviceNumber, TRUE)) {
9483                                 goto reject_srb;
9484                             }
9485                         }
9486                         if(!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
9487                             goto reject_srb;
9488                         }
9489                     } else
9490                     if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) {
9491                         // allow
9492                     } else {
9493                         goto reject_srb;
9494                     }
9495                 }
9496 #endif //NAVO_TEST
9497 
9498                 if(atapiDev &&
9499                    (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)/* &&
9500                    (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
9501                     KdPrint3((PRINT_PREFIX "Try ATAPI send %x\n", Srb->Cdb[0]));
9502                     status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
9503                 } else {
9504                     KdPrint2((PRINT_PREFIX "Try IDE send\n"));
9505 /*                    {
9506                         ULONG __ebp__ = 0;
9507                         ULONG __esp__ = 0;
9508 
9509                         KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
9510                         __asm {
9511                             mov eax,ebp
9512                             mov __ebp__, eax
9513                             mov eax,esp
9514                             mov __esp__, eax
9515                         }
9516                         KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
9517                     }*/
9518                     status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
9519                 }
9520 /*                KeBugCheckEx(0xc000000e,
9521                              (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
9522                              Srb->Function,
9523                              status, 0x80000002);*/
9524 
9525             }
9526 //skip_exec:
9527             TopLevel = FALSE;
9528 
9529             break;
9530 
9531         case SRB_FUNCTION_ABORT_COMMAND:
9532 
9533             tmpSrb = ScsiPortGetSrb(HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun,
9534                                Srb->QueueTag);
9535             // Verify that SRB to abort is still outstanding.
9536             if((tmpSrb != Srb->NextSrb) ||
9537                !chan->queue_depth) {
9538 
9539                 KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB to abort already completed\n"));
9540 
9541                 // Complete abort SRB.
9542                 status = SRB_STATUS_ABORT_FAILED;
9543                 break;
9544             }
9545 
9546             AtaReq = (PATA_REQ)(tmpSrb->SrbExtension);
9547             if(AtaReq->ReqState > REQ_STATE_READY_TO_TRANSFER) {
9548                 if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_CURRENT)) {
9549                       KdPrint2((PRINT_PREFIX "AtapiStartIo: Abort command failed\n"));
9550                     // Log reset failure.
9551                     KdPrint3((PRINT_PREFIX
9552                                 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
9553                                       HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
9554                                 ));
9555                     ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8);
9556                     status = SRB_STATUS_ERROR;
9557 
9558                 } else {
9559                     status = SRB_STATUS_SUCCESS;
9560                 }
9561             } else {
9562                 KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove aborted srb %#x\n", tmpSrb));
9563                 if (tmpSrb->SenseInfoBuffer &&
9564                     tmpSrb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) {
9565 
9566                     PSENSE_DATA  senseBuffer = (PSENSE_DATA)tmpSrb->SenseInfoBuffer;
9567 
9568                     senseBuffer->ErrorCode = 0;
9569                     senseBuffer->Valid     = 1;
9570                     senseBuffer->AdditionalSenseLength = 0xb;
9571                     senseBuffer->SenseKey =  SCSI_SENSE_ABORTED_COMMAND;
9572                     senseBuffer->AdditionalSenseCode = 0;
9573                     senseBuffer->AdditionalSenseCodeQualifier = 0;
9574 
9575                     tmpSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
9576                 }
9577                 AtapiDmaDBSync(chan, tmpSrb);
9578                 UniataRemoveRequest(chan, tmpSrb);
9579                 // Indicate command complete.
9580                 ScsiPortNotification(RequestComplete,
9581                                      deviceExtension,
9582                                      tmpSrb);
9583                 status = SRB_STATUS_SUCCESS;
9584             }
9585             break;
9586 
9587             // Abort function indicates that a request timed out.
9588             // Call reset routine. Card will only be reset if
9589             // status indicates something is wrong.
9590             // Fall through to reset code.
9591 
9592         case SRB_FUNCTION_RESET_DEVICE:
9593         case SRB_FUNCTION_RESET_LOGICAL_UNIT:
9594 
9595             // Reset single device.
9596             // For now we support only Lun=0
9597 
9598             // Note: reset is immediate command, it cannot be queued since it is usually used to
9599             // revert not-responding device to operational state
9600             KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device request received\n"));
9601             UniataUserDeviceReset(deviceExtension, LunExt, lChannel);
9602             status = SRB_STATUS_SUCCESS;
9603             break;
9604 
9605         case SRB_FUNCTION_RESET_BUS:
9606 do_bus_reset:
9607             // Reset Atapi and SCSI bus.
9608 
9609             // Note: reset is immediate command, it cannot be queued since it is usually used to
9610             // revert not- responding device to operational state
9611             KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus request received\n"));
9612             if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_ALL)) {
9613                   KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus failed\n"));
9614                 // Log reset failure.
9615                 KdPrint3((PRINT_PREFIX
9616                             "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
9617                                   HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
9618                             ));
9619                 ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8);
9620                 status = SRB_STATUS_ERROR;
9621 
9622             } else {
9623                 status = SRB_STATUS_SUCCESS;
9624             }
9625 
9626             break;
9627 
9628         case SRB_FUNCTION_SHUTDOWN:
9629 
9630             KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown\n"));
9631             if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
9632                 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - no such device\n"));
9633             } else
9634             if(atapiDev) {
9635                 // FLUSH ATAPI device - do nothing
9636                 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - ATAPI device\n"));
9637             } else {
9638                 // FLUSH IDE/ATA device
9639                 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - IDE device\n"));
9640                 AtapiDisableInterrupts(deviceExtension, lChannel);
9641                 status = AtaCommand(deviceExtension, DeviceNumber, GET_CHANNEL(Srb),
9642                            IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_IDLE);
9643                 // If supported & allowed, reset write cacheing
9644                 if(LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) {
9645 
9646                     // Disable write cache
9647                     status = AtaCommand(deviceExtension, DeviceNumber, lChannel,
9648                                         IDE_COMMAND_SET_FEATURES, 0, 0, 0,
9649                                         0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY);
9650                     // Check for errors.
9651                     if (status & IDE_STATUS_ERROR) {
9652                         KdPrint2((PRINT_PREFIX
9653                                     "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
9654                                     DeviceNumber));
9655                     }
9656                     LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
9657 
9658                     // Re-enable write cache
9659                     status = AtaCommand(deviceExtension, DeviceNumber, lChannel,
9660                                         IDE_COMMAND_SET_FEATURES, 0, 0, 0,
9661                                         0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
9662                     // Check for errors.
9663                     if (status & IDE_STATUS_ERROR) {
9664                         KdPrint2((PRINT_PREFIX
9665                                     "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
9666                                     DeviceNumber));
9667                         LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
9668                     } else {
9669                         LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED;
9670                     }
9671                 }
9672 
9673                 AtapiEnableInterrupts(deviceExtension, lChannel);
9674             }
9675             status = SRB_STATUS_SUCCESS;
9676 
9677             break;
9678 
9679         case SRB_FUNCTION_FLUSH:
9680 
9681             KdPrint2((PRINT_PREFIX "AtapiStartIo: Flush (do nothing)\n"));
9682             status = SRB_STATUS_SUCCESS;
9683             break;
9684 
9685         case SRB_FUNCTION_IO_CONTROL: {
9686 
9687             ULONG len;
9688 
9689             KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
9690 
9691             len = Srb->DataTransferLength;
9692 
9693             if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
9694 
9695                 ULONG targetId = (ULONG)(-1);
9696 
9697                 if(len < sizeof(SRB_IO_CONTROL)) {
9698                     goto wrong_buffer_size;
9699                 }
9700 
9701                 // extract bogus bus address
9702                 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
9703                 case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
9704                     PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9705 
9706                     if(len < sizeof(SRB_IO_CONTROL)+sizeof(GETVERSIONINPARAMS)) {
9707                         goto wrong_buffer_size;
9708                     }
9709 
9710                     targetId = versionParameters->bIDEDeviceMap;
9711                     KdPrint2((PRINT_PREFIX "targetId (smart ver) %d\n", targetId));
9712                     break; }
9713                 case IOCTL_SCSI_MINIPORT_IDENTIFY:
9714                 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9715                 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9716                 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9717                 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9718                 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9719                 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9720                 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9721                 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9722                 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE:
9723                 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG:
9724                 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG:
9725                     {
9726                     PSENDCMDINPARAMS   cmdInParameters = (PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9727 
9728                     if(len < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDINPARAMS) - 1) {
9729                         goto wrong_buffer_size;
9730                     }
9731 
9732                     targetId = cmdInParameters->bDriveNumber;
9733                     KdPrint2((PRINT_PREFIX "targetId (smart/ident) %d\n", targetId));
9734                     break; }
9735                 default:
9736 invalid_request:
9737                     KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9738                                 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9739                     status = SRB_STATUS_INVALID_REQUEST;
9740                     goto complete_req;
9741                 } // end switch()
9742 
9743                 // adjust (if necessary) bus address
9744                 if(targetId != (ULONG)(-1)) {
9745 
9746                     // This is done because of how the IOCTL_SCSI_MINIPORT
9747                     // determines 'targetid's'. Disk.sys places the real target id value
9748                     // in the DeviceMap field. Once we do some parameter checking, the value passed
9749                     // back to the application will be determined.
9750 
9751                     if (deviceExtension->NumberChannels == 1) {
9752                         // do this for legacy controllers and legacy callers
9753                         KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call\n"));
9754                         DeviceNumber = (targetId & 0x01);
9755                         lChannel = 0;
9756                     } else
9757                     if(commPort) {
9758                         // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
9759                         // due to DISK.SYS design bug, we have invalid SCSI address in SRB
9760                         KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call (2)\n"));
9761                         if(deviceExtension->HwFlags & UNIATA_AHCI) {
9762                             lChannel = (UCHAR)targetId / 2;
9763                             DeviceNumber = 0;
9764                         } else {
9765                             lChannel = (UCHAR)(targetId / 2);
9766                             DeviceNumber = targetId & 0x01;
9767                         }
9768                     } else {
9769                         // otherwise assume lChannel and DeviceNumber from Srb are ok
9770                     }
9771                     if(lChannel >= deviceExtension->NumberChannels ||
9772                         DeviceNumber >= deviceExtension->NumberLuns) {
9773                         KdPrint2((PRINT_PREFIX
9774                                    "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
9775                                        targetId));
9776                         // Indicate no device found at this address.
9777                         goto reject_srb;
9778                     }
9779                     targetId = lChannel*deviceExtension->NumberLuns+DeviceNumber;
9780                     chan = &(deviceExtension->chan[lChannel]);
9781                     LunExt = chan->lun[DeviceNumber];
9782                     if(!LunExt) {
9783                         goto reject_srb;
9784                     }
9785                     atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
9786 
9787                     if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
9788                         goto reject_srb;
9789                     }
9790                 }
9791 
9792                 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
9793                 case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
9794 
9795                     PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9796                     UCHAR deviceNumberMap;
9797 
9798                     KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
9799 
9800                     // Version and revision per SMART 1.03
9801 
9802                     versionParameters->bVersion = 1;
9803                     versionParameters->bRevision = 1;
9804                     versionParameters->bReserved = 0;
9805 
9806                     // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
9807                     versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD);
9808 
9809                     if (atapiDev) {
9810                         goto invalid_request;
9811                     }
9812 
9813                     // NOTE: This will only set the bit
9814                     // corresponding to this drive's target id.
9815                     // The bit mask is as follows:
9816                     //
9817                     //     -Sec Pri
9818                     //     S M S M
9819                     //     3 2 1 0
9820 
9821                     if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
9822                         deviceNumberMap = 1 << lChannel;
9823                         DeviceNumber = 0;
9824                     } else
9825                     if (deviceExtension->NumberChannels == 1) {
9826                         if (chan->PrimaryAddress) {
9827                             deviceNumberMap = 1 << DeviceNumber;
9828                         } else {
9829                             deviceNumberMap = 4 << DeviceNumber;
9830                         }
9831                     } else {
9832                         deviceNumberMap = 1 << (DeviceNumber+lChannel*2);
9833                     }
9834 
9835                     versionParameters->bIDEDeviceMap = deviceNumberMap;
9836 
9837                     status = SRB_STATUS_SUCCESS;
9838                     break;
9839                 }
9840 
9841                 case IOCTL_SCSI_MINIPORT_IDENTIFY: {
9842 
9843                     PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9844                     SENDCMDINPARAMS   cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9845 
9846                     KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
9847                     // Extract the target.
9848                     KdPrint2((PRINT_PREFIX "targetId %d\n", targetId));
9849 
9850                     switch(cmdInParameters.irDriveRegs.bCommandReg) {
9851                     case ID_CMD:
9852                         if(atapiDev) {
9853                             KdPrint2((PRINT_PREFIX "Error: ID_CMD for ATAPI\n"));
9854                             goto invalid_request;
9855                         }
9856                         /* FALL THROUGH */
9857                     case ATAPI_ID_CMD:
9858 
9859                         if(!atapiDev &&
9860                            (cmdInParameters.irDriveRegs.bCommandReg == ATAPI_ID_CMD)) {
9861                             KdPrint2((PRINT_PREFIX "Error: ATAPI_ID_CMD for non-ATAPI\n"));
9862                             goto invalid_request;
9863                         }
9864 
9865                         len = min(len, sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE);
9866                         // Zero the output buffer
9867                         RtlZeroMemory(cmdOutParameters, len);
9868 /*                        for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
9869                             ((PUCHAR)cmdOutParameters)[i] = 0;
9870                         }*/
9871 
9872                         // Build status block.
9873                         cmdOutParameters->cBufferSize = min(IDENTIFY_BUFFER_SIZE, len - sizeof(SENDCMDOUTPARAMS) + 1);
9874                         cmdOutParameters->DriverStatus.bDriverError = 0;
9875                         cmdOutParameters->DriverStatus.bIDEError = 0;
9876 
9877                         // Extract the identify data from the device extension.
9878                         ScsiPortMoveMemory (cmdOutParameters->bBuffer, &(LunExt->IdentifyData),
9879                             cmdOutParameters->cBufferSize);
9880 
9881                         if((cmdOutParameters->cBufferSize == IDENTIFY_BUFFER_SIZE) &&
9882                            (LunExt->IdentifyData.ChecksumValid == ATA_ChecksumValid)) {
9883                             // adjust checksum if it is possible
9884                             CHAR csum = 0;
9885                             ULONG i;
9886 
9887                             for(i=0; i < IDENTIFY_BUFFER_SIZE-1; i++) {
9888                                 csum += (CHAR)(cmdOutParameters->bBuffer[i]);
9889                             }
9890                             cmdOutParameters->bBuffer[i] = -csum;
9891                             KdPrint2((PRINT_PREFIX "AtapiStartIo: adjust checksum %d\n"));
9892                         }
9893                         KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
9894 
9895                         status = SRB_STATUS_SUCCESS;
9896 
9897                         break;
9898                     default:
9899                         KdPrint2((PRINT_PREFIX "AtapiStartIo: not supported ID code %x\n",
9900                             cmdInParameters.irDriveRegs.bCommandReg));
9901                         status = SRB_STATUS_INVALID_REQUEST;
9902                         break;
9903                     }
9904                     break;
9905                 }
9906 /*
9907                 case  IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9908                 case  IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9909                 case  IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9910                 case  IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9911                 case  IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9912                 case  IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9913                 case  IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9914                 case  IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9915 */
9916                 default:
9917                     // *all* IOCTLs here are SMART
9918                     if(commPort) {
9919                         KdPrint2((PRINT_PREFIX
9920                                    "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
9921                     }
9922                     if (atapiDev) {
9923                         goto invalid_request;
9924                     }
9925 
9926                     PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
9927 
9928                     if(PostReq || TopLevel) {
9929                         UniataQueueRequest(chan, Srb);
9930                         AtaReq = (PATA_REQ)(Srb->SrbExtension);
9931                         AtaReq->ReqState = REQ_STATE_QUEUED;
9932                     }
9933 
9934                     if(PostReq) {
9935 
9936                         KdPrint2((PRINT_PREFIX "Non-empty queue (SMART)\n"));
9937                         status = SRB_STATUS_PENDING;
9938 
9939                         KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
9940                     } else {
9941 
9942                         status = IdeSendSmartCommand(HwDeviceExtension, Srb, targetId);
9943                     }
9944                     break;
9945 
9946                 // we should not get here, checked above
9947 /*                default :
9948                     KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9949                                 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9950                     status = SRB_STATUS_INVALID_REQUEST;
9951                     break;
9952 */
9953                 }
9954             } else
9955             if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"-UNIATA-", sizeof("-UNIATA-")-1)) {
9956 
9957                 PUNIATA_CTL AtaCtl = (PUNIATA_CTL)(Srb->DataBuffer);
9958                 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
9959                 ULONG DeviceNumber = AtaCtl->addr.TargetId;
9960                 BOOLEAN bad_ldev;
9961                 ULONG i, pos;
9962 
9963                 pos = FIELD_OFFSET(UNIATA_CTL, RawData);
9964                 //chan = &(deviceExtension->chan[lChannel]);
9965                 if(len < pos) {
9966                     KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9967                         FIELD_OFFSET(UNIATA_CTL, RawData) ));
9968                     goto wrong_buffer_size;
9969                 }
9970 
9971                 if(AtaCtl->addr.Lun ||
9972                    AtaCtl->addr.TargetId >= deviceExtension->NumberLuns ||
9973                    AtaCtl->addr.PathId >= deviceExtension->NumberChannels) {
9974 
9975                     chan = NULL;
9976                     bad_ldev = TRUE;
9977                     LunExt = NULL;
9978 
9979                 } else {
9980                     bad_ldev = FALSE;
9981                     lChannel = AtaCtl->addr.PathId;
9982                     chan = &(deviceExtension->chan[lChannel]);
9983                     LunExt = chan->lun[DeviceNumber];
9984                 }
9985 
9986                 KdPrint2((PRINT_PREFIX "AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl->hdr.ControlCode, DeviceNumber));
9987 
9988                 /* check for valid LUN */
9989                 switch (AtaCtl->hdr.ControlCode) {
9990                 case  IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
9991                 case  IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE:
9992                     // this would be BUS reset
9993                     if(bad_ldev &&
9994                        (AtaCtl->addr.PathId >= deviceExtension->NumberChannels ||
9995                         AtaCtl->addr.TargetId != 0xff ||
9996                         AtaCtl->addr.Lun != 0
9997                         )) {
9998                         if(AtaCtl->hdr.ControlCode == IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES &&
9999                            DeviceNumber < deviceExtension->NumberLuns) { // AtaCtl->addr.TargetId != 0xff
10000                             lChannel = AtaCtl->addr.PathId;
10001                             chan = &(deviceExtension->chan[lChannel]);
10002                             LunExt = chan->lun[DeviceNumber];
10003                             // OK
10004                         } else {
10005                             goto handle_bad_ldev;
10006                         }
10007                     } else {
10008                         lChannel = AtaCtl->addr.PathId;
10009                         chan = &(deviceExtension->chan[lChannel]);
10010                     }
10011                     break;
10012                 case  IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE:
10013                 case  IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
10014                 case  IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE:
10015                 case  IOCTL_SCSI_MINIPORT_UNIATA_RESETBB:
10016 //                case  IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
10017                     if(bad_ldev) {
10018 handle_bad_ldev:
10019                         KdPrint2((PRINT_PREFIX
10020                                    "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
10021                         // Indicate no device found at this address.
10022                         goto reject_srb;
10023                     }
10024                 }
10025 
10026                 /* check if queueing is necessary */
10027                 switch (AtaCtl->hdr.ControlCode) {
10028                 case  IOCTL_SCSI_MINIPORT_UNIATA_RESETBB:
10029                     if(!LunExt->nBadBlocks) {
10030                         break;
10031                     }
10032                     goto uata_ctl_queue;
10033                 case  IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
10034                     if(len < pos+sizeof(AtaCtl->SetMode)) {
10035                         KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
10036                             pos+sizeof(AtaCtl->SetMode) ));
10037                         goto wrong_buffer_size;
10038                     }
10039                     if(!AtaCtl->SetMode.ApplyImmediately) {
10040                         break;
10041                     }
10042                     goto uata_ctl_queue;
10043                 case  IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
10044                 //case  IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
10045 uata_ctl_queue:
10046                     KdPrint2((PRINT_PREFIX "put to queue (UNIATA)\n"));
10047                     PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
10048 
10049                     if(PostReq || TopLevel) {
10050                         UniataQueueRequest(chan, Srb);
10051                         AtaReq = (PATA_REQ)(Srb->SrbExtension);
10052                         AtaReq->ReqState = REQ_STATE_QUEUED;
10053                     }
10054                     if(PostReq) {
10055                         KdPrint2((PRINT_PREFIX "Non-empty queue (UNIATA)\n"));
10056                         status = SRB_STATUS_PENDING;
10057 
10058                         KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
10059                         goto complete_req;
10060                     }
10061                 } // end switch (AtaCtl->hdr.ControlCode)
10062 
10063                 /* process request */
10064                 switch (AtaCtl->hdr.ControlCode) {
10065                 case  IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
10066 
10067                     KdPrint2((PRINT_PREFIX "AtapiStartIo: rescan bus\n"));
10068 
10069                     if(len < pos+sizeof(AtaCtl->FindDelDev)) {
10070                         KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
10071                             pos+sizeof(AtaCtl->FindDelDev) ));
10072                         goto wrong_buffer_size;
10073                     }
10074                     if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) {
10075                         KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n"));
10076                         if(AtaCtl->addr.TargetId != 0xff) {
10077                             LunExt->DeviceFlags &= ~DFLAGS_HIDDEN;
10078                         } else {
10079                         }
10080                     }
10081 
10082                     for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
10083                         AtapiStallExecution(1000 * 1000);
10084                     }
10085 
10086                     FindDevices(HwDeviceExtension,
10087                                 ((AtaCtl->addr.TargetId == 0xff) && (AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE))
10088                                      ? UNIATA_FIND_DEV_UNHIDE : 0,
10089                                 AtaCtl->addr.PathId);
10090                     status = SRB_STATUS_SUCCESS;
10091 
10092                     break;
10093 
10094                 case  IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE: {
10095 
10096                     KdPrint2((PRINT_PREFIX "AtapiStartIo: remove %#x:%#x\n", AtaCtl->addr.PathId, AtaCtl->addr.TargetId));
10097 
10098                     if(len < pos+sizeof(AtaCtl->FindDelDev)) {
10099                         KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
10100                             pos+sizeof(AtaCtl->FindDelDev) ));
10101                         goto wrong_buffer_size;
10102                     }
10103                     LunExt->DeviceFlags = 0;
10104                     if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) {
10105                         KdPrint2((PRINT_PREFIX "AtapiStartIo: hide from further detection\n"));
10106                         //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
10107                         UniataForgetDevice(LunExt);
10108                     }
10109 
10110                     for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
10111                         AtapiStallExecution(1000 * 1000);
10112                     }
10113 
10114                     status = SRB_STATUS_SUCCESS;
10115                     break;
10116                 }
10117                 case  IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE: {
10118 
10119                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Set transfer mode\n"));
10120 
10121                     if(len < pos+sizeof(AtaCtl->SetMode)) {
10122                         KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
10123                             pos+sizeof(AtaCtl->SetMode) ));
10124                         goto wrong_buffer_size;
10125                     }
10126                     if(AtaCtl->SetMode.OrigMode != IOMODE_NOT_SPECIFIED) {
10127                         LunExt->OrigTransferMode = (UCHAR)(AtaCtl->SetMode.OrigMode);
10128                     }
10129                     if(AtaCtl->SetMode.MaxMode != IOMODE_NOT_SPECIFIED) {
10130                         LunExt->LimitedTransferMode = (UCHAR)(AtaCtl->SetMode.MaxMode);
10131                         if(LunExt->LimitedTransferMode >
10132                            LunExt->OrigTransferMode) {
10133                             // check for incorrect value
10134                             LunExt->LimitedTransferMode =
10135                                 LunExt->OrigTransferMode;
10136                         }
10137                     }
10138                     LunExt->TransferMode = min(LunExt->LimitedTransferMode, LunExt->OrigTransferMode);
10139 
10140                     LunExt->DeviceFlags |= DFLAGS_REINIT_DMA;  // force PIO/DMA reinit
10141                     if(AtaCtl->SetMode.ApplyImmediately) {
10142                         AtapiDmaInit__(deviceExtension, LunExt);
10143                     }
10144 /*                    LunExt->TransferMode =
10145                     LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
10146                     status = SRB_STATUS_SUCCESS;
10147                     break;
10148                 }
10149                 case  IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE: {
10150 
10151                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Get transfer mode\n"));
10152 
10153                     if(len < pos+sizeof(AtaCtl->GetMode)) {
10154                         KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
10155                             pos+sizeof(AtaCtl->GetMode) ));
10156                         goto wrong_buffer_size;
10157                     }
10158                     AtaCtl->GetMode.OrigMode    = LunExt->OrigTransferMode;
10159                     AtaCtl->GetMode.MaxMode     = LunExt->LimitedTransferMode;
10160                     AtaCtl->GetMode.CurrentMode = LunExt->TransferMode;
10161                     AtaCtl->GetMode.PhyMode     = LunExt->PhyTransferMode;
10162 
10163                     status = SRB_STATUS_SUCCESS;
10164                     break;
10165                 }
10166                 case  IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION: {
10167 
10168                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Get version\n"));
10169 
10170                     if(len < pos+sizeof(AtaCtl->Version)) {
10171                         KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
10172                             pos+sizeof(AtaCtl->Version) ));
10173                         goto wrong_buffer_size;
10174                     }
10175                     AtaCtl->Version.Length      = sizeof(GETDRVVERSION);
10176                     AtaCtl->Version.VersionMj   = UNIATA_VER_MJ;
10177                     AtaCtl->Version.VersionMn   = UNIATA_VER_MN;
10178                     AtaCtl->Version.SubVerMj    = UNIATA_VER_SUB_MJ;
10179                     AtaCtl->Version.SubVerMn    = UNIATA_VER_SUB_MN;
10180 
10181                     status = SRB_STATUS_SUCCESS;
10182                     break;
10183                 }
10184                 case  IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO: {
10185 
10186                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Get adapter info\n"));
10187 
10188                     if(len < pos+sizeof(AtaCtl->AdapterInfo)) {
10189                         KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
10190                             pos+sizeof(AtaCtl->AdapterInfo) ));
10191                         goto wrong_buffer_size;
10192                     }
10193                     AtaCtl->AdapterInfo.HeaderLength = sizeof(ADAPTERINFO);
10194 
10195                     AtaCtl->AdapterInfo.DevID      = deviceExtension->DevID;
10196                     AtaCtl->AdapterInfo.RevID      = deviceExtension->RevID;
10197                     AtaCtl->AdapterInfo.slotNumber = deviceExtension->slotNumber;
10198                     AtaCtl->AdapterInfo.SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
10199                     AtaCtl->AdapterInfo.DevIndex   = deviceExtension->DevIndex;
10200                     AtaCtl->AdapterInfo.Channel    = deviceExtension->Channel;
10201                     AtaCtl->AdapterInfo.HbaCtrlFlags = deviceExtension->HbaCtrlFlags;
10202                     AtaCtl->AdapterInfo.simplexOnly= deviceExtension->simplexOnly;
10203                     AtaCtl->AdapterInfo.MemIo      = FALSE;/*deviceExtension->MemIo;*/
10204                     AtaCtl->AdapterInfo.UnknownDev = deviceExtension->UnknownDev;
10205                     AtaCtl->AdapterInfo.MasterDev  = deviceExtension->MasterDev;
10206                     AtaCtl->AdapterInfo.MaxTransferMode = deviceExtension->MaxTransferMode;
10207                     AtaCtl->AdapterInfo.HwFlags    = deviceExtension->HwFlags;
10208                     AtaCtl->AdapterInfo.OrigAdapterInterfaceType = deviceExtension->OrigAdapterInterfaceType;
10209                     AtaCtl->AdapterInfo.BusInterruptLevel = deviceExtension->BusInterruptLevel;
10210                     AtaCtl->AdapterInfo.InterruptMode = deviceExtension->InterruptMode;
10211                     AtaCtl->AdapterInfo.BusInterruptVector = deviceExtension->BusInterruptVector;
10212                     AtaCtl->AdapterInfo.NumberChannels = deviceExtension->NumberChannels;
10213                     AtaCtl->AdapterInfo.NumberLuns = (UCHAR)deviceExtension->NumberLuns;
10214                     AtaCtl->AdapterInfo.AdapterInterfaceType = deviceExtension->AdapterInterfaceType;
10215                     if(deviceExtension->FullDevName) {
10216                         strncpy(AtaCtl->AdapterInfo.DeviceName, deviceExtension->FullDevName, 64);
10217                     }
10218                     AtaCtl->AdapterInfo.ChanInfoValid = FALSE;
10219                     AtaCtl->AdapterInfo.LunInfoValid = FALSE;
10220                     AtaCtl->AdapterInfo.ChanHeaderLengthValid = TRUE;
10221 
10222                     pos += AtaCtl->AdapterInfo.HeaderLength;
10223 
10224                     // zero tail
10225                     RtlZeroMemory(((PCHAR)AtaCtl)+pos,
10226                         len-pos);
10227 
10228                     if(len >= pos+AtaCtl->AdapterInfo.NumberChannels*sizeof(CHANINFO)) {
10229                         PCHANINFO ChanInfo = (PCHANINFO)( ((PCHAR)AtaCtl)+pos );
10230                         PHW_CHANNEL cur_chan;
10231                         KdPrint2((PRINT_PREFIX "AtapiStartIo: Fill channel info\n"));
10232                         for(i=0;i<AtaCtl->AdapterInfo.NumberChannels;i++) {
10233                             KdPrint2((PRINT_PREFIX "chan[%d] %x\n", i, cur_chan));
10234                             cur_chan = &(deviceExtension->chan[i]);
10235                             ChanInfo->MaxTransferMode = cur_chan->MaxTransferMode;
10236                             ChanInfo->ChannelCtrlFlags = cur_chan->ChannelCtrlFlags;
10237                             RtlCopyMemory(&(ChanInfo->QueueStat), &(cur_chan->QueueStat), sizeof(ChanInfo->QueueStat));
10238                             ChanInfo->ReorderCount        = cur_chan->ReorderCount;
10239                             ChanInfo->IntersectCount      = cur_chan->IntersectCount;
10240                             ChanInfo->TryReorderCount     = cur_chan->TryReorderCount;
10241                             ChanInfo->TryReorderHeadCount = cur_chan->TryReorderHeadCount;
10242                             ChanInfo->TryReorderTailCount = cur_chan->TryReorderTailCount;
10243                             //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
10244                             ChanInfo++;
10245                         }
10246                         AtaCtl->AdapterInfo.ChanInfoValid = TRUE;
10247                         AtaCtl->AdapterInfo.ChanHeaderLength = sizeof(*ChanInfo);
10248                     }
10249 
10250                     status = SRB_STATUS_SUCCESS;
10251                     break;
10252                 }
10253                 case  IOCTL_SCSI_MINIPORT_UNIATA_RESETBB: {
10254 
10255                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Forget BB list\n"));
10256 
10257                     ForgetBadBlocks(LunExt);
10258 
10259                     status = SRB_STATUS_SUCCESS;
10260                     break;
10261                 }
10262                 case  IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: {
10263 
10264                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device\n"));
10265 
10266                     if(bad_ldev) {
10267                         goto do_bus_reset;
10268                     } else {
10269                         UniataUserDeviceReset(deviceExtension, LunExt, AtaCtl->addr.PathId);
10270                     }
10271 
10272                     status = SRB_STATUS_SUCCESS;
10273                     break;
10274                 }
10275                 default :
10276                     KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
10277                                 AtaCtl->hdr.ControlCode ));
10278                     status = SRB_STATUS_INVALID_REQUEST;
10279                     break;
10280                 }
10281 
10282             } else {
10283                 KdPrint2((PRINT_PREFIX "AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
10284                             ((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature,
10285                             "SCSIDISK", "-UNIATA-"));
10286 
10287                 status = SRB_STATUS_INVALID_REQUEST;
10288                 break;
10289             }
10290 
10291             break;
10292         } // end SRB_FUNCTION_IO_CONTROL
10293         default:
10294 
10295             KdPrint2((PRINT_PREFIX "AtapiStartIo: Unknown IOCTL\n"));
10296             // Indicate unsupported command.
10297             status = SRB_STATUS_INVALID_REQUEST;
10298 
10299 //            break;
10300 
10301         } // end switch
10302 
10303 complete_req:
10304 
10305         PathId   = Srb->PathId;
10306         TargetId = Srb->TargetId;
10307         Lun      = Srb->Lun;
10308 
10309         if (status != SRB_STATUS_PENDING) {
10310 
10311             KdPrint2((PRINT_PREFIX
10312                        "AtapiStartIo: Srb %#x complete with status %#x\n",
10313                        Srb,
10314                        status));
10315 
10316             // Set status in SRB.
10317             Srb->SrbStatus = (UCHAR)status;
10318 
10319             if(chan && Srb) {
10320                 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan, Srb));
10321                 AtapiDmaDBSync(chan, Srb);
10322             }
10323             KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan, Srb));
10324             UniataRemoveRequest(chan, Srb);
10325             // Indicate command complete.
10326             KdPrint2((PRINT_PREFIX "AtapiStartIo: ScsiPortNotification\n"));
10327             ScsiPortNotification(RequestComplete,
10328                                  deviceExtension,
10329                                  Srb);
10330 
10331             KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataGetCurRequest\n"));
10332             // Remove current Srb & get next one
10333             if((Srb = UniataGetCurRequest(chan))) {
10334                 AtaReq = (PATA_REQ)(Srb->SrbExtension);
10335                 if(AtaReq->ReqState > REQ_STATE_QUEUED) {
10336                     // current request is under precessing, thus
10337                     // we should do nothing here
10338                     Srb = NULL;
10339                 }
10340             }
10341             KdPrint2((PRINT_PREFIX "AtapiStartIo: chan %x, Src %x\n", chan, Srb));
10342             if(!chan) {
10343                 //ASSERT(TopLevel);
10344             }
10345         }
10346         KdPrint2((PRINT_PREFIX "AtapiStartIo: next Srb %x\n", Srb));
10347 
10348     } while (Srb && (status != SRB_STATUS_PENDING));
10349 
10350     KdPrint2((PRINT_PREFIX "AtapiStartIo: query PORT for next request\n"));
10351     // Indicate ready for next request.
10352     ScsiPortNotification(NextRequest,
10353                          deviceExtension,
10354                          NULL);
10355 
10356     ScsiPortNotification(NextLuRequest,
10357                          deviceExtension,
10358                          PathId,
10359                          TargetId,
10360                          Lun);
10361 
10362     return TRUE;
10363 
10364 } // end AtapiStartIo__()
10365 
10366 #if 0
10367 void
10368 NTAPI
10369 UniataInitAtaCommands()
10370 {
10371     int i;
10372     UCHAR command;
10373     UCHAR flags;
10374 
10375     KdPrint2((PRINT_PREFIX "UniataInitAtaCommands:\n"));
10376 
10377     for(i=0; i<256; i++) {
10378 
10379         flags = 0;
10380         command = i;
10381 
10382         //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
10383 
10384         switch(command) {
10385         case IDE_COMMAND_READ_DMA48:
10386         case IDE_COMMAND_READ_DMA_Q48:
10387         case IDE_COMMAND_READ_STREAM_DMA48:
10388         case IDE_COMMAND_READ_STREAM48:
10389         case IDE_COMMAND_WRITE_DMA48:
10390         case IDE_COMMAND_WRITE_DMA_Q48:
10391         case IDE_COMMAND_READ_DMA_Q:
10392         case IDE_COMMAND_READ_DMA:
10393         case IDE_COMMAND_WRITE_DMA:
10394         case IDE_COMMAND_WRITE_DMA_Q:
10395         case IDE_COMMAND_WRITE_STREAM_DMA48:
10396         case IDE_COMMAND_WRITE_STREAM48:
10397         case IDE_COMMAND_WRITE_FUA_DMA48:
10398         case IDE_COMMAND_WRITE_FUA_DMA_Q48:
10399         case IDE_COMMAND_READ_LOG_DMA48:
10400         case IDE_COMMAND_WRITE_LOG_DMA48:
10401         case IDE_COMMAND_TRUSTED_RCV_DMA:
10402         case IDE_COMMAND_TRUSTED_SEND_DMA:
10403         case IDE_COMMAND_DATA_SET_MGMT: // TRIM
10404             //KdPrint2((PRINT_PREFIX "DMA "));
10405             flags |= ATA_CMD_FLAG_DMA;
10406         }
10407 
10408         switch(command) {
10409         case IDE_COMMAND_WRITE_FUA_DMA48:
10410         case IDE_COMMAND_WRITE_FUA_DMA_Q48:
10411         case IDE_COMMAND_WRITE_MUL_FUA48:
10412 
10413             flags |= ATA_CMD_FLAG_FUA;
10414             /* FALL THROUGH */
10415 
10416         case IDE_COMMAND_READ48:
10417         case IDE_COMMAND_READ_DMA48:
10418         case IDE_COMMAND_READ_DMA_Q48:
10419         case IDE_COMMAND_READ_MUL48:
10420         case IDE_COMMAND_READ_STREAM_DMA48:
10421         case IDE_COMMAND_READ_STREAM48:
10422         case IDE_COMMAND_WRITE48:
10423         case IDE_COMMAND_WRITE_DMA48:
10424         case IDE_COMMAND_WRITE_DMA_Q48:
10425         case IDE_COMMAND_WRITE_MUL48:
10426         case IDE_COMMAND_WRITE_STREAM_DMA48:
10427         case IDE_COMMAND_WRITE_STREAM48:
10428         case IDE_COMMAND_FLUSH_CACHE48:
10429         case IDE_COMMAND_VERIFY48:
10430 
10431             //KdPrint2((PRINT_PREFIX "48 "));
10432             flags |= ATA_CMD_FLAG_48;
10433             /* FALL THROUGH */
10434 
10435         case IDE_COMMAND_READ:
10436         case IDE_COMMAND_READ_MULTIPLE:
10437         case IDE_COMMAND_READ_DMA:
10438         case IDE_COMMAND_READ_DMA_Q:
10439         case IDE_COMMAND_WRITE:
10440         case IDE_COMMAND_WRITE_MULTIPLE:
10441         case IDE_COMMAND_WRITE_DMA:
10442         case IDE_COMMAND_WRITE_DMA_Q:
10443         case IDE_COMMAND_FLUSH_CACHE:
10444         case IDE_COMMAND_VERIFY:
10445 
10446             //KdPrint2((PRINT_PREFIX "LBA "));
10447             flags |= ATA_CMD_FLAG_LBAIOsupp;
10448         }
10449 
10450         switch(command) {
10451         case IDE_COMMAND_READ_NATIVE_SIZE48:
10452         case IDE_COMMAND_SET_NATIVE_SIZE48:
10453             // we cannot set LBA flag for these commands to avoid BadBlock handling
10454             //flags |= ATA_CMD_FLAG_LBAIOsupp;
10455             flags |= ATA_CMD_FLAG_48;
10456 
10457         case IDE_COMMAND_READ_NATIVE_SIZE:
10458         case IDE_COMMAND_SET_NATIVE_SIZE:
10459 
10460             flags |= ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_FUA;
10461         }
10462 
10463         flags |= ATA_CMD_FLAG_48supp;
10464 
10465         switch (command) {
10466         case IDE_COMMAND_READ:
10467             command = IDE_COMMAND_READ48; break;
10468         case IDE_COMMAND_READ_MULTIPLE:
10469             command = IDE_COMMAND_READ_MUL48; break;
10470         case IDE_COMMAND_READ_DMA:
10471             command = IDE_COMMAND_READ_DMA48; break;
10472         case IDE_COMMAND_READ_DMA_Q:
10473             command = IDE_COMMAND_READ_DMA_Q48; break;
10474         case IDE_COMMAND_WRITE:
10475             command = IDE_COMMAND_WRITE48; break;
10476         case IDE_COMMAND_WRITE_MULTIPLE:
10477             command = IDE_COMMAND_WRITE_MUL48; break;
10478         case IDE_COMMAND_WRITE_DMA:
10479             command = IDE_COMMAND_WRITE_DMA48; break;
10480         case IDE_COMMAND_WRITE_DMA_Q:
10481             command = IDE_COMMAND_WRITE_DMA_Q48; break;
10482         case IDE_COMMAND_FLUSH_CACHE:
10483             command = IDE_COMMAND_FLUSH_CACHE48; break;
10484     //    case IDE_COMMAND_READ_NATIVE_SIZE:
10485     //            command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
10486         case IDE_COMMAND_SET_NATIVE_SIZE:
10487             command = IDE_COMMAND_SET_NATIVE_SIZE48; break;
10488         case IDE_COMMAND_VERIFY:
10489             command = IDE_COMMAND_VERIFY48; break;
10490         default:
10491             //KdPrint2((PRINT_PREFIX "!28->48 "));
10492             flags &= ~ATA_CMD_FLAG_48supp;
10493         }
10494 
10495         switch (command) {
10496         case IDE_COMMAND_READ:
10497         case IDE_COMMAND_READ_MULTIPLE:
10498         case IDE_COMMAND_READ_DMA48:
10499         case IDE_COMMAND_READ_DMA_Q48:
10500         case IDE_COMMAND_READ_STREAM_DMA48:
10501         case IDE_COMMAND_READ_STREAM48:
10502         case IDE_COMMAND_READ_DMA_Q:
10503         case IDE_COMMAND_READ_DMA:
10504         case IDE_COMMAND_READ_LOG_DMA48:
10505         case IDE_COMMAND_TRUSTED_RCV_DMA:
10506         case IDE_COMMAND_IDENTIFY:
10507         case IDE_COMMAND_ATAPI_IDENTIFY:
10508             //KdPrint2((PRINT_PREFIX "RD "));
10509             flags |= ATA_CMD_FLAG_In;
10510             break;
10511         case IDE_COMMAND_WRITE:
10512         case IDE_COMMAND_WRITE_MULTIPLE:
10513         case IDE_COMMAND_WRITE_DMA48:
10514         case IDE_COMMAND_WRITE_DMA_Q48:
10515         case IDE_COMMAND_WRITE_DMA:
10516         case IDE_COMMAND_WRITE_DMA_Q:
10517         case IDE_COMMAND_WRITE_STREAM_DMA48:
10518         case IDE_COMMAND_WRITE_STREAM48:
10519         case IDE_COMMAND_WRITE_FUA_DMA48:
10520         case IDE_COMMAND_WRITE_FUA_DMA_Q48:
10521             //KdPrint2((PRINT_PREFIX "WR "));
10522             flags |= ATA_CMD_FLAG_Out;
10523             break;
10524         }
10525 
10526         //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
10527         AtaCommands48[i]   = command;
10528         AtaCommandFlags[i] = flags;
10529     }
10530 } // end UniataInitAtaCommands()
10531 #endif
10532 
10533 /*++
10534 
10535 Routine Description:
10536 
10537     Installable driver initialization entry point for system.
10538 
10539 Arguments:
10540 
10541     Driver Object
10542 
10543 Return Value:
10544 
10545     Status from ScsiPortInitialize()
10546 
10547 --*/
10548 extern "C"
10549 ULONG
10550 NTAPI
10551 DriverEntry(
10552     IN PVOID DriverObject,
10553     IN PVOID Argument2
10554     )
10555 {
10556     HW_INITIALIZATION_DATA_COMMON hwInitializationData;
10557     ULONG                  adapterCount;
10558     ULONG                  i, c, alt, pref_alt;
10559     ULONG                  statusToReturn, newStatus;
10560     PUNICODE_STRING        RegistryPath = (PUNICODE_STRING)Argument2;
10561     BOOLEAN                ReEnter = FALSE;
10562 //    WCHAR                  a;
10563 #ifndef USE_REACTOS_DDK
10564     NTSTATUS               status;
10565 #endif
10566 
10567     PCONFIGURATION_INFORMATION GlobalConfig = IoGetConfigurationInformation();
10568     BOOLEAN PrimaryClaimed   = FALSE;
10569     BOOLEAN SecondaryClaimed = FALSE;
10570     BOOLEAN IgnoreIsaCompatiblePci = FALSE;
10571     BOOLEAN IgnoreNativePci = FALSE;
10572 
10573     LARGE_INTEGER t0, t1;
10574 
10575     KdPrint2((PRINT_PREFIX "%s", (PCCHAR)ver_string));
10576     //a = (WCHAR)strlen(ver_string);
10577 
10578     statusToReturn = 0xffffffff;
10579 
10580     // Zero out structure.
10581     RtlZeroMemory(((PCHAR)&hwInitializationData), sizeof(hwInitializationData));
10582 
10583     // Set size of hwInitializationData.
10584     hwInitializationData.comm.HwInitializationDataSize =
10585       sizeof(hwInitializationData.comm) +
10586 //      sizeof(hwInitializationData.nt4) +
10587       ((WinVer_Id() <= WinVer_NT) ? 0 : sizeof(hwInitializationData.w2k));
10588     KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData.comm.HwInitializationDataSize));
10589 
10590     // Set entry points.
10591     hwInitializationData.comm.HwInitialize = (PHW_INITIALIZE)AtapiHwInitialize;
10592     hwInitializationData.comm.HwResetBus = (PHW_RESET_BUS)AtapiResetController;
10593     hwInitializationData.comm.HwStartIo = (PHW_STARTIO)AtapiStartIo;
10594     hwInitializationData.comm.HwInterrupt = (PHW_INTERRUPT)AtapiInterrupt;
10595 
10596     // Specify size of extensions.
10597     hwInitializationData.comm.DeviceExtensionSize     = sizeof(HW_DEVICE_EXTENSION);
10598     hwInitializationData.comm.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION);
10599     hwInitializationData.comm.SrbExtensionSize        = sizeof(ATA_REQ);
10600 
10601     // Indicate PIO device.
10602     hwInitializationData.comm.MapBuffers = TRUE;
10603 
10604     // Request and parse arument string.
10605     KdPrint2((PRINT_PREFIX "\n\nUniATA: parse ArgumentString\n"));
10606     // Zero out structure.
10607     hwInitializationData.comm.NumberOfAccessRanges = 2;
10608     hwInitializationData.comm.HwFindAdapter = AtapiReadArgumentString;
10609     ScsiPortInitialize(DriverObject,
10610                                     Argument2,
10611                                     &hwInitializationData.comm,
10612                                     &adapterCount);
10613 
10614     if(!g_Dump) {
10615         Connect_DbgPrint();
10616         g_opt_Verbose = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PrintLogo", 0);
10617         if(g_opt_Verbose) {
10618             _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR "\n");
10619         }
10620         IgnoreIsaCompatiblePci = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", IgnoreIsaCompatiblePci) ? TRUE : FALSE;
10621         IgnoreNativePci = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreNativePci", IgnoreNativePci) ? TRUE : FALSE;
10622     } else {
10623         KdPrint(("crashdump mode\n"));
10624     }
10625 
10626     if(!SavedDriverObject) {
10627         SavedDriverObject = (PDRIVER_OBJECT)DriverObject;
10628 #ifdef USE_REACTOS_DDK
10629         KdPrint(("UniATA Init: OS should be ReactOS\n"));
10630         MajorVersion=0x04;
10631         MinorVersion=0x01;
10632         BuildNumber=1;
10633         CPU_num = KeNumberProcessors;
10634 #else
10635         // we are here for the 1st time
10636         // init CrossNT and get OS version
10637         if(!NT_SUCCESS(status = CrNtInit(SavedDriverObject, RegistryPath))) {
10638             KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status));
10639             //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
10640             return status;
10641         }
10642         CPU_num = *KeNumberProcessors;
10643 #endif // USE_REACTOS_DDK
10644         KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion, MinorVersion, BuildNumber, CPU_num));
10645 
10646         KeQuerySystemTime(&t0);
10647         do {
10648             KeQuerySystemTime(&t1);
10649         } while(t0.QuadPart == t1.QuadPart);
10650         t0=t1;
10651         g_Perf=0;
10652         do {
10653             KeQuerySystemTime(&t1);
10654             g_Perf++;
10655         } while(t0.QuadPart == t1.QuadPart);
10656         g_PerfDt = (ULONG)((t1.QuadPart - t0.QuadPart)/10);
10657         KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt, g_Perf ));
10658     } else {
10659         KdPrint(("UniATA Init: ReEnter\n"));
10660         ReEnter = TRUE;
10661     }
10662 
10663     // (re)read bad block list
10664     InitBadBlocks(NULL);
10665 
10666     if(!ReEnter) {
10667         // init ATA command translation table
10668         //UniataInitAtaCommands();
10669 
10670         // get registry path to settings
10671         RtlCopyMemory(&SavedRegPath, RegistryPath, sizeof(UNICODE_STRING));
10672         SavedRegPath.Buffer = (PWCHAR)&SavedRegPathBuffer;
10673         SavedRegPath.Length = min(RegistryPath->Length, 255*sizeof(WCHAR));
10674         SavedRegPath.MaximumLength = 255*sizeof(WCHAR);
10675         RtlCopyMemory(SavedRegPath.Buffer, RegistryPath->Buffer, SavedRegPath.Length);
10676         SavedRegPath.Buffer[SavedRegPath.Length/sizeof(WCHAR)] = 0;
10677     }
10678 
10679     if(WinVer_Id() >= WinVer_2k) {
10680         if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"1", 0)) {
10681             KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
10682             WinVer_WDM_Model = TRUE;
10683         }
10684         if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"5", 0)) {
10685             KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
10686             WinVer_WDM_Model = TRUE;
10687         }
10688     }
10689 
10690     SkipRaids = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"SkipRaids", 1);
10691     ForceSimplex = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"ForceSimplex", 0);
10692 #ifdef _DEBUG
10693     g_LogToDisplay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"LogToDisplay", 0);
10694 #endif //_DEBUG
10695 
10696     // Set PnP-specific API
10697     if(WinVer_Id() > WinVer_NT) {
10698         KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
10699         hwInitializationData.comm.NeedPhysicalAddresses = TRUE;
10700         KdPrint(("set AtapiAdapterControl() ptr\n"));
10701         hwInitializationData.w2k.HwAdapterControl = (PHW_ADAPTER_CONTROL)AtapiAdapterControl;
10702     }
10703 
10704     KdPrint2((PRINT_PREFIX "\n\nUniATA init... (%d)\n", ReEnter));
10705     if(!ReEnter) {
10706 
10707         g_opt_VirtualMachine = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualMachineType", g_opt_VirtualMachine);
10708         if(g_opt_VirtualMachine > VM_MAX_KNOWN) {
10709             g_opt_VirtualMachine = 0;
10710         }
10711         if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualBox", (g_opt_VirtualMachine == VM_VBOX))) {
10712             g_opt_VirtualMachine = VM_VBOX;
10713         }
10714         // Pre-scan PCI bus, also check if we are under VM
10715         // But do not perform scan if PCI bus is claimed as unused
10716         if(!IgnoreIsaCompatiblePci || !IgnoreNativePci) {
10717             KdPrint2((PRINT_PREFIX "\nATAPI IDE enum supported PCI BusMaster Devices\n"));
10718             UniataEnumBusMasterController(DriverObject, Argument2);
10719         }
10720 
10721         switch(g_opt_VirtualMachine) {
10722         case VM_VBOX:
10723             KdPrint2((PRINT_PREFIX "adjust options for VirtualBox\n"));
10724             // adjust options for VirtualBox
10725             g_opt_WaitBusyCount = 20000;
10726             g_opt_WaitBusyDelay = 150;
10727             g_opt_WaitDrqDelay  = 100;
10728             g_opt_WaitBusyLongCount = 20000;
10729             g_opt_MaxIsrWait = 200;
10730             g_opt_AtapiSendDisableIntr = FALSE;
10731             g_opt_AtapiDmaRawRead = FALSE;
10732             break;
10733         case VM_BOCHS:
10734             KdPrint2((PRINT_PREFIX "adjust options for Bochs\n"));
10735             g_opt_AtapiNoDma = TRUE;
10736         }
10737 
10738         if(!hasPCI) {
10739             KdPrint2((PRINT_PREFIX "old slow machine, adjust timings\n"));
10740             // old slow machine, adjust timings (us)
10741             g_opt_WaitBusyResetCount = 20000;
10742             g_opt_WaitBusyCount = 20000;
10743             g_opt_WaitBusyDelay = 150;
10744             g_opt_WaitDrqDelay  = 100;
10745             g_opt_WaitBusyLongCount = 20000;
10746             g_opt_MaxIsrWait = 200;
10747             g_opt_DriveSelectNanoDelay = 400;
10748         }
10749         if(g_opt_VirtualMachine > VM_NONE) {
10750             g_opt_DriveSelectNanoDelay = 0;
10751         }
10752         if(CPU_num > 1) {
10753             g_opt_AtapiSendDisableIntr = TRUE;
10754         }
10755 
10756         g_opt_WaitBusyCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyCount", g_opt_WaitBusyCount); // 200 vs 20000
10757         g_opt_WaitBusyDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyDelay", g_opt_WaitBusyDelay); // 10 vs 150
10758         g_opt_WaitDrqDelay  = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitDrqDelay",  g_opt_WaitDrqDelay);  // 10 vs 100
10759         g_opt_WaitBusyLongCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongCount", g_opt_WaitBusyLongCount); // 2000 vs 20000
10760         g_opt_WaitBusyLongDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongDelay", g_opt_WaitBusyLongDelay); // 250 vs 250
10761         g_opt_AtapiSendDisableIntr = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiSendDisableIntr",  g_opt_AtapiSendDisableIntr) ? TRUE : FALSE;  // 1 vs 0
10762         g_opt_AtapiDmaRawRead      = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiDmaRawRead",       g_opt_AtapiDmaRawRead) ? TRUE : FALSE;       // 1 vs 0
10763         g_opt_AtapiNoDma    = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiNoDma", g_opt_AtapiNoDma) ? TRUE : FALSE;       // 1 vs 0
10764         g_opt_MaxIsrWait    = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"MaxIsrWait", g_opt_MaxIsrWait);       // 40 vs xxx
10765         g_opt_DriveSelectNanoDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"DriveSelectNanoDelay", g_opt_DriveSelectNanoDelay);
10766     } // end !re-enter
10767 
10768     // Look for legacy ISA-bridged PCI IDE controller (onboard)
10769     KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
10770     KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: BMListLen %d\n", BMListLen));
10771     for (i=0; i <BMListLen; i++) {
10772 
10773         if(!BMList[i].MasterDev) {
10774             KdPrint2((PRINT_PREFIX "!BMList[i].MasterDev\n"));
10775             break;
10776         }
10777         if(IgnoreIsaCompatiblePci) {
10778             break;
10779         }
10780         if(ReEnter) {
10781             KdPrint2((PRINT_PREFIX "ReEnter, skip it\n"));
10782             if(BMList[i].ChanInitOk & 0x03) {
10783                 KdPrint2((PRINT_PREFIX "Already initialized, skip it\n"));
10784                 statusToReturn =
10785                 newStatus = STATUS_SUCCESS;
10786             }
10787             continue;
10788         }
10789         //BMList[i].AltInitMasterDev = (UCHAR)0xff;
10790 
10791         if(GlobalConfig->AtDiskPrimaryAddressClaimed)
10792             PrimaryClaimed = TRUE;
10793         if(GlobalConfig->AtDiskSecondaryAddressClaimed)
10794             SecondaryClaimed = TRUE;
10795         pref_alt = 0;
10796 
10797         if(!WinVer_WDM_Model && !PrimaryClaimed && !SecondaryClaimed && !g_Dump &&
10798             !(BMList[i].ChanInitOk & 0x80)) {
10799 
10800             // We just want to claim our PCI device in compatible mode, since we shall not
10801             // tell system that we use it inside HwInitialize
10802             // Even more, we shall cheat system, that work with ISA
10803             // Note: this call may (but not 'must' or 'can') cause IO resource
10804             // reallocation and switch to native mode if HAL supports this
10805             newStatus = (ULONG)UniataClaimLegacyPCIIDE(i);
10806             // Special check for NT3.51/NT4 (not ReactOS !!!)
10807             if(((NTSTATUS)newStatus == STATUS_CONFLICTING_ADDRESSES) &&
10808                //(BMList[i].ChanInitOk & 0x40) &&
10809                /*CPU_num > 1 &&*/
10810                (WinVer_Id() <= WinVer_NT)) {
10811                 // Some NT3/4 SMP (but not only) HALs cannot reallocate IO resources of
10812                 // BusMaster PCI controller
10813                 // Since nobody claimed Primary/Secondary yet, try init and claim them
10814                 // However it is not 100% safe way, especially under ReactOS, which doesn't resolve
10815                 // conflicts yet.
10816                 // We relay on ScsiPort internal checks
10817                 KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster on SMP NT3/4 system, try init anyway.\n"));
10818                 newStatus = STATUS_SUCCESS;
10819                 // Prefer alternative init method (try to change Isa -> PCI in ConfigInfo first)
10820                 pref_alt = 1;
10821             }
10822             if(newStatus != STATUS_SUCCESS) {
10823                 KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
10824                 break;
10825             }
10826         }
10827 
10828         if(g_opt_Verbose) {
10829             _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
10830         }
10831 
10832         for(alt = 0; alt < (ULONG)(WinVer_WDM_Model ? 1 : 2) ; alt++) {
10833 
10834             for(c=0; c<2; c++) {
10835                 // check is channel is manually excluded
10836                 if(AtapiRegCheckDevValue(NULL, c, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) {
10837                     break;
10838                 }
10839                 if(c==0) {
10840                     if(PrimaryClaimed) {
10841                         KdPrint2((PRINT_PREFIX "Primary already claimed\n"));
10842                         continue;
10843                     }
10844                 } else
10845                 if(c==1) {
10846                     if(SecondaryClaimed) {
10847                         KdPrint2((PRINT_PREFIX "Secondary already claimed\n"));
10848                         continue;
10849                     }
10850                 }
10851 
10852                 if((WinVer_Id() < WinVer_2k)) {
10853                     // do not even try if already claimed
10854                     if(c==0) {
10855                         GlobalConfig->AtDiskPrimaryAddressClaimed = FALSE;
10856                     } else
10857                     if(c==1) {
10858                         GlobalConfig->AtDiskSecondaryAddressClaimed = FALSE;
10859                     }
10860                 }
10861                 if(!WinVer_WDM_Model) {
10862                     hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
10863                 } else {
10864                     // in WDM model things are different....
10865                     hwInitializationData.comm.HwFindAdapter = (c == 0) ?
10866                         UniataFindCompatBusMasterController1 : UniataFindCompatBusMasterController2;
10867                 }
10868                 hwInitializationData.comm.NumberOfAccessRanges = 6;
10869                 hwInitializationData.comm.AdapterInterfaceType = Isa;
10870 
10871                 if(!WinVer_WDM_Model) {
10872                     BMList[i].channel = (UCHAR)c;
10873                 }
10874 
10875                 KdPrint2((PRINT_PREFIX "Try init channel %d, method %d\n", c, alt));
10876                 newStatus = ScsiPortInitialize(DriverObject,
10877                                                Argument2,
10878                                                &hwInitializationData.comm,
10879                                                UlongToPtr(i | ((alt ^ pref_alt) ? 0x80000000 : 0)));
10880                 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
10881                 if (newStatus < statusToReturn) {
10882                     statusToReturn = newStatus;
10883                 }
10884                 if (newStatus == STATUS_SUCCESS) {
10885                     if(WinVer_Id() < WinVer_2k) {
10886                         // This should be done in HwInitialize under w2k+ to ensure that
10887                         // channel is actually initialized
10888                         BMList[i].ChanInitOk |= 0x01 << c;
10889                     } else {
10890                         if(BMList[i].ChanInitOk & (0x01 << c)) {
10891                             KdPrint2((PRINT_PREFIX "HwInit passed\n"));
10892                         }
10893                     }
10894 /*
10895                     if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
10896                         c = 1; // this will break our for()
10897                         BMList[i].ChanInitOk |= 0x01 << c;
10898                     }
10899 */
10900                 }
10901             }
10902 /*            if(WinVer_Id() >= WinVer_2k) {
10903                 // the following didn't work under higher OSes,
10904                 // until we move setting of FLAGS to HwInit
10905                 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
10906                 continue;
10907             }*/
10908             if(BMList[i].ChanInitOk & 0x03) {
10909                 // Under NT we receive status immediately, so
10910                 // we can omit alternative init method if STATUS_SUCCESS returned.
10911                 // Under w2k+ we relay on flags, set in HwInitialize.
10912                 KdPrint2((PRINT_PREFIX "Ok, no more retries required\n"));
10913                 break;
10914             } else
10915             if(WinVer_Id() >= WinVer_2k) {
10916                 // try AltInit if HwInit was not called immediately under w2k+
10917                 KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n"));
10918             } else {
10919                 // if (WinVer_Id() == WinVer_NT) and some error occured
10920                 // try alternative init method
10921                 KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n"));
10922             }
10923         } // for(alt...)
10924         if(g_opt_Verbose) {
10925             if(BMList[i].ChanInitOk & 0x03) {
10926                 _PrintNtConsole("  OK\n");
10927             } else {
10928                 _PrintNtConsole("  failed\n");
10929             }
10930         }
10931 
10932     }
10933 
10934 /*    KeBugCheckEx(0xc000000e,
10935                  (i << 16) | BMList[0].ChanInitOk,
10936                  c,
10937                  newStatus, statusToReturn);*/
10938 
10939     // Look for PCI IDE controller
10940     KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for PCI IDE controller\n"));
10941     KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: i %d, BMListLen %d\n", i, BMListLen));
10942     for (; i <BMListLen; i++) {
10943 
10944         if(IgnoreNativePci) {
10945             break;
10946         }
10947 /*        if(BMList[i].MasterDev)
10948             continue;*/
10949         if(g_opt_Verbose) {
10950             _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
10951                 BMList[i].VendorId, BMList[i].DeviceId,
10952                 BMList[i].busNumber,
10953                 BMList[i].slotNumber % PCI_MAX_FUNCTION,
10954                 (BMList[i].slotNumber / PCI_MAX_FUNCTION) % PCI_MAX_DEVICES);
10955         }
10956 
10957         hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
10958         hwInitializationData.comm.NumberOfAccessRanges = 6;
10959         hwInitializationData.comm.AdapterInterfaceType = PCIBus;
10960 
10961         hwInitializationData.comm.VendorId             = (PVOID)BMList[i].VendorId;
10962         hwInitializationData.comm.VendorIdLength       = (USHORT) BMList[i].VendorIdLength;
10963         hwInitializationData.comm.DeviceId             = (PVOID)BMList[i].DeviceId;
10964         hwInitializationData.comm.DeviceIdLength       = (USHORT) BMList[i].DeviceIdLength;
10965 
10966         BMList[i].channel = 0/*(UCHAR)c*/;
10967 
10968         KdPrint2((PRINT_PREFIX "Try init %4.4s %4.4s \n",
10969                                hwInitializationData.comm.VendorId,
10970                                hwInitializationData.comm.DeviceId));
10971         newStatus = ScsiPortInitialize(DriverObject,
10972                                        Argument2,
10973                                        &hwInitializationData.comm,
10974                                        UlongToPtr(i));
10975         KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
10976         if(newStatus == (ULONG)STATUS_DEVICE_DOES_NOT_EXIST && BMList[i].NeedAltInit) {
10977             // Note: this is actually a BUG in scsiport.sys
10978             // It stops scanning PCI bus when reaches empty PCI Function inside Slot
10979             // However, this PCI Slot may have higher non-empty Functions
10980             // UniATA will perform all staff instead of ScsiPort under NT,
10981             // but for ReactOS it is better to patch ScsiPort.
10982             KdPrint2((PRINT_PREFIX "STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
10983             hwInitializationData.comm.AdapterInterfaceType = Isa;
10984             newStatus = ScsiPortInitialize(DriverObject,
10985                                            Argument2,
10986                                            &hwInitializationData.comm,
10987                                            UlongToPtr(i | 0x80000000));
10988             KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x (2)\n", newStatus));
10989         }
10990         if (newStatus < statusToReturn)
10991             statusToReturn = newStatus;
10992 
10993         if(g_opt_Verbose) {
10994             if(newStatus == STATUS_SUCCESS) {
10995                 _PrintNtConsole("  OK\n");
10996             } else {
10997                 _PrintNtConsole("  failed\n");
10998             }
10999         }
11000 
11001     }
11002 
11003 /*    KeBugCheckEx(0xc000000e,
11004                  i,
11005                  c,
11006                  newStatus, statusToReturn);*/
11007 
11008     // --------------
11009 
11010     hwInitializationData.comm.VendorId             = 0;
11011     hwInitializationData.comm.VendorIdLength       = 0;
11012     hwInitializationData.comm.DeviceId             = 0;
11013     hwInitializationData.comm.DeviceIdLength       = 0;
11014 
11015     if(!BMListLen) {
11016         hwInitializationData.comm.SrbExtensionSize        = //FIELD_OFFSET(ATA_REQ, ata);
11017                                                             sizeof(ATA_REQ);
11018         KdPrint2((PRINT_PREFIX "using AtaReq sz %x\n", hwInitializationData.comm.SrbExtensionSize));
11019     }
11020 
11021     // The adapter count is used by the find adapter routine to track how
11022     // which adapter addresses have been tested.
11023 
11024     // Indicate 2 access ranges and reset FindAdapter.
11025     hwInitializationData.comm.NumberOfAccessRanges = 2;
11026     hwInitializationData.comm.HwFindAdapter = AtapiFindIsaController;
11027 
11028     if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsa", 0)) {
11029         // Indicate ISA bustype.
11030         hwInitializationData.comm.AdapterInterfaceType = Isa;
11031         adapterCount = 0;
11032 
11033         // Call initialization for ISA bustype.
11034         KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for ISA Controllers\n"));
11035         newStatus =  ScsiPortInitialize(DriverObject,
11036                                         Argument2,
11037                                         &hwInitializationData.comm,
11038                                         &adapterCount);
11039         KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
11040         if (newStatus < statusToReturn)
11041             statusToReturn = newStatus;
11042     }
11043     if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreMca", 0)) {
11044         // Set up for MCA
11045         KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for MCA Controllers\n"));
11046         hwInitializationData.comm.AdapterInterfaceType = MicroChannel;
11047         adapterCount = 0;
11048 
11049         newStatus =  ScsiPortInitialize(DriverObject,
11050                                         Argument2,
11051                                         &hwInitializationData.comm,
11052                                         &adapterCount);
11053         KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
11054         if (newStatus < statusToReturn)
11055             statusToReturn = newStatus;
11056     }
11057     InDriverEntry = FALSE;
11058 
11059     KdPrint2((PRINT_PREFIX "\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn));
11060 
11061     return statusToReturn;
11062 
11063 } // end DriverEntry()
11064 
11065 
11066 PSCSI_REQUEST_BLOCK
11067 NTAPI
11068 BuildMechanismStatusSrb(
11069     IN PVOID HwDeviceExtension,
11070     IN PSCSI_REQUEST_BLOCK Srb
11071     )
11072 {
11073     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
11074     PSCSI_REQUEST_BLOCK srb;
11075     PCDB cdb;
11076     PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
11077 
11078     srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb);
11079 
11080     RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
11081 
11082     srb->PathId     = (UCHAR)(Srb->PathId);
11083     srb->TargetId   = (UCHAR)(Srb->TargetId);
11084     srb->Function   = SRB_FUNCTION_EXECUTE_SCSI;
11085     srb->Length     = sizeof(SCSI_REQUEST_BLOCK);
11086 
11087     // Set flags to disable synchronous negociation.
11088     srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
11089 
11090     // Set timeout to 4 seconds.
11091     srb->TimeOutValue = 4;
11092 
11093     srb->CdbLength          = 6;
11094     srb->DataBuffer         = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusData);
11095     srb->DataTransferLength = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
11096     srb->SrbExtension       = AtaReq;
11097 
11098     // Set CDB operation code.
11099     cdb = (PCDB)srb->Cdb;
11100     cdb->MECH_STATUS.OperationCode       = SCSIOP_MECHANISM_STATUS;
11101     cdb->MECH_STATUS.AllocationLength[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
11102 
11103     KdPrint2((PRINT_PREFIX " MechanismStatusSrb %#x\n", srb));
11104 
11105     return srb;
11106 } // end BuildMechanismStatusSrb()
11107 
11108 #endif //UNIATA_CORE
11109 
11110 PSCSI_REQUEST_BLOCK
11111 NTAPI
11112 BuildRequestSenseSrb (
11113     IN PVOID HwDeviceExtension,
11114     IN PSCSI_REQUEST_BLOCK Srb
11115     )
11116 {
11117     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
11118     PSCSI_REQUEST_BLOCK srb;
11119     PCDB cdb;
11120     PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
11121 
11122     srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb);
11123 
11124     RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
11125 
11126     srb->PathId     = (UCHAR)(Srb->PathId);
11127     srb->TargetId   = (UCHAR)(Srb->TargetId);
11128     srb->Function   = SRB_FUNCTION_EXECUTE_SCSI;
11129     srb->Length     = sizeof(SCSI_REQUEST_BLOCK);
11130 
11131     // Set flags to disable synchronous negociation.
11132     srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
11133 
11134     // Set timeout to 2 seconds.
11135     srb->TimeOutValue = 4;
11136 
11137     srb->CdbLength          = 6;
11138     srb->DataBuffer         = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusSense);
11139     srb->DataTransferLength = sizeof(SENSE_DATA);
11140     srb->SrbExtension       = AtaReq;
11141 
11142     // Set CDB operation code.
11143     cdb = (PCDB)srb->Cdb;
11144     cdb->CDB6INQUIRY.OperationCode    = SCSIOP_REQUEST_SENSE;
11145     cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
11146 
11147     KdPrint2((PRINT_PREFIX " RequestSenseSrb %#x\n", srb));
11148 
11149     return srb;
11150 } // end BuildRequestSenseSrb()
11151 
11152 #ifndef UNIATA_CORE
11153 
11154 ULONG
11155 NTAPI
11156 AtapiRegCheckDevLunValue(
11157     IN PVOID HwDeviceExtension,
11158     IN PCWCH NamePrefix,
11159     IN ULONG chan,
11160     IN ULONG dev,
11161     IN PCWSTR Name,
11162     IN ULONG Default
11163     )
11164 {
11165     WCHAR namex[160];
11166     ULONG val = Default;
11167 
11168     val = AtapiRegCheckParameterValue(
11169         HwDeviceExtension, NamePrefix, Name, val);
11170 
11171     if(chan != CHAN_NOT_SPECIFIED) {
11172         swprintf(namex, L"%s\\Chan_%1.1d", NamePrefix, chan);
11173         val = AtapiRegCheckParameterValue(
11174             HwDeviceExtension, namex, Name, val);
11175         if(dev != DEVNUM_NOT_SPECIFIED) {
11176             swprintf(namex, L"%s\\Chan_%1.1d\\%s", NamePrefix, chan, (dev & 0x01) ? L"Lun_1" : L"Lun_0");
11177             val = AtapiRegCheckParameterValue(
11178                 HwDeviceExtension, namex, Name, val);
11179         }
11180     }
11181     return val;
11182 } // end AtapiRegCheckDevLunValue()
11183 
11184 ULONG
11185 NTAPI
11186 EncodeVendorStr(
11187    OUT PWCHAR Buffer,
11188     IN PUCHAR Str,
11189     IN ULONG  Length
11190     )
11191 {
11192     ULONG i,j;
11193     WCHAR a;
11194 
11195     for(i=0, j=0; i<Length; i++, j++) {
11196         // fix byte-order
11197         a = Str[i ^ 0x01];
11198         if(!a) {
11199             Buffer[j] = 0;
11200             return j;
11201         } else
11202         if(a == ' ') {
11203             Buffer[j] = '_';
11204         } else
11205         if((a == '_') ||
11206            (a == '#') ||
11207            (a == '\\') ||
11208            (a == '\"') ||
11209            (a == '\'') ||
11210            (a <  ' ') ||
11211            (a >= 127)) {
11212             Buffer[j] = '#';
11213             j++;
11214             swprintf(Buffer+j, L"%2.2x", a);
11215             j++;
11216         } else {
11217             Buffer[j] = a;
11218         }
11219     }
11220     Buffer[j] = 0;
11221     return j;
11222 } // end EncodeVendorStr()
11223 
11224 ULONG
11225 NTAPI
11226 AtapiRegCheckDevValue(
11227     IN PVOID HwDeviceExtension,
11228     IN ULONG chan,
11229     IN ULONG dev,
11230     IN PCWSTR Name,
11231     IN ULONG Default
11232     )
11233 {
11234     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
11235 //    WCHAR name0[11];
11236 //    WCHAR name1[11+4+5];
11237 //    WCHAR name2[11+4+4+10];
11238 //    WCHAR name3[11+4+4+5+20];
11239 //    WCHAR name3[11+4+4+5+20+1];
11240     WCHAR namex[160];
11241 
11242     WCHAR namev[16];
11243     WCHAR named[16];
11244     WCHAR names[20];
11245 
11246     IN ULONG VendorID;
11247     IN ULONG DeviceID;
11248     IN ULONG SlotNumber;
11249     IN ULONG HwFlags;
11250 
11251     ULONG val = Default;
11252 
11253     KdPrint(( " Parameter %ws\n", Name));
11254 
11255     if(deviceExtension) {
11256         VendorID   =  deviceExtension->DevID        & 0xffff;
11257         DeviceID   = (deviceExtension->DevID >> 16) & 0xffff;
11258         SlotNumber = deviceExtension->slotNumber;
11259         HwFlags    = deviceExtension->HwFlags;
11260     } else {
11261         VendorID   = 0xffff;
11262         DeviceID   = 0xffff;
11263         SlotNumber = 0xffffffff;
11264         HwFlags    = 0;
11265     }
11266 
11267     val = AtapiRegCheckDevLunValue(
11268         HwDeviceExtension, L"Parameters", chan, dev, Name, val);
11269 
11270     if(deviceExtension) {
11271 
11272         if(HwFlags & UNIATA_SATA) {
11273             swprintf(namev, L"\\SATA");
11274             swprintf(namex, L"Parameters%s", namev);
11275             val = AtapiRegCheckDevLunValue(
11276                 HwDeviceExtension, namex, chan, dev, Name, val);
11277         }
11278         if(HwFlags & UNIATA_AHCI) {
11279             swprintf(namev, L"\\AHCI");
11280             swprintf(namex, L"Parameters%s", namev);
11281             val = AtapiRegCheckDevLunValue(
11282                 HwDeviceExtension, namex, chan, dev, Name, val);
11283         }
11284         if(!(HwFlags & (UNIATA_SATA | UNIATA_AHCI))) {
11285             swprintf(namev, L"\\PATA");
11286             swprintf(namex, L"Parameters%s", namev);
11287             val = AtapiRegCheckDevLunValue(
11288                 HwDeviceExtension, namex, chan, dev, Name, val);
11289         }
11290 
11291         if(deviceExtension->AdapterInterfaceType == PCIBus) {
11292             // PCI
11293             swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex);
11294             swprintf(namex, L"Parameters%s", namev);
11295             val = AtapiRegCheckDevLunValue(
11296                 HwDeviceExtension, namex, chan, dev, Name, val);
11297 
11298 
11299             swprintf(namev, L"\\Ven_%4.4x", VendorID);
11300             swprintf(named, L"\\Dev_%4.4x", DeviceID);
11301             swprintf(names, L"\\Slot_%8.8x", SlotNumber);
11302 
11303             swprintf(namex, L"Parameters%s", namev);
11304             val = AtapiRegCheckDevLunValue(
11305                 HwDeviceExtension, namex, chan, dev, Name, val);
11306 
11307             swprintf(namex, L"Parameters%s%s", namev, named);
11308             val = AtapiRegCheckDevLunValue(
11309                 HwDeviceExtension, namex, chan, dev, Name, val);
11310 
11311             swprintf(namex, L"Parameters%s%s%s", namev, named, names);
11312             val = AtapiRegCheckDevLunValue(
11313                 HwDeviceExtension, namex, chan, dev, Name, val);
11314         } else
11315         if(deviceExtension->AdapterInterfaceType == Isa) {
11316             // Isa
11317             swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen);
11318             swprintf(namex, L"Parameters%s", namev);
11319             val = AtapiRegCheckDevLunValue(
11320                 HwDeviceExtension, namex, chan, dev, Name, val);
11321 
11322             swprintf(namev, L"\\ISA_%d", deviceExtension->DevIndex);
11323             swprintf(namex, L"Parameters%s", namev);
11324             val = AtapiRegCheckDevLunValue(
11325                 HwDeviceExtension, namex, chan, dev, Name, val);
11326 
11327         } else
11328         if(deviceExtension->AdapterInterfaceType == MicroChannel) {
11329             // MicroChannel
11330             swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen+IsaCount);
11331             swprintf(namex, L"Parameters%s", namev);
11332             val = AtapiRegCheckDevLunValue(
11333                 HwDeviceExtension, namex, chan, dev, Name, val);
11334 
11335             swprintf(namev, L"\\MCA_%d", deviceExtension->DevIndex);
11336             swprintf(namex, L"Parameters%s", namev);
11337             val = AtapiRegCheckDevLunValue(
11338                 HwDeviceExtension, namex, chan, dev, Name, val);
11339 
11340         }
11341     }
11342 
11343     KdPrint(( " Parameter %ws = %#x\n", Name, val));
11344     return val;
11345 
11346 } // end AtapiRegCheckDevValue()
11347 
11348 /*
11349     The user must specify that Xxx is to run on the platform
11350     by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
11351     Services\UniATA\Xxx:REG_DWORD:Zzz.
11352 
11353     The user can override the global setting to enable or disable Xxx on a
11354     specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
11355     CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
11356 
11357     If this registry value does not exist or contains the value zero then
11358     the timer to check for media change does not run.
11359 
11360     Arguments:
11361 
11362     RegistryPath - pointer to the unicode string inside
11363                    ...\CurrentControlSet\Services\UniATA
11364     DeviceNumber - The number of the HBA device object
11365 
11366     Returns:    Registry Key value
11367  */
11368 ULONG
11369 NTAPI
11370 AtapiRegCheckParameterValue(
11371     IN PVOID HwDeviceExtension,
11372     IN PCWSTR PathSuffix,
11373     IN PCWSTR Name,
11374     IN ULONG Default
11375     )
11376 {
11377 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
11378 
11379 //    PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
11380     NTSTATUS          status;
11381     LONG              zero = Default;
11382 
11383     RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY];
11384 
11385 //    LONG              tmp = 0;
11386     LONG              doRun = Default;
11387 
11388     PUNICODE_STRING   RegistryPath = &SavedRegPath;
11389 
11390     UNICODE_STRING    paramPath;
11391 
11392     if(g_Dump) {
11393         goto failed;
11394     }
11395 
11396     // <SavedRegPath>\<PathSuffix> -> <Name>
11397 //    KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
11398 //    KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
11399 
11400     paramPath.Length = 0;
11401     paramPath.MaximumLength = RegistryPath->Length +
11402         (wcslen(PathSuffix)+2)*sizeof(WCHAR);
11403     paramPath.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, paramPath.MaximumLength);
11404     if(!paramPath.Buffer) {
11405         KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
11406         return Default;
11407     }
11408 
11409     RtlZeroMemory(paramPath.Buffer, paramPath.MaximumLength);
11410     RtlAppendUnicodeToString(&paramPath, RegistryPath->Buffer);
11411     RtlAppendUnicodeToString(&paramPath, L"\\");
11412     RtlAppendUnicodeToString(&paramPath, REGRTL_STR_PTYPE PathSuffix);
11413 
11414     // Check for the Xxx value.
11415     RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
11416 
11417     parameters[0].Flags         = RTL_QUERY_REGISTRY_DIRECT;
11418     parameters[0].Name          = REGRTL_STR_PTYPE Name;
11419     parameters[0].EntryContext  = &doRun;
11420     parameters[0].DefaultType   = REG_DWORD;
11421     parameters[0].DefaultData   = &zero;
11422     parameters[0].DefaultLength = sizeof(ULONG);
11423 
11424     status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/,
11425                                     paramPath.Buffer, parameters, NULL, NULL);
11426     if(NT_SUCCESS(status)) {
11427         KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun));
11428     }
11429 
11430     ExFreePool(paramPath.Buffer);
11431 
11432     if(!NT_SUCCESS(status)) {
11433 failed:
11434         doRun = Default;
11435     }
11436 
11437     return doRun;
11438 
11439 #undef ITEMS_TO_QUERY
11440 
11441 } // end AtapiRegCheckParameterValue()
11442 
11443 
11444 SCSI_ADAPTER_CONTROL_STATUS
11445 NTAPI
11446 AtapiAdapterControl(
11447     IN PVOID HwDeviceExtension,
11448     IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
11449     IN PVOID Parameters
11450     )
11451 {
11452     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
11453     PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList;
11454     ULONG                numberChannels  = deviceExtension->NumberChannels;
11455     ULONG c;
11456     NTSTATUS status;
11457 
11458     KdPrint(( "AtapiAdapterControl: %#x\n", ControlType));
11459 
11460     switch(ControlType) {
11461         case ScsiQuerySupportedControlTypes: {
11462             BOOLEAN supportedTypes[ScsiAdapterControlMax] = {
11463                 TRUE,       // ScsiQuerySupportedControlTypes
11464                 TRUE,       // ScsiStopAdapter
11465                 TRUE,       // ScsiRestartAdapter
11466                 FALSE,      // ScsiSetBootConfig
11467                 FALSE       // ScsiSetRunningConfig
11468             };
11469 
11470             ULONG lim = ScsiAdapterControlMax;
11471             ULONG i;
11472 
11473             pControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST) Parameters;
11474 
11475             if(pControlTypeList->MaxControlType < lim) {
11476                 lim = pControlTypeList->MaxControlType;
11477             }
11478 
11479             for(i = 0; i < lim; i++) {
11480                 pControlTypeList->SupportedTypeList[i] = supportedTypes[i];
11481             }
11482 
11483             break;
11484 
11485         }
11486         case ScsiStopAdapter: {
11487 
11488             KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
11489             // Shut down all interrupts on the adapter.  They'll get re-enabled
11490             // by the initialization routines.
11491             for (c = 0; c < numberChannels; c++) {
11492                 AtapiResetController(deviceExtension, c);
11493                 AtapiDisableInterrupts(deviceExtension, c);
11494             }
11495             if(deviceExtension->AdapterInterfaceType == PCIBus) {
11496                 // we must never get here for non-PCI
11497                 /*status =*/ UniataDisconnectIntr2(HwDeviceExtension);
11498                 BMList[deviceExtension->DevIndex].Isr2Enable = FALSE;
11499             }
11500             break;
11501         }
11502         case ScsiRestartAdapter: {
11503 
11504             KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
11505             // Enable all the interrupts on the adapter while port driver call
11506             // for power up an HBA that was shut down for power management
11507 
11508             AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
11509             status = UniataConnectIntr2(HwDeviceExtension);
11510             if(NT_SUCCESS(status)) {
11511                 for (c = 0; c < numberChannels; c++) {
11512                     AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, c);
11513                     FindDevices(HwDeviceExtension, 0, c);
11514                     AtapiEnableInterrupts(deviceExtension, c);
11515                     AtapiHwInitialize__(deviceExtension, c);
11516                 }
11517                 if(deviceExtension->Isr2DevObj) {
11518                     // we must never get here for non-PCI
11519                     BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
11520                 }
11521             }
11522 
11523             break;
11524         }
11525 
11526         default: {
11527             KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
11528             return ScsiAdapterControlUnsuccessful;
11529         }
11530     }
11531 
11532     return ScsiAdapterControlSuccess;
11533 } // end AtapiAdapterControl()
11534 
11535 #endif //UNIATA_CORE
11536 
11537 extern "C"
11538 NTHALAPI
11539 VOID
11540 NTAPI
11541 HalDisplayString (
11542     PUCHAR String
11543     );
11544 
11545 #define DEBUG_MSG_BUFFER_SIZE   512
11546 
11547 extern "C"
11548 VOID
11549 _cdecl
11550 _PrintNtConsole(
11551     PCCH DebugMessage,
11552     ...
11553     )
11554 {
11555     //int len;
11556     UCHAR dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE];
11557 //    UNICODE_STRING msgBuff;
11558     va_list ap;
11559     va_start(ap, DebugMessage);
11560 
11561     /*len =*/ _vsnprintf((PCHAR)&dbg_print_tmp_buff[0], DEBUG_MSG_BUFFER_SIZE-1, DebugMessage, ap);
11562 
11563     dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE-1] = 0;
11564 
11565     //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro
11566     HalDisplayString(dbg_print_tmp_buff);
11567 
11568 #ifdef _DEBUG
11569     if(g_LogToDisplay > 1) {
11570         AtapiStallExecution(g_LogToDisplay*1000);
11571     }
11572 #endif // _DEBUG
11573 
11574     va_end(ap);
11575 
11576 } // end PrintNtConsole()
11577 
11578