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