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