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