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