83f41ea6460304b739ad8dabb530f744015f4782
[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 if(deviceExtension->HwFlags & UNIATA_AHCI) {
4024 // keep interrupts disabled
4025 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
4026 } else {
4027 AtapiWritePort1(chan, IDX_IO2_o_Control,
4028 IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4029 }
4030 }
4031 return;
4032 } // end AtapiEnableInterrupts()
4033
4034 VOID
4035 NTAPI
4036 AtapiDisableInterrupts(
4037 IN PVOID HwDeviceExtension,
4038 IN ULONG c
4039 )
4040 {
4041 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4042 PHW_CHANNEL chan;
4043 if(c >= deviceExtension->NumberChannels) {
4044 KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c));
4045 return;
4046 }
4047 chan = &(deviceExtension->chan[c]);
4048 KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: %d\n",c, chan->DisableIntr));
4049 // mark channel as busy
4050 if(InterlockedIncrement(&chan->DisableIntr)) {
4051 if(deviceExtension->HwFlags & UNIATA_AHCI) {
4052 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
4053 } else {
4054 //SelectDrive(chan, 0);
4055 AtapiWritePort1(chan, IDX_IO2_o_Control,
4056 IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4057 //if(chan->NumberLuns) {
4058 // SelectDrive(chan, 1);
4059 // AtapiWritePort1(chan, IDX_IO2_o_Control,
4060 // IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4061 // SelectDrive(chan, chan->cur_cdev);
4062 //}
4063 }
4064 chan->ChannelCtrlFlags |= CTRFLAGS_INTR_DISABLED;
4065 }
4066
4067 return;
4068 } // end AtapiDisableInterrupts()
4069
4070 VOID
4071 UniataExpectChannelInterrupt(
4072 IN struct _HW_CHANNEL* chan,
4073 IN BOOLEAN Expecting
4074 )
4075 {
4076 chan->ExpectingInterrupt = Expecting;
4077 if(Expecting) {
4078 chan->DeviceExtension->ExpectingInterrupt++;
4079 } else
4080 if(chan->DeviceExtension->ExpectingInterrupt) {
4081 chan->DeviceExtension->ExpectingInterrupt--;
4082 }
4083 return;
4084 } // end UniataExpectChannelInterrupt()
4085
4086 /*
4087 Check hardware for interrupt state
4088 */
4089 BOOLEAN
4090 NTAPI
4091 AtapiCheckInterrupt__(
4092 IN PVOID HwDeviceExtension,
4093 IN UCHAR c // logical channel
4094 )
4095 {
4096 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4097 PHW_CHANNEL chan = &(deviceExtension->chan[c]);
4098 PHW_LU_EXTENSION LunExt;
4099
4100 ULONG VendorID = deviceExtension->DevID & 0xffff;
4101 ULONG ChipType = deviceExtension->HwFlags & CHIPTYPE_MASK;
4102
4103 ULONG status;
4104 ULONG pr_status = 0;
4105 UCHAR dma_status = 0;
4106 UCHAR reg8 = 0;
4107 ULONG reg32 = 0;
4108 UCHAR statusByte = 0;
4109 ULONG slotNumber = deviceExtension->slotNumber;
4110 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
4111 ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
4112 UCHAR Channel;
4113 UCHAR lChannel;
4114 BOOLEAN DmaTransfer = FALSE;
4115 BOOLEAN OurInterrupt = FALSE;
4116 BOOLEAN StatusValid = FALSE;
4117 // ULONG k;
4118 UCHAR interruptReason;
4119 BOOLEAN EarlyIntr = FALSE;
4120 BOOLEAN SingleBlockIntr = FALSE;
4121
4122 KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__:\n"));
4123
4124 lChannel = c;
4125 Channel = (UCHAR)(deviceExtension->Channel + lChannel);
4126 LunExt = chan->lun[chan->cur_cdev];
4127
4128 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ chan %#x:\n", chan));
4129 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ (%d/%d):\n", Channel, chan->cur_cdev));
4130
4131 if((ChipFlags & UNIATA_AHCI) &&
4132 UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
4133
4134 if(!UniataAhciChanImplemented(deviceExtension, lChannel)) {
4135 return OurInterrupt;
4136 }
4137
4138 OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED);
4139 if((OurInterrupt == INTERRUPT_REASON_UNEXPECTED) &&
4140 (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
4141 UniataAhciWaitCommandReady(chan, 2 /* ms */ );
4142 statusByte = (UCHAR)UniataAhciWaitReady(chan, 0 /* immediate */);
4143 if(!(statusByte & (IDE_STATUS_BUSY)) ) {
4144 KdPrint2((PRINT_PREFIX "ATAPI special case READY\n"));
4145 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
4146 OurInterrupt = INTERRUPT_REASON_OUR;
4147 } else
4148 if((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRDY)) == (IDE_STATUS_BUSY | IDE_STATUS_DRDY) ) {
4149 KdPrint2((PRINT_PREFIX "ATAPI special case pre ERR-READY\n"));
4150 OurInterrupt = INTERRUPT_REASON_OUR;
4151 } else
4152 if(statusByte & IDE_STATUS_ERROR) {
4153 KdPrint2((PRINT_PREFIX "ATAPI special case ERR-READY\n"));
4154 OurInterrupt = INTERRUPT_REASON_OUR;
4155 } else {
4156 KdPrint2((PRINT_PREFIX "ATAPI special case ? %x\n", statusByte));
4157 OurInterrupt = INTERRUPT_REASON_OUR;
4158 }
4159 }
4160 return OurInterrupt;
4161 }
4162
4163 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) {
4164 DmaTransfer = TRUE;
4165 KdPrint2((PRINT_PREFIX " cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension->DevIndex,
4166 deviceExtension->Channel + c, c));
4167 } else {
4168 KdPrint2((PRINT_PREFIX " cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension->DevIndex,
4169 deviceExtension->Channel + c, c));
4170 dma_status = GetDmaStatus(deviceExtension, lChannel);
4171 KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
4172 }
4173
4174 // do controller-specific interrupt servicing staff
4175 if(deviceExtension->UnknownDev) {
4176 KdPrint2((PRINT_PREFIX " UnknownDev\n"));
4177 goto check_unknown;
4178 }
4179
4180 // Attention !
4181 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
4182 // Such behavior was observed with Intel ICH-xxx chips
4183 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
4184
4185 switch(VendorID) {
4186
4187 case ATA_PROMISE_ID: {
4188 switch(ChipType) {
4189 case PROLD:
4190 case PRNEW:
4191 status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x1c);
4192 if (!DmaTransfer)
4193 break;
4194 if (!(status &
4195 ((Channel) ? 0x00004000 : 0x00000400))) {
4196 KdPrint2((PRINT_PREFIX " Promise old/new unexpected\n"));
4197 return INTERRUPT_REASON_IGNORE;
4198 }
4199 break;
4200 case PRTX:
4201 AtapiWritePort1(chan, IDX_BM_DeviceSpecific0, 0x0b);
4202 status = AtapiReadPort1(chan, IDX_BM_DeviceSpecific1);
4203 if (!DmaTransfer)
4204 break;
4205 if(!(status & 0x20)) {
4206 KdPrint2((PRINT_PREFIX " Promise tx unexpected\n"));
4207 return INTERRUPT_REASON_IGNORE;
4208 }
4209 break;
4210 case PRMIO: {
4211 ULONG stat_reg = (ChipFlags & PRG2) ? 0x60 : 0x6c;
4212 status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x40);
4213 AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x40, status);
4214
4215 if(status & (1 << (Channel+1))) {
4216 // our
4217 } else {
4218 KdPrint2((PRINT_PREFIX " Promise mio unexpected\n"));
4219 return INTERRUPT_REASON_IGNORE;
4220 }
4221
4222 if(!(ChipFlags & UNIATA_SATA))
4223 break;
4224
4225 pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),stat_reg);
4226 AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),stat_reg, (pr_status & (0x11 << Channel)));
4227 if(pr_status & (0x11 << Channel)) {
4228 // TODO: reset channel
4229 KdPrint2((PRINT_PREFIX " Promise mio unexpected + reset req\n"));
4230 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, 0);
4231 }
4232 if(!(status & (0x01 << Channel))) {
4233 // Connect event
4234 KdPrint2((PRINT_PREFIX " Promise mio unexpected attach\n"));
4235 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, 0);
4236 }
4237 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
4238 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4239 } else {
4240 return INTERRUPT_REASON_IGNORE;
4241 }
4242
4243 AtapiWritePort4(chan, IDX_BM_DeviceSpecific0, 0x00000001);
4244 break; }
4245 }
4246 break; }
4247 case ATA_NVIDIA_ID: {
4248 if(!(ChipFlags & UNIATA_SATA))
4249 break;
4250
4251 KdPrint2((PRINT_PREFIX "NVIDIA\n"));
4252
4253 ULONG offs = (ChipFlags & NV4OFF) ? 0x0440 : 0x0010;
4254 ULONG shift = Channel << ((ChipFlags & NVQ) ? 4 : 2);
4255
4256 /* get and clear interrupt status */
4257 if(ChipFlags & NVQ) {
4258 pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs);
4259 AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0fUL << shift) | 0x00f000f0);
4260 } else {
4261 pr_status = AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs);
4262 AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0f << shift));
4263 }
4264 KdPrint2((PRINT_PREFIX " pr_status %x\n", pr_status));
4265
4266 /* check for and handle connect events */
4267 if(((pr_status & (0x0cUL << shift)) == (0x04UL << shift)) ) {
4268 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, 0);
4269 }
4270 /* check for and handle disconnect events */
4271 if((pr_status & (0x08UL << shift)) &&
4272 !((pr_status & (0x04UL << shift) &&
4273 UniataSataReadPort4(chan, IDX_SATA_SStatus, 0))) ) {
4274 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, 0);
4275 }
4276 /* do we have any device action ? */
4277 if(!(pr_status & (0x01UL << shift))) {
4278 KdPrint2((PRINT_PREFIX " nVidia unexpected\n"));
4279 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
4280 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4281 } else {
4282 return INTERRUPT_REASON_IGNORE;
4283 }
4284 }
4285
4286 break; }
4287 case ATA_ATI_ID:
4288 KdPrint2((PRINT_PREFIX "ATI\n"));
4289 if(ChipType == SIIMIO) {
4290 // fall to SiI
4291 } else {
4292 break;
4293 }
4294 case ATA_SILICON_IMAGE_ID:
4295
4296 if(ChipType == SIIMIO) {
4297
4298 reg32 = AtapiReadPort4(chan, IDX_BM_DeviceSpecific0);
4299 KdPrint2((PRINT_PREFIX " Sii DS0 %x\n", reg32));
4300 if(reg32 == 0xffffffff) {
4301 KdPrint2((PRINT_PREFIX " Sii mio unexpected\n"));
4302 return INTERRUPT_REASON_IGNORE;
4303 }
4304 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))) {
4305 KdPrint2((PRINT_PREFIX " Sii mio unexpected (2)\n"));
4306 return INTERRUPT_REASON_IGNORE;
4307 }
4308
4309 if(ChipFlags & UNIATA_SATA) {
4310 if(reg32 & (BM_DS0_SII_DMA_SATA_IRQ | BM_DS0_SII_IRQ)) {
4311
4312 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
4313 * controllers continue to assert IRQ as long as
4314 * SError bits are pending. Clear SError immediately.
4315 */
4316 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
4317 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4318 }
4319 }
4320 }
4321
4322 if (!DmaTransfer)
4323 break;
4324 if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
4325 KdPrint2((PRINT_PREFIX " Sii mio unexpected (3)\n"));
4326 return OurInterrupt;
4327 }
4328 AtapiWritePort1(chan, IDX_BM_Status, dma_status & ~BM_STATUS_ERR);
4329 goto skip_dma_stat_check;
4330
4331 } else {
4332 if(!(deviceExtension->HwFlags & SIIINTR))
4333 break;
4334 GetPciConfig1(0x71, reg8);
4335 KdPrint2((PRINT_PREFIX " 0x71 = %#x\n", reg8));
4336 if (!(reg8 &
4337 (Channel ? 0x08 : 0x04))) {
4338 return INTERRUPT_REASON_IGNORE;
4339 }
4340 if (!DmaTransfer) {
4341 KdPrint2((PRINT_PREFIX " cmd our\n"));
4342 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4343 }
4344 SetPciConfig1(0x71, (Channel ? 0x08 : 0x04));
4345 }
4346 break;
4347
4348 case ATA_ACARD_ID:
4349 if (!DmaTransfer)
4350 break;
4351 //dma_status = GetDmaStatus(deviceExtension, lChannel);
4352 if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
4353 KdPrint2((PRINT_PREFIX " Acard unexpected\n"));
4354 return INTERRUPT_REASON_IGNORE;
4355 }
4356 AtapiWritePort1(chan, IDX_BM_Status, dma_status | BM_STATUS_INTR);
4357 AtapiStallExecution(1);
4358 AtapiWritePort1(chan, IDX_BM_Command,
4359 AtapiReadPort1(chan, IDX_BM_Command) & ~BM_COMMAND_START_STOP);
4360 goto skip_dma_stat_check;
4361 case ATA_INTEL_ID:
4362 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
4363 if(ChipFlags & UNIATA_AHCI) {
4364 // Do nothing here
4365 } else
4366 if(ChipFlags & UNIATA_SATA) {
4367 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
4368 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4369 }
4370 if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
4371 if(UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1)) {
4372 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4373 }
4374 }
4375 }
4376 }
4377 break;
4378 default:
4379 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
4380 if(ChipFlags & UNIATA_AHCI) {
4381 // Do nothing here
4382 } else
4383 if(ChipFlags & UNIATA_SATA) {
4384 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
4385 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4386 }
4387 }
4388 }
4389 }
4390 check_unknown:
4391 KdPrint2((PRINT_PREFIX " perform generic check\n"));
4392 if (DmaTransfer) {
4393 if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
4394 KdPrint2((PRINT_PREFIX " DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status));
4395 if(dma_status & BM_STATUS_ERR) {
4396 KdPrint2((PRINT_PREFIX " DmaTransfer + BM_STATUS_ERR -> our\n"));
4397 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4398 } else {
4399 KdPrint2((PRINT_PREFIX " getting status...\n"));
4400 GetStatus(chan, statusByte);
4401 StatusValid = 1;
4402 KdPrint2((PRINT_PREFIX " status %#x\n", statusByte));
4403 if(statusByte & IDE_STATUS_ERROR) {
4404 KdPrint2((PRINT_PREFIX " IDE_STATUS_ERROR -> our\n", statusByte));
4405 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4406 } else
4407 if ((statusByte & IDE_STATUS_DSC) &&
4408 (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
4409 (dma_status == BM_STATUS_ACTIVE)) {
4410 KdPrint2((PRINT_PREFIX " special case DMA + ATAPI + IDE_STATUS_DSC -> our\n", statusByte));
4411 // some devices interrupts on each block transfer even in DMA mode
4412 if(LunExt->TransferMode >= ATA_SDMA && LunExt->TransferMode <= ATA_WDMA2) {
4413 KdPrint2((PRINT_PREFIX " wait for completion\n"));
4414 ///* clear interrupt and get status */
4415 //GetBaseStatus(chan, statusByte);
4416 //return INTERRUPT_REASON_IGNORE;
4417 SingleBlockIntr = TRUE;
4418 }
4419 } else {
4420 return INTERRUPT_REASON_IGNORE;
4421 }
4422 }
4423 }
4424 } else {
4425 if(dma_status & BM_STATUS_INTR) {
4426 // bullshit, we have DMA interrupt, but had never initiate DMA operation
4427 KdPrint2((PRINT_PREFIX " clear unexpected DMA intr\n"));
4428 AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL);
4429 // catch it !
4430 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4431 }
4432 }
4433 skip_dma_stat_check:
4434 if(!(ChipFlags & UNIATA_SATA) && chan->ExpectingInterrupt) {
4435 AtapiStallExecution(1);
4436 }
4437
4438 /* if drive is busy it didn't interrupt */
4439 /* the exception is DCS + BSY state of ATAPI devices */
4440 if(!StatusValid) {
4441 KdPrint2((PRINT_PREFIX " getting status...\n"));
4442 GetStatus(chan, statusByte);
4443 }
4444 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
4445 KdPrint3((PRINT_PREFIX " ATAPI status %#x\n", statusByte));
4446 } else {
4447 KdPrint2((PRINT_PREFIX " IDE status %#x\n", statusByte));
4448 }
4449 if (statusByte == IDE_STATUS_WRONG) {
4450 // interrupt from empty controller ?
4451 } else
4452 if (statusByte & IDE_STATUS_BUSY) {
4453 if(!chan->ExpectingInterrupt) {
4454 KdPrint3((PRINT_PREFIX " unexpected intr + BUSY\n"));
4455 return OurInterrupt;
4456 }
4457
4458 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
4459 KdPrint2((PRINT_PREFIX " ATAPI additional check\n"));
4460 } else {
4461 KdPrint2((PRINT_PREFIX " expecting intr + BUSY (3), non ATAPI\n"));
4462 return INTERRUPT_REASON_IGNORE;
4463 }
4464 if((statusByte & ~IDE_STATUS_DRQ) != (IDE_STATUS_BUSY | IDE_STATUS_DRDY | IDE_STATUS_DSC)) {
4465 KdPrint3((PRINT_PREFIX " unexpected status, seems it is not our\n"));
4466 return INTERRUPT_REASON_IGNORE;
4467 }
4468 if(!(LunExt->DeviceFlags & DFLAGS_INT_DRQ) && (statusByte & IDE_STATUS_DRQ)) {
4469 KdPrint3((PRINT_PREFIX " unexpected DRQ, seems it is not our\n"));
4470 return INTERRUPT_REASON_IGNORE;
4471 }
4472
4473 EarlyIntr = TRUE;
4474
4475 if(dma_status & BM_STATUS_INTR) {
4476 KdPrint3((PRINT_PREFIX " our interrupt with BSY set, try wait in ISR or post to DPC\n"));
4477 /* clear interrupt and get status */
4478 GetBaseStatus(chan, statusByte);
4479 if(!(dma_status & BM_STATUS_ACTIVE)) {
4480 AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL);
4481 }
4482 KdPrint3((PRINT_PREFIX " base status %#x (+BM_STATUS_INTR)\n", statusByte));
4483 return INTERRUPT_REASON_OUR;
4484 }
4485
4486 if(g_WaitBusyInISR) {
4487 GetStatus(chan, statusByte);
4488 KdPrint2((PRINT_PREFIX " status re-check %#x\n", statusByte));
4489 reg8 = AtapiReadPort1(chan, IDX_IO1_i_Error);
4490 KdPrint2((PRINT_PREFIX " Error reg (%#x)\n", reg8));
4491 if (!(statusByte & IDE_STATUS_BUSY)) {
4492 KdPrint2((PRINT_PREFIX " expecting intr + cleared BUSY\n"));
4493 }
4494 if (statusByte & IDE_STATUS_BUSY) {
4495 KdPrint2((PRINT_PREFIX " still BUSY, seems it is not our\n"));
4496 return INTERRUPT_REASON_IGNORE;
4497 }
4498 }
4499
4500 }
4501
4502 /* clear interrupt and get status */
4503 GetBaseStatus(chan, statusByte);
4504 KdPrint2((PRINT_PREFIX " base status %#x\n", statusByte));
4505 if (statusByte == IDE_STATUS_WRONG) {
4506 // interrupt from empty controller ?
4507 } else
4508 if(!(statusByte & (IDE_STATUS_DRQ | IDE_STATUS_DRDY))) {
4509 KdPrint2((PRINT_PREFIX " no DRQ/DRDY set\n"));
4510 return OurInterrupt;
4511 }
4512
4513 #ifndef UNIATA_PIO_ONLY
4514 if(DmaTransfer) {
4515 if(!SingleBlockIntr && (!EarlyIntr || g_WaitBusyInISR)) {
4516 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
4517 } else {
4518 PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
4519 PATA_REQ AtaReq = srb ? (PATA_REQ)(srb->SrbExtension) : NULL;
4520
4521 //ASSERT(AtaReq);
4522
4523 if(SingleBlockIntr) {
4524 KdPrint2((PRINT_PREFIX " set REQ_STATE_ATAPI_EXPECTING_DATA_INTR2.\n"));
4525 } else {
4526 KdPrint2((PRINT_PREFIX " set REQ_STATE_EARLY_INTR.\n"));
4527 }
4528 if(AtaReq) {
4529 AtaReq->ReqState = SingleBlockIntr ? REQ_STATE_ATAPI_EXPECTING_DATA_INTR2 : REQ_STATE_EARLY_INTR;
4530 }
4531 }
4532 }
4533 #endif //
4534
4535 if (!(chan->ExpectingInterrupt)) {
4536
4537 KdPrint2((PRINT_PREFIX " Unexpected interrupt.\n"));
4538
4539 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
4540 KdPrint2((PRINT_PREFIX " ATAPI additional check\n"));
4541 } else {
4542 KdPrint2((PRINT_PREFIX " OurInterrupt = %d\n", OurInterrupt));
4543 return OurInterrupt;
4544 }
4545 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
4546 KdPrint3((PRINT_PREFIX "AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason));
4547 return OurInterrupt;
4548 }
4549 //ASSERT(!chan->queue_depth || chan->cur_req);
4550
4551 KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__: exit with TRUE\n"));
4552 return INTERRUPT_REASON_OUR;
4553
4554 } // end AtapiCheckInterrupt__()
4555
4556
4557 BOOLEAN
4558 NTAPI
4559 AtapiInterrupt__(
4560 IN PVOID HwDeviceExtension,
4561 IN UCHAR c
4562 )
4563 {
4564 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4565 PHW_CHANNEL chan = &(deviceExtension->chan[c]);
4566 // Get current Srb
4567 PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
4568 PATA_REQ AtaReq = srb ? (PATA_REQ)(srb->SrbExtension) : NULL;
4569
4570 ULONG wordCount = 0, wordsThisInterrupt = DEV_BSIZE/2;
4571 ULONG status = SRB_STATUS_SUCCESS;
4572 UCHAR dma_status = 0;
4573 ULONG i;
4574 ULONG k;
4575 UCHAR statusByte = 0,interruptReason;
4576
4577 BOOLEAN atapiDev = FALSE;
4578
4579 #ifdef DBG
4580 UCHAR Channel;
4581 #endif //DBG
4582 UCHAR lChannel;
4583 UCHAR DeviceNumber;
4584 BOOLEAN DmaTransfer = FALSE;
4585 UCHAR error = 0;
4586 ULONG TimerValue = 1000;
4587 ULONG TotalTimerValue = 0;
4588 #ifdef UNIATA_USE_XXableInterrupts
4589 BOOLEAN InDpc = (KeGetCurrentIrql() == DISPATCH_LEVEL);
4590 #else
4591 BOOLEAN InDpc = (chan->DpcState != DPC_STATE_ISR);
4592 #endif // UNIATA_USE_XXableInterrupts
4593 BOOLEAN UseDpc = deviceExtension->UseDpc;
4594 // BOOLEAN RestoreUseDpc = FALSE;
4595 BOOLEAN DataOverrun = FALSE;
4596 BOOLEAN NoStartIo = TRUE;
4597 BOOLEAN NoRetry = FALSE;
4598
4599 KdPrint2((PRINT_PREFIX "AtapiInterrupt:\n"));
4600 if(InDpc) {
4601 KdPrint2((PRINT_PREFIX " InDpc = TRUE\n"));
4602 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
4603 }
4604
4605 UCHAR PathId;
4606 UCHAR TargetId;
4607 UCHAR Lun;
4608 UCHAR OldReqState = REQ_STATE_NONE;
4609 //ULONG ldev;
4610 PHW_LU_EXTENSION LunExt;
4611
4612 lChannel = c;
4613
4614 #ifdef DBG
4615 Channel = (UCHAR)(deviceExtension->Channel + lChannel);
4616
4617 KdPrint2((PRINT_PREFIX " cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension->DevIndex, Channel, KeGetCurrentIrql(), c));
4618 #endif //DBG
4619
4620 if((chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
4621 (AtaReq && (AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) ||
4622 (deviceExtension->HwFlags & UNIATA_AHCI)) {
4623 DmaTransfer = TRUE;
4624 KdPrint2((PRINT_PREFIX " DmaTransfer = TRUE\n"));
4625 }
4626
4627 if (srb) {
4628 PathId = srb->PathId;
4629 TargetId = srb->TargetId;
4630 Lun = srb->Lun;
4631 } else {
4632 PathId = (UCHAR)c;
4633 TargetId =
4634 Lun = 0;
4635 goto enqueue_next_req;
4636 }
4637
4638 //ldev = GET_LDEV2(PathId, TargetId, Lun);
4639 DeviceNumber = (UCHAR)(TargetId);
4640 LunExt = chan->lun[DeviceNumber];
4641 atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
4642 KdPrint2((PRINT_PREFIX " dev_type %s\n", atapiDev ? "ATAPI" : "IDE"));
4643
4644 // check if we are in ISR DPC
4645 if(InDpc) {
4646 KdPrint2((PRINT_PREFIX " InDpc -> CTRFLAGS_INTR_DISABLED\n"));
4647 goto ServiceInterrupt;
4648 }
4649
4650 if (DmaTransfer) {
4651 dma_status = GetDmaStatus(deviceExtension, lChannel);
4652 }
4653
4654 if (!(chan->ExpectingInterrupt)) {
4655
4656 KdPrint2((PRINT_PREFIX " Unexpected interrupt for this channel.\n"));
4657 return FALSE;
4658 }
4659
4660 // change request state
4661 if(AtaReq) {
4662 OldReqState = AtaReq->ReqState;
4663 AtaReq->ReqState = REQ_STATE_PROCESSING_INTR;
4664 KdPrint2((PRINT_PREFIX " OldReqState = %x\n", OldReqState));
4665 }
4666
4667 // We don't want using DPC for fast operations, like
4668 // DMA completion, sending CDB, short ATAPI transfers, etc.
4669 // !!!! BUT !!!!
4670 // We MUST use DPC, because of interprocessor synchronization
4671 // on multiprocessor platforms
4672
4673 if(DmaTransfer)
4674 goto ServiceInterrupt;
4675
4676 switch(OldReqState) {
4677 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR:
4678 KdPrint3((PRINT_PREFIX " EXPECTING_CMD_INTR\n"));
4679 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR:
4680 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2:
4681 case REQ_STATE_DPC_WAIT_BUSY0:
4682 case REQ_STATE_DPC_WAIT_BUSY1:
4683 KdPrint2((PRINT_PREFIX " continue service interrupt\n"));
4684 goto ServiceInterrupt;
4685 case REQ_STATE_ATAPI_DO_NOTHING_INTR:
4686 KdPrint2((PRINT_PREFIX " do nothing on interrupt\n"));
4687 return TRUE;
4688 }
4689
4690 if(!DmaTransfer && !atapiDev) {
4691 KdPrint2((PRINT_PREFIX " service PIO HDD\n"));
4692 UseDpc = FALSE;
4693 }
4694
4695 #ifndef UNIATA_CORE
4696
4697 if(!UseDpc)
4698 goto ServiceInterrupt;
4699
4700 #ifdef UNIATA_USE_XXableInterrupts
4701 if(InDpc) {
4702 KdPrint2((PRINT_PREFIX " Unexpected InDpc\n"));
4703 ASSERT(FALSE);
4704 // shall never get here
4705 TimerValue = 1;
4706 goto CallTimerDpc;
4707 }
4708
4709 KdPrint2((PRINT_PREFIX " this is direct DPC call on DRQL\n"));
4710 if(AtaReq) {
4711 AtaReq->ReqState = REQ_STATE_DPC_INTR_REQ;
4712 KdPrint2((PRINT_PREFIX " ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
4713 } else {
4714 KdPrint2((PRINT_PREFIX " DPC without AtaReq!!!\n"));
4715 }
4716 #else
4717 KdPrint2((PRINT_PREFIX "call service interrupt\n"));
4718 goto ServiceInterrupt;
4719 #endif // UNIATA_USE_XXableInterrupts
4720
4721 PostToDpc:
4722
4723 // Attention !!!
4724 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
4725 // We always get here when are called from timer callback, which is invoked on DRQL.
4726 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
4727
4728 KdPrint2((PRINT_PREFIX "AtapiInterrupt: start DPC init...\n"));
4729 // disable interrupts for this channel,
4730 // but avoid recursion and double-disable
4731 if(OldReqState != REQ_STATE_DPC_WAIT_BUSY1) {
4732 UniataExpectChannelInterrupt(chan, FALSE);
4733 AtapiDisableInterrupts(deviceExtension, lChannel);
4734 }
4735 // go to ISR DPC
4736 chan->ChannelCtrlFlags |= CTRFLAGS_DPC_REQ;
4737
4738 #ifdef UNIATA_USE_XXableInterrupts
4739 // Will lower IRQL to DISPATCH_LEVEL
4740 ScsiPortNotification(CallEnableInterrupts, HwDeviceExtension,
4741 /*c ?*/ AtapiInterruptDpc/*_1 : AtapiInterruptDpc_0*/);
4742 KdPrint2((PRINT_PREFIX "AtapiInterrupt: DPC inited\n"));
4743 #else
4744 // Will raise IRQL to DIRQL
4745 AtapiQueueTimerDpc(HwDeviceExtension, c,
4746 AtapiInterruptDpc,
4747 TimerValue);
4748 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
4749 #endif // UNIATA_USE_XXableInterrupts
4750 return TRUE;
4751
4752 #ifndef UNIATA_CORE
4753 CallTimerDpc:
4754 AtaReq->ReqState = REQ_STATE_PROCESSING_INTR;
4755 CallTimerDpc2:
4756 if(!InDpc && OldReqState != REQ_STATE_DPC_WAIT_BUSY1) {
4757 // we must block interrupts from this channel
4758 // If device generate new interrupt before we get to DPC,
4759 // ISR will assume, that it is NOT our interrupt
4760 AtapiDisableInterrupts(deviceExtension, lChannel);
4761 // We should not clean ExpectingInterrupt flag on channel, since it is used in DPC
4762 }
4763 // Will raise IRQL to DIRQL
4764 AtapiQueueTimerDpc(HwDeviceExtension, c,
4765 AtapiCallBack_X,
4766 TimerValue);
4767 return TRUE;
4768 #endif //UNIATA_CORE
4769
4770 ServiceInterrupt:
4771
4772 if(AtaReq && InDpc) {
4773 switch(AtaReq->ReqState) {
4774 case REQ_STATE_DPC_WAIT_DRQ0:
4775 goto PIO_wait_DRQ0;
4776 case REQ_STATE_DPC_WAIT_BUSY:
4777 goto PIO_wait_busy;
4778 case REQ_STATE_DPC_WAIT_DRQ:
4779 goto PIO_wait_DRQ;
4780 case REQ_STATE_DPC_WAIT_DRQ_ERR:
4781 goto continue_err;
4782 case REQ_STATE_DPC_WAIT_BUSY0:
4783 case REQ_STATE_DPC_WAIT_BUSY1:
4784 // continue normal execution
4785 break;
4786 }
4787 }
4788 #else
4789 ServiceInterrupt:
4790 #endif //UNIATA_CORE
4791 /*
4792 // make additional delay for old devices (if we are not in DPC)
4793 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
4794 &&
4795 !InDpc &&
4796 !atapiDev &&
4797 !(deviceExtension->HwFlags & UNIATA_SATA)
4798 ) {
4799 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
4800 AtapiStallExecution(10);
4801 }
4802 */
4803
4804 /* clear interrupt and get status */
4805 if(deviceExtension->HwFlags & UNIATA_AHCI) {
4806 UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, srb);
4807 statusByte = (UCHAR)(AtaReq->ahci.in_status & IDE_STATUS_MASK);
4808
4809 if(chan->AhciLastIS & ~(ATA_AHCI_P_IX_DHR | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_SDB)) {
4810 KdPrint3((PRINT_PREFIX "Err intr (%#x), SE (%#x)\n",
4811 chan->AhciLastIS & ~(ATA_AHCI_P_IX_DHR | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_SDB),
4812 chan->AhciLastSError));
4813 if(chan->AhciLastIS & ~ATA_AHCI_P_IX_OF) {
4814 //KdPrint3((PRINT_PREFIX "Err mask (%#x)\n", chan->AhciLastIS & ~ATA_AHCI_P_IX_OF));
4815 // We have some other error except Overflow
4816 // Just signal ERROR, operation will be aborted in ERROR branch.
4817 statusByte |= IDE_STATUS_ERROR;
4818 AtaReq->ahci.in_serror = chan->AhciLastSError;
4819 if(chan->AhciLastSError & (ATA_SE_HANDSHAKE_ERR | ATA_SE_LINKSEQ_ERR | ATA_SE_TRANSPORT_ERR | ATA_SE_UNKNOWN_FIS)) {
4820 KdPrint2((PRINT_PREFIX "Unrecoverable\n"));
4821 NoRetry = TRUE;
4822 }
4823 } else {
4824 // We have only Overflow. Abort operation and continue
4825 #ifdef _DEBUG
4826 UniataDumpAhciPortRegs(chan);
4827 #endif
4828 if(!UniataAhciAbortOperation(chan)) {
4829 KdPrint2((PRINT_PREFIX "need UniataAhciReset\n"));
4830 }
4831 #ifdef _DEBUG
4832 UniataDumpAhciPortRegs(chan);
4833 #endif
4834 UniataAhciWaitCommandReady(chan, 10);
4835 }
4836 }
4837
4838 } else {
4839 GetBaseStatus(chan, statusByte);
4840 }
4841 if(atapiDev) {
4842 KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte));
4843 } else {
4844 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Entered with status (%#x)\n", statusByte));
4845 }
4846
4847 if(!UseDpc) {
4848 KdPrint2((PRINT_PREFIX " operate like in DPC\n"));
4849 InDpc = TRUE;
4850 }
4851
4852 if (!atapiDev) {
4853 // IDE
4854 if(deviceExtension->HwFlags & UNIATA_AHCI) {
4855 KdPrint3((PRINT_PREFIX " AHCI branch (IDE)\n"));
4856 } else
4857 if (statusByte & IDE_STATUS_BUSY) {
4858 if (deviceExtension->DriverMustPoll) {
4859 // Crashdump is polling and we got caught with busy asserted.
4860 // Just go away, and we will be polled again shortly.
4861 KdPrint2((PRINT_PREFIX " Hit BUSY while polling during crashdump.\n"));
4862 goto ReturnEnableIntr;
4863 }
4864 try_dpc_wait:
4865 // Ensure BUSY is non-asserted.
4866 // make a very small idle before falling to DPC
4867 k = (InDpc && UseDpc) ? 1000 : 2;
4868
4869 for (i = 0; i < k; i++) {
4870
4871 GetBaseStatus(chan, statusByte);
4872 if (!(statusByte & IDE_STATUS_BUSY)) {
4873 break;
4874 }
4875 AtapiStallExecution(10);
4876 }
4877
4878 if (!InDpc && UseDpc && i == 2) {
4879
4880 KdPrint2((PRINT_PREFIX " BUSY on entry. Status %#x, Base IO %#x\n", statusByte));
4881
4882 TimerValue = 50;
4883 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
4884
4885 #ifndef UNIATA_CORE
4886 goto PostToDpc;
4887 #else //UNIATA_CORE
4888 AtapiStallExecution(TimerValue);
4889 goto ServiceInterrupt;
4890 #endif //UNIATA_CORE
4891 } else
4892 if (InDpc && i == k) {
4893 // reset the controller.
4894 KdPrint2((PRINT_PREFIX
4895 " Resetting due to BUSY on entry - %#x.\n",
4896 statusByte));
4897 goto IntrPrepareResetController;
4898 }
4899 }
4900 } else {
4901 // ATAPI
4902 if(!LunExt->IdentifyData.MajorRevision &&
4903 InDpc &&
4904 /*!atapiDev &&*/
4905 !(deviceExtension->HwFlags & UNIATA_SATA)
4906 ) {
4907 //KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n"));
4908 //AtapiStallExecution(10);
4909 }
4910 if(deviceExtension->HwFlags & UNIATA_AHCI) {
4911 KdPrint3((PRINT_PREFIX " AHCI branch (ATAPI)\n"));
4912 } else {
4913 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
4914 KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
4915 }
4916
4917 if (statusByte & IDE_STATUS_BUSY) {
4918 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
4919 /*
4920 #ifndef UNIATA_CORE
4921 // This is just workaround
4922 // We should DISABLE interrupts before entering WAIT state
4923 UniataExpectChannelInterrupt(chan, TRUE);
4924 #endif //UNIATA_CORE
4925 */
4926 KdPrint3((PRINT_PREFIX " BUSY on ATAPI device, waiting %d us\n", LunExt->AtapiReadyWaitDelay));
4927 #ifndef UNIATA_CORE
4928 if(LunExt->AtapiReadyWaitDelay && (LunExt->AtapiReadyWaitDelay > g_opt_MaxIsrWait) && !InDpc && UseDpc) {
4929 TimerValue = LunExt->AtapiReadyWaitDelay;
4930 KdPrint2((PRINT_PREFIX " too long wait: ISR -> DPC (0)\n"));
4931 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
4932 goto CallTimerDpc2;
4933 }
4934 #endif //UNIATA_CORE
4935 TimerValue = 10;
4936 for(k=20; k; k--) {
4937 GetBaseStatus(chan, statusByte);
4938 KdPrint3((PRINT_PREFIX " status re-check %#x\n", statusByte));
4939 KdPrint3((PRINT_PREFIX " Error reg (%#x)\n",
4940 AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Error)));
4941 if (!(statusByte & IDE_STATUS_BUSY)) {
4942 KdPrint2((PRINT_PREFIX " expecting intr + cleared BUSY\n"));
4943 break;
4944 }
4945 TotalTimerValue += TimerValue;
4946 if(k <= 1) {
4947 KdPrint3((PRINT_PREFIX " too long wait -> DPC\n"));
4948 if(!InDpc) {
4949 KdPrint2((PRINT_PREFIX " too long wait: ISR -> DPC\n"));
4950 TimerValue = 100;
4951 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
4952 } else {
4953 KdPrint2((PRINT_PREFIX " too long wait: DPC -> DPC\n"));
4954 TimerValue = 1000;
4955 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY1;
4956 }
4957 #ifndef UNIATA_CORE
4958 if(UseDpc) {
4959 if(!LunExt->AtapiReadyWaitDelay) {
4960 LunExt->AtapiReadyWaitDelay = TotalTimerValue*2/3;
4961 }
4962 goto CallTimerDpc2;
4963 }
4964 #endif //UNIATA_CORE
4965 }
4966
4967 AtapiStallExecution(TimerValue);
4968 TimerValue += 10;
4969 }
4970 if(!LunExt->AtapiReadyWaitDelay) {
4971 LunExt->AtapiReadyWaitDelay = TotalTimerValue*2/3;
4972 KdPrint2((PRINT_PREFIX " store AtapiReadyWaitDelay: %d\n", LunExt->AtapiReadyWaitDelay));
4973 }
4974 if (statusByte & IDE_STATUS_BUSY) {
4975 KdPrint3((PRINT_PREFIX " expecting intr + BUSY (2), try DPC wait\n"));
4976 goto try_dpc_wait;
4977 }
4978 }
4979 }
4980
4981 if(AtaReq && DmaTransfer && !(deviceExtension->HwFlags & UNIATA_AHCI)) {
4982 switch(OldReqState) {
4983 case REQ_STATE_EARLY_INTR:
4984 case REQ_STATE_DPC_WAIT_BUSY0:
4985
4986 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) {
4987 KdPrint2((PRINT_PREFIX "AtapiInterrupt: DMA still active\n"));
4988 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
4989 }
4990 break;
4991 }
4992 }
4993
4994 //retry_check:
4995 // Check for error conditions.
4996 if ((statusByte & IDE_STATUS_ERROR) ||
4997 (dma_status & BM_STATUS_ERR)) {
4998
4999 if(deviceExtension->HwFlags & UNIATA_AHCI) {
5000 error = AtaReq->ahci.in_error;
5001 // wait ready
5002 #ifdef _DEBUG
5003 UniataDumpAhciPortRegs(chan);
5004 #endif
5005 if(!UniataAhciAbortOperation(chan)) {
5006 KdPrint2((PRINT_PREFIX "need UniataAhciReset\n"));
5007 }
5008 // clear interrupts again
5009 UniataAhciWaitCommandReady(chan, 10);
5010 #ifdef _DEBUG
5011 UniataDumpAhciPortRegs(chan);
5012 #endif
5013 UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED);
5014 if(NoRetry) {
5015 AtaReq->retry += MAX_RETRIES;
5016 if(!error && (statusByte & IDE_STATUS_ERROR)) {
5017 KdPrint2((PRINT_PREFIX "AtapiInterrupt: force error status\n"));
5018 error |= IDE_STATUS_ERROR;
5019 }
5020 }
5021 #ifdef _DEBUG
5022 UniataDumpAhciPortRegs(chan);
5023 #endif
5024 } else {
5025 error = AtapiReadPort1(chan, IDX_IO1_i_Error);
5026 }
5027 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Error %#x\n", error));
5028 /*
5029 if(error & IDE_STATUS_CORRECTED_ERROR) {
5030 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
5031 statusByte &= ~IDE_STATUS_ERROR;
5032 goto retry_check;
5033 }
5034 */
5035 if(AtaReq) {
5036 KdPrint2((PRINT_PREFIX " Bad Lba %#I64x\n", AtaReq->lba));
5037 } else {
5038 KdPrint2((PRINT_PREFIX " Bad Lba unknown\n"));
5039 }
5040
5041 if(deviceExtension->HwFlags & UNIATA_AHCI) {
5042 KdPrint2((PRINT_PREFIX " no wait ready after error\n"));
5043 } else
5044 if(!atapiDev) {
5045 KdPrint2((PRINT_PREFIX " wait 100 ready after IDE error\n"));
5046 AtapiStallExecution(100);
5047 } else {
5048 KdPrint2((PRINT_PREFIX " wait 10 ready after ATAPI error\n"));
5049 AtapiStallExecution(10);
5050 }
5051 continue_err:
5052
5053 KdPrint3((PRINT_PREFIX " Intr on DRQ %x\n",
5054 LunExt->DeviceFlags & DFLAGS_INT_DRQ));
5055
5056 for (k = atapiDev ? 0 : 200; k; k--) {
5057 GetBaseStatus(chan, statusByte);
5058 if (!(statusByte & IDE_STATUS_DRQ)) {
5059 AtapiStallExecution(50);
5060 } else {
5061 break;
5062 }
5063 }
5064
5065 if (!atapiDev) {
5066 /* if this is a UDMA CRC error, reinject request */
5067
5068 AtaReq->retry++;
5069 if(AtaReq->retry < MAX_RETRIES) {
5070 #ifdef IO_STATISTICS
5071 chan->lun[DeviceNumber]->ModeErrorCount[AtaReq->retry]++;
5072 #endif //IO_STATISTICS
5073 if(DmaTransfer /*&&
5074 (error & IDE_ERROR_ICRC)*/) {
5075 KdPrint2((PRINT_PREFIX "Errors in DMA mode\n"));
5076 if(AtaReq->retry < MAX_RETRIES) {
5077 //fallback_pio:
5078 if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
5079 //AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
5080 // Downrate will happen in AtapiDmaReinit(), try UDMA-2 for HDD only
5081 AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
5082 }
5083 AtaReq->ReqState = REQ_STATE_QUEUED;
5084 goto reenqueue_req;
5085 }
5086 } else {
5087 if(!(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE)) {
5088 AtaReq->retry++;
5089 }
5090 KdPrint2((PRINT_PREFIX "Errors in PIO mode\n"));
5091 }
5092 }
5093 } else {
5094 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
5095 KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason));
5096
5097 if(DmaTransfer && (chan->lun[DeviceNumber]->TransferMode > ATA_UDMA2) &&
5098 ((error >> 4) == SCSI_SENSE_HARDWARE_ERROR)) {
5099 if(AtaReq->retry < MAX_RETRIES) {
5100 //fallback_pio:
5101 // Downrate will happen in AtapiDmaReinit(), use PIO immediately for ATAPI
5102 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
5103 AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
5104 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5105 AtaReq->ReqState = REQ_STATE_QUEUED;
5106 goto reenqueue_req;
5107 }
5108 } else {
5109 if(!(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE)) {
5110 AtaReq->retry++;
5111 }
5112 KdPrint3((PRINT_PREFIX "Errors in PIO mode\n"));
5113 }
5114 }
5115
5116 KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error\n"));
5117 if (srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
5118 // Fail this request.
5119 status = SRB_STATUS_ERROR;
5120 goto CompleteRequest;
5121 } else {
5122 KdPrint2((PRINT_PREFIX " continue with SCSIOP_REQUEST_SENSE\n"));
5123 }
5124 } else
5125 if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE_LBA48) {
5126 KdPrint2((PRINT_PREFIX "DMA doesn't work right with LBA48\n"));
5127 deviceExtension->HbaCtrlFlags |= HBAFLAGS_DMA_DISABLED_LBA48;
5128 } else
5129 if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE) {
5130 #ifdef IO_STATISTICS
5131 KdPrint2((PRINT_PREFIX "Some higher mode doesn't work right :((\n"));
5132 KdPrint2((PRINT_PREFIX "Recovery stats[%d]: %d vs %d\n",
5133 AtaReq->retry,
5134 LunExt->RecoverCount[AtaReq->retry],
5135 LunExt->BlockIoCount
5136 ));
5137 LunExt->RecoverCount[AtaReq->retry]++;
5138 if(LunExt->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->BlockIoCount/3 ||
5139 (deviceExtension->HwFlags & UNIATA_NO80CHK)
5140 ) {
5141 #else
5142 if(deviceExtension->HwFlags & UNIATA_NO80CHK) {
5143 #endif //IO_STATISTICS
5144 KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", LunExt->TransferMode));
5145 LunExt->LimitedTransferMode =
5146 LunExt->TransferMode;
5147 }
5148 }
5149 #ifdef IO_STATISTICS
5150 if(AtaReq->bcount) {
5151 // we need stats for Read/Write operations
5152 LunExt->BlockIoCount++;
5153 }
5154 LunExt->IoCount++;
5155 #endif //IO_STATISTICS
5156
5157 continue_PIO:
5158
5159 // check reason for this interrupt.
5160 if (atapiDev) {
5161
5162 KdPrint2((PRINT_PREFIX "AtapiInterrupt: ATAPI branch\n"));
5163 // ATAPI branch
5164
5165 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
5166 KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
5167 if(DmaTransfer) {
5168 wordsThisInterrupt = DEV_BSIZE/2*512;
5169 } else {
5170 wordsThisInterrupt = DEV_BSIZE/2;
5171 }
5172
5173 } else {
5174
5175 // ATA branch
5176
5177 if(DmaTransfer) {
5178 // simulate DRQ for DMA transfers
5179 statusByte |= IDE_STATUS_DRQ;
5180 }
5181 if (statusByte & IDE_STATUS_DRQ) {
5182
5183 if(DmaTransfer) {
5184 wordsThisInterrupt = DEV_BSIZE/2*512;
5185 } else
5186 if (LunExt->MaximumBlockXfer) {
5187 wordsThisInterrupt = DEV_BSIZE/2 * LunExt->MaximumBlockXfer;
5188 }
5189
5190 if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
5191
5192 interruptReason = ATAPI_IR_IO_toHost;
5193
5194 } else if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
5195 interruptReason = ATAPI_IR_IO_toDev;
5196
5197 } else {
5198 status = SRB_STATUS_ERROR;
5199 goto CompleteRequest;
5200 }
5201
5202 } else if (statusByte & IDE_STATUS_BUSY) {
5203
5204 //AtapiEnableInterrupts(deviceExtension, lChannel);
5205 KdPrint2((PRINT_PREFIX "AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
5206 return FALSE;
5207
5208 } else {
5209
5210 KdPrint2((PRINT_PREFIX "AtapiInterrupt: !DRQ, !BUSY, WordsLeft %#x\n", AtaReq->WordsLeft));
5211 if (AtaReq->WordsLeft) {
5212
5213 // Funky behaviour seen with PCI IDE (not all, just one).
5214 PIO_wait_DRQ0:
5215 // The ISR hits with DRQ low, but comes up later.
5216 for (k = 0; k < 5000; k++) {
5217 GetBaseStatus(chan, statusByte);
5218 if (statusByte & IDE_STATUS_DRQ) {
5219 break;
5220 }
5221 if(!InDpc) {
5222 // goto DPC
5223 AtaReq->ReqState = REQ_STATE_DPC_WAIT_DRQ0;
5224 TimerValue = 100;
5225 KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (drq0)\n"));
5226 #ifndef UNIATA_CORE
5227 goto PostToDpc;
5228 #else //UNIATA_CORE
5229 AtapiStallExecution(TimerValue);
5230 goto ServiceInterrupt;
5231 #endif //UNIATA_CORE
5232 }
5233 AtapiStallExecution(100);
5234 }
5235 if (k == 5000) {
5236 // reset the controller.
5237 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
5238 statusByte));
5239 IntrPrepareResetController:
5240 AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_CURRENT);
5241 goto ReturnEnableIntr;
5242
5243 } else {
5244 interruptReason = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ? ATAPI_IR_IO_toHost : ATAPI_IR_IO_toDev;
5245 }
5246
5247 } else {
5248 // Command complete - verify, write, or the SMART enable/disable.
5249 // Also get_media_status
5250 interruptReason = ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd;
5251 }
5252 }
5253 }
5254
5255 KdPrint2((PRINT_PREFIX "AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason, statusByte));
5256 if(deviceExtension->HwFlags & UNIATA_AHCI) {
5257 KdPrint2((PRINT_PREFIX " AHCI path, WordsTransfered %x, WordsLeft %x\n", AtaReq->WordsTransfered, AtaReq->WordsLeft));
5258 /* if(chan->AhciLastIS & ATA_AHCI_P_IX_OF) {
5259 //status = SRB_STATUS_DATA_OVERRUN;
5260 DataOverrun = TRUE;
5261 } else {
5262 status = SRB_STATUS_SUCCESS;
5263 }*/
5264 if(AtaReq->WordsTransfered >= AtaReq->WordsLeft) {
5265 AtaReq->WordsLeft = 0;
5266 } else {
5267 AtaReq->WordsLeft -= AtaReq->WordsTransfered;
5268 }
5269 //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
5270 // status = SRB_STATUS_DATA_OVERRUN;
5271 //}
5272 status = SRB_STATUS_SUCCESS;
5273 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
5274 goto CompleteRequest;
5275 } else
5276 if (interruptReason == ATAPI_IR_COD_Cmd && (statusByte & IDE_STATUS_DRQ)) {
5277 // Write the packet.
5278 KdPrint3((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n"));
5279 // Send CDB to device.
5280 WriteBuffer(chan, (PUSHORT)srb->Cdb,
5281 LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
5282 0);
5283 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
5284
5285 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
5286 KdPrint2((PRINT_PREFIX "AtapiInterrupt: AtapiDmaStart().\n"));
5287 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, srb);
5288 }
5289
5290 goto ReturnEnableIntr;
5291
5292 } else if (interruptReason == ATAPI_IR_IO_toDev && (statusByte & IDE_STATUS_DRQ)) {
5293
5294 // Write the data.
5295 if (atapiDev) {
5296
5297 // Pick up bytes to transfer and convert to words.
5298 wordCount =
5299 AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
5300
5301 wordCount |=
5302 (USHORT)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8;
5303
5304 // Covert bytes to words.
5305 wordCount >>= 1;
5306 KdPrint2((PRINT_PREFIX "AtapiInterrupt: get W wordCount %#x\n", wordCount));
5307
5308 if (wordCount != AtaReq->WordsLeft) {
5309 KdPrint2((PRINT_PREFIX
5310 "AtapiInterrupt: %d words requested; %d words xferred\n",
5311 AtaReq->WordsLeft,
5312 wordCount));
5313 }
5314
5315 // Verify this makes sense.
5316 if (wordCount > AtaReq->WordsLeft) {
5317 wordCount = AtaReq->WordsLeft;
5318 KdPrint2((PRINT_PREFIX
5319 "AtapiInterrupt: Write underrun\n"));
5320 DataOverrun = TRUE;
5321 }
5322
5323 } else {
5324
5325 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
5326 if (AtaReq->WordsLeft < wordsThisInterrupt) {
5327 // Transfer only words requested.
5328 wordCount = AtaReq->WordsLeft;
5329 } else {
5330 // Transfer next block.
5331 wordCount = wordsThisInterrupt;
5332 }
5333 }
5334
5335 if (DmaTransfer &&
5336 (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
5337 //ASSERT(AtaReq->WordsLeft == wordCount);
5338 if(AtaReq->ReqState == REQ_STATE_ATAPI_EXPECTING_DATA_INTR2) {
5339 KdPrint2((PRINT_PREFIX
5340 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount));
5341 if(AtaReq->WordsLeft > wordCount) {
5342 AtaReq->WordsLeft -= wordCount;
5343 AtaReq->WordsTransfered += wordCount;
5344 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
5345 goto ReturnEnableIntr;
5346 }
5347 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
5348 }
5349 AtaReq->WordsTransfered = AtaReq->WordsLeft;
5350 AtaReq->WordsLeft = 0;
5351 status = SRB_STATUS_SUCCESS;
5352 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
5353 goto CompleteRequest;
5354 }
5355
5356 // Ensure that this is a write command.
5357 if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
5358
5359 KdPrint2((PRINT_PREFIX
5360 "AtapiInterrupt: Write interrupt\n"));
5361
5362 statusByte = WaitOnBusy(chan);
5363
5364 if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
5365
5366 WriteBuffer(chan,
5367 AtaReq->DataBuffer,
5368 wordCount,
5369 UniataGetPioTiming(LunExt));
5370 } else {
5371
5372 WriteBuffer2(chan,
5373 (PULONG)(AtaReq->DataBuffer),
5374 wordCount / 2,
5375 UniataGetPioTiming(LunExt));
5376 }
5377 } else {
5378
5379 KdPrint3((PRINT_PREFIX
5380 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5381 interruptReason,
5382 srb));
5383
5384 // Fail this request.
5385 status = SRB_STATUS_ERROR;
5386 goto CompleteRequest;
5387 }
5388 // Advance data buffer pointer and bytes left.
5389 AtaReq->DataBuffer += wordCount;
5390 AtaReq->WordsLeft -= wordCount;
5391 AtaReq->WordsTransfered += wordCount;
5392
5393 if (atapiDev) {
5394 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
5395 }
5396
5397 goto ReturnEnableIntr;
5398
5399 } else if (interruptReason == ATAPI_IR_IO_toHost && (statusByte & IDE_STATUS_DRQ)) {
5400
5401
5402 if (atapiDev) {
5403
5404 // Pick up bytes to transfer and convert to words.
5405 wordCount =
5406 AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow) |
5407 (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8);
5408
5409 // Convert bytes to words.
5410 wordCount >>= 1;
5411 KdPrint2((PRINT_PREFIX "AtapiInterrupt: get R wordCount %#x\n", wordCount));
5412
5413 if (wordCount != AtaReq->WordsLeft) {
5414 KdPrint2((PRINT_PREFIX
5415 "AtapiInterrupt: %d words requested; %d words xferred\n",
5416 AtaReq->WordsLeft,
5417 wordCount));
5418 }
5419
5420 // Verify this makes sense.
5421 if (wordCount > AtaReq->WordsLeft) {
5422 wordCount = AtaReq->WordsLeft;
5423 DataOverrun = TRUE;
5424 }
5425
5426 } else {
5427
5428 // Check if words left is at least 256.
5429 if (AtaReq->WordsLeft < wordsThisInterrupt) {
5430 // Transfer only words requested.
5431 wordCount = AtaReq->WordsLeft;
5432 } else {
5433 // Transfer next block.
5434 wordCount = wordsThisInterrupt;
5435 }
5436 }
5437
5438 if(DmaTransfer &&
5439 (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
5440 if(AtaReq->ReqState == REQ_STATE_ATAPI_EXPECTING_DATA_INTR2) {
5441 KdPrint2((PRINT_PREFIX
5442 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount));
5443 if(AtaReq->WordsLeft > wordCount) {
5444 AtaReq->WordsLeft -= wordCount;
5445 AtaReq->WordsTransfered += wordCount;
5446 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
5447 goto ReturnEnableIntr;
5448 }
5449 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
5450 }
5451 //ASSERT(AtaReq->WordsLeft == wordCount);
5452 AtaReq->WordsTransfered = AtaReq->WordsLeft;
5453 AtaReq->WordsLeft = 0;
5454 status = SRB_STATUS_SUCCESS;
5455 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
5456 goto CompleteRequest;
5457 }
5458 continue_read_drq:
5459 // Ensure that this is a read command.
5460 if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
5461
5462 /* KdPrint2((
5463 "AtapiInterrupt: Read interrupt\n"));*/
5464
5465 statusByte = WaitOnBusy(chan);
5466
5467 if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
5468 KdPrint2((PRINT_PREFIX
5469 "IdeIntr: Read %#x words\n", wordCount));
5470
5471 ReadBuffer(chan,
5472 AtaReq->DataBuffer,
5473 wordCount,
5474 UniataGetPioTiming(LunExt));
5475 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)-1) ));
5476 //KdDump(AtaReq->DataBuffer, wordCount*2);
5477 if(srb && atapiDev && srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
5478 KdDump(AtaReq->DataBuffer, wordCount*2);
5479 }
5480
5481 GetBaseStatus(chan, statusByte);
5482 KdPrint2((PRINT_PREFIX " status re-check %#x\n", statusByte));
5483
5484 if(DataOverrun) {
5485 KdPrint2((PRINT_PREFIX " DataOverrun\n"));
5486 AtapiSuckPort2(chan);
5487 GetBaseStatus(chan, statusByte);
5488 }
5489
5490 if(statusByte & IDE_STATUS_BUSY) {
5491 for (i = 0; i < 2; i++) {
5492 AtapiStallExecution(10);
5493 GetBaseStatus(chan, statusByte);
5494 if (!(statusByte & IDE_STATUS_BUSY)) {
5495 break;
5496 }
5497 }
5498 }
5499 } else {
5500 KdPrint2((PRINT_PREFIX
5501 "IdeIntr: Read %#x Dwords\n", wordCount/2));
5502
5503 ReadBuffer2(chan,
5504 (PULONG)(AtaReq->DataBuffer),
5505 wordCount / 2,
5506 UniataGetPioTiming(LunExt));
5507 }
5508 } else {
5509
5510 KdPrint3((PRINT_PREFIX
5511 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5512 interruptReason,
5513 srb));
5514
5515 // Fail this request.
5516 status = SRB_STATUS_ERROR;
5517 goto CompleteRequest;
5518 }
5519
5520 // Advance data buffer pointer and bytes left.
5521 AtaReq->DataBuffer += wordCount;
5522 AtaReq->WordsLeft -= wordCount;
5523 AtaReq->WordsTransfered += wordCount;
5524
5525 // Check for read command complete.
5526 if (AtaReq->WordsLeft == 0) {
5527
5528 KdPrint2((PRINT_PREFIX "AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
5529 if (atapiDev) {
5530
5531 // Work around to make many atapi devices return correct sector size
5532 // of 2048. Also certain devices will have sector count == 0x00, check
5533 // for that also.
5534 if ((srb->Cdb[0] == SCSIOP_READ_CAPACITY) &&
5535 (LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM)) {
5536
5537 AtaReq->DataBuffer -= wordCount;
5538 if (AtaReq->DataBuffer[0] == 0x00) {
5539
5540 *((ULONG *) &(AtaReq->DataBuffer[0])) = 0xFFFFFF7F;
5541
5542 }
5543
5544 *((ULONG *) &(AtaReq->DataBuffer[2])) = 0x00080000;
5545 AtaReq->DataBuffer += wordCount;
5546 }
5547
5548 GetStatus(chan, statusByte);
5549 if(!(statusByte & IDE_STATUS_BUSY)) {
5550 // Assume command is completed if BUSY is cleared
5551 // and all data read
5552 // Optionally, we may receive COMPLETE interrupt later and
5553 // treat it as unexpected
5554 KdPrint2((PRINT_PREFIX "AtapiInterrupt: early complete ? status %x\n", statusByte));
5555
5556 status = SRB_STATUS_SUCCESS;
5557 goto CompleteRequest;
5558 }
5559
5560 } else {
5561
5562 /*
5563 // Completion for IDE drives.
5564 if (AtaReq->WordsLeft) {
5565 status = SRB_STATUS_DATA_OVERRUN;
5566 } else {
5567 status = SRB_STATUS_SUCCESS;
5568 }
5569
5570 goto CompleteRequest;
5571 */
5572 status = SRB_STATUS_SUCCESS;
5573 goto CompleteRequest;
5574
5575 }
5576 } else {
5577 if (atapiDev) {
5578 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
5579 GetStatus(chan, statusByte);
5580 if(!(statusByte & IDE_STATUS_BUSY)) {
5581 // Assume command is completed if BUSY is cleared
5582 // even if NOT all data read
5583 // Optionally, we may receive COMPLETE interrupt later and
5584 // treat it as unexpected
5585 KdPrint2((PRINT_PREFIX "AtapiInterrupt: early complete + underrun ? status %x\n", statusByte));
5586
5587 status = SRB_STATUS_SUCCESS;
5588 goto CompleteRequest;
5589 }
5590 } else {
5591 if(!atapiDev && !DataOverrun && (srb->SrbFlags & SRB_FLAGS_DATA_IN) &&
5592 (statusByte == (IDE_STATUS_IDLE | IDE_STATUS_DRQ))) {
5593 KdPrint2((PRINT_PREFIX " HDD read data ready \n"));
5594 goto continue_read_drq;
5595 }
5596 }
5597 }
5598
5599 goto ReturnEnableIntr;
5600
5601 } else if (interruptReason == (ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd) && !(statusByte & IDE_STATUS_DRQ)) {
5602
5603 KdPrint2((PRINT_PREFIX "AtapiInterrupt: interruptReason = CompleteRequest\n"));
5604 // Command complete. We exactly know this because of IReason.
5605
5606 if(DmaTransfer) {
5607 KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
5608 AtaReq->WordsTransfered += AtaReq->WordsLeft;
5609 AtaReq->WordsLeft = 0;
5610 } else {
5611 KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was PIO\n"));
5612
5613 wordCount = AtaReq->WordsLeft;
5614 // Advance data buffer pointer and bytes left.
5615 AtaReq->DataBuffer += wordCount;
5616 AtaReq->WordsLeft -= wordCount;
5617 AtaReq->WordsTransfered += wordCount;
5618
5619 KdPrint2((PRINT_PREFIX "AtapiInterrupt: wordCount %#x, WordsTransfered %#x\n", wordCount, AtaReq->WordsTransfered));
5620
5621 }
5622 //if (AtaReq->WordsLeft) {
5623 // status = SRB_STATUS_DATA_OVERRUN;
5624 //} else {
5625 status = SRB_STATUS_SUCCESS;
5626 //}
5627
5628 #ifdef UNIATA_DUMP_ATAPI
5629 if(srb &&
5630 srb->SrbFlags & SRB_FLAGS_DATA_IN) {
5631 UCHAR ScsiCommand;
5632 PCDB Cdb;
5633 PCHAR CdbData;
5634 PCHAR ModeSelectData;
5635 ULONG CdbDataLen;
5636 PSCSI_REQUEST_BLOCK Srb = srb;
5637
5638 Cdb = (PCDB)(Srb->Cdb);
5639 ScsiCommand = Cdb->CDB6.OperationCode;
5640 CdbData = (PCHAR)(Srb->DataBuffer);
5641 CdbDataLen = Srb->DataTransferLength;
5642
5643 if(CdbDataLen > 0x1000) {
5644 CdbDataLen = 0x1000;
5645 }
5646
5647 KdPrint(("--\n"));
5648 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
5649 KdPrint2(("P:T:D=%d:%d:%d\n",
5650 Srb->PathId,
5651 Srb->TargetId,
5652 Srb->Lun));
5653 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand));
5654 KdDump(Cdb, 16);
5655
5656 if(ScsiCommand == SCSIOP_MODE_SENSE) {
5657 KdPrint(("ModeSense 6\n"));
5658 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
5659 ModeSelectData = CdbData+4;
5660 KdDump(CdbData, CdbDataLen);
5661 } else
5662 if(ScsiCommand == SCSIOP_MODE_SENSE10) {
5663 KdPrint(("ModeSense 10\n"));
5664 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
5665 ModeSelectData = CdbData+8;
5666 KdDump(CdbData, CdbDataLen);
5667 } else {
5668 if(srb->SrbFlags & SRB_FLAGS_DATA_IN) {
5669 KdPrint(("Read buffer from device:\n"));
5670 KdDump(CdbData, CdbDataLen);
5671 }
5672 }
5673 KdPrint(("--\n"));
5674 }
5675 #endif //UNIATA_DUMP_ATAPI
5676
5677 CompleteRequest:
5678
5679 KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, srbstatus %x\n", status));
5680 // Check and see if we are processing our secret (mechanism status/request sense) srb
5681
5682 if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
5683 KdPrint2((PRINT_PREFIX "WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq->WordsLeft));
5684 status = SRB_STATUS_DATA_OVERRUN;
5685 }
5686
5687 if (AtaReq->OriginalSrb) {
5688
5689 ULONG srbStatus;
5690
5691 KdPrint2((PRINT_PREFIX "AtapiInterrupt: OriginalSrb != NULL\n"));
5692 if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
5693
5694 KdPrint3((PRINT_PREFIX "AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status));
5695 if (status == SRB_STATUS_SUCCESS) {
5696 // Bingo!!
5697 AtapiHwInitializeChanger (HwDeviceExtension,
5698 srb,
5699 (PMECHANICAL_STATUS_INFORMATION_HEADER) srb->DataBuffer);
5700
5701 // Get ready to issue the original srb
5702 srb = AtaReq->Srb = AtaReq->OriginalSrb;
5703 AtaReq->OriginalSrb = NULL;
5704
5705 } else {
5706 // failed! Get the sense key and maybe try again
5707 srb = AtaReq->Srb = BuildRequestSenseSrb (
5708 HwDeviceExtension,
5709 AtaReq->OriginalSrb);
5710 }
5711 /*
5712 // do not enable interrupts in DPC, do not waste time, do it now!
5713 if(UseDpc && chan->DisableIntr) {
5714 AtapiEnableInterrupts(HwDeviceExtension, c);
5715 UseDpc = FALSE;
5716 RestoreUseDpc = TRUE;
5717 }
5718 */
5719 srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL);
5720
5721 KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt));
5722
5723 if (srbStatus == SRB_STATUS_PENDING) {
5724 KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
5725 goto ReturnEnableIntr;
5726 }
5727 /*
5728 if(RestoreUseDpc) {
5729 // restore state on error
5730 UseDpc = TRUE;
5731 AtapiDisableInterrupts(HwDeviceExtension, c);
5732 }
5733 */
5734
5735 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
5736
5737 PSENSE_DATA senseData = (PSENSE_DATA) srb->DataBuffer;
5738
5739 KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI command status %#x\n", status));
5740 if (status == SRB_STATUS_DATA_OVERRUN) {
5741 // Check to see if we at least get mininum number of bytes
5742 if ((srb->DataTransferLength - AtaReq->WordsLeft) >
5743 (FIELD_OFFSET (SENSE_DATA, AdditionalSenseLength) + sizeof(senseData->AdditionalSenseLength))) {
5744 status = SRB_STATUS_SUCCESS;
5745 }
5746 }
5747
5748 if (status == SRB_STATUS_SUCCESS) {
5749 #ifndef UNIATA_CORE
5750 if ((senseData->SenseKey != SCSI_SENSE_ILLEGAL_REQUEST) &&
5751 chan->MechStatusRetryCount) {
5752
5753 KdPrint3((PRINT_PREFIX "AtapiInterrupt: MechStatusRetryCount %#x\n", chan->MechStatusRetryCount));
5754 // The sense key doesn't say the last request is illegal, so try again
5755 chan->MechStatusRetryCount--;
5756 srb = AtaReq->Srb = BuildMechanismStatusSrb (
5757 HwDeviceExtension,
5758 AtaReq->OriginalSrb);
5759 } else {
5760
5761 // last request was illegal. No point trying again.
5762 // Do-nothing call ?
5763 AtapiHwInitializeChanger (HwDeviceExtension,
5764 srb,
5765 (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
5766
5767 // Get ready to issue the original srb
5768 srb = AtaReq->Srb = AtaReq->OriginalSrb;
5769 AtaReq->OriginalSrb = NULL;
5770 }
5771 #endif //UNIATA_CORE
5772 /*
5773 // do not enable interrupts in DPC, do not waste time, do it now!
5774 if(UseDpc && chan->DisableIntr) {
5775 AtapiEnableInterrupts(HwDeviceExtension, c);
5776 UseDpc = FALSE;
5777 RestoreUseDpc = TRUE;
5778 }
5779 */
5780 srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL);
5781
5782 KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan->ExpectingInterrupt));
5783
5784 if (srbStatus == SRB_STATUS_PENDING) {
5785 KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
5786 goto ReturnEnableIntr;
5787 }
5788 /*
5789 if(RestoreUseDpc) {
5790 // restore state on error
5791 UseDpc = TRUE;
5792 AtapiDisableInterrupts(HwDeviceExtension, c);
5793 }
5794 */
5795 }
5796 }
5797
5798 // If we get here, it means AtapiSendCommand() has failed
5799 // Can't recover. Pretend the original srb has failed and complete it.
5800
5801 KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. complete OriginalSrb\n"));
5802
5803 if (AtaReq->OriginalSrb) {
5804 KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
5805 // Do-nothing call ?
5806 AtapiHwInitializeChanger (HwDeviceExtension,
5807 srb,
5808 (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
5809 srb = AtaReq->Srb = AtaReq->OriginalSrb;
5810 AtaReq->OriginalSrb = NULL;
5811 }
5812
5813 KdPrint2((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan->ExpectingInterrupt));
5814
5815 // fake an error and read no data
5816 status = SRB_STATUS_ERROR;
5817 srb->ScsiStatus = 0;
5818 AtaReq->DataBuffer = (PUSHORT)(srb->DataBuffer);
5819 AtaReq->WordsLeft = srb->DataTransferLength;
5820 chan->RDP = FALSE;
5821
5822 } else if (status == SRB_STATUS_ERROR) {
5823
5824 // Map error to specific SRB status and handle request sense.
5825 KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. Begin mapping...\n"));
5826 status = MapError(deviceExtension,
5827 srb);
5828
5829 chan->RDP = FALSE;
5830
5831 } else if(!DmaTransfer) {
5832
5833 KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion\n"));
5834 // Command complete.
5835 PIO_wait_busy:
5836 KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion, wait BUSY\n"));
5837 // Wait for busy to drop.
5838 for (i = 0; i < 5*30; i++) {
5839 GetBaseStatus(chan, statusByte);
5840 if (!(statusByte & IDE_STATUS_BUSY)) {
5841 break;
5842 }
5843 if(!InDpc) {
5844 // goto DPC
5845 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY;
5846 TimerValue = 200;
5847 KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (busy)\n"));
5848 #ifndef UNIATA_CORE
5849 goto PostToDpc;
5850 #else //UNIATA_CORE
5851 AtapiStallExecution(TimerValue);
5852 goto ServiceInterrupt;
5853 #endif //UNIATA_CORE
5854 }
5855 AtapiStallExecution(100);
5856 }
5857
5858 if (i == 5*30) {
5859
5860 // reset the controller.
5861 KdPrint2((PRINT_PREFIX
5862 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
5863 statusByte));
5864 goto IntrPrepareResetController;
5865 }
5866 // Check to see if DRQ is still up.
5867 if(statusByte & IDE_STATUS_DRQ) {
5868 KdPrint2((PRINT_PREFIX "AtapiInterrupt: DRQ...\n"));
5869 if(srb) {
5870 if(srb->SrbFlags & SRB_FLAGS_DATA_IN) {
5871 KdPrint2((PRINT_PREFIX "srb %x data in\n", srb));
5872 } else {
5873 KdPrint2((PRINT_PREFIX "srb %x data out\n", srb));
5874 }
5875 } else {
5876 KdPrint2((PRINT_PREFIX "srb NULL\n"));
5877 }
5878 if(AtaReq) {
5879 KdPrint2((PRINT_PREFIX "AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq, AtaReq->WordsLeft));
5880 } else {
5881 KdPrint2((PRINT_PREFIX "AtaReq NULL\n"));
5882 }
5883 if(AtaReq && AtaReq->WordsLeft /*&&
5884 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
5885 KdPrint2((PRINT_PREFIX "DRQ+AtaReq->WordsLeft -> next portion\n"));
5886 goto continue_PIO;
5887 }
5888 }
5889 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
5890 //if ((statusByte & IDE_STATUS_DRQ)) {}
5891 if((statusByte & IDE_STATUS_DRQ) &&
5892 (LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED)) ) {
5893
5894 PIO_wait_DRQ:
5895 KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO_wait_DRQ\n"));
5896 for (i = 0; i < 200; i++) {
5897 GetBaseStatus(chan, statusByte);
5898 if (!(statusByte & IDE_STATUS_DRQ)) {
5899 break;
5900 }
5901 if(!InDpc) {
5902 // goto DPC
5903 KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (drq)\n"));
5904 AtaReq->ReqState = REQ_STATE_DPC_WAIT_DRQ;
5905 TimerValue = 100;
5906 #ifndef UNIATA_CORE
5907 goto PostToDpc;
5908 #else //UNIATA_CORE
5909 AtapiStallExecution(TimerValue);
5910 goto ServiceInterrupt;
5911 #endif //UNIATA_CORE
5912 }
5913 AtapiStallExecution(100);
5914 }
5915
5916 if (i == 200) {
5917 // reset the controller.
5918 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
5919 statusByte));
5920 goto IntrPrepareResetController;
5921 }
5922 }
5923 if(atapiDev) {
5924 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
5925 AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)(-1)), srb->DataTransferLength ));
5926 //KdDump(srb->DataBuffer, srb->DataTransferLength);
5927 }
5928 if(!AtapiDmaPioSync(HwDeviceExtension, srb, (PUCHAR)(srb->DataBuffer), srb->DataTransferLength)) {
5929 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
5930 }
5931 }
5932
5933 // Clear interrupt expecting flag.
5934 UniataExpectChannelInterrupt(chan, FALSE);
5935 // clear this flag now, it can be set again in sub-calls
5936 InterlockedExchange(&(chan->CheckIntr),
5937 CHECK_INTR_IDLE);
5938
5939 // Sanity check that there is a current request.
5940 if(srb != NULL) {
5941 // Set status in SRB.
5942 srb->SrbStatus = (UCHAR)status;
5943
5944 // Check for underflow.
5945 if(AtaReq->WordsLeft) {
5946
5947 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq->WordsLeft));
5948 // Subtract out residual words and update if filemark hit,
5949 // setmark hit , end of data, end of media...
5950 if (!(LunExt->DeviceFlags & DFLAGS_TAPE_DEVICE)) {
5951 if (status == SRB_STATUS_DATA_OVERRUN) {
5952 srb->DataTransferLength -= AtaReq->WordsLeft*2;
5953 } else {
5954 srb->DataTransferLength = 0;
5955 }
5956 } else {
5957 srb->DataTransferLength -= AtaReq->WordsLeft*2;
5958 }
5959 }
5960 if(status == SRB_STATUS_SUCCESS) {
5961 //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) {
5962 // // This should be set in UniataAhciEndTransaction() for AHCI
5963 // AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
5964 //}
5965 if(!atapiDev &&
5966 AtaReq->WordsTransfered*2 < AtaReq->TransferLength) {
5967 KdPrint2((PRINT_PREFIX "AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
5968 AtaReq->WordsTransfered*2, AtaReq->TransferLength));
5969 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
5970 AtaReq->ReqState = REQ_STATE_PREPARE_TO_NEXT;
5971 goto reenqueue_req;
5972 } else {
5973 KdPrint2((PRINT_PREFIX " Transfered %x, full size %x\n",
5974 AtaReq->WordsTransfered*2, AtaReq->TransferLength));
5975 }
5976 }
5977
5978 if (srb->Function != SRB_FUNCTION_IO_CONTROL) {
5979
5980 CompleteRDP:
5981 // Indicate command complete.
5982 if (!(chan->RDP)) {
5983 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete\n"));
5984 IntrCompleteReq:
5985
5986 if (status == SRB_STATUS_SUCCESS &&
5987 srb->SenseInfoBuffer &&
5988 srb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) {
5989
5990 PSENSE_DATA senseBuffer = (PSENSE_DATA)srb->SenseInfoBuffer;
5991
5992 KdPrint2((PRINT_PREFIX "AtapiInterrupt: set AutoSense\n"));
5993 senseBuffer->ErrorCode = 0;
5994 senseBuffer->Valid = 1;
5995 senseBuffer->AdditionalSenseLength = 0xb;
5996 senseBuffer->SenseKey = 0;
5997 senseBuffer->AdditionalSenseCode = 0;
5998 senseBuffer->AdditionalSenseCodeQualifier = 0;
5999
6000 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
6001 }
6002 AtapiDmaDBSync(chan, srb);
6003 KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove srb %#x, status %x\n", srb, status));
6004 UniataRemoveRequest(chan, srb);
6005 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete, srb %#x\n", srb));
6006 ScsiPortNotification(RequestComplete,
6007 deviceExtension,
6008 srb);
6009 }
6010 } else {
6011
6012 KdPrint2((PRINT_PREFIX "AtapiInterrupt: IOCTL completion\n"));
6013
6014 if (status != SRB_STATUS_SUCCESS) {
6015 error = AtapiReadPort1(chan, IDX_IO1_i_Error);
6016 KdPrint2((PRINT_PREFIX "AtapiInterrupt: error %#x\n", error));
6017 }
6018
6019 if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
6020
6021 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
6022 // Build the SMART status block depending upon the completion status.
6023 cmdOutParameters->cBufferSize = wordCount;
6024 cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0;
6025 cmdOutParameters->DriverStatus.bIDEError = error;
6026
6027 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
6028 // data buffer.
6029 if (chan->SmartCommand == RETURN_SMART_STATUS) {
6030 PIDEREGS_EX regs = (PIDEREGS_EX)&(cmdOutParameters->bBuffer);
6031
6032 regs->bOpFlags = 0;
6033 UniataSnapAtaRegs(chan, 0, regs);
6034
6035 regs->bCommandReg = SMART_CMD;
6036 regs->bFeaturesReg = RETURN_SMART_STATUS;
6037
6038 cmdOutParameters->cBufferSize = 8;
6039 }
6040 chan->SmartCommand = 0; // cleanup after execution
6041 }
6042 // Indicate command complete.
6043 goto IntrCompleteReq;
6044 }
6045
6046 } else {
6047
6048 KdPrint2((PRINT_PREFIX "AtapiInterrupt: No SRB!\n"));
6049 }
6050
6051 if (chan->RDP) {
6052 // Check DSC
6053 for (i = 0; i < 5; i++) {
6054 GetBaseStatus(chan, statusByte);
6055 if(!(statusByte & IDE_STATUS_BUSY)) {
6056 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RDP + cleared BUSY\n"));
6057 chan->RDP = FALSE;
6058 goto CompleteRDP;
6059 } else
6060 if (statusByte & IDE_STATUS_DSC) {
6061 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Clear RDP\n"));
6062 chan->RDP = FALSE;
6063 goto CompleteRDP;
6064 }
6065 AtapiStallExecution(50);
6066 }
6067 }
6068 // RDP can be cleared since previous check
6069 if (chan->RDP) {
6070 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestTimerCall 2000\n"));
6071
6072 TimerValue = 2000;
6073 #ifndef UNIATA_CORE
6074 goto CallTimerDpc;
6075 #else //UNIATA_CORE
6076 AtapiStallExecution(TimerValue);
6077 goto ServiceInterrupt;
6078 #endif //UNIATA_CORE
6079 }
6080
6081 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
6082 enqueue_next_req:
6083 // Get next request
6084 srb = UniataGetCurRequest(chan);
6085
6086 reenqueue_req:
6087
6088 #ifndef UNIATA_CORE
6089 KdPrint2((PRINT_PREFIX "AtapiInterrupt: NextRequest, srb=%#x\n",srb));
6090 if(!srb) {
6091 ScsiPortNotification(NextRequest,
6092 deviceExtension,
6093 NULL);
6094 } else {
6095 ScsiPortNotification(NextLuRequest,
6096 deviceExtension,
6097 PathId,
6098 TargetId,
6099 Lun);
6100 // in simplex mode next command must NOT be sent here
6101 if(!deviceExtension->simplexOnly) {
6102 AtapiStartIo__(HwDeviceExtension, srb, FALSE);
6103 }
6104 }
6105 // Try to get SRB fron any non-empty queue (later)
6106 if(deviceExtension->simplexOnly) {
6107 NoStartIo = FALSE;
6108 }
6109 #endif //UNIATA_CORE
6110
6111 goto ReturnEnableIntr;
6112
6113 } else {
6114
6115 // Unexpected int. Catch it
6116 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
6117 interruptReason,
6118 statusByte));
6119
6120 if(OldReqState == REQ_STATE_DPC_WAIT_BUSY0 &&
6121 AtaReq->WordsLeft == 0) {
6122 KdPrint2((PRINT_PREFIX "AtapiInterrupt: pending WAIT_BUSY0. Complete.\n"));
6123 status = SRB_STATUS_SUCCESS;
6124 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
6125 goto CompleteRequest;
6126 }
6127 }
6128
6129 ReturnEnableIntr:
6130
6131 KdPrint2((PRINT_PREFIX "AtapiInterrupt: ReturnEnableIntr\n",srb));
6132 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6133 deviceExtension->ExpectingInterrupt = TRUE;
6134 if(UseDpc) {
6135 if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) {
6136 KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
6137 #ifdef UNIATA_USE_XXableInterrupts
6138 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
6139 chan->ChannelCtrlFlags |= CTRFLAGS_ENABLE_INTR_REQ;
6140 // must be called on DISPATCH_LEVEL
6141 ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension,
6142 AtapiEnableInterrupts__);
6143 #else
6144 AtapiEnableInterrupts(HwDeviceExtension, c);
6145 InterlockedExchange(&(chan->CheckIntr),
6146 CHECK_INTR_IDLE);
6147 // Will raise IRQL to DIRQL
6148 #ifndef UNIATA_CORE
6149 AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
6150 AtapiEnableInterrupts__,
6151 1);
6152 #endif // UNIATA_CORE
6153 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
6154 #endif // UNIATA_USE_XXableInterrupts
6155 }
6156 }
6157
6158 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
6159 // in simplex mode next command must be sent here if
6160 // DPC is not used
6161 KdPrint2((PRINT_PREFIX "AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc, NoStartIo));
6162
6163 #ifndef UNIATA_CORE
6164 if(!UseDpc && /*deviceExtension->simplexOnly &&*/ !NoStartIo) {
6165 chan = UniataGetNextChannel(chan);
6166 if(chan) {
6167 srb = UniataGetCurRequest(chan);
6168 } else {
6169 srb = NULL;
6170 }
6171 KdPrint2((PRINT_PREFIX "AtapiInterrupt: run srb %x\n", srb));
6172 if(srb) {
6173 AtapiStartIo__(HwDeviceExtension, srb, FALSE);
6174 }
6175 }
6176 #endif //UNIATA_CORE
6177 return TRUE;
6178
6179 } // end AtapiInterrupt__()
6180
6181 #ifndef UNIATA_CORE
6182
6183 /*++
6184
6185 Routine Description:
6186
6187 This routine handles SMART enable, disable, read attributes and threshold commands.
6188
6189 Arguments:
6190
6191 HwDeviceExtension - HBA miniport driver's adapter data storage
6192 Srb - IO request packet
6193
6194 Return Value:
6195
6196 SRB status
6197
6198 --*/
6199 ULONG
6200 NTAPI
6201 IdeSendSmartCommand(
6202 IN PVOID HwDeviceExtension,
6203 IN PSCSI_REQUEST_BLOCK Srb,
6204 IN ULONG targetId // assume it is always valid
6205 )
6206 {
6207 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
6208 ULONG c ; // = GET_CHANNEL(Srb); may be invalid
6209 PHW_CHANNEL chan ; // = &(deviceExtension->chan[c]);
6210 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
6211 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
6212 SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
6213 PIDEREGS regs = &cmdInParameters.irDriveRegs;
6214 // ULONG i;
6215 UCHAR statusByte;
6216 ULONG DeviceNumber;
6217
6218 if (regs->bCommandReg != SMART_CMD) {
6219 KdPrint2((PRINT_PREFIX
6220 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
6221 return SRB_STATUS_INVALID_REQUEST;
6222 }
6223
6224 c = targetId / deviceExtension->NumberLuns;
6225 DeviceNumber = targetId % deviceExtension->NumberLuns;
6226 KdPrint2((PRINT_PREFIX " c %d, dev %d\n", c, DeviceNumber));
6227
6228 chan = &(deviceExtension->chan[c]);
6229
6230 chan->SmartCommand = regs->bFeaturesReg;
6231
6232 // Determine which of the commands to carry out.
6233 switch(regs->bFeaturesReg) {
6234 case READ_ATTRIBUTES:
6235 case READ_THRESHOLDS:
6236 case READ_LOG_SECTOR:
6237 case WRITE_LOG_SECTOR:
6238
6239 if(Srb->DataTransferLength < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1) {
6240 KdPrint2((PRINT_PREFIX
6241 "IdeSendSmartCommand: wrong buffer size\n"));
6242 return SRB_STATUS_DATA_OVERRUN;
6243 }
6244
6245 statusByte = WaitOnBusy(chan);
6246
6247 if (statusByte & IDE_STATUS_BUSY) {
6248 KdPrint2((PRINT_PREFIX
6249 "IdeSendSmartCommand: Returning BUSY status\n"));
6250 return SRB_STATUS_BUSY;
6251 }
6252
6253 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6254 RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1);
6255
6256 // Set data buffer pointer and words left.
6257 AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
6258 AtaReq->WordsLeft = READ_ATTRIBUTE_BUFFER_SIZE / 2;
6259
6260 statusByte = AtaCommand(deviceExtension, DeviceNumber, c,
6261 regs->bCommandReg,
6262 (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
6263 0,
6264 regs->bSectorNumberReg,
6265 regs->bSectorCountReg,
6266 regs->bFeaturesReg,
6267 ATA_IMMEDIATE);
6268
6269 if(!(statusByte & IDE_STATUS_ERROR)) {
6270 // Wait for interrupt.
6271 return SRB_STATUS_PENDING;
6272 }
6273 return SRB_STATUS_ERROR;
6274
6275 case ENABLE_SMART:
6276 case DISABLE_SMART:
6277 case RETURN_SMART_STATUS:
6278 case ENABLE_DISABLE_AUTOSAVE:
6279 case EXECUTE_OFFLINE_DIAGS:
6280 case SAVE_ATTRIBUTE_VALUES:
6281 case AUTO_OFFLINE:
6282
6283 statusByte = WaitOnBusy(chan);
6284
6285 if (statusByte & IDE_STATUS_BUSY) {
6286 KdPrint2((PRINT_PREFIX
6287 "IdeSendSmartCommand: Returning BUSY status\n"));
6288 return SRB_STATUS_BUSY;
6289 }
6290
6291 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6292 RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) - 1);
6293
6294 // Set data buffer pointer and indicate no data transfer.
6295 AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
6296 AtaReq->WordsLeft = 0;
6297
6298 statusByte = AtaCommand(deviceExtension, DeviceNumber, c,
6299 regs->bCommandReg,
6300 (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
6301 0,
6302 regs->bSectorNumberReg,
6303 regs->bSectorCountReg,
6304 regs->bFeaturesReg,
6305 ATA_IMMEDIATE);
6306
6307 if(!(statusByte & IDE_STATUS_ERROR)) {
6308 // Wait for interrupt.
6309 UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6310 return SRB_STATUS_PENDING;
6311 }
6312 return SRB_STATUS_ERROR;
6313 } // end switch(regs->bFeaturesReg)
6314
6315 return SRB_STATUS_INVALID_REQUEST;
6316
6317 } // end IdeSendSmartCommand()
6318
6319 #endif //UNIATA_CORE
6320
6321 ULONGLONG
6322 NTAPI
6323 UniAtaCalculateLBARegs(
6324 PHW_LU_EXTENSION LunExt,
6325 ULONGLONG startingSector,
6326 PULONG max_bcount
6327 )
6328 {
6329 UCHAR drvSelect,sectorNumber;
6330 USHORT cylinder;
6331 ULONG tmp;
6332
6333 if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
6334 if(LunExt->LimitedTransferMode >= ATA_DMA) {
6335 if(LunExt->DeviceExtension) {
6336 (*max_bcount) = LunExt->DeviceExtension->MaximumDmaTransferLength / DEV_BSIZE;
6337 }
6338 }
6339 return startingSector;
6340 }
6341 tmp = LunExt->IdentifyData.SectorsPerTrack *
6342 LunExt->IdentifyData.NumberOfHeads;
6343 if(!tmp) {
6344 KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: 0-sized\n"));
6345 cylinder = 0;
6346 drvSelect = 0;
6347 sectorNumber = 1;
6348 (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack;
6349 } else {
6350 cylinder = (USHORT)(startingSector / tmp);
6351 drvSelect = (UCHAR)((startingSector % tmp) / LunExt->IdentifyData.SectorsPerTrack);
6352 sectorNumber = (UCHAR)(startingSector % LunExt->IdentifyData.SectorsPerTrack) + 1;
6353 (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack - sectorNumber + 1;
6354 KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
6355 cylinder, drvSelect, sectorNumber, (*max_bcount)));
6356 }
6357 (*max_bcount) = 0;
6358
6359 return (ULONG)(sectorNumber&0xff) | (((ULONG)cylinder&0xffff)<<8) | (((ULONG)drvSelect&0xf)<<24);
6360 } // end UniAtaCalculateLBARegs()
6361
6362 ULONGLONG
6363 NTAPI
6364 UniAtaCalculateLBARegsBack(
6365 PHW_LU_EXTENSION LunExt,
6366 ULONGLONG lba
6367 )
6368 {
6369 ULONG drvSelect,sectorNumber;
6370 ULONG cylinder;
6371 ULONG tmp;
6372
6373 if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
6374 return lba;
6375 }
6376 tmp = LunExt->IdentifyData.SectorsPerTrack *
6377 LunExt->IdentifyData.NumberOfHeads;
6378
6379 cylinder = (USHORT)((lba >> 8) & 0xffff);
6380 drvSelect = (UCHAR)((lba >> 24) & 0xf);
6381 sectorNumber = (UCHAR)(lba & 0xff);
6382
6383 lba = sectorNumber-1 +
6384 (drvSelect*LunExt->IdentifyData.SectorsPerTrack) +
6385 (cylinder*tmp);
6386
6387 return lba;
6388 } // end UniAtaCalculateLBARegsBack()
6389
6390
6391 /*++
6392
6393 Routine Description:
6394
6395 This routine handles IDE read and writes.
6396
6397 Arguments:
6398
6399 HwDeviceExtension - HBA miniport driver's adapter data storage
6400 Srb - IO request packet
6401
6402 Return Value:
6403
6404 SRB status
6405
6406 --*/
6407 ULONG
6408 NTAPI
6409 IdeReadWrite(
6410 IN PVOID HwDeviceExtension,
6411 IN PSCSI_REQUEST_BLOCK Srb,
6412 IN ULONG CmdAction
6413 )
6414 {
6415 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
6416 UCHAR lChannel = GET_CHANNEL(Srb);
6417 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
6418 PHW_LU_EXTENSION LunExt;
6419 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
6420 //ULONG ldev = GET_LDEV(Srb);
6421 UCHAR DeviceNumber = GET_CDEV(Srb);;
6422 ULONGLONG startingSector=0;
6423 ULONG max_bcount;
6424 ULONG wordCount = 0;
6425 UCHAR statusByte,statusByte2;
6426 UCHAR cmd;
6427 ULONGLONG lba;
6428 BOOLEAN use_dma = FALSE;
6429 ULONG fis_size;
6430
6431 AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD;
6432 LunExt = chan->lun[DeviceNumber];
6433
6434 if((CmdAction & CMD_ACTION_PREPARE) &&
6435 (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
6436
6437 if(LunExt->opt_ReadOnly &&
6438 (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) {
6439 if(LunExt->opt_ReadOnly == 1) {
6440 KdPrint2((PRINT_PREFIX "Abort WRITE (Soft R/O)\n"));
6441 return SRB_STATUS_ERROR;
6442 } else {
6443 KdPrint2((PRINT_PREFIX "Ignore WRITE (Soft R/O)\n"));
6444 return SRB_STATUS_SUCCESS;
6445 }
6446 }
6447
6448 // Set data buffer pointer and words left.
6449 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
6450
6451 if(AtaReq->WordsTransfered) {
6452 AtaReq->DataBuffer = ((PUSHORT)(Srb->DataBuffer)) + AtaReq->WordsTransfered;
6453 startingSector = (UniAtaCalculateLBARegsBack(LunExt, AtaReq->lba)) /* latest lba */ + AtaReq->bcount /* previous bcount */;
6454 AtaReq->bcount = (AtaReq->TransferLength - AtaReq->WordsTransfered*2 + DEV_BSIZE-1) / DEV_BSIZE;
6455 KdPrint2((PRINT_PREFIX "IdeReadWrite (Chained REQ): Starting sector %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
6456 startingSector,
6457 AtaReq->TransferLength/2,
6458 AtaReq->WordsTransfered,
6459 AtaReq->bcount));
6460 } else {
6461 AtaReq->DataBuffer = (PUSHORT)(Srb->DataBuffer);
6462 AtaReq->TransferLength = Srb->DataTransferLength;
6463 // Set up 1st block.
6464 switch(Srb->Cdb[0]) {
6465 case SCSIOP_READ:
6466 case SCSIOP_WRITE:
6467 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA);
6468 MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
6469 break;
6470 case SCSIOP_READ12:
6471 case SCSIOP_WRITE12:
6472 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB12READWRITE.LBA);
6473 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks);
6474 break;
6475 case SCSIOP_READ16:
6476 case SCSIOP_WRITE16:
6477 MOV_QD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA);
6478 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks);
6479 break;
6480 }
6481 KdPrint2((PRINT_PREFIX "IdeReadWrite (Orig REQ): Starting sector %I64x, OrigWordsRequested %#x, DevSize %#x\n",
6482 startingSector,
6483 AtaReq->TransferLength/2,
6484 AtaReq->bcount));
6485 }
6486 lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount);
6487
6488 if(max_bcount) {
6489 AtaReq->bcount = min(AtaReq->bcount, max_bcount);
6490 }
6491 AtaReq->WordsLeft = min(AtaReq->TransferLength - AtaReq->WordsTransfered*2,
6492 AtaReq->bcount * DEV_BSIZE) / 2;
6493
6494 KdPrint2((PRINT_PREFIX "IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n",
6495 startingSector,
6496 AtaReq->WordsLeft,
6497 AtaReq->bcount));
6498
6499 AtaReq->lba = lba;
6500
6501 // assume best case here
6502 // we cannot reinit Dma until previous request is completed
6503 if(deviceExtension->HwFlags & UNIATA_AHCI) {
6504 UniataAhciSetupCmdPtr(AtaReq);
6505 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
6506 (PUCHAR)(AtaReq->DataBuffer),
6507 AtaReq->bcount * DEV_BSIZE)) {
6508 KdPrint3((PRINT_PREFIX "IdeReadWrite: AHCI !DMA\n"));
6509 return SRB_STATUS_ERROR;
6510 }
6511 } else
6512 if ((LunExt->LimitedTransferMode >= ATA_DMA)) {
6513 use_dma = TRUE;
6514 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6515 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
6516 (PUCHAR)(AtaReq->DataBuffer),
6517 AtaReq->bcount * DEV_BSIZE)) {
6518 use_dma = FALSE;
6519 }
6520 }
6521
6522 if(deviceExtension->HwFlags & UNIATA_AHCI) {
6523 KdPrint2((PRINT_PREFIX "IdeReadWrite: setup AHCI FIS\n"));
6524 RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
6525
6526 fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
6527 &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]),
6528 (AtaReq->Flags & REQ_FLAG_READ) ? IDE_COMMAND_READ_DMA : IDE_COMMAND_WRITE_DMA,
6529 lba,
6530 (USHORT)(AtaReq->bcount),
6531 0
6532 /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/
6533 );
6534
6535 if(!fis_size) {
6536 KdPrint3((PRINT_PREFIX "IdeReadWrite: AHCI !FIS\n"));
6537 return SRB_STATUS_ERROR;
6538 }
6539
6540 AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0, (AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE, fis_size, DeviceNumber);
6541 KdPrint2((PRINT_PREFIX "IdeReadWrite ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags));
6542 }
6543
6544 AtaReq->ReqState = REQ_STATE_READY_TO_TRANSFER;
6545
6546 } else { // exec_only
6547 KdPrint2((PRINT_PREFIX "IdeReadWrite (ExecOnly): \n"));
6548 lba = AtaReq->lba;
6549
6550 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
6551 use_dma = TRUE;
6552 }
6553 }
6554 if(!(CmdAction & CMD_ACTION_EXEC)) {
6555
6556 return SRB_STATUS_PENDING;
6557 }
6558
6559 // if this is queued request, reinit DMA and check
6560 // if DMA mode is still available
6561 AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
6562 if (/*EnableDma &&*/
6563 (LunExt->TransferMode >= ATA_DMA)) {
6564 use_dma = TRUE;
6565 } else {
6566 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
6567 use_dma = FALSE;
6568 }
6569
6570 // Check if write request.
6571 if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
6572
6573 // Prepare read command.
6574 if(use_dma) {
6575 cmd = IDE_COMMAND_READ_DMA;
6576 } else
6577 if(LunExt->MaximumBlockXfer) {
6578 cmd = IDE_COMMAND_READ_MULTIPLE;
6579 } else {
6580 cmd = IDE_COMMAND_READ;
6581 }
6582 } else {
6583
6584 // Prepare write command.
6585 if (use_dma) {
6586 wordCount = AtaReq->bcount*DEV_BSIZE/2;
6587 cmd = IDE_COMMAND_WRITE_DMA;
6588 } else
6589 if (LunExt->MaximumBlockXfer) {
6590 wordCount = DEV_BSIZE/2 * LunExt->MaximumBlockXfer;
6591
6592 if (AtaReq->WordsLeft < wordCount) {
6593 // Transfer only words requested.
6594 wordCount = AtaReq->WordsLeft;
6595 }
6596 cmd = IDE_COMMAND_WRITE_MULTIPLE;
6597
6598 } else {
6599 wordCount = DEV_BSIZE/2;
6600 cmd = IDE_COMMAND_WRITE;
6601 }
6602 }
6603
6604 // Send IO command.
6605 KdPrint2((PRINT_PREFIX "IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba, ((Srb->DataTransferLength + 0x1FF) / 0x200),
6606 ((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE)));
6607 if(use_dma) {
6608 chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
6609 } else {
6610 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
6611 }
6612
6613 if(deviceExtension->HwFlags & UNIATA_AHCI) {
6614 // AHCI doesn't distinguish DMA and PIO
6615 //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
6616 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
6617 UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6618 InterlockedExchange(&(chan->CheckIntr),
6619 CHECK_INTR_IDLE);
6620 return SRB_STATUS_PENDING;
6621 }
6622
6623 if ((Srb->SrbFlags & SRB_FLAGS_DATA_IN) ||
6624 use_dma) {
6625 statusByte2 = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
6626 cmd, lba,
6627 (USHORT)(AtaReq->bcount),
6628 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6629 0, ATA_IMMEDIATE);
6630 if(statusByte2 != IDE_STATUS_WRONG) {
6631 GetStatus(chan, statusByte2);
6632 }
6633 if(statusByte2 & IDE_STATUS_ERROR) {
6634 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
6635 KdPrint2((PRINT_PREFIX "IdeReadWrite: status %#x, error %#x\n", statusByte2, statusByte));
6636 return SRB_STATUS_ERROR;
6637 }
6638 if(use_dma) {
6639 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
6640 }
6641 return SRB_STATUS_PENDING;
6642 }
6643
6644 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
6645 cmd, lba,
6646 (USHORT)(AtaReq->bcount),
6647 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6648 0, ATA_WAIT_INTR);
6649
6650 if (!(statusByte & IDE_STATUS_DRQ) ||
6651 statusByte == IDE_STATUS_WRONG) {
6652
6653 if(statusByte == IDE_STATUS_WRONG) {
6654 KdPrint2((PRINT_PREFIX
6655 "IdeReadWrite: error sending command (%#x)\n",
6656 statusByte));
6657 } else {
6658 KdPrint2((PRINT_PREFIX
6659 "IdeReadWrite: DRQ never asserted (%#x)\n",
6660 statusByte));
6661 }
6662
6663 AtaReq->WordsLeft = 0;
6664
6665 // Clear interrupt expecting flag.
6666 UniataExpectChannelInterrupt(chan, FALSE);
6667 InterlockedExchange(&(chan->CheckIntr),
6668 CHECK_INTR_IDLE);
6669
6670 // Clear current SRB.
6671 UniataRemoveRequest(chan, Srb);
6672
6673 return (statusByte == IDE_STATUS_WRONG) ? SRB_STATUS_ERROR : SRB_STATUS_TIMEOUT;
6674 }
6675
6676 UniataExpectChannelInterrupt(chan, TRUE);
6677 InterlockedExchange(&(chan->CheckIntr),
6678 CHECK_INTR_IDLE);
6679
6680 // Write next DEV_BSIZE/2*N words.
6681 if (!(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED)) {
6682 KdPrint2((PRINT_PREFIX
6683 "IdeReadWrite: Write %#x words\n", wordCount));
6684
6685 WriteBuffer(chan,
6686 AtaReq->DataBuffer,
6687 wordCount,
6688 UniataGetPioTiming(LunExt));
6689
6690 } else {
6691
6692 KdPrint2((PRINT_PREFIX
6693 "IdeReadWrite: Write %#x Dwords\n", wordCount/2));
6694
6695 WriteBuffer2(chan,
6696 (PULONG)(AtaReq->DataBuffer),
6697 wordCount / 2,
6698 UniataGetPioTiming(LunExt));
6699 }
6700
6701 // Adjust buffer address and words left count.
6702 AtaReq->WordsLeft -= wordCount;
6703 AtaReq->DataBuffer += wordCount;
6704 AtaReq->WordsTransfered += wordCount;
6705
6706 // Wait for interrupt.
6707 return SRB_STATUS_PENDING;
6708
6709 } // end IdeReadWrite()
6710
6711 #ifndef UNIATA_CORE
6712
6713 /*++
6714
6715 Routine Description:
6716 This routine handles IDE Verify.
6717
6718 Arguments:
6719 HwDeviceExtension - HBA miniport driver's adapter data storage
6720 Srb - IO request packet
6721 `
6722 Return Value:
6723 SRB status
6724
6725 --*/
6726 ULONG
6727 NTAPI
6728 IdeVerify(
6729 IN PVOID HwDeviceExtension,
6730 IN PSCSI_REQUEST_BLOCK Srb
6731 )
6732 {
6733 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
6734 UCHAR lChannel = GET_CHANNEL(Srb);
6735 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
6736 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
6737 PHW_LU_EXTENSION LunExt;
6738 //ULONG ldev = GET_LDEV(Srb);
6739 ULONG DeviceNumber = GET_CDEV(Srb);
6740 UCHAR statusByte;
6741 ULONGLONG startingSector=0;
6742 ULONG max_bcount;
6743 ULONGLONG sectors;
6744 ULONGLONG endSector;
6745 ULONG sectorCount=0;
6746 ULONGLONG lba;
6747
6748 LunExt = chan->lun[DeviceNumber];
6749 // Drive has these number sectors.
6750 if(!(sectors = (ULONG)(LunExt->NumOfSectors))) {
6751 sectors = LunExt->IdentifyData.SectorsPerTrack *
6752 LunExt->IdentifyData.NumberOfHeads *
6753 LunExt->IdentifyData.NumberOfCylinders;
6754 }
6755
6756 KdPrint2((PRINT_PREFIX
6757 "IdeVerify: Total sectors %#x\n",
6758 sectors));
6759
6760 // Get starting sector number from CDB.
6761 switch(Srb->Cdb[0]) {
6762 case SCSIOP_VERIFY:
6763 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA);
6764 MOV_SWP_DW2DD(sectorCount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
6765 break;
6766 case SCSIOP_VERIFY12:
6767 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB12READWRITE.LBA);
6768 MOV_DD_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks);
6769 break;
6770 case SCSIOP_VERIFY16:
6771 MOV_QD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA);
6772 MOV_DD_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks);
6773 break;
6774 }
6775
6776 KdPrint2((PRINT_PREFIX
6777 "IdeVerify: Starting sector %#I64x. Number of blocks %#x\n",
6778 startingSector,
6779 sectorCount));
6780
6781 endSector = startingSector + sectorCount;
6782
6783 KdPrint2((PRINT_PREFIX
6784 "IdeVerify: Ending sector %#I64x\n",
6785 endSector));
6786
6787 if (endSector > sectors) {
6788
6789 // Too big, round down.
6790 KdPrint2((PRINT_PREFIX
6791 "IdeVerify: Truncating request to %#x blocks\n",
6792 sectors - startingSector - 1));
6793
6794 sectorCount = (ULONG)(sectors - startingSector - 1);
6795
6796 } else {
6797
6798 // Set up sector count register. Round up to next block.
6799 if (sectorCount > 0xFF) {
6800 sectorCount = (USHORT)0xFF;
6801 }
6802 }
6803
6804 // Set data buffer pointer and words left.
6805 AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
6806 AtaReq->WordsLeft = Srb->DataTransferLength / 2;
6807
6808 // Indicate expecting an interrupt.
6809 InterlockedExchange(&(chan->CheckIntr),
6810 CHECK_INTR_IDLE);
6811
6812 lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount);
6813
6814 statusByte = AtaCommand48(deviceExtension, LunExt->Lun, GET_CHANNEL(Srb),
6815 IDE_COMMAND_VERIFY, lba,
6816 (USHORT)sectorCount,
6817 0, ATA_IMMEDIATE);
6818
6819 if(!(statusByte & IDE_STATUS_ERROR)) {
6820 // Wait for interrupt.
6821 return SRB_STATUS_PENDING;
6822 }
6823 return SRB_STATUS_ERROR;
6824
6825 } // end IdeVerify()
6826
6827 #endif //UNIATA_CORE
6828
6829 /*++
6830
6831 Routine Description:
6832 Send ATAPI packet command to device.
6833
6834 Arguments:
6835 HwDeviceExtension - HBA miniport driver's adapter data storage
6836 Srb - IO request packet
6837
6838 Return Value:
6839
6840 --*/
6841 ULONG
6842 NTAPI
6843 AtapiSendCommand(
6844 IN PVOID HwDeviceExtension,
6845 IN PSCSI_REQUEST_BLOCK Srb,
6846 IN ULONG CmdAction
6847 )
6848 {
6849 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
6850 UCHAR lChannel = GET_CHANNEL(Srb);
6851 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
6852 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
6853 PHW_LU_EXTENSION LunExt;
6854 //ULONG ldev = GET_LDEV(Srb);
6855 ULONG DeviceNumber = GET_CDEV(Srb);
6856 ULONG flags;
6857 UCHAR statusByte,statusByte0,byteCountLow,byteCountHigh;
6858 BOOLEAN use_dma = FALSE;
6859 BOOLEAN dma_reinited = FALSE;
6860 BOOLEAN retried = FALSE;
6861 ULONG fis_size;
6862 UCHAR FeatureReg=0;
6863
6864 LunExt = chan->lun[DeviceNumber];
6865
6866 KdPrint3((PRINT_PREFIX "AtapiSendCommand: req state %#x, Action %x\n", AtaReq->ReqState, CmdAction));
6867 if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
6868 AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER;
6869
6870
6871 #ifdef UNIATA_DUMP_ATAPI
6872 if(CmdAction & CMD_ACTION_PREPARE) {
6873 UCHAR ScsiCommand;
6874 PCDB Cdb;
6875 PCHAR CdbData;
6876 PCHAR ModeSelectData;
6877 ULONG CdbDataLen;
6878
6879 Cdb = (PCDB)(Srb->Cdb);
6880 ScsiCommand = Cdb->CDB6.OperationCode;
6881 CdbData = (PCHAR)(Srb->DataBuffer);
6882 CdbDataLen = Srb->DataTransferLength;
6883
6884 if(CdbDataLen > 0x1000) {
6885 CdbDataLen = 0x1000;
6886 }
6887
6888 KdPrint(("--\n"));
6889 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
6890 KdPrint2(("P:T:D=%d:%d:%d\n",
6891 Srb->PathId,
6892 Srb->TargetId,
6893 Srb->Lun));
6894 KdPrint(("SCSI Command %2.2x\n", ScsiCommand));
6895 KdDump(Cdb, 16);
6896
6897 if(ScsiCommand == SCSIOP_WRITE_CD) {
6898 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
6899 Cdb->WRITE_CD.LBA[0],
6900 Cdb->WRITE_CD.LBA[1],
6901 Cdb->WRITE_CD.LBA[2],
6902 Cdb->WRITE_CD.LBA[3]
6903 ));
6904 } else
6905 if(ScsiCommand == SCSIOP_WRITE12) {
6906 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
6907 Cdb->CDB12READWRITE.LBA[0],
6908 Cdb->CDB12READWRITE.LBA[1],
6909 Cdb->CDB12READWRITE.LBA[2],
6910 Cdb->CDB12READWRITE.LBA[3]
6911 ));
6912 } else
6913 if(ScsiCommand == SCSIOP_WRITE16) {
6914 KdPrint(("Write16, LBA %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
6915 Cdb->CDB16READWRITE.LBA[0],
6916 Cdb->CDB16READWRITE.LBA[1],
6917 Cdb->CDB16READWRITE.LBA[2],
6918 Cdb->CDB16READWRITE.LBA[3],
6919 Cdb->CDB16READWRITE.LBA[4],
6920 Cdb->CDB16READWRITE.LBA[5],
6921 Cdb->CDB16READWRITE.LBA[6],
6922 Cdb->CDB16READWRITE.LBA[7]
6923 ));
6924 } else
6925 if(ScsiCommand == SCSIOP_MODE_SELECT) {
6926 KdPrint(("ModeSelect 6\n"));
6927 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
6928 ModeSelectData = CdbData+4;
6929 KdDump(CdbData, CdbDataLen);
6930 } else
6931 if(ScsiCommand == SCSIOP_MODE_SELECT10) {
6932 KdPrint(("ModeSelect 10\n"));
6933 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
6934 ModeSelectData = CdbData+8;
6935 KdDump(CdbData, CdbDataLen);
6936 } else {
6937 if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
6938 KdPrint(("Send buffer to device:\n"));
6939 KdDump(CdbData, CdbDataLen);
6940 }
6941 }
6942 KdPrint(("--\n"));
6943 }
6944 #endif //UNIATA_DUMP_ATAPI
6945
6946
6947 if(CmdAction == CMD_ACTION_PREPARE) {
6948 KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb->Cdb)));
6949
6950 switch (Srb->Cdb[0]) {
6951 case SCSIOP_RECEIVE:
6952 case SCSIOP_SEND:
6953 case SCSIOP_READ:
6954 case SCSIOP_WRITE:
6955 case SCSIOP_READ12:
6956 case SCSIOP_WRITE12:
6957 case SCSIOP_READ16:
6958 case SCSIOP_WRITE16:
6959 // all right
6960 break;
6961 case SCSIOP_READ_CD:
6962 case SCSIOP_READ_CD_MSF:
6963 if(deviceExtension->opt_AtapiDmaRawRead) {
6964 // all right
6965 break;
6966 }
6967 /* FALL THROUGH */
6968 default:
6969 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY\n"));
6970 return SRB_STATUS_BUSY;
6971 }
6972 //
6973 if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
6974 !AtaReq->OriginalSrb) {
6975 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
6976 return SRB_STATUS_BUSY;
6977 }
6978 }
6979
6980 #ifndef UNIATA_CORE
6981 // We need to know how many platters our atapi cd-rom device might have.
6982 // Before anyone tries to send a srb to our target for the first time,
6983 // we must "secretly" send down a separate mechanism status srb in order to
6984 // initialize our device extension changer data. That's how we know how
6985 // many platters our target has.
6986
6987 if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
6988 !AtaReq->OriginalSrb) {
6989
6990 ULONG srbStatus;
6991
6992 KdPrint3((PRINT_PREFIX "AtapiSendCommand: BuildMechanismStatusSrb()\n"));
6993 // Set this flag now. If the device hangs on the mech. status
6994 // command, we will not have the chance to set it.
6995 LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED;
6996
6997 chan->MechStatusRetryCount = 3;
6998 AtaReq->OriginalSrb = Srb;
6999 AtaReq->Srb = BuildMechanismStatusSrb (
7000 HwDeviceExtension,
7001 Srb);
7002
7003 KdPrint3((PRINT_PREFIX "AtapiSendCommand: AtapiSendCommand recursive\n"));
7004 srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL);
7005 if (srbStatus == SRB_STATUS_PENDING) {
7006 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
7007 return srbStatus;
7008 } else {
7009
7010 // failed! Get the sense key and maybe try again
7011 AtaReq->Srb = BuildRequestSenseSrb ( HwDeviceExtension,
7012 AtaReq->OriginalSrb);
7013
7014 srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL);
7015
7016 KdPrint3((PRINT_PREFIX "AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt));
7017
7018 if (srbStatus == SRB_STATUS_PENDING) {
7019 KdPrint2((PRINT_PREFIX "AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n"));
7020 return srbStatus;
7021 }
7022
7023 // failed again ? should not get here
7024
7025 AtaReq->Srb = AtaReq->OriginalSrb;
7026 AtaReq->OriginalSrb = NULL;
7027
7028 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiHwInitializeChanger()\n"));
7029 // Do-nothing call ?
7030 AtapiHwInitializeChanger (HwDeviceExtension, Srb,
7031 (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
7032 // fall out
7033 }
7034 }
7035 #endif //UNIATA_CORE
7036
7037 if((CmdAction & CMD_ACTION_PREPARE) &&
7038 (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
7039
7040 KdPrint2((PRINT_PREFIX "AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb->Cdb[0], &(Srb->Cdb)));
7041
7042 if(!LunExt->IdentifyData.AtapiCmdSize &&
7043 (Srb->CdbLength > 12)) {
7044 KdPrint2((PRINT_PREFIX "Cdb16 not supported\n"));
7045 return SRB_STATUS_INVALID_REQUEST;
7046 }
7047
7048 // Set data buffer pointer and words left.
7049 AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
7050 AtaReq->WordsLeft = Srb->DataTransferLength / 2;
7051 AtaReq->TransferLength = Srb->DataTransferLength;
7052 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7053 // reset this to force PRD init. May be already setup by recursive SRB
7054 AtaReq->dma_entries = 0;
7055
7056 // check if reorderable
7057 switch(Srb->Cdb[0]) {
7058 case SCSIOP_READ16:
7059 case SCSIOP_WRITE16:
7060
7061 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks);
7062 MOV_QD_SWP(AtaReq->lba, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA);
7063 goto GetLba2;
7064
7065 case SCSIOP_READ12:
7066 case SCSIOP_WRITE12:
7067
7068 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks);
7069 goto GetLba;
7070
7071 case SCSIOP_READ:
7072 case SCSIOP_WRITE:
7073
7074 MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
7075 GetLba:
7076 MOV_DD_SWP(AtaReq->lba, ((PCDB)Srb->Cdb)->CDB10.LBA);
7077 GetLba2:
7078 AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD;
7079 AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
7080 AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE ||
7081 Srb->Cdb[0] == SCSIOP_WRITE12 ||
7082 Srb->Cdb[0] == SCSIOP_WRITE16) ?
7083 REQ_FLAG_WRITE : REQ_FLAG_READ;
7084 break;
7085 default:
7086 AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
7087 if(!AtaReq->TransferLength) {
7088 KdPrint((" assume 0-transfer\n"));
7089 } else
7090 if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
7091 KdPrint((" assume OUT\n"));
7092 AtaReq->Flags |= REQ_FLAG_WRITE;
7093 } else
7094 if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
7095 KdPrint((" assume IN\n"));
7096 AtaReq->Flags |= REQ_FLAG_READ;
7097 }
7098 break;
7099 }
7100
7101 // check if DMA read/write
7102 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7103 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (ahci)\n"));
7104 use_dma = TRUE;
7105 goto setup_dma;
7106 } else
7107 /* if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) {
7108 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n"));
7109 use_dma = TRUE;
7110 goto setup_dma;
7111 } else*/
7112 if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
7113 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
7114 } else
7115 if(AtaReq->TransferLength) {
7116 // try use DMA
7117 switch(Srb->Cdb[0]) {
7118 case SCSIOP_WRITE:
7119 case SCSIOP_WRITE12:
7120 case SCSIOP_WRITE16:
7121 case SCSIOP_SEND:
7122 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO)
7123 break;
7124 /* FALLTHROUGH */
7125 case SCSIOP_RECEIVE:
7126 case SCSIOP_READ:
7127 case SCSIOP_READ12:
7128 case SCSIOP_READ16:
7129
7130 if(deviceExtension->opt_AtapiDmaReadWrite) {
7131 call_dma_setup:
7132 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7133 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n"));
7134 use_dma = TRUE;
7135 } else
7136 if(AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
7137 (PUCHAR)(AtaReq->DataBuffer),
7138 Srb->DataTransferLength
7139 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
7140 )) {
7141 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n"));
7142 use_dma = TRUE;
7143 }
7144 }
7145 break;
7146 case SCSIOP_READ_CD:
7147 case SCSIOP_READ_CD_MSF:
7148 if(deviceExtension->opt_AtapiDmaRawRead)
7149 goto call_dma_setup;
7150 break;
7151 default:
7152
7153 if(deviceExtension->opt_AtapiDmaControlCmd) {
7154 if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
7155 // read operation
7156 use_dma = TRUE;
7157 } else {
7158 // write operation
7159 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO) {
7160 KdPrint2((PRINT_PREFIX "dma RO\n"));
7161 use_dma = FALSE;
7162 } else {
7163 use_dma = TRUE;
7164 }
7165 }
7166 }
7167 break;
7168 }
7169 // try setup DMA
7170 setup_dma:
7171 if(use_dma) {
7172 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7173 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n"));
7174 //use_dma = TRUE;
7175 } else
7176 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
7177 (PUCHAR)(AtaReq->DataBuffer),
7178 Srb->DataTransferLength)) {
7179 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma\n"));
7180 use_dma = FALSE;
7181 } else {
7182 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n"));
7183 }
7184 }
7185 } else {
7186 KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer, no DMA setup\n"));
7187 }
7188
7189
7190 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7191
7192 UniataAhciSetupCmdPtr(AtaReq);
7193
7194 if(!Srb->DataTransferLength) {
7195 KdPrint2((PRINT_PREFIX "zero-transfer\n"));
7196 use_dma = FALSE;
7197 } else
7198 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
7199 (PUCHAR)(AtaReq->DataBuffer),
7200 Srb->DataTransferLength)) {
7201 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no AHCI dma!\n"));
7202 return SRB_STATUS_ERROR;
7203 }
7204 if(!use_dma) {
7205 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7206 } else {
7207 FeatureReg |= ATA_F_DMA;
7208 if(LunExt->IdentifyData.AtapiDMA.DMADirRequired &&
7209 (Srb->SrbFlags & SRB_FLAGS_DATA_IN)) {
7210 FeatureReg |= ATA_F_DMAREAD;
7211 }
7212 }
7213
7214 KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n"));
7215 // this is done in UniataAhciSetupFIS_H2D()
7216 //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
7217 RtlCopyMemory(&(AtaReq->ahci.ahci_cmd_ptr->acmd), Srb->Cdb, Srb->CdbLength);
7218
7219 fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
7220 &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]),
7221 IDE_COMMAND_ATAPI_PACKET /* command */,
7222 0 /* lba */,
7223 (Srb->DataTransferLength >= 0x10000) ? (USHORT)(0xffff) : (USHORT)(Srb->DataTransferLength),
7224 FeatureReg/* feature */
7225 );
7226
7227 if(!fis_size) {
7228 KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n"));
7229 return SRB_STATUS_ERROR;
7230 }
7231
7232 AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0,
7233 ((Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) ? ATA_AHCI_CMD_WRITE : 0) |
7234 (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH),
7235 fis_size, DeviceNumber);
7236
7237 KdPrint2((PRINT_PREFIX "AtapiSendCommand ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags));
7238 }
7239
7240 } else {
7241 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
7242 // if this is queued request, reinit DMA and check
7243 // if DMA mode is still available
7244 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() (1)\n"));
7245 AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7246 if (/*EnableDma &&*/
7247 (LunExt->TransferMode >= ATA_DMA)) {
7248 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (2)\n"));
7249 use_dma = TRUE;
7250 } else {
7251 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7252 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma (2)\n"));
7253 use_dma = FALSE;
7254 }
7255 dma_reinited = TRUE;
7256 }
7257 }
7258
7259 if(!(CmdAction & CMD_ACTION_EXEC)) {
7260 KdPrint2((PRINT_PREFIX "AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
7261 return SRB_STATUS_PENDING;
7262 }
7263 KdPrint3((PRINT_PREFIX "AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma, Srb->Cdb[0]));
7264 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
7265 KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n"));
7266 }
7267
7268 if((Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) && !(deviceExtension->HwFlags & UNIATA_SATA)) {
7269 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
7270 use_dma = FALSE;
7271 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7272 AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7273 } if(AtaReq->TransferLength) {
7274 if(!dma_reinited) {
7275 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit()\n"));
7276 AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7277 if (/*EnableDma &&*/
7278 (LunExt->TransferMode >= ATA_DMA)) {
7279 use_dma = TRUE;
7280 } else {
7281 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7282 use_dma = FALSE;
7283 }
7284 }
7285 } else {
7286 KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer\n"));
7287 use_dma = FALSE;
7288 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7289 if(!deviceExtension->opt_AtapiDmaZeroTransfer && !(deviceExtension->HwFlags & UNIATA_SATA)) {
7290 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
7291 AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7292 }
7293 }
7294 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use_dma=%d\n", use_dma));
7295 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
7296 KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n"));
7297 }
7298
7299 KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_EXEC\n"));
7300
7301 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
7302 &(Srb->Cdb), Srb->Cdb[0], Srb->TargetId, Srb->Lun));
7303
7304 // Make sure command is to ATAPI device.
7305 flags = LunExt->DeviceFlags;
7306 if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
7307 if((Srb->Lun) > (LunExt->DiscsPresent - 1)) {
7308
7309 // Indicate no device found at this address.
7310 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7311 return SRB_STATUS_SELECTION_TIMEOUT;
7312 }
7313 } else if(Srb->Lun > 0) {
7314 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7315 return SRB_STATUS_SELECTION_TIMEOUT;
7316 }
7317
7318 if(!(flags & DFLAGS_ATAPI_DEVICE)) {
7319 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7320 return SRB_STATUS_SELECTION_TIMEOUT;
7321 }
7322 retry:
7323 // Select device 0 or 1. Or more for PM
7324 SelectDrive(chan, DeviceNumber);
7325
7326 // Verify that controller is ready for next command.
7327 GetStatus(chan, statusByte);
7328 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status %#x\n", statusByte));
7329
7330 if(statusByte == IDE_STATUS_WRONG) {
7331 KdPrint2((PRINT_PREFIX "AtapiSendCommand: bad status 0xff on entry\n"));
7332 goto make_reset;
7333 }
7334 if(statusByte & IDE_STATUS_BUSY) {
7335 if(statusByte & IDE_STATUS_DSC) {
7336 KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte));
7337 } else {
7338 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte));
7339 // We have to make reset here, since we are expecting device to be available
7340 //return SRB_STATUS_BUSY; // this cause queue freeze
7341 goto make_reset;
7342 }
7343 }
7344 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7345 ULONG CI;
7346 // Check if command list is free
7347 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
7348 if(CI) {
7349 // controller is busy, however we expect it to be free
7350 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI));
7351 goto make_reset;
7352 }
7353 }
7354 if(statusByte & IDE_STATUS_ERROR) {
7355 if (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
7356
7357 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on entry: (%#x)\n", statusByte));
7358 // Read the error reg. to clear it and fail this request.
7359 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7360 return MapError(deviceExtension, Srb);
7361 } else {
7362 KdPrint2((PRINT_PREFIX " continue with SCSIOP_REQUEST_SENSE\n", statusByte));
7363 }
7364 }
7365 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
7366 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
7367 if((!(statusByte & IDE_STATUS_DSC)) &&
7368 (flags & (DFLAGS_TAPE_DEVICE | DFLAGS_ATAPI_DEVICE)) && chan->RDP) {
7369
7370 AtapiStallExecution(200);
7371 KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte));
7372 AtaReq->ReqState = REQ_STATE_QUEUED;
7373 return SRB_STATUS_PENDING;
7374 }
7375
7376 if(IS_RDP(Srb->Cdb[0])) {
7377 chan->RDP = TRUE;
7378 KdPrint2((PRINT_PREFIX "AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb->Cdb[0]));
7379 } else {
7380 chan->RDP = FALSE;
7381 }
7382 if(statusByte & IDE_STATUS_DRQ) {
7383
7384 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
7385 statusByte));
7386 // Try to drain the data that one preliminary device thinks that it has
7387 // to transfer. Hopefully this random assertion of DRQ will not be present
7388 // in production devices.
7389 statusByte = AtapiSuckPort2(chan);
7390 /*
7391 for (i = 0; i < 0x10000; i++) {
7392 GetStatus(chan, statusByte);
7393 if(statusByte & IDE_STATUS_DRQ) {
7394 AtapiReadPort2(chan, IDX_IO1_i_Data);
7395 } else {
7396 break;
7397 }
7398 }
7399 */
7400 if (statusByte & IDE_STATUS_DRQ) {
7401 make_reset:
7402 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte));
7403
7404 AtapiDisableInterrupts(deviceExtension, lChannel);
7405
7406 AtapiSoftReset(chan, DeviceNumber);
7407
7408 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Issued soft reset to Atapi device. \n"));
7409 // Re-initialize Atapi device.
7410 CheckDevice(HwDeviceExtension, GET_CHANNEL(Srb), DeviceNumber, TRUE);
7411 /*
7412 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
7413 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
7414 */
7415 // Inform the port driver that the bus has been reset.
7416 ScsiPortNotification(ResetDetected, HwDeviceExtension, 0);
7417 // Clean up device extension fields that AtapiStartIo won't.
7418 UniataExpectChannelInterrupt(chan, FALSE);
7419 chan->RDP = FALSE;
7420 InterlockedExchange(&(deviceExtension->chan[GET_CHANNEL(Srb)].CheckIntr),
7421 CHECK_INTR_IDLE);
7422
7423 AtapiEnableInterrupts(deviceExtension, lChannel);
7424 /*
7425 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7426 return SRB_STATUS_BUS_RESET;
7427 */
7428 if(!retried) {
7429 KdPrint3((PRINT_PREFIX "AtapiSendCommand: retry after reset.\n"));
7430 retried = TRUE;
7431 goto retry;
7432 }
7433 KdPrint3((PRINT_PREFIX "AtapiSendCommand: selection timeout.\n"));
7434 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7435 return SRB_STATUS_SELECTION_TIMEOUT;
7436 }
7437 }
7438
7439 if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
7440 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
7441 Srb->Cdb[1] &= ~0xE0;
7442 if((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY) && (flags & DFLAGS_SANYO_ATAPI_CHANGER)) {
7443 // Torisan changer. TUR's are overloaded to be platter switches.
7444 Srb->Cdb[7] = Srb->Lun;
7445 }
7446 }
7447
7448 // SETUP DMA !!!!!
7449
7450 if(use_dma) {
7451 chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
7452 } else {
7453 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
7454 }
7455
7456 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7457 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AHCI, begin transaction\n"));
7458 //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
7459 UniataExpectChannelInterrupt(chan, TRUE);
7460 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
7461 return SRB_STATUS_PENDING;
7462 }
7463
7464 statusByte = WaitOnBusy(chan);
7465 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entry Status (%#x)\n",
7466 statusByte));
7467
7468 if(use_dma) {
7469 FeatureReg |= ATA_F_DMA;
7470 if(LunExt->IdentifyData.AtapiDMA.DMADirRequired &&
7471 (Srb->SrbFlags & SRB_FLAGS_DATA_IN)) {
7472 FeatureReg |= ATA_F_DMAREAD;
7473 }
7474 }
7475
7476 AtapiWritePort1(chan, IDX_IO1_o_Feature, FeatureReg);
7477
7478 // Write transfer byte count to registers.
7479 byteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF);
7480 byteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8);
7481
7482 if (Srb->DataTransferLength >= 0x10000) {
7483 byteCountLow = byteCountHigh = 0xFF;
7484 }
7485
7486 AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountLow, byteCountLow);
7487 AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh, byteCountHigh);
7488
7489 if (flags & DFLAGS_INT_DRQ) {
7490
7491 // This device interrupts when ready to receive the packet.
7492
7493 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
7494 statusByte));
7495
7496 UniataExpectChannelInterrupt(chan, TRUE);
7497 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_CMD_INTR;
7498 InterlockedExchange(&(chan->CheckIntr),
7499 CHECK_INTR_IDLE);
7500
7501 // Write ATAPI packet command.
7502 AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
7503
7504 KdPrint3((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
7505 return SRB_STATUS_PENDING;
7506
7507 }
7508
7509 // This device quickly sets DRQ when ready to receive the packet.
7510
7511 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
7512 statusByte));
7513
7514 UniataExpectChannelInterrupt(chan, TRUE);
7515 AtaReq->ReqState = REQ_STATE_ATAPI_DO_NOTHING_INTR;
7516 InterlockedExchange(&(chan->CheckIntr),
7517 CHECK_INTR_IDLE);
7518
7519 if(g_opt_AtapiSendDisableIntr) {
7520 AtapiDisableInterrupts(deviceExtension, lChannel);
7521 }
7522 // remember status. Later we may check if error appeared after cmd packet
7523 statusByte0 = statusByte;
7524
7525 // Write ATAPI packet command.
7526 AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
7527
7528 // Wait for DRQ.
7529 WaitOnBusy(chan);
7530 statusByte = WaitForDrq(chan);
7531
7532 // Need to read status register and clear interrupt (if any)
7533 GetBaseStatus(chan, statusByte);
7534
7535 if (!(statusByte & IDE_STATUS_DRQ)) {
7536
7537 if(g_opt_AtapiSendDisableIntr) {
7538 AtapiEnableInterrupts(deviceExtension, lChannel);
7539 }
7540 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte));
7541 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7542 return SRB_STATUS_ERROR;
7543 }
7544
7545 GetStatus(chan, statusByte);
7546 KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte));
7547
7548 // Send CDB to device.
7549 statusByte = WaitOnBaseBusy(chan);
7550
7551 // Indicate expecting an interrupt and wait for it.
7552 UniataExpectChannelInterrupt(chan, TRUE);
7553 InterlockedExchange(&(chan->CheckIntr),
7554 CHECK_INTR_IDLE);
7555 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
7556
7557 GetBaseStatus(chan, statusByte);
7558
7559 if(g_opt_AtapiSendDisableIntr) {
7560 AtapiEnableInterrupts(deviceExtension, lChannel);
7561 }
7562
7563 WriteBuffer(chan,
7564 (PUSHORT)Srb->Cdb,
7565 LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
7566 0);
7567
7568 GetStatus(chan, statusByte);
7569 KdPrint3((PRINT_PREFIX "AtapiSendCommand: cmd status (%#x)\n", statusByte));
7570
7571 // When we operate in DMA mode, we should not start transfer when there is an error on entry
7572 // Interrupt may never come in such case.
7573 if(statusByte & IDE_STATUS_ERROR) {
7574 UCHAR interruptReason;
7575
7576 GetBaseStatus(chan, statusByte);
7577 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on cmd: (%#x)\n", statusByte));
7578
7579 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
7580 KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x\n", interruptReason));
7581
7582 // TODO: we should check interruptReason and decide what to do now
7583
7584 // Read the error reg. to clear it and fail this request.
7585 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7586 return MapError(deviceExtension, Srb);
7587 }
7588 /* if(statusByte & IDE_STATUS_DSC) {
7589 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DSC on cmd: (%#x)\n", statusByte));
7590 // Read the error reg. to clear it and fail this request.
7591 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7592 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte));
7593 if(statusByte >> 4) {
7594 GetBaseStatus(chan, statusByte);
7595 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7596 return MapError(deviceExtension, Srb);
7597 }
7598 }
7599 */
7600 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
7601 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
7602 }
7603
7604 KdPrint3((PRINT_PREFIX "AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan->ExpectingInterrupt));
7605
7606 KdPrint2((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
7607 return SRB_STATUS_PENDING;
7608
7609 } // end AtapiSendCommand()
7610
7611
7612 #ifndef UNIATA_CORE
7613
7614 /*++
7615
7616 Routine Description:
7617 Program ATA registers for IDE disk transfer.
7618
7619 Arguments:
7620 HwDeviceExtension - ATAPI driver storage.
7621 Srb - System request block.
7622
7623 Return Value:
7624 SRB status (pending if all goes well).
7625
7626 --*/
7627
7628 #ifdef _DEBUG
7629 ULONG check_point = 0;
7630 #define SetCheckPoint(cp) { check_point = (cp) ; }
7631 #else
7632 #define SetCheckPoint(cp)
7633 #endif
7634
7635 ULONG
7636 NTAPI
7637 IdeSendCommand(
7638 IN PVOID HwDeviceExtension,
7639 IN PSCSI_REQUEST_BLOCK Srb,
7640 IN ULONG CmdAction
7641 )
7642 {
7643 SetCheckPoint(1);
7644 KdPrint2((PRINT_PREFIX "** Ide: Command: entryway\n"));
7645 SetCheckPoint(2);
7646
7647 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
7648 SetCheckPoint(3);
7649 UCHAR lChannel;
7650 PHW_CHANNEL chan;
7651 PCDB cdb;
7652 PHW_LU_EXTENSION LunExt;
7653
7654 SetCheckPoint(4);
7655
7656 UCHAR statusByte,errorByte;
7657 ULONG status = SRB_STATUS_INVALID_REQUEST;
7658 ULONG i;
7659 ULONGLONG lba;
7660 PMODE_PARAMETER_HEADER modeData;
7661 //ULONG ldev;
7662 ULONG DeviceNumber;
7663 PATA_REQ AtaReq;
7664 UCHAR command;
7665
7666 SetCheckPoint(5);
7667 //ULONG __ebp__ = 0;
7668
7669 SetCheckPoint(0x20);
7670 KdPrint2((PRINT_PREFIX "** Ide: Command:\n\n"));
7671 /* __asm {
7672 mov eax,ebp
7673 mov __ebp__, eax
7674 }*/
7675 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
7676 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
7677 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
7678 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
7679 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
7680 Srb));
7681 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
7682 Srb->SrbExtension));
7683 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
7684 Srb->TargetId));*/
7685
7686 SetCheckPoint(0x30);
7687 AtaReq = (PATA_REQ)(Srb->SrbExtension);
7688
7689 KdPrint2((PRINT_PREFIX "** Ide: Command &AtaReq %#x\n",
7690 &AtaReq));
7691 KdPrint2((PRINT_PREFIX "** Ide: Command AtaReq %#x\n",
7692 AtaReq));
7693 KdPrint2((PRINT_PREFIX "** --- **\n"));
7694
7695 lChannel = GET_CHANNEL(Srb);
7696 chan = &(deviceExtension->chan[lChannel]);
7697 //ldev = GET_LDEV(Srb);
7698 DeviceNumber = GET_CDEV(Srb);
7699 LunExt = chan->lun[DeviceNumber];
7700
7701 SetCheckPoint(0x40);
7702 if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
7703 AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER;
7704
7705 cdb = (PCDB)(Srb->Cdb);
7706
7707 if(CmdAction == CMD_ACTION_PREPARE) {
7708 switch (Srb->Cdb[0]) {
7709 case SCSIOP_SERVICE_ACTION16:
7710 if( cdb->SERVICE_ACTION16.ServiceAction==SCSIOP_SA_READ_CAPACITY16 ) {
7711 // ok
7712 } else {
7713 goto default_no_prep;
7714 }
7715 #ifdef NAVO_TEST
7716 case SCSIOP_INQUIRY: // now it requires device access
7717 #endif //NAVO_TEST
7718 case SCSIOP_READ_CAPACITY:
7719 case SCSIOP_READ:
7720 case SCSIOP_WRITE:
7721 case SCSIOP_READ12:
7722 case SCSIOP_WRITE12:
7723 case SCSIOP_READ16:
7724 case SCSIOP_WRITE16:
7725 case SCSIOP_REQUEST_SENSE:
7726 // all right
7727 KdPrint2((PRINT_PREFIX "** Ide: Command continue prep\n"));
7728 SetCheckPoint(50);
7729 break;
7730 default:
7731 default_no_prep:
7732 SetCheckPoint(0);
7733 KdPrint2((PRINT_PREFIX "** Ide: Command break prep\n"));
7734 return SRB_STATUS_BUSY;
7735 }
7736 }
7737
7738 SetCheckPoint(0x100 | Srb->Cdb[0]);
7739 switch (Srb->Cdb[0]) {
7740 case SCSIOP_INQUIRY:
7741
7742 KdPrint2((PRINT_PREFIX
7743 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
7744 Srb->PathId, Srb->Lun, Srb->TargetId));
7745 // Filter out wrong TIDs.
7746 if ((Srb->Lun != 0) ||
7747 (Srb->PathId >= deviceExtension->NumberChannels) ||
7748 (Srb->TargetId >= deviceExtension->NumberLuns)) {
7749
7750 KdPrint2((PRINT_PREFIX
7751 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
7752 // Indicate no device found at this address.
7753 status = SRB_STATUS_SELECTION_TIMEOUT;
7754 break;
7755
7756 } else {
7757
7758 KdPrint2((PRINT_PREFIX
7759 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
7760 PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer);
7761 PIDENTIFY_DATA2 identifyData = &(LunExt->IdentifyData);
7762
7763 if (!(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
7764
7765 if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
7766 KdPrint2((PRINT_PREFIX
7767 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
7768 // Indicate no device found at this address.
7769 #ifndef NAVO_TEST
7770 status = SRB_STATUS_SELECTION_TIMEOUT;
7771 break;
7772 }
7773 } else {
7774 if(!UniataAnybodyHome(HwDeviceExtension, lChannel, DeviceNumber)) {
7775 KdPrint2((PRINT_PREFIX
7776 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
7777 // Indicate no device found at this address.
7778 UniataForgetDevice(chan->lun[DeviceNumber]);
7779 #endif //NAVO_TEST
7780 status = SRB_STATUS_SELECTION_TIMEOUT;
7781 break;
7782 }
7783 }
7784
7785 // Zero INQUIRY data structure.
7786 RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength);
7787
7788 // Standard IDE interface only supports disks.
7789 inquiryData->DeviceType = DIRECT_ACCESS_DEVICE;
7790
7791 // Set the removable bit, if applicable.
7792 if (LunExt->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) {
7793 KdPrint2((PRINT_PREFIX
7794 "RemovableMedia\n"));
7795 inquiryData->RemovableMedia = 1;
7796 }
7797 // Set the Relative Addressing (LBA) bit, if applicable.
7798 if (LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
7799 inquiryData->RelativeAddressing = 1;
7800 KdPrint2((PRINT_PREFIX
7801 "RelativeAddressing\n"));
7802 }
7803 // Set the CommandQueue bit
7804 inquiryData->CommandQueue = 1;
7805
7806 // Fill in vendor identification fields.
7807 for (i = 0; i < 24; i += 2) {
7808 MOV_DW_SWP(inquiryData->DeviceIdentificationString[i], ((PUCHAR)identifyData->ModelNumber)[i]);
7809 }
7810 /*
7811 // Initialize unused portion of product id.
7812 for (i = 0; i < 4; i++) {
7813 inquiryData->ProductId[12+i] = ' ';
7814 }
7815 */
7816 // Move firmware revision from IDENTIFY data to
7817 // product revision in INQUIRY data.
7818 for (i = 0; i < 4; i += 2) {
7819 MOV_DW_SWP(inquiryData->ProductRevisionLevel[i], ((PUCHAR)identifyData->FirmwareRevision)[i]);
7820 }
7821
7822 status = SRB_STATUS_SUCCESS;
7823 }
7824
7825 break;
7826
7827 case SCSIOP_REPORT_LUNS: {
7828
7829 ULONG alen;
7830 PREPORT_LUNS_INFO_HDR LunInfo;
7831
7832 KdPrint2((PRINT_PREFIX
7833 "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
7834 Srb->PathId, Srb->Lun, Srb->TargetId));
7835
7836 MOV_DD_SWP(alen, cdb->REPORT_LUNS.AllocationLength);
7837
7838 if(alen < 16) {
7839 goto invalid_cdb;
7840 }
7841 alen = 8;
7842
7843 LunInfo = (PREPORT_LUNS_INFO_HDR)(Srb->DataBuffer);
7844 RtlZeroMemory(LunInfo, 16);
7845
7846 MOV_DD_SWP( LunInfo->ListLength, alen );
7847 Srb->DataTransferLength = 16;
7848 status = SRB_STATUS_SUCCESS;
7849
7850 break; }
7851
7852 case SCSIOP_MODE_SENSE:
7853
7854 KdPrint2((PRINT_PREFIX
7855 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
7856 Srb->PathId, Srb->Lun, Srb->TargetId));
7857
7858 if(cdb->MODE_SENSE.PageCode == MODE_PAGE_POWER_CONDITION) {
7859 PMODE_POWER_CONDITION_PAGE modeData;
7860
7861 KdPrint2((PRINT_PREFIX "MODE_PAGE_POWER_CONDITION\n"));
7862 modeData = (PMODE_POWER_CONDITION_PAGE)(Srb->DataBuffer);
7863 if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_POWER_CONDITION_PAGE)) {
7864 status = SRB_STATUS_DATA_OVERRUN;
7865 } else {
7866 RtlZeroMemory(modeData, sizeof(MODE_POWER_CONDITION_PAGE));
7867 modeData->PageCode = MODE_PAGE_POWER_CONDITION;
7868 modeData->PageLength = sizeof(MODE_POWER_CONDITION_PAGE)-sizeof(MODE_PARAMETER_HEADER);
7869 modeData->Byte3.Fields.Idle = LunExt->PowerState <= StartStop_Power_Idle;
7870 modeData->Byte3.Fields.Standby = LunExt->PowerState == StartStop_Power_Standby;
7871 Srb->DataTransferLength = sizeof(MODE_POWER_CONDITION_PAGE);
7872 status = SRB_STATUS_SUCCESS;
7873 }
7874 } else
7875 if(cdb->MODE_SENSE.PageCode == MODE_PAGE_CACHING) {
7876 PMODE_CACHING_PAGE modeData;
7877
7878 KdPrint2((PRINT_PREFIX "MODE_PAGE_CACHING\n"));
7879 modeData = (PMODE_CACHING_PAGE)(Srb->DataBuffer);
7880 if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_CACHING_PAGE)) {
7881 status = SRB_STATUS_DATA_OVERRUN;
7882 } else {
7883 RtlZeroMemory(modeData, sizeof(MODE_CACHING_PAGE));
7884 modeData->PageCode = MODE_PAGE_CACHING;
7885 modeData->PageLength = sizeof(MODE_CACHING_PAGE)-sizeof(MODE_PARAMETER_HEADER);
7886 modeData->ReadDisableCache = (LunExt->DeviceFlags & DFLAGS_RCACHE_ENABLED) ? 0 : 1;
7887 modeData->WriteCacheEnable = (LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) ? 1 : 0;
7888 Srb->DataTransferLength = sizeof(MODE_CACHING_PAGE);
7889 status = SRB_STATUS_SUCCESS;
7890 }
7891 } else
7892 if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
7893
7894 // This is used to determine if the media is write-protected.
7895 // Since IDE does not support mode sense then we will modify just the portion we need
7896 // so the higher level driver can determine if media is protected.
7897
7898 //SelectDrive(chan, DeviceNumber);
7899 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7900 //statusByte = WaitOnBusy(chan);
7901 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY);
7902
7903 if (!(statusByte & IDE_STATUS_ERROR)) {
7904
7905 // no error occured return success, media is not protected
7906 UniataExpectChannelInterrupt(chan, FALSE);
7907 InterlockedExchange(&(chan->CheckIntr),
7908 CHECK_INTR_IDLE);
7909 status = SRB_STATUS_SUCCESS;
7910
7911 } else {
7912
7913 // error occured, handle it locally, clear interrupt
7914 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7915
7916 GetBaseStatus(chan, statusByte);
7917 UniataExpectChannelInterrupt(chan, FALSE);
7918 InterlockedExchange(&(chan->CheckIntr),
7919 CHECK_INTR_IDLE);
7920 status = SRB_STATUS_SUCCESS;
7921
7922 if (errorByte & IDE_ERROR_DATA_ERROR) {
7923
7924 //media is write-protected, set bit in mode sense buffer
7925 modeData = (PMODE_PARAMETER_HEADER)Srb->DataBuffer;
7926
7927 Srb->DataTransferLength = sizeof(MODE_PARAMETER_HEADER);
7928 modeData->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
7929 }
7930 }
7931 status = SRB_STATUS_SUCCESS;
7932 } else {
7933 status = SRB_STATUS_INVALID_REQUEST;
7934 }
7935 break;
7936
7937 case SCSIOP_TEST_UNIT_READY:
7938
7939 KdPrint2((PRINT_PREFIX
7940 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
7941 Srb->PathId, Srb->Lun, Srb->TargetId));
7942 if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
7943
7944 // Select device 0 or 1.
7945 //SelectDrive(chan, DeviceNumber);
7946 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7947 // Wait for busy. If media has not changed, return success
7948 //statusByte = WaitOnBusy(chan);
7949 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY);
7950
7951 if (!(statusByte & IDE_STATUS_ERROR)){
7952 UniataExpectChannelInterrupt(chan, FALSE);
7953 InterlockedExchange(&(chan->CheckIntr),
7954 CHECK_INTR_IDLE);
7955 status = SRB_STATUS_SUCCESS;
7956 } else {
7957 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7958 if (errorByte == IDE_ERROR_DATA_ERROR){
7959
7960 // Special case: If current media is write-protected,
7961 // the 0xDA command will always fail since the write-protect bit
7962 // is sticky,so we can ignore this error
7963 GetBaseStatus(chan, statusByte);
7964 UniataExpectChannelInterrupt(chan, FALSE);
7965 InterlockedExchange(&(chan->CheckIntr),
7966 CHECK_INTR_IDLE);
7967 status = SRB_STATUS_SUCCESS;
7968
7969 } else {
7970
7971 // Request sense buffer to be build
7972 UniataExpectChannelInterrupt(chan, TRUE);
7973 InterlockedExchange(&(chan->CheckIntr),
7974 CHECK_INTR_IDLE);
7975 status = SRB_STATUS_PENDING;
7976 }
7977 }
7978 } else {
7979 status = SRB_STATUS_SUCCESS;
7980 }
7981
7982 break;
7983
7984 case SCSIOP_READ_CAPACITY:
7985
7986 KdPrint2((PRINT_PREFIX
7987 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7988 Srb->PathId, Srb->Lun, Srb->TargetId));
7989 // Claim 512 byte blocks (big-endian).
7990 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7991 i = DEV_BSIZE;
7992 RtlZeroMemory(Srb->DataBuffer, sizeof(READ_CAPACITY_DATA));
7993 MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock, i );
7994
7995 // Calculate last sector.
7996 if(!(i = (ULONG)LunExt->NumOfSectors)) {
7997 i = LunExt->IdentifyData.SectorsPerTrack *
7998 LunExt->IdentifyData.NumberOfHeads *
7999 LunExt->IdentifyData.NumberOfCylinders;
8000 }
8001 i--;
8002
8003 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
8004 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
8005 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
8006
8007 MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress, i );
8008
8009 KdPrint2((PRINT_PREFIX
8010 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
8011 Srb->TargetId,
8012 LunExt->IdentifyData.SectorsPerTrack,
8013 LunExt->IdentifyData.NumberOfHeads,
8014 LunExt->IdentifyData.NumberOfCylinders));
8015
8016
8017 status = SRB_STATUS_SUCCESS;
8018 break;
8019
8020 case SCSIOP_SERVICE_ACTION16:
8021
8022 if( cdb->SERVICE_ACTION16.ServiceAction==SCSIOP_SA_READ_CAPACITY16 ) {
8023 KdPrint2((PRINT_PREFIX
8024 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
8025 Srb->PathId, Srb->Lun, Srb->TargetId));
8026 // Claim 512 byte blocks (big-endian).
8027 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
8028 i = DEV_BSIZE;
8029 RtlZeroMemory(Srb->DataBuffer, sizeof(READ_CAPACITY16_DATA));
8030 MOV_DD_SWP( ((PREAD_CAPACITY16_DATA)Srb->DataBuffer)->BytesPerBlock, i );
8031
8032 // Calculate last sector.
8033 if(!(lba = LunExt->NumOfSectors)) {
8034 lba = LunExt->IdentifyData.SectorsPerTrack *
8035 LunExt->IdentifyData.NumberOfHeads *
8036 LunExt->IdentifyData.NumberOfCylinders;
8037 }
8038 lba--;
8039 MOV_QD_SWP( ((PREAD_CAPACITY16_DATA)Srb->DataBuffer)->LogicalBlockAddress, lba );
8040
8041 KdPrint2((PRINT_PREFIX
8042 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n",
8043 Srb->TargetId,
8044 LunExt->IdentifyData.SectorsPerTrack,
8045 LunExt->IdentifyData.NumberOfHeads,
8046 LunExt->IdentifyData.NumberOfCylinders));
8047
8048 status = SRB_STATUS_SUCCESS;
8049 } else {
8050 goto default_abort;
8051 }
8052 break;
8053
8054 case SCSIOP_VERIFY:
8055 case SCSIOP_VERIFY12:
8056 case SCSIOP_VERIFY16:
8057
8058 KdPrint2((PRINT_PREFIX
8059 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
8060 Srb->PathId, Srb->Lun, Srb->TargetId));
8061 status = IdeVerify(HwDeviceExtension,Srb);
8062
8063 break;
8064
8065 case SCSIOP_READ:
8066 case SCSIOP_WRITE:
8067 case SCSIOP_READ12:
8068 case SCSIOP_WRITE12:
8069 case SCSIOP_READ16:
8070 case SCSIOP_WRITE16:
8071
8072 KdPrint2((PRINT_PREFIX
8073 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
8074 (Srb->Cdb[0] == SCSIOP_WRITE) ? "WRITE" : "READ",
8075 Srb->PathId, Srb->Lun, Srb->TargetId));
8076 AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
8077 AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE ||
8078 Srb->Cdb[0] == SCSIOP_WRITE12 ||
8079 Srb->Cdb[0] == SCSIOP_WRITE16) ? REQ_FLAG_WRITE : REQ_FLAG_READ;
8080 status = IdeReadWrite(HwDeviceExtension,
8081 Srb, CmdAction);
8082 break;
8083
8084 case SCSIOP_START_STOP_UNIT:
8085
8086 KdPrint2((PRINT_PREFIX
8087 "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
8088 cdb->START_STOP.Immediate, Srb->PathId, Srb->Lun, Srb->TargetId));
8089 //Determine what type of operation we should perform
8090
8091 command = 0;
8092
8093 if(cdb->START_STOP.FL ||
8094 cdb->START_STOP.FormatLayerNumber ||
8095 cdb->START_STOP.Reserved2 ||
8096 cdb->START_STOP.Reserved2_2 ||
8097 cdb->START_STOP.Reserved3 ||
8098 FALSE) {
8099 goto invalid_cdb;
8100 }
8101
8102 if (cdb->START_STOP.PowerConditions) {
8103 KdPrint2((PRINT_PREFIX "START_STOP Power %d\n", cdb->START_STOP.PowerConditions));
8104 switch(cdb->START_STOP.PowerConditions) {
8105 case StartStop_Power_Idle:
8106 command = IDE_COMMAND_IDLE_IMMED;
8107 break;
8108 case StartStop_Power_Standby:
8109 command = IDE_COMMAND_STANDBY_IMMED;
8110 break;
8111 case StartStop_Power_Sleep:
8112 // TODO: we should save power state in order to know
8113 // that RESET sould be issued to revert device into
8114 // operable state
8115
8116 command = IDE_COMMAND_SLEEP;
8117 break;
8118 default:
8119 goto invalid_cdb;
8120 }
8121 LunExt->PowerState = cdb->START_STOP.PowerConditions;
8122 } else
8123 if (cdb->START_STOP.LoadEject == 1) {
8124 KdPrint2((PRINT_PREFIX "START_STOP eject\n"));
8125 // Eject media,
8126 // first select device 0 or 1.
8127 //SelectDrive(chan, DeviceNumber);
8128 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
8129 command = IDE_COMMAND_MEDIA_EJECT;
8130 } else
8131 if (cdb->START_STOP.Start == 0) {
8132 KdPrint2((PRINT_PREFIX "START_STOP standby\n"));
8133 command = IDE_COMMAND_STANDBY_IMMED;
8134 } else {
8135 // TODO: we may need to perform hard reset (after sleep) or
8136 // issue IDE_COMMAND_IDLE_IMMED in order to activate device
8137 KdPrint2((PRINT_PREFIX "START_STOP activate\n"));
8138
8139 if(LunExt->PowerState == StartStop_Power_Sleep) {
8140 UniataUserDeviceReset(deviceExtension, LunExt, lChannel);
8141 status = SRB_STATUS_SUCCESS;
8142 break;
8143 } else
8144 if(LunExt->PowerState > StartStop_Power_Idle) {
8145 KdPrint2((PRINT_PREFIX " issue IDLE\n"));
8146 command = IDE_COMMAND_IDLE_IMMED;
8147 } else {
8148 KdPrint2((PRINT_PREFIX " do nothing\n"));
8149 status = SRB_STATUS_SUCCESS;
8150 break;
8151 }
8152 }
8153 if(command) {
8154 statusByte = WaitOnBaseBusy(chan);
8155 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, command, 0, 0, 0, 0, 0,
8156 cdb->START_STOP.Immediate ? ATA_IMMEDIATE : ATA_WAIT_READY);
8157 status = (statusByte & IDE_STATUS_ERROR) ? SRB_STATUS_ERROR : SRB_STATUS_SUCCESS;
8158 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
8159
8160 } else {
8161 invalid_cdb:
8162 KdPrint2((PRINT_PREFIX "START_STOP invalid\n"));
8163 if (Srb->SenseInfoBuffer) {
8164
8165 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
8166
8167 senseBuffer->ErrorCode = 0x70;
8168 senseBuffer->Valid = 1;
8169 senseBuffer->AdditionalSenseLength = 0xb;
8170 senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST;
8171 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_CDB;
8172 senseBuffer->AdditionalSenseCodeQualifier = 0;
8173
8174 Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID;
8175 Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
8176 }
8177 status = SRB_STATUS_ERROR;
8178 }
8179 break;
8180
8181 case SCSIOP_MEDIUM_REMOVAL:
8182
8183 cdb = (PCDB)Srb->Cdb;
8184
8185 if(LunExt->IdentifyData.Removable) {
8186 statusByte = WaitOnBaseBusy(chan);
8187
8188 //SelectDrive(chan, DeviceNumber);
8189 if (cdb->MEDIA_REMOVAL.Prevent == TRUE) {
8190 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
8191 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_LOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
8192 } else {
8193 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
8194 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_UNLOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
8195 }
8196 status = SRB_STATUS_SUCCESS;
8197 } else {
8198 status = SRB_STATUS_INVALID_REQUEST;
8199 }
8200 break;
8201
8202 #if 0
8203 // Note: I don't implement this, because NTFS driver too often issues this command
8204 // It causes awful performance degrade. However, if somebody wants, I will implement
8205 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
8206 case SCSIOP_FLUSH_BUFFER:
8207 case SCSIOP_SYNCHRONIZE_CACHE:
8208
8209 SelectDrive(chan, DeviceNumber);
8210 AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_FLUSH_CACHE);
8211 status = SRB_STATUS_SUCCESS;
8212 // status = SRB_STATUS_PENDING;
8213 statusByte = WaitOnBusy(chan);
8214 break;
8215 #endif
8216
8217 case SCSIOP_REQUEST_SENSE:
8218 // this function makes sense buffers to report the results
8219 // of the original GET_MEDIA_STATUS command
8220
8221 KdPrint2((PRINT_PREFIX
8222 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8223 Srb->PathId, Srb->Lun, Srb->TargetId));
8224 if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
8225 status = IdeBuildSenseBuffer(HwDeviceExtension,Srb);
8226 break;
8227 }
8228 status = SRB_STATUS_INVALID_REQUEST;
8229 break;
8230
8231 // ATA_PASSTHORUGH
8232 case SCSIOP_ATA_PASSTHROUGH:
8233 {
8234 PIDEREGS_EX regs;
8235 BOOLEAN use_dma = FALSE;
8236 ULONG to_lim;
8237
8238 regs = (PIDEREGS_EX) &(Srb->Cdb[2]);
8239
8240 if(chan->DeviceExtension->HwFlags & UNIATA_SATA) {
8241 //lChannel = Srb->TargetId >> 1;
8242 } else {
8243 DeviceNumber = max(DeviceNumber, 1);
8244 regs->bDriveHeadReg &= 0x0f;
8245 regs->bDriveHeadReg |= (UCHAR) (((DeviceNumber & 0x1) << 4) | 0xA0);
8246 }
8247
8248 if((regs->bOpFlags & 1) == 0) { // execute ATA command
8249
8250 KdPrint2((PRINT_PREFIX
8251 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
8252 Srb->PathId, Srb->Lun, Srb->TargetId));
8253
8254 if((regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) == UNIATA_SPTI_EX_SPEC_TO) {
8255 to_lim = Srb->TimeOutValue;
8256 } else {
8257 if(Srb->TimeOutValue <= 2) {
8258 to_lim = Srb->TimeOutValue*900;
8259 } else {
8260 to_lim = (Srb->TimeOutValue*999) - 500;
8261 }
8262 }
8263
8264 AtapiDisableInterrupts(deviceExtension, lChannel);
8265
8266 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
8267 // AHCI
8268 statusByte = UniataAhciSendPIOCommandDirect(
8269 deviceExtension,
8270 lChannel,
8271 DeviceNumber,
8272 Srb,
8273 regs,
8274 ATA_WAIT_INTR,
8275 to_lim
8276 );
8277 if(statusByte == IDE_STATUS_WRONG) {
8278 goto passthrough_err;
8279 }
8280 if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
8281 UniataAhciAbortOperation(chan);
8282 goto passthrough_err;
8283 }
8284 goto passthrough_done;
8285 }
8286
8287 // SATA/PATA
8288 if((AtaCommandFlags[regs->bCommandReg] & ATA_CMD_FLAG_DMA) || (regs->bOpFlags & UNIATA_SPTI_EX_USE_DMA)) {
8289 if((chan->lun[DeviceNumber]->LimitedTransferMode >= ATA_DMA)) {
8290 use_dma = TRUE;
8291 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
8292 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
8293 (PUCHAR)(Srb->DataBuffer),
8294 ((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1)))) {
8295 use_dma = FALSE;
8296 }
8297 }
8298 }
8299
8300 AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, regs->bDriveHeadReg);
8301 AtapiStallExecution(10);
8302
8303 if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { // execute ATA command
8304 AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesReg);
8305 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountReg);
8306 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberReg);
8307 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowReg);
8308 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg);
8309 } else {
8310 AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesRegH);
8311 AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesReg);
8312 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountRegH);
8313 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountReg);
8314 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberRegH);
8315 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberReg);
8316 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowRegH);
8317 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowReg);
8318 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighRegH);
8319 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg);
8320 }
8321 AtapiWritePort1(chan, IDX_IO1_o_Command, regs->bCommandReg);
8322
8323 if(use_dma) {
8324 GetBaseStatus(chan, statusByte);
8325 if(statusByte & IDE_STATUS_ERROR) {
8326 goto passthrough_err;
8327 }
8328 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
8329 }
8330
8331 ScsiPortStallExecution(1); // wait for busy to be set
8332
8333 for(i=0; i<to_lim;i+=2) { // 2 msec from WaitOnBaseBusy()
8334 statusByte = WaitOnBaseBusy(chan); // wait for busy to be clear, up to 2 msec
8335 GetBaseStatus(chan, statusByte);
8336 if(statusByte & IDE_STATUS_ERROR) {
8337 break;
8338 }
8339 if(!(statusByte & IDE_STATUS_BUSY)) {
8340 break;
8341 }
8342 }
8343 if(i >= to_lim) {
8344 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
8345 //}
8346 AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_NONE);
8347 goto passthrough_err;
8348 }
8349
8350 if(use_dma) {
8351 AtapiCheckInterrupt__(deviceExtension, (UCHAR)lChannel);
8352 }
8353 AtapiDmaDone(deviceExtension, DeviceNumber, lChannel, NULL);
8354 GetBaseStatus(chan, statusByte);
8355
8356 if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
8357 AtapiSuckPort2(chan);
8358 passthrough_err:
8359 if (Srb->SenseInfoBuffer) {
8360
8361 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
8362
8363 senseBuffer->ErrorCode = 0x70;
8364 senseBuffer->Valid = 1;
8365 senseBuffer->AdditionalSenseLength = 0xb;
8366 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
8367 senseBuffer->AdditionalSenseCode = 0;
8368 senseBuffer->AdditionalSenseCodeQualifier = 0;
8369
8370 Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID;
8371 Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
8372 }
8373 status = SRB_STATUS_ERROR;
8374 } else {
8375
8376 if(!use_dma) {
8377 if (statusByte & IDE_STATUS_DRQ) {
8378 if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
8379 ReadBuffer(chan,
8380 (PUSHORT) Srb->DataBuffer,
8381 Srb->DataTransferLength / 2,
8382 0);
8383 } else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
8384 WriteBuffer(chan,
8385 (PUSHORT) Srb->DataBuffer,
8386 Srb->DataTransferLength / 2,
8387 0);
8388 }
8389 }
8390 }
8391 status = SRB_STATUS_SUCCESS;
8392 }
8393 passthrough_done:;
8394 AtapiEnableInterrupts(deviceExtension, lChannel);
8395
8396 } else { // read task register
8397
8398 BOOLEAN use48;
8399 regs = (PIDEREGS_EX) Srb->DataBuffer;
8400
8401 KdPrint2((PRINT_PREFIX
8402 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
8403 Srb->PathId, Srb->Lun, Srb->TargetId));
8404
8405 if((Srb->DataTransferLength >= sizeof(IDEREGS_EX)) &&
8406 (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND)) {
8407 use48 = TRUE;
8408 } else
8409 if(Srb->DataTransferLength >= sizeof(IDEREGS)) {
8410 use48 = FALSE;
8411 } else {
8412 KdPrint2((PRINT_PREFIX " buffer too small \n"));
8413 status = SRB_STATUS_DATA_OVERRUN;
8414 break;
8415 }
8416 RtlZeroMemory(regs, use48 ? sizeof(IDEREGS_EX) : sizeof(IDEREGS));
8417 regs->bOpFlags = use48 ? ATA_FLAGS_48BIT_COMMAND : 0;
8418 UniataSnapAtaRegs(chan, 0, regs);
8419
8420 status = SRB_STATUS_SUCCESS;
8421 }
8422 break;
8423 }
8424
8425 default:
8426 default_abort:
8427 KdPrint2((PRINT_PREFIX
8428 "IdeSendCommand: Unsupported command %#x\n",
8429 Srb->Cdb[0]));
8430
8431 status = SRB_STATUS_INVALID_REQUEST;
8432
8433 } // end switch
8434
8435 if(status == SRB_STATUS_PENDING) {
8436 KdPrint2((PRINT_PREFIX "IdeSendCommand: SRB_STATUS_PENDING\n"));
8437 if(CmdAction & CMD_ACTION_EXEC) {
8438 KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
8439 AtaReq->ReqState = REQ_STATE_EXPECTING_INTR;
8440 }
8441 } else {
8442 KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
8443 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
8444 }
8445
8446 return status;
8447
8448 } // end IdeSendCommand()
8449
8450
8451 /*++
8452
8453 Routine Description:
8454 Enables disables media status notification
8455
8456 Arguments:
8457 HwDeviceExtension - ATAPI driver storage.
8458
8459 --*/
8460 VOID
8461 NTAPI
8462 IdeMediaStatus(
8463 BOOLEAN EnableMSN,
8464 IN PVOID HwDeviceExtension,
8465 IN ULONG lChannel,
8466 IN ULONG DeviceNumber
8467 )
8468 {
8469 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
8470 PHW_CHANNEL chan;
8471 UCHAR statusByte,errorByte;
8472
8473 chan = &(deviceExtension->chan[lChannel]);
8474 SelectDrive(chan, DeviceNumber);
8475
8476 if (EnableMSN == TRUE){
8477
8478 // If supported enable Media Status Notification support
8479 if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_REMOVABLE_DRIVE)) {
8480
8481 // enable
8482 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
8483 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
8484 0, ATA_C_F_ENAB_MEDIASTAT, ATA_WAIT_BASE_READY);
8485
8486 if (statusByte & IDE_STATUS_ERROR) {
8487 // Read the error register.
8488 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
8489
8490 KdPrint2((PRINT_PREFIX
8491 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
8492 statusByte,
8493 errorByte));
8494 } else {
8495 chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_MEDIA_STATUS_ENABLED;
8496 KdPrint2((PRINT_PREFIX "IdeMediaStatus: Media Status Notification Supported\n"));
8497 chan->ReturningMediaStatus = 0;
8498
8499 }
8500
8501 }
8502 } else { // end if EnableMSN == TRUE
8503
8504 // disable if previously enabled
8505 if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)) {
8506
8507 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
8508 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
8509 0, ATA_C_F_DIS_MEDIASTAT, ATA_WAIT_BASE_READY);
8510 chan->lun[DeviceNumber]->DeviceFlags &= ~DFLAGS_MEDIA_STATUS_ENABLED;
8511 }
8512
8513
8514 }
8515
8516
8517 } // end IdeMediaStatus()
8518
8519
8520 /*++
8521
8522 Routine Description:
8523
8524 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
8525 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
8526 Arguments:
8527
8528 HwDeviceExtension - ATAPI driver storage.
8529 Srb - System request block.
8530
8531 Return Value:
8532
8533 SRB status (ALWAYS SUCCESS).
8534
8535 --*/
8536 ULONG
8537 NTAPI
8538 IdeBuildSenseBuffer(
8539 IN PVOID HwDeviceExtension,
8540 IN PSCSI_REQUEST_BLOCK Srb
8541 )
8542 {
8543 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
8544 // ULONG status;
8545 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->DataBuffer;
8546 UCHAR ReturningMediaStatus = deviceExtension->chan[GET_CHANNEL(Srb)].ReturningMediaStatus;
8547
8548 if (senseBuffer){
8549
8550 if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE) {
8551
8552 senseBuffer->ErrorCode = 0x70;
8553 senseBuffer->Valid = 1;
8554 senseBuffer->AdditionalSenseLength = 0xb;
8555 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
8556 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
8557 senseBuffer->AdditionalSenseCodeQualifier = 0;
8558 } else if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE_REQ) {
8559
8560 senseBuffer->ErrorCode = 0x70;
8561 senseBuffer->Valid = 1;
8562 senseBuffer->AdditionalSenseLength = 0xb;
8563 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
8564 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
8565 senseBuffer->AdditionalSenseCodeQualifier = 0;
8566 } else if(ReturningMediaStatus & IDE_ERROR_END_OF_MEDIA) {
8567
8568 senseBuffer->ErrorCode = 0x70;
8569 senseBuffer->Valid = 1;
8570 senseBuffer->AdditionalSenseLength = 0xb;
8571 senseBuffer->SenseKey = SCSI_SENSE_NOT_READY;
8572 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
8573 senseBuffer->AdditionalSenseCodeQualifier = 0;
8574 } else if(ReturningMediaStatus & IDE_ERROR_DATA_ERROR) {
8575
8576 senseBuffer->ErrorCode = 0x70;
8577 senseBuffer->Valid = 1;
8578 senseBuffer->AdditionalSenseLength = 0xb;
8579 senseBuffer->SenseKey = SCSI_SENSE_DATA_PROTECT;
8580 senseBuffer->AdditionalSenseCode = 0;
8581 senseBuffer->AdditionalSenseCodeQualifier = 0;
8582 }
8583 return SRB_STATUS_SUCCESS;
8584 }
8585 return SRB_STATUS_ERROR;
8586
8587 }// End of IdeBuildSenseBuffer
8588
8589 VOID
8590 NTAPI
8591 UniataUserDeviceReset(
8592 PHW_DEVICE_EXTENSION deviceExtension,
8593 PHW_LU_EXTENSION LunExt,
8594 ULONG lChannel
8595 )
8596 {
8597 ULONG i;
8598 AtapiDisableInterrupts(deviceExtension, lChannel);
8599 if ((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
8600 (LunExt->PowerState != StartStop_Power_Sleep)) {
8601 KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset ATAPI\n"));
8602 AtapiSoftReset(&(deviceExtension->chan[lChannel]), LunExt->Lun);
8603 } else {
8604 KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
8605 AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_NONE);
8606 for(i=0; i<deviceExtension->NumberLuns; i++) {
8607 deviceExtension->chan[lChannel].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
8608 }
8609 }
8610 LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit
8611 AtapiEnableInterrupts(deviceExtension, lChannel);
8612 return;
8613 } // end UniataUserDeviceReset()
8614
8615 BOOLEAN
8616 NTAPI
8617 UniataNeedQueueing(
8618 PHW_DEVICE_EXTENSION deviceExtension,
8619 PHW_CHANNEL chan,
8620 BOOLEAN TopLevel
8621 )
8622 {
8623 BOOLEAN PostReq = FALSE;
8624 if(TopLevel) {
8625 KdPrint3((PRINT_PREFIX "UniataNeedQueueing: TopLevel, qd=%x\n", chan->queue_depth));
8626 if(chan->queue_depth > 0) {
8627 #if 0
8628 if(atapiDev &&
8629 ((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY)/* ||
8630 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
8631 KdPrint2((PRINT_PREFIX "spec: SCSIOP_TEST_UNIT_READY\n"));
8632 //PostReq = FALSE;
8633 status = SRB_STATUS_BUSY;
8634 goto skip_exec;
8635 } else {
8636 PostReq = TRUE;
8637 }
8638 #else
8639 PostReq = TRUE;
8640 #endif
8641 } else
8642 if(deviceExtension->simplexOnly && deviceExtension->queue_depth > 0) {
8643 PostReq = TRUE;
8644 }
8645 } else {
8646 KdPrint3((PRINT_PREFIX "UniataNeedQueueing: qd=%x\n", chan->queue_depth));
8647 }
8648 return PostReq;
8649 } // end UniataNeedQueueing()
8650
8651 /*++
8652
8653 Routine Description:
8654
8655 This routine is called from the SCSI port driver synchronized
8656 with the kernel to start an IO request.
8657 ->HwStartIo
8658
8659 Arguments:
8660
8661 HwDeviceExtension - HBA miniport driver's adapter data storage
8662 Srb - IO request packet
8663
8664 Return Value:
8665
8666 TRUE
8667
8668 --*/
8669 BOOLEAN
8670 NTAPI
8671 AtapiStartIo(
8672 IN PVOID HwDeviceExtension,
8673 IN PSCSI_REQUEST_BLOCK Srb
8674 )
8675 {
8676 return AtapiStartIo__(HwDeviceExtension, Srb, TRUE);
8677 } // end AtapiStartIo()
8678
8679 BOOLEAN
8680 NTAPI
8681 AtapiStartIo__(
8682 IN PVOID HwDeviceExtension,
8683 IN PSCSI_REQUEST_BLOCK Srb,
8684 IN BOOLEAN TopLevel
8685 )
8686 {
8687 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
8688 UCHAR lChannel;
8689 PHW_CHANNEL chan;
8690 PHW_LU_EXTENSION LunExt;
8691 ULONG status;
8692 //ULONG ldev;
8693 ULONG DeviceNumber;
8694 UCHAR PathId;
8695 UCHAR TargetId;
8696 UCHAR Lun;
8697 PATA_REQ AtaReq;
8698 PSCSI_REQUEST_BLOCK tmpSrb;
8699 BOOLEAN PostReq = FALSE;
8700 BOOLEAN atapiDev;
8701 BOOLEAN commPort = FALSE;
8702
8703 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
8704 if(deviceExtension->Isr2DevObj && !BMList[deviceExtension->DevIndex].Isr2Enable) {
8705 KdPrint2((PRINT_PREFIX "Isr2Enable -> 1\n"));
8706 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
8707 }
8708 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
8709
8710 /* KeBugCheckEx(0xc000000e,
8711 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8712 Srb->Function,
8713 TopLevel, 0x80000001);
8714 */
8715 if(TopLevel && Srb && Srb->SrbExtension) {
8716 KdPrint2((PRINT_PREFIX "TopLevel\n"));
8717 //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
8718 UniAtaClearAtaReq(Srb->SrbExtension);
8719 }
8720
8721 do { // fetch all queued commands for the channel (if valid)
8722
8723 lChannel = GET_CHANNEL(Srb);
8724 //ldev = GET_LDEV(Srb);
8725 chan = NULL;
8726 LunExt = NULL;
8727 DeviceNumber = GET_CDEV(Srb);
8728 commPort = FALSE;
8729
8730 //ASSERT(deviceExtension);
8731 //ASSERT(chan);
8732
8733 KdPrint2((PRINT_PREFIX
8734 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8735 Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId));
8736 KdPrint2((PRINT_PREFIX " VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
8737
8738 if(lChannel == deviceExtension->NumberChannels &&
8739 !Srb->Lun && !Srb->TargetId &&
8740 ((Srb->Function == SRB_FUNCTION_IO_CONTROL) ||
8741 (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI && Srb->Cdb[0] == SCSIOP_INQUIRY))
8742 ) {
8743 // This is our virtual device
8744 KdPrint2((PRINT_PREFIX
8745 "AtapiStartIo: Communication port\n"));
8746 if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
8747
8748 if(Srb->DataTransferLength < sizeof(PINQUIRYDATA)) {
8749 KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", Srb->DataTransferLength,
8750 sizeof(PINQUIRYDATA) ));
8751 wrong_buffer_size:
8752 status = SRB_STATUS_DATA_OVERRUN;
8753 goto complete_req;
8754 }
8755
8756 PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer);
8757
8758 KdPrint2((PRINT_PREFIX
8759 " INQUIRY\n"));
8760 // Zero INQUIRY data structure.
8761 RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength);
8762
8763 inquiryData->DeviceType = COMMUNICATION_DEVICE;
8764
8765 // Fill in vendor identification fields.
8766 RtlCopyMemory(&inquiryData->VendorId, &uniata_comm_name, 28);
8767
8768 status = SRB_STATUS_SUCCESS;
8769 goto complete_req;
8770 }
8771 commPort = TRUE;
8772 /* Pass IOCTL request down */
8773 } else
8774 if(lChannel >= deviceExtension->NumberChannels ||
8775 Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns ||
8776 Srb->Lun) {
8777
8778 if(lChannel >= deviceExtension->NumberChannels) {
8779 chan = NULL;
8780 }
8781
8782 reject_srb:
8783 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8784 KdPrint3((PRINT_PREFIX
8785 "AtapiStartIo: SRB rejected\n"));
8786 // Indicate no device found at this address.
8787 KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
8788 status = SRB_STATUS_SELECTION_TIMEOUT;
8789 goto complete_req;
8790 //}
8791 } else
8792 if((deviceExtension->HwFlags & UNIATA_AHCI) &&
8793 !UniataAhciChanImplemented(deviceExtension, lChannel)) {
8794 chan = NULL;
8795 }
8796
8797 if(!commPort) {
8798 chan = &(deviceExtension->chan[lChannel]);
8799 LunExt = chan->lun[DeviceNumber];
8800 if(!LunExt) {
8801 goto reject_srb;
8802 }
8803 atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
8804 } else {
8805 atapiDev = FALSE;
8806 }
8807
8808 #ifdef _DEBUG
8809 if(!commPort && !LunExt) {
8810 #if 0
8811 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
8812 deviceExtension,
8813 chan, DeviceNumber,
8814 deviceExtension->NumberChannels);
8815 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
8816 lChannel, GET_CDEV(Srb), deviceExtension->chan[0].lun[0]);
8817 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8818 Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId);
8819 #endif //0
8820 /*
8821 int i;
8822 for(i=0; i<1000; i++) {
8823 AtapiStallExecution(3*1000);
8824 }
8825 */
8826 goto reject_srb;
8827 }
8828 #endif //_DEBUG
8829
8830 // Determine which function.
8831 switch (Srb->Function) {
8832
8833 case SRB_FUNCTION_EXECUTE_SCSI:
8834
8835 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
8836 if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) {
8837 // let passthrough go
8838 } else
8839 if(Srb->Cdb[0] == SCSIOP_INQUIRY) {
8840 // let INQUIRY go
8841 } else {
8842
8843 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8844 KdPrint2((PRINT_PREFIX
8845 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
8846 // Indicate no device found at this address.
8847 KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
8848 status = SRB_STATUS_SELECTION_TIMEOUT;
8849 break;
8850 //}
8851 }
8852 } else {
8853 KdPrint2((PRINT_PREFIX
8854 " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb, &(Srb->Cdb), Srb->SrbExtension, Srb->Cdb[0]));
8855 }
8856 /*
8857 __try {
8858 if(Srb->DataTransferLength) {
8859 UCHAR a;
8860 a = ((PUCHAR)(Srb->DataBuffer))[0];
8861 g_foo += a;
8862 }
8863 } __except(EXCEPTION_EXECUTE_HANDLER) {
8864 KdPrint3((PRINT_PREFIX
8865 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
8866 // Indicate no device found at this address.
8867 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
8868 status = SRB_STATUS_ERROR;
8869 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
8870 ASSERT(FALSE);
8871 break;
8872 }
8873 */
8874 PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
8875
8876 if(PostReq) {
8877
8878 KdPrint3((PRINT_PREFIX "Non-empty queue\n"));
8879 if (atapiDev &&
8880 (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) {
8881 KdPrint3((PRINT_PREFIX "Try ATAPI prepare\n"));
8882
8883 status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE);
8884 } else {
8885 KdPrint2((PRINT_PREFIX "Try IDE prepare\n"));
8886 status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE);
8887 }
8888 /*KeBugCheckEx(0xc000000e,
8889 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8890 Srb->Function,
8891 status, 0x80000001);*/
8892 if(status == SRB_STATUS_BUSY)
8893 status = SRB_STATUS_PENDING;
8894 // Insert requests AFTER they have been initialized on
8895 // CMD_ACTION_PREPARE stage
8896 // we should not check TopLevel here (it is always TRUE)
8897 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8898 UniataQueueRequest(chan, Srb);
8899
8900 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
8901
8902 } else {
8903
8904 // Send command to device.
8905 KdPrint2((PRINT_PREFIX "Send to device %x\n", Srb->Cdb[0]));
8906 if(TopLevel) {
8907 KdPrint2((PRINT_PREFIX "TopLevel (2), srb %#x\n", Srb));
8908 AtaReq = (PATA_REQ)(Srb->SrbExtension);
8909 KdPrint2((PRINT_PREFIX "TopLevel (3), AtaReq %#x\n", AtaReq));
8910 //ASSERT(!AtaReq->Flags);
8911 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8912 UniataQueueRequest(chan, Srb);
8913 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
8914 //ASSERT(!AtaReq->Flags);
8915 AtaReq->ReqState = REQ_STATE_QUEUED;
8916 //ASSERT(!AtaReq->Flags);
8917 }
8918
8919 #ifndef NAVO_TEST
8920 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
8921 if(!LunExt) {
8922 goto reject_srb;
8923 }
8924 if(Srb->Cdb[0] == SCSIOP_INQUIRY) {
8925 if(UniataAnybodyHome(deviceExtension, chan->lChannel, DeviceNumber)) {
8926 if(!CheckDevice(HwDeviceExtension, chan->lChannel, DeviceNumber, TRUE)) {
8927 goto reject_srb;
8928 }
8929 }
8930 if(!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
8931 goto reject_srb;
8932 }
8933 } else
8934 if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) {
8935 // allow
8936 } else {
8937 goto reject_srb;
8938 }
8939 }
8940 #endif //NAVO_TEST
8941
8942 if(atapiDev &&
8943 (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)/* &&
8944 (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
8945 KdPrint3((PRINT_PREFIX "Try ATAPI send %x\n", Srb->Cdb[0]));
8946 status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
8947 } else {
8948 KdPrint2((PRINT_PREFIX "Try IDE send\n"));
8949 /* {
8950 ULONG __ebp__ = 0;
8951 ULONG __esp__ = 0;
8952
8953 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
8954 __asm {
8955 mov eax,ebp
8956 mov __ebp__, eax
8957 mov eax,esp
8958 mov __esp__, eax
8959 }
8960 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
8961 }*/
8962 status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
8963 }
8964 /* KeBugCheckEx(0xc000000e,
8965 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8966 Srb->Function,
8967 status, 0x80000002);*/
8968
8969 }
8970 //skip_exec:
8971 TopLevel = FALSE;
8972
8973 break;
8974
8975 case SRB_FUNCTION_ABORT_COMMAND:
8976
8977 tmpSrb = ScsiPortGetSrb(HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun,
8978 Srb->QueueTag);
8979 // Verify that SRB to abort is still outstanding.
8980 if((tmpSrb != Srb->NextSrb) ||
8981 !chan->queue_depth) {
8982
8983 KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB to abort already completed\n"));
8984
8985 // Complete abort SRB.
8986 status = SRB_STATUS_ABORT_FAILED;
8987 break;
8988 }
8989
8990 AtaReq = (PATA_REQ)(tmpSrb->SrbExtension);
8991 if(AtaReq->ReqState > REQ_STATE_READY_TO_TRANSFER) {
8992 if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_CURRENT)) {
8993 KdPrint2((PRINT_PREFIX "AtapiStartIo: Abort command failed\n"));
8994 // Log reset failure.
8995 KdPrint3((PRINT_PREFIX
8996 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
8997 HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
8998 ));
8999 ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8);
9000 status = SRB_STATUS_ERROR;
9001
9002 } else {
9003 status = SRB_STATUS_SUCCESS;
9004 }
9005 } else {
9006 KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove aborted srb %#x\n", tmpSrb));
9007 if (tmpSrb->SenseInfoBuffer &&
9008 tmpSrb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) {
9009
9010 PSENSE_DATA senseBuffer = (PSENSE_DATA)tmpSrb->SenseInfoBuffer;
9011
9012 senseBuffer->ErrorCode = 0;
9013 senseBuffer->Valid = 1;
9014 senseBuffer->AdditionalSenseLength = 0xb;
9015 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
9016 senseBuffer->AdditionalSenseCode = 0;
9017 senseBuffer->AdditionalSenseCodeQualifier = 0;
9018
9019 tmpSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
9020 }
9021 AtapiDmaDBSync(chan, tmpSrb);
9022 UniataRemoveRequest(chan, tmpSrb);
9023 // Indicate command complete.
9024 ScsiPortNotification(RequestComplete,
9025 deviceExtension,
9026 tmpSrb);
9027 status = SRB_STATUS_SUCCESS;
9028 }
9029 break;
9030
9031 // Abort function indicates that a request timed out.
9032 // Call reset routine. Card will only be reset if
9033 // status indicates something is wrong.
9034 // Fall through to reset code.
9035
9036 case SRB_FUNCTION_RESET_DEVICE:
9037 case SRB_FUNCTION_RESET_LOGICAL_UNIT:
9038
9039 // Reset single device.
9040 // For now we support only Lun=0
9041
9042 // Note: reset is immediate command, it cannot be queued since it is usually used to
9043 // revert not-responding device to operational state
9044 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device request received\n"));
9045 UniataUserDeviceReset(deviceExtension, LunExt, lChannel);
9046 status = SRB_STATUS_SUCCESS;
9047 break;
9048
9049 case SRB_FUNCTION_RESET_BUS:
9050 do_bus_reset:
9051 // Reset Atapi and SCSI bus.
9052
9053 // Note: reset is immediate command, it cannot be queued since it is usually used to
9054 // revert not- responding device to operational state
9055 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus request received\n"));
9056 if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_ALL)) {
9057 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus failed\n"));
9058 // Log reset failure.
9059 KdPrint3((PRINT_PREFIX
9060 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
9061 HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
9062 ));
9063 ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8);
9064 status = SRB_STATUS_ERROR;
9065
9066 } else {
9067 status = SRB_STATUS_SUCCESS;
9068 }
9069
9070 break;
9071
9072 case SRB_FUNCTION_SHUTDOWN:
9073
9074 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown\n"));
9075 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
9076 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - no such device\n"));
9077 } else
9078 if(atapiDev) {
9079 // FLUSH ATAPI device - do nothing
9080 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - ATAPI device\n"));
9081 } else {
9082 // FLUSH IDE/ATA device
9083 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - IDE device\n"));
9084 AtapiDisableInterrupts(deviceExtension, lChannel);
9085 status = AtaCommand(deviceExtension, DeviceNumber, GET_CHANNEL(Srb),
9086 IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_IDLE);
9087 // If supported & allowed, reset write cacheing
9088 if(LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) {
9089
9090 // Disable write cache
9091 status = AtaCommand(deviceExtension, DeviceNumber, lChannel,
9092 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
9093 0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY);
9094 // Check for errors.
9095 if (status & IDE_STATUS_ERROR) {
9096 KdPrint2((PRINT_PREFIX
9097 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
9098 DeviceNumber));
9099 }
9100 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
9101
9102 // Re-enable write cache
9103 status = AtaCommand(deviceExtension, DeviceNumber, lChannel,
9104 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
9105 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
9106 // Check for errors.
9107 if (status & IDE_STATUS_ERROR) {
9108 KdPrint2((PRINT_PREFIX
9109 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
9110 DeviceNumber));
9111 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
9112 } else {
9113 LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED;
9114 }
9115 }
9116
9117 AtapiEnableInterrupts(deviceExtension, lChannel);
9118 }
9119 status = SRB_STATUS_SUCCESS;
9120
9121 break;
9122
9123 case SRB_FUNCTION_FLUSH:
9124
9125 KdPrint2((PRINT_PREFIX "AtapiStartIo: Flush (do nothing)\n"));
9126 status = SRB_STATUS_SUCCESS;
9127 break;
9128
9129 case SRB_FUNCTION_IO_CONTROL: {
9130
9131 ULONG len;
9132
9133 KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
9134
9135 len = Srb->DataTransferLength;
9136
9137 if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
9138
9139 ULONG targetId = (ULONG)(-1);
9140
9141 if(len < sizeof(SRB_IO_CONTROL)) {
9142 goto wrong_buffer_size;
9143 }
9144
9145 // extract bogus bus address
9146 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
9147 case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
9148 PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9149
9150 if(len < sizeof(SRB_IO_CONTROL)+sizeof(GETVERSIONINPARAMS)) {
9151 goto wrong_buffer_size;
9152 }
9153
9154 targetId = versionParameters->bIDEDeviceMap;
9155 KdPrint2((PRINT_PREFIX "targetId (smart ver) %d\n", targetId));
9156 break; }
9157 case IOCTL_SCSI_MINIPORT_IDENTIFY:
9158 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9159 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9160 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9161 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9162 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9163 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9164 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9165 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9166 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE:
9167 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG:
9168 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG:
9169 {
9170 PSENDCMDINPARAMS cmdInParameters = (PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9171
9172 if(len < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDINPARAMS) - 1) {
9173 goto wrong_buffer_size;
9174 }
9175
9176 targetId = cmdInParameters->bDriveNumber;
9177 KdPrint2((PRINT_PREFIX "targetId (smart/ident) %d\n", targetId));
9178 break; }
9179 default:
9180 invalid_request:
9181 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9182 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9183 status = SRB_STATUS_INVALID_REQUEST;
9184 goto complete_req;
9185 } // end switch()
9186
9187 // adjust (if necessary) bus address
9188 if(targetId != (ULONG)(-1)) {
9189
9190 // This is done because of how the IOCTL_SCSI_MINIPORT
9191 // determines 'targetid's'. Disk.sys places the real target id value
9192 // in the DeviceMap field. Once we do some parameter checking, the value passed
9193 // back to the application will be determined.
9194
9195 if (deviceExtension->NumberChannels == 1) {
9196 // do this for legacy controllers and legacy callers
9197 KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call\n"));
9198 DeviceNumber = (targetId & 0x01);
9199 lChannel = 0;
9200 } else
9201 if(commPort) {
9202 // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
9203 // due to DISK.SYS design bug, we have invalid SCSI address in SRB
9204 KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call (2)\n"));
9205 if(deviceExtension->HwFlags & UNIATA_AHCI) {
9206 lChannel = (UCHAR)targetId / 2;
9207 DeviceNumber = 0;
9208 } else {
9209 lChannel = (UCHAR)(targetId / 2);
9210 DeviceNumber = targetId & 0x01;
9211 }
9212 } else {
9213 // otherwise assume lChannel and DeviceNumber from Srb are ok
9214 }
9215 if(lChannel >= deviceExtension->NumberChannels ||
9216 DeviceNumber >= deviceExtension->NumberLuns) {
9217 KdPrint2((PRINT_PREFIX
9218 "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
9219 targetId));
9220 // Indicate no device found at this address.
9221 goto reject_srb;
9222 }
9223 targetId = lChannel*deviceExtension->NumberLuns+DeviceNumber;
9224 chan = &(deviceExtension->chan[lChannel]);
9225 LunExt = chan->lun[DeviceNumber];
9226 if(!LunExt) {
9227 goto reject_srb;
9228 }
9229 atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
9230
9231 if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
9232 goto reject_srb;
9233 }
9234 }
9235
9236 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
9237 case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
9238
9239 PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9240 UCHAR deviceNumberMap;
9241
9242 KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
9243
9244 // Version and revision per SMART 1.03
9245
9246 versionParameters->bVersion = 1;
9247 versionParameters->bRevision = 1;
9248 versionParameters->bReserved = 0;
9249
9250 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
9251 versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD);
9252
9253 if (atapiDev) {
9254 goto invalid_request;
9255 }
9256
9257 // NOTE: This will only set the bit
9258 // corresponding to this drive's target id.
9259 // The bit mask is as follows:
9260 //
9261 // -Sec Pri
9262 // S M S M
9263 // 3 2 1 0
9264
9265 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
9266 deviceNumberMap = 1 << lChannel;
9267 DeviceNumber = 0;
9268 } else
9269 if (deviceExtension->NumberChannels == 1) {
9270 if (chan->PrimaryAddress) {
9271 deviceNumberMap = 1 << DeviceNumber;
9272 } else {
9273 deviceNumberMap = 4 << DeviceNumber;
9274 }
9275 } else {
9276 deviceNumberMap = 1 << (DeviceNumber+lChannel*2);
9277 }
9278
9279 versionParameters->bIDEDeviceMap = deviceNumberMap;
9280
9281 status = SRB_STATUS_SUCCESS;
9282 break;
9283 }
9284
9285 case IOCTL_SCSI_MINIPORT_IDENTIFY: {
9286
9287 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9288 SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9289
9290 KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
9291 // Extract the target.
9292 KdPrint2((PRINT_PREFIX "targetId %d\n", targetId));
9293
9294 switch(cmdInParameters.irDriveRegs.bCommandReg) {
9295 case ID_CMD:
9296 if(atapiDev) {
9297 KdPrint2((PRINT_PREFIX "Error: ID_CMD for ATAPI\n"));
9298 goto invalid_request;
9299 }
9300 /* FALL THROUGH */
9301 case ATAPI_ID_CMD:
9302
9303 if(!atapiDev &&
9304 (cmdInParameters.irDriveRegs.bCommandReg == ATAPI_ID_CMD)) {
9305 KdPrint2((PRINT_PREFIX "Error: ATAPI_ID_CMD for non-ATAPI\n"));
9306 goto invalid_request;
9307 }
9308
9309 len = min(len, sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE);
9310 // Zero the output buffer
9311 RtlZeroMemory(cmdOutParameters, len);
9312 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
9313 ((PUCHAR)cmdOutParameters)[i] = 0;
9314 }*/
9315
9316 // Build status block.
9317 cmdOutParameters->cBufferSize = min(IDENTIFY_BUFFER_SIZE, len - sizeof(SENDCMDOUTPARAMS) + 1);
9318 cmdOutParameters->DriverStatus.bDriverError = 0;
9319 cmdOutParameters->DriverStatus.bIDEError = 0;
9320
9321 // Extract the identify data from the device extension.
9322 ScsiPortMoveMemory (cmdOutParameters->bBuffer, &(LunExt->IdentifyData),
9323 cmdOutParameters->cBufferSize);
9324
9325 if((cmdOutParameters->cBufferSize == IDENTIFY_BUFFER_SIZE) &&
9326 (LunExt->IdentifyData.ChecksumValid == ATA_ChecksumValid)) {
9327 // adjust checksum if it is possible
9328 CHAR csum = 0;
9329 ULONG i;
9330
9331 for(i=0; i < IDENTIFY_BUFFER_SIZE-1; i++) {
9332 csum += (CHAR)(cmdOutParameters->bBuffer[i]);
9333 }
9334 cmdOutParameters->bBuffer[i] = -csum;
9335 KdPrint2((PRINT_PREFIX "AtapiStartIo: adjust checksum %d\n"));
9336 }
9337 KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
9338
9339 status = SRB_STATUS_SUCCESS;
9340
9341 break;
9342 default:
9343 KdPrint2((PRINT_PREFIX "AtapiStartIo: not supported ID code %x\n",
9344 cmdInParameters.irDriveRegs.bCommandReg));
9345 status = SRB_STATUS_INVALID_REQUEST;
9346 break;
9347 }
9348 break;
9349 }
9350 /*
9351 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9352 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9353 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9354 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9355 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9356 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9357 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9358 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9359 */
9360 default:
9361 // *all* IOCTLs here are SMART
9362 if(commPort) {
9363 KdPrint2((PRINT_PREFIX
9364 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
9365 }
9366 if (atapiDev) {
9367 goto invalid_request;
9368 }
9369
9370 PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
9371
9372 if(PostReq || TopLevel) {
9373 UniataQueueRequest(chan, Srb);
9374 AtaReq = (PATA_REQ)(Srb->SrbExtension);
9375 AtaReq->ReqState = REQ_STATE_QUEUED;
9376 }
9377
9378 if(PostReq) {
9379
9380 KdPrint2((PRINT_PREFIX "Non-empty queue (SMART)\n"));
9381 status = SRB_STATUS_PENDING;
9382
9383 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
9384 } else {
9385
9386 status = IdeSendSmartCommand(HwDeviceExtension, Srb, targetId);
9387 }
9388 break;
9389
9390 // we should not get here, checked above
9391 /* default :
9392 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9393 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9394 status = SRB_STATUS_INVALID_REQUEST;
9395 break;
9396 */
9397 }
9398 } else
9399 if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"-UNIATA-", sizeof("-UNIATA-")-1)) {
9400
9401 PUNIATA_CTL AtaCtl = (PUNIATA_CTL)(Srb->DataBuffer);
9402 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
9403 ULONG DeviceNumber = AtaCtl->addr.TargetId;
9404 BOOLEAN bad_ldev;
9405 ULONG i, pos;
9406
9407 pos = FIELD_OFFSET(UNIATA_CTL, RawData);
9408 //chan = &(deviceExtension->chan[lChannel]);
9409 if(len < pos) {
9410 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9411 FIELD_OFFSET(UNIATA_CTL, RawData) ));
9412 goto wrong_buffer_size;
9413 }
9414
9415 if(AtaCtl->addr.Lun ||
9416 AtaCtl->addr.TargetId >= deviceExtension->NumberLuns ||
9417 AtaCtl->addr.PathId >= deviceExtension->NumberChannels) {
9418
9419 chan = NULL;
9420 bad_ldev = TRUE;
9421 LunExt = NULL;
9422
9423 } else {
9424 bad_ldev = FALSE;
9425 lChannel = AtaCtl->addr.PathId;
9426 chan = &(deviceExtension->chan[lChannel]);
9427 LunExt = chan->lun[DeviceNumber];
9428 }
9429
9430 KdPrint2((PRINT_PREFIX "AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl->hdr.ControlCode, DeviceNumber));
9431
9432 /* check for valid LUN */
9433 switch (AtaCtl->hdr.ControlCode) {
9434 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
9435 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE:
9436 // this would be BUS reset
9437 if(bad_ldev &&
9438 (AtaCtl->addr.PathId >= deviceExtension->NumberChannels ||
9439 AtaCtl->addr.TargetId != 0xff ||
9440 AtaCtl->addr.Lun != 0
9441 )) {
9442 if(AtaCtl->hdr.ControlCode == IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES &&
9443 DeviceNumber < deviceExtension->NumberLuns) { // AtaCtl->addr.TargetId != 0xff
9444 lChannel = AtaCtl->addr.PathId;
9445 chan = &(deviceExtension->chan[lChannel]);
9446 LunExt = chan->lun[DeviceNumber];
9447 // OK
9448 } else {
9449 goto handle_bad_ldev;
9450 }
9451 } else {
9452 lChannel = AtaCtl->addr.PathId;
9453 chan = &(deviceExtension->chan[lChannel]);
9454 }
9455 break;
9456 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE:
9457 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
9458 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE:
9459 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB:
9460 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
9461 if(bad_ldev) {
9462 handle_bad_ldev:
9463 KdPrint2((PRINT_PREFIX
9464 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
9465 // Indicate no device found at this address.
9466 goto reject_srb;
9467 }
9468 }
9469
9470 /* check if queueing is necessary */
9471 switch (AtaCtl->hdr.ControlCode) {
9472 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB:
9473 if(!LunExt->nBadBlocks) {
9474 break;
9475 }
9476 goto uata_ctl_queue;
9477 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
9478 if(len < pos+sizeof(AtaCtl->SetMode)) {
9479 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9480 pos+sizeof(AtaCtl->SetMode) ));
9481 goto wrong_buffer_size;
9482 }
9483 if(!AtaCtl->SetMode.ApplyImmediately) {
9484 break;
9485 }
9486 goto uata_ctl_queue;
9487 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
9488 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
9489 uata_ctl_queue:
9490 KdPrint2((PRINT_PREFIX "put to queue (UNIATA)\n"));
9491 PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
9492
9493 if(PostReq || TopLevel) {
9494 UniataQueueRequest(chan, Srb);
9495 AtaReq = (PATA_REQ)(Srb->SrbExtension);
9496 AtaReq->ReqState = REQ_STATE_QUEUED;
9497 }
9498 if(PostReq) {
9499 KdPrint2((PRINT_PREFIX "Non-empty queue (UNIATA)\n"));
9500 status = SRB_STATUS_PENDING;
9501
9502 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
9503 goto complete_req;
9504 }
9505 } // end switch (AtaCtl->hdr.ControlCode)
9506
9507 /* process request */
9508 switch (AtaCtl->hdr.ControlCode) {
9509 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
9510
9511 KdPrint2((PRINT_PREFIX "AtapiStartIo: rescan bus\n"));
9512
9513 if(len < pos+sizeof(AtaCtl->FindDelDev)) {
9514 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9515 pos+sizeof(AtaCtl->FindDelDev) ));
9516 goto wrong_buffer_size;
9517 }
9518 if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) {
9519 KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n"));
9520 if(AtaCtl->addr.TargetId != 0xff) {
9521 LunExt->DeviceFlags &= ~DFLAGS_HIDDEN;
9522 } else {
9523 }
9524 }
9525
9526 for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
9527 AtapiStallExecution(1000 * 1000);
9528 }
9529
9530 FindDevices(HwDeviceExtension,
9531 ((AtaCtl->addr.TargetId == 0xff) && (AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE))
9532 ? UNIATA_FIND_DEV_UNHIDE : 0,
9533 AtaCtl->addr.PathId);
9534 status = SRB_STATUS_SUCCESS;
9535
9536 break;
9537
9538 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE: {
9539
9540 KdPrint2((PRINT_PREFIX "AtapiStartIo: remove %#x:%#x\n", AtaCtl->addr.PathId, AtaCtl->addr.TargetId));
9541
9542 if(len < pos+sizeof(AtaCtl->FindDelDev)) {
9543 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9544 pos+sizeof(AtaCtl->FindDelDev) ));
9545 goto wrong_buffer_size;
9546 }
9547 LunExt->DeviceFlags = 0;
9548 if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) {
9549 KdPrint2((PRINT_PREFIX "AtapiStartIo: hide from further detection\n"));
9550 //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
9551 UniataForgetDevice(LunExt);
9552 }
9553
9554 for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
9555 AtapiStallExecution(1000 * 1000);
9556 }
9557
9558 status = SRB_STATUS_SUCCESS;
9559 break;
9560 }
9561 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE: {
9562
9563 KdPrint2((PRINT_PREFIX "AtapiStartIo: Set transfer mode\n"));
9564
9565 if(len < pos+sizeof(AtaCtl->SetMode)) {
9566 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9567 pos+sizeof(AtaCtl->SetMode) ));
9568 goto wrong_buffer_size;
9569 }
9570 if(AtaCtl->SetMode.OrigMode != IOMODE_NOT_SPECIFIED) {
9571 LunExt->OrigTransferMode = (UCHAR)(AtaCtl->SetMode.OrigMode);
9572 }
9573 if(AtaCtl->SetMode.MaxMode != IOMODE_NOT_SPECIFIED) {
9574 LunExt->LimitedTransferMode = (UCHAR)(AtaCtl->SetMode.MaxMode);
9575 if(LunExt->LimitedTransferMode >
9576 LunExt->OrigTransferMode) {
9577 // check for incorrect value
9578 LunExt->LimitedTransferMode =
9579 LunExt->OrigTransferMode;
9580 }
9581 }
9582 LunExt->TransferMode = min(LunExt->LimitedTransferMode, LunExt->OrigTransferMode);
9583
9584 LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit
9585 if(AtaCtl->SetMode.ApplyImmediately) {
9586 AtapiDmaInit__(deviceExtension, LunExt);
9587 }
9588 /* LunExt->TransferMode =
9589 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
9590 status = SRB_STATUS_SUCCESS;
9591 break;
9592 }
9593 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE: {
9594
9595 KdPrint2((PRINT_PREFIX "AtapiStartIo: Get transfer mode\n"));
9596
9597 if(len < pos+sizeof(AtaCtl->GetMode)) {
9598 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9599 pos+sizeof(AtaCtl->GetMode) ));
9600 goto wrong_buffer_size;
9601 }
9602 AtaCtl->GetMode.OrigMode = LunExt->OrigTransferMode;
9603 AtaCtl->GetMode.MaxMode = LunExt->LimitedTransferMode;
9604 AtaCtl->GetMode.CurrentMode = LunExt->TransferMode;
9605 AtaCtl->GetMode.PhyMode = LunExt->PhyTransferMode;
9606
9607 status = SRB_STATUS_SUCCESS;
9608 break;
9609 }
9610 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION: {
9611
9612 KdPrint2((PRINT_PREFIX "AtapiStartIo: Get version\n"));
9613
9614 if(len < pos+sizeof(AtaCtl->Version)) {
9615 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9616 pos+sizeof(AtaCtl->Version) ));
9617 goto wrong_buffer_size;
9618 }
9619 AtaCtl->Version.Length = sizeof(GETDRVVERSION);
9620 AtaCtl->Version.VersionMj = UNIATA_VER_MJ;
9621 AtaCtl->Version.VersionMn = UNIATA_VER_MN;
9622 AtaCtl->Version.SubVerMj = UNIATA_VER_SUB_MJ;
9623 AtaCtl->Version.SubVerMn = UNIATA_VER_SUB_MN;
9624
9625 status = SRB_STATUS_SUCCESS;
9626 break;
9627 }
9628 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO: {
9629
9630 KdPrint2((PRINT_PREFIX "AtapiStartIo: Get adapter info\n"));
9631
9632 if(len < pos+sizeof(AtaCtl->AdapterInfo)) {
9633 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9634 pos+sizeof(AtaCtl->AdapterInfo) ));
9635 goto wrong_buffer_size;
9636 }
9637 AtaCtl->AdapterInfo.HeaderLength = sizeof(ADAPTERINFO);
9638
9639 AtaCtl->AdapterInfo.DevID = deviceExtension->DevID;
9640 AtaCtl->AdapterInfo.RevID = deviceExtension->RevID;
9641 AtaCtl->AdapterInfo.slotNumber = deviceExtension->slotNumber;
9642 AtaCtl->AdapterInfo.SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
9643 AtaCtl->AdapterInfo.DevIndex = deviceExtension->DevIndex;
9644 AtaCtl->AdapterInfo.Channel = deviceExtension->Channel;
9645 AtaCtl->AdapterInfo.HbaCtrlFlags = deviceExtension->HbaCtrlFlags;
9646 AtaCtl->AdapterInfo.simplexOnly= deviceExtension->simplexOnly;
9647 AtaCtl->AdapterInfo.MemIo = FALSE;/*deviceExtension->MemIo;*/
9648 AtaCtl->AdapterInfo.UnknownDev = deviceExtension->UnknownDev;
9649 AtaCtl->AdapterInfo.MasterDev = deviceExtension->MasterDev;
9650 AtaCtl->AdapterInfo.MaxTransferMode = deviceExtension->MaxTransferMode;
9651 AtaCtl->AdapterInfo.HwFlags = deviceExtension->HwFlags;
9652 AtaCtl->AdapterInfo.OrigAdapterInterfaceType = deviceExtension->OrigAdapterInterfaceType;
9653 AtaCtl->AdapterInfo.BusInterruptLevel = deviceExtension->BusInterruptLevel;
9654 AtaCtl->AdapterInfo.InterruptMode = deviceExtension->InterruptMode;
9655 AtaCtl->AdapterInfo.BusInterruptVector = deviceExtension->BusInterruptVector;
9656 AtaCtl->AdapterInfo.NumberChannels = deviceExtension->NumberChannels;
9657 AtaCtl->AdapterInfo.NumberLuns = (UCHAR)deviceExtension->NumberLuns;
9658 AtaCtl->AdapterInfo.AdapterInterfaceType = deviceExtension->AdapterInterfaceType;
9659 if(deviceExtension->FullDevName) {
9660 strncpy(AtaCtl->AdapterInfo.DeviceName, deviceExtension->FullDevName, 64);
9661 }
9662 AtaCtl->AdapterInfo.ChanInfoValid = FALSE;
9663 AtaCtl->AdapterInfo.LunInfoValid = FALSE;
9664 AtaCtl->AdapterInfo.ChanHeaderLengthValid = TRUE;
9665
9666 pos += AtaCtl->AdapterInfo.HeaderLength;
9667
9668 // zero tail
9669 RtlZeroMemory(((PCHAR)AtaCtl)+pos,
9670 len-pos);
9671
9672 if(len >= pos+AtaCtl->AdapterInfo.NumberChannels*sizeof(CHANINFO)) {
9673 PCHANINFO ChanInfo = (PCHANINFO)( ((PCHAR)AtaCtl)+pos );
9674 PHW_CHANNEL cur_chan;
9675 KdPrint2((PRINT_PREFIX "AtapiStartIo: Fill channel info\n"));
9676 for(i=0;i<AtaCtl->AdapterInfo.NumberChannels;i++) {
9677 KdPrint2((PRINT_PREFIX "chan[%d] %x\n", i, cur_chan));
9678 cur_chan = &(deviceExtension->chan[i]);
9679 ChanInfo->MaxTransferMode = cur_chan->MaxTransferMode;
9680 ChanInfo->ChannelCtrlFlags = cur_chan->ChannelCtrlFlags;
9681 RtlCopyMemory(&(ChanInfo->QueueStat), &(cur_chan->QueueStat), sizeof(ChanInfo->QueueStat));
9682 ChanInfo->ReorderCount = cur_chan->ReorderCount;
9683 ChanInfo->IntersectCount = cur_chan->IntersectCount;
9684 ChanInfo->TryReorderCount = cur_chan->TryReorderCount;
9685 ChanInfo->TryReorderHeadCount = cur_chan->TryReorderHeadCount;
9686 ChanInfo->TryReorderTailCount = cur_chan->TryReorderTailCount;
9687 //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
9688 ChanInfo++;
9689 }
9690 AtaCtl->AdapterInfo.ChanInfoValid = TRUE;
9691 AtaCtl->AdapterInfo.ChanHeaderLength = sizeof(*ChanInfo);
9692 }
9693
9694 status = SRB_STATUS_SUCCESS;
9695 break;
9696 }
9697 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB: {
9698
9699 KdPrint2((PRINT_PREFIX "AtapiStartIo: Forget BB list\n"));
9700
9701 ForgetBadBlocks(LunExt);
9702
9703 status = SRB_STATUS_SUCCESS;
9704 break;
9705 }
9706 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: {
9707
9708 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device\n"));
9709
9710 if(bad_ldev) {
9711 goto do_bus_reset;
9712 } else {
9713 UniataUserDeviceReset(deviceExtension, LunExt, AtaCtl->addr.PathId);
9714 }
9715
9716 status = SRB_STATUS_SUCCESS;
9717 break;
9718 }
9719 default :
9720 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
9721 AtaCtl->hdr.ControlCode ));
9722 status = SRB_STATUS_INVALID_REQUEST;
9723 break;
9724 }
9725
9726 } else {
9727 KdPrint2((PRINT_PREFIX "AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
9728 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature,
9729 "SCSIDISK", "-UNIATA-"));
9730
9731 status = SRB_STATUS_INVALID_REQUEST;
9732 break;
9733 }
9734
9735 break;
9736 } // end SRB_FUNCTION_IO_CONTROL
9737 default:
9738
9739 KdPrint2((PRINT_PREFIX "AtapiStartIo: Unknown IOCTL\n"));
9740 // Indicate unsupported command.
9741 status = SRB_STATUS_INVALID_REQUEST;
9742
9743 // break;
9744
9745 } // end switch
9746
9747 complete_req:
9748
9749 PathId = Srb->PathId;
9750 TargetId = Srb->TargetId;
9751 Lun = Srb->Lun;
9752
9753 if (status != SRB_STATUS_PENDING) {
9754
9755 KdPrint2((PRINT_PREFIX
9756 "AtapiStartIo: Srb %#x complete with status %#x\n",
9757 Srb,
9758 status));
9759
9760 // Set status in SRB.
9761 Srb->SrbStatus = (UCHAR)status;
9762
9763 if(chan && Srb) {
9764 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan, Srb));
9765 AtapiDmaDBSync(chan, Srb);
9766 }
9767 KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan, Srb));
9768 UniataRemoveRequest(chan, Srb);
9769 // Indicate command complete.
9770 KdPrint2((PRINT_PREFIX "AtapiStartIo: ScsiPortNotification\n"));
9771 ScsiPortNotification(RequestComplete,
9772 deviceExtension,
9773 Srb);
9774
9775 KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataGetCurRequest\n"));
9776 // Remove current Srb & get next one
9777 if((Srb = UniataGetCurRequest(chan))) {
9778 AtaReq = (PATA_REQ)(Srb->SrbExtension);
9779 if(AtaReq->ReqState > REQ_STATE_QUEUED) {
9780 // current request is under precessing, thus
9781 // we should do nothing here
9782 Srb = NULL;
9783 }
9784 }
9785 KdPrint2((PRINT_PREFIX "AtapiStartIo: chan %x, Src %x\n", chan, Srb));
9786 if(!chan) {
9787 //ASSERT(TopLevel);
9788 }
9789 }
9790 KdPrint2((PRINT_PREFIX "AtapiStartIo: next Srb %x\n", Srb));
9791
9792 } while (Srb && (status != SRB_STATUS_PENDING));
9793
9794 KdPrint2((PRINT_PREFIX "AtapiStartIo: query PORT for next request\n"));
9795 // Indicate ready for next request.
9796 ScsiPortNotification(NextRequest,
9797 deviceExtension,
9798 NULL);
9799
9800 ScsiPortNotification(NextLuRequest,
9801 deviceExtension,
9802 PathId,
9803 TargetId,
9804 Lun);
9805
9806 return TRUE;
9807
9808 } // end AtapiStartIo__()
9809
9810
9811 void
9812 NTAPI
9813 UniataInitAtaCommands()
9814 {
9815 int i;
9816 UCHAR command;
9817 UCHAR flags;
9818
9819 KdPrint2((PRINT_PREFIX "UniataInitAtaCommands:\n"));
9820
9821 for(i=0; i<256; i++) {
9822
9823 flags = 0;
9824 command = i;
9825
9826 //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
9827
9828 switch(command) {
9829 case IDE_COMMAND_READ_DMA48:
9830 case IDE_COMMAND_READ_DMA_Q48:
9831 case IDE_COMMAND_READ_STREAM_DMA48:
9832 case IDE_COMMAND_READ_STREAM48:
9833 case IDE_COMMAND_WRITE_DMA48:
9834 case IDE_COMMAND_WRITE_DMA_Q48:
9835 case IDE_COMMAND_READ_DMA_Q:
9836 case IDE_COMMAND_READ_DMA:
9837 case IDE_COMMAND_WRITE_DMA:
9838 case IDE_COMMAND_WRITE_DMA_Q:
9839 case IDE_COMMAND_WRITE_STREAM_DMA48:
9840 case IDE_COMMAND_WRITE_STREAM48:
9841 case IDE_COMMAND_WRITE_FUA_DMA48:
9842 case IDE_COMMAND_WRITE_FUA_DMA_Q48:
9843 case IDE_COMMAND_READ_LOG_DMA48:
9844 case IDE_COMMAND_WRITE_LOG_DMA48:
9845 case IDE_COMMAND_TRUSTED_RCV_DMA:
9846 case IDE_COMMAND_TRUSTED_SEND_DMA:
9847 case IDE_COMMAND_DATA_SET_MGMT:
9848 //KdPrint2((PRINT_PREFIX "DMA "));
9849 flags |= ATA_CMD_FLAG_DMA;
9850 }
9851
9852 switch(command) {
9853 case IDE_COMMAND_WRITE_FUA_DMA48:
9854 case IDE_COMMAND_WRITE_FUA_DMA_Q48:
9855 case IDE_COMMAND_WRITE_MUL_FUA48:
9856
9857 flags |= ATA_CMD_FLAG_FUA;
9858 /* FALL THROUGH */
9859
9860 case IDE_COMMAND_READ48:
9861 case IDE_COMMAND_READ_DMA48:
9862 case IDE_COMMAND_READ_DMA_Q48:
9863 case IDE_COMMAND_READ_MUL48:
9864 case IDE_COMMAND_READ_STREAM_DMA48:
9865 case IDE_COMMAND_READ_STREAM48:
9866 case IDE_COMMAND_WRITE48:
9867 case IDE_COMMAND_WRITE_DMA48:
9868 case IDE_COMMAND_WRITE_DMA_Q48:
9869 case IDE_COMMAND_WRITE_MUL48:
9870 case IDE_COMMAND_WRITE_STREAM_DMA48:
9871 case IDE_COMMAND_WRITE_STREAM48:
9872 case IDE_COMMAND_FLUSH_CACHE48:
9873 case IDE_COMMAND_VERIFY48:
9874
9875 //KdPrint2((PRINT_PREFIX "48 "));
9876 flags |= ATA_CMD_FLAG_48;
9877 /* FALL THROUGH */
9878
9879 case IDE_COMMAND_READ:
9880 case IDE_COMMAND_READ_MULTIPLE:
9881 case IDE_COMMAND_READ_DMA:
9882 case IDE_COMMAND_READ_DMA_Q:
9883 case IDE_COMMAND_WRITE:
9884 case IDE_COMMAND_WRITE_MULTIPLE:
9885 case IDE_COMMAND_WRITE_DMA:
9886 case IDE_COMMAND_WRITE_DMA_Q:
9887 case IDE_COMMAND_FLUSH_CACHE:
9888 case IDE_COMMAND_VERIFY:
9889
9890 //KdPrint2((PRINT_PREFIX "LBA "));
9891 flags |= ATA_CMD_FLAG_LBAIOsupp;
9892 }
9893
9894 switch(command) {
9895 case IDE_COMMAND_READ_NATIVE_SIZE48:
9896 case IDE_COMMAND_SET_NATIVE_SIZE48:
9897 // we cannot set LBA flag for these commands to avoid BadBlock handling
9898 //flags |= ATA_CMD_FLAG_LBAIOsupp;
9899 flags |= ATA_CMD_FLAG_48;
9900
9901 case IDE_COMMAND_READ_NATIVE_SIZE:
9902 case IDE_COMMAND_SET_NATIVE_SIZE:
9903
9904 flags |= ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_FUA;
9905 }
9906
9907 flags |= ATA_CMD_FLAG_48supp;
9908
9909 switch (command) {
9910 case IDE_COMMAND_READ:
9911 command = IDE_COMMAND_READ48; break;
9912 case IDE_COMMAND_READ_MULTIPLE:
9913 command = IDE_COMMAND_READ_MUL48; break;
9914 case IDE_COMMAND_READ_DMA:
9915 command = IDE_COMMAND_READ_DMA48; break;
9916 case IDE_COMMAND_READ_DMA_Q:
9917 command = IDE_COMMAND_READ_DMA_Q48; break;
9918 case IDE_COMMAND_WRITE:
9919 command = IDE_COMMAND_WRITE48; break;
9920 case IDE_COMMAND_WRITE_MULTIPLE:
9921 command = IDE_COMMAND_WRITE_MUL48; break;
9922 case IDE_COMMAND_WRITE_DMA:
9923 command = IDE_COMMAND_WRITE_DMA48; break;
9924 case IDE_COMMAND_WRITE_DMA_Q:
9925 command = IDE_COMMAND_WRITE_DMA_Q48; break;
9926 case IDE_COMMAND_FLUSH_CACHE:
9927 command = IDE_COMMAND_FLUSH_CACHE48; break;
9928 // case IDE_COMMAND_READ_NATIVE_SIZE:
9929 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
9930 case IDE_COMMAND_SET_NATIVE_SIZE:
9931 command = IDE_COMMAND_SET_NATIVE_SIZE48; break;
9932 case IDE_COMMAND_VERIFY:
9933 command = IDE_COMMAND_VERIFY48; break;
9934 default:
9935 //KdPrint2((PRINT_PREFIX "!28->48 "));
9936 flags &= ~ATA_CMD_FLAG_48supp;
9937 }
9938
9939 switch (command) {
9940 case IDE_COMMAND_READ:
9941 case IDE_COMMAND_READ_MULTIPLE:
9942 case IDE_COMMAND_READ_DMA48:
9943 case IDE_COMMAND_READ_DMA_Q48:
9944 case IDE_COMMAND_READ_STREAM_DMA48:
9945 case IDE_COMMAND_READ_STREAM48:
9946 case IDE_COMMAND_READ_DMA_Q:
9947 case IDE_COMMAND_READ_DMA:
9948 case IDE_COMMAND_READ_LOG_DMA48:
9949 case IDE_COMMAND_TRUSTED_RCV_DMA:
9950 case IDE_COMMAND_IDENTIFY:
9951 case IDE_COMMAND_ATAPI_IDENTIFY:
9952 //KdPrint2((PRINT_PREFIX "RD "));
9953 flags |= ATA_CMD_FLAG_In;
9954 break;
9955 case IDE_COMMAND_WRITE:
9956 case IDE_COMMAND_WRITE_MULTIPLE:
9957 case IDE_COMMAND_WRITE_DMA48:
9958 case IDE_COMMAND_WRITE_DMA_Q48:
9959 case IDE_COMMAND_WRITE_DMA:
9960 case IDE_COMMAND_WRITE_DMA_Q:
9961 case IDE_COMMAND_WRITE_STREAM_DMA48:
9962 case IDE_COMMAND_WRITE_STREAM48:
9963 case IDE_COMMAND_WRITE_FUA_DMA48:
9964 case IDE_COMMAND_WRITE_FUA_DMA_Q48:
9965 //KdPrint2((PRINT_PREFIX "WR "));
9966 flags |= ATA_CMD_FLAG_Out;
9967 break;
9968 }
9969
9970 //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
9971 AtaCommands48[i] = command;
9972 AtaCommandFlags[i] = flags;
9973 }
9974 } // end UniataInitAtaCommands()
9975
9976 /*++
9977
9978 Routine Description:
9979
9980 Installable driver initialization entry point for system.
9981
9982 Arguments:
9983
9984 Driver Object
9985
9986 Return Value:
9987
9988 Status from ScsiPortInitialize()
9989
9990 --*/
9991 extern "C"
9992 ULONG
9993 NTAPI
9994 DriverEntry(
9995 IN PVOID DriverObject,
9996 IN PVOID Argument2
9997 )
9998 {
9999 HW_INITIALIZATION_DATA_COMMON hwInitializationData;
10000 ULONG adapterCount;
10001 ULONG i, c, alt;
10002 ULONG statusToReturn, newStatus;
10003 PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
10004 BOOLEAN ReEnter = FALSE;
10005 // WCHAR a;
10006 #ifndef USE_REACTOS_DDK
10007 NTSTATUS status;
10008 #endif
10009
10010 PCONFIGURATION_INFORMATION GlobalConfig = IoGetConfigurationInformation();
10011 BOOLEAN PrimaryClaimed = FALSE;
10012 BOOLEAN SecondaryClaimed = FALSE;
10013
10014 LARGE_INTEGER t0, t1;
10015
10016 Connect_DbgPrint();
10017 KdPrint2((PRINT_PREFIX "%s", (PCCHAR)ver_string));
10018 //a = (WCHAR)strlen(ver_string);
10019
10020 g_opt_Verbose = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PrintLogo", 0);
10021 if(g_opt_Verbose) {
10022 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR "\n");
10023 }
10024
10025 if(!SavedDriverObject) {
10026 SavedDriverObject = (PDRIVER_OBJECT)DriverObject;
10027 #ifdef USE_REACTOS_DDK
10028 KdPrint(("UniATA Init: OS should be ReactOS\n"));
10029 MajorVersion=0x04;
10030 MinorVersion=0x01;
10031 BuildNumber=1;
10032 #else
10033 // we are here for the 1st time
10034 // init CrossNT and get OS version
10035 if(!NT_SUCCESS(status = CrNtInit(SavedDriverObject, RegistryPath))) {
10036 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status));
10037 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
10038 return status;
10039 }
10040 #endif // USE_REACTOS_DDK
10041 KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion, MinorVersion, BuildNumber, KeNumberProcessors));
10042
10043 KeQuerySystemTime(&t0);
10044 do {
10045 KeQuerySystemTime(&t1);
10046 } while(t0.QuadPart == t1.QuadPart);
10047 t0=t1;
10048 g_Perf=0;
10049 do {
10050 KeQuerySystemTime(&t1);
10051 g_Perf++;
10052 } while(t0.QuadPart == t1.QuadPart);
10053 g_PerfDt = (ULONG)((t1.QuadPart - t0.QuadPart)/10);
10054 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt, g_Perf ));
10055 } else {
10056 KdPrint(("UniATA Init: ReEnter\n"));
10057 ReEnter = TRUE;
10058 }
10059
10060 // (re)read bad block list
10061 InitBadBlocks(NULL);
10062
10063 if(!ReEnter) {
10064 // init ATA command translation table
10065 UniataInitAtaCommands();
10066 // get registry path to settings
10067 RtlCopyMemory(&SavedRegPath, RegistryPath, sizeof(UNICODE_STRING));
10068 SavedRegPath.Buffer = (PWCHAR)&SavedRegPathBuffer;
10069 SavedRegPath.Length = min(RegistryPath->Length, 255*sizeof(WCHAR));
10070 SavedRegPath.MaximumLength = 255*sizeof(WCHAR);
10071 RtlCopyMemory(SavedRegPath.Buffer, RegistryPath->Buffer, SavedRegPath.Length);
10072 SavedRegPath.Buffer[SavedRegPath.Length/sizeof(WCHAR)] = 0;
10073 }
10074
10075 if(WinVer_Id() >= WinVer_2k) {
10076 if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"1", 0)) {
10077 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
10078 WinVer_WDM_Model = TRUE;
10079 }
10080 if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"5", 0)) {
10081 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
10082 WinVer_WDM_Model = TRUE;
10083 }
10084 }
10085
10086 SkipRaids = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"SkipRaids", 1);
10087 ForceSimplex = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"ForceSimplex", 0);
10088 #ifdef _DEBUG
10089 g_LogToDisplay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"LogToDisplay", 0);
10090 #endif //_DEBUG
10091
10092 statusToReturn = 0xffffffff;
10093
10094 // Zero out structure.
10095 RtlZeroMemory(((PCHAR)&hwInitializationData), sizeof(hwInitializationData));
10096
10097 // Set size of hwInitializationData.
10098 hwInitializationData.comm.HwInitializationDataSize =
10099 sizeof(hwInitializationData.comm) +
10100 // sizeof(hwInitializationData.nt4) +
10101 ((WinVer_Id() <= WinVer_NT) ? 0 : sizeof(hwInitializationData.w2k));
10102 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData.comm.HwInitializationDataSize));
10103
10104 // Set entry points.
10105 hwInitializationData.comm.HwInitialize = (PHW_INITIALIZE)AtapiHwInitialize;
10106 hwInitializationData.comm.HwResetBus = (PHW_RESET_BUS)AtapiResetController;
10107 hwInitializationData.comm.HwStartIo = (PHW_STARTIO)AtapiStartIo;
10108 hwInitializationData.comm.HwInterrupt = (PHW_INTERRUPT)AtapiInterrupt;
10109
10110 // Specify size of extensions.
10111 hwInitializationData.comm.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
10112 hwInitializationData.comm.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION);
10113 hwInitializationData.comm.SrbExtensionSize = sizeof(ATA_REQ);
10114
10115 // Indicate PIO device.
10116 hwInitializationData.comm.MapBuffers = TRUE;
10117 // Set PnP-specific API
10118 if(WinVer_Id() > WinVer_NT) {
10119 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
10120 hwInitializationData.comm.NeedPhysicalAddresses = TRUE;
10121 KdPrint(("set AtapiAdapterControl() ptr\n"));
10122 hwInitializationData.w2k.HwAdapterControl = (PHW_ADAPTER_CONTROL)AtapiAdapterControl;
10123 }
10124
10125 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE enum supported BusMaster Devices\n"));
10126
10127 if(!ReEnter) {
10128
10129 g_opt_VirtualMachine = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualMachineType", g_opt_VirtualMachine);
10130 if(g_opt_VirtualMachine > VM_MAX_KNOWN) {
10131 g_opt_VirtualMachine = 0;
10132 }
10133 if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualBox", (g_opt_VirtualMachine == VM_VBOX))) {
10134 g_opt_VirtualMachine = VM_VBOX;
10135 }
10136 // Pre-scan PCI bus, also check if we are under VM
10137 UniataEnumBusMasterController(DriverObject, Argument2);
10138
10139 switch(g_opt_VirtualMachine) {
10140 case VM_VBOX:
10141 KdPrint2((PRINT_PREFIX "adjust options for VirtualBox\n"));
10142 // adjust options for VirtualBox
10143 g_opt_WaitBusyCount = 20000;
10144 g_opt_WaitBusyDelay = 150;
10145 g_opt_WaitDrqDelay = 100;
10146 g_opt_WaitBusyLongCount = 20000;
10147 g_opt_MaxIsrWait = 200;
10148 g_opt_AtapiSendDisableIntr = 0;
10149 g_opt_AtapiDmaRawRead = FALSE;
10150 break;
10151 }
10152
10153 if(!hasPCI) {
10154 KdPrint2((PRINT_PREFIX "old slow machine, adjust timings\n"));
10155 // old slow machine, adjust timings
10156 g_opt_WaitBusyCount = 20000;
10157 g_opt_WaitBusyDelay = 150;
10158 g_opt_WaitDrqDelay = 100;
10159 g_opt_WaitBusyLongCount = 20000;
10160 g_opt_MaxIsrWait = 200;
10161 }
10162
10163 g_opt_WaitBusyCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyCount", g_opt_WaitBusyCount); // 200 vs 20000
10164 g_opt_WaitBusyDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyDelay", g_opt_WaitBusyDelay); // 10 vs 150
10165 g_opt_WaitDrqDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitDrqDelay", g_opt_WaitDrqDelay); // 10 vs 100
10166 g_opt_WaitBusyLongCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongCount", g_opt_WaitBusyLongCount); // 2000 vs 20000
10167 g_opt_WaitBusyLongDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongDelay", g_opt_WaitBusyLongDelay); // 250 vs 250
10168 g_opt_AtapiSendDisableIntr = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr); // 1 vs 0
10169 g_opt_AtapiDmaRawRead = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiDmaRawRead", g_opt_AtapiDmaRawRead); // 1 vs 0
10170 g_opt_MaxIsrWait = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"MaxIsrWait", g_opt_MaxIsrWait); // 40 vs xxx
10171 }
10172
10173 // Look for legacy ISA-bridged PCI IDE controller (onboard)
10174 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
10175 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: BMListLen %d\n", BMListLen));
10176 for (i=0; i <BMListLen; i++) {
10177
10178 if(!BMList[i].MasterDev) {
10179 KdPrint2((PRINT_PREFIX "!BMList[i].MasterDev\n"));
10180 break;
10181 }
10182 if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) {
10183 break;
10184 }
10185 if(ReEnter) {
10186 KdPrint2((PRINT_PREFIX "ReEnter, skip it\n"));
10187 if(BMList[i].ChanInitOk & 0x03) {
10188 KdPrint2((PRINT_PREFIX "Already initialized, skip it\n"));
10189 statusToReturn =
10190 newStatus = STATUS_SUCCESS;
10191 }
10192 continue;
10193 }
10194 //BMList[i].AltInitMasterDev = (UCHAR)0xff;
10195
10196 if(GlobalConfig->AtDiskPrimaryAddressClaimed)
10197 PrimaryClaimed = TRUE;
10198 if(GlobalConfig->AtDiskSecondaryAddressClaimed)
10199 SecondaryClaimed = TRUE;
10200
10201 if(!WinVer_WDM_Model && !PrimaryClaimed && !SecondaryClaimed &&
10202 !(BMList[i].ChanInitOk & 0x80)) {
10203 newStatus = UniataClaimLegacyPCIIDE(i);
10204 if(newStatus != STATUS_SUCCESS) {
10205 KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
10206 break;
10207 }
10208 }
10209
10210 if(g_opt_Verbose) {
10211 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
10212 }
10213
10214
10215 for(alt = 0; alt < (ULONG)(WinVer_WDM_Model ? 1 : 2) ; alt++) {
10216
10217 for(c=0; c<2; c++) {
10218
10219 if(AtapiRegCheckDevValue(NULL, c, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) {
10220 break;
10221 }
10222 if(c==0) {
10223 if(PrimaryClaimed) {
10224 KdPrint2((PRINT_PREFIX "Primary already claimed\n"));
10225 continue;
10226 }
10227 } else
10228 if(c==1) {
10229 if(SecondaryClaimed) {
10230 KdPrint2((PRINT_PREFIX "Secondary already claimed\n"));
10231 continue;
10232 }
10233 }
10234
10235 if((WinVer_Id() < WinVer_2k)) {
10236 // do not even try if already claimed
10237 if(c==0) {
10238 GlobalConfig->AtDiskPrimaryAddressClaimed = FALSE;
10239 } else
10240 if(c==1) {
10241 GlobalConfig->AtDiskSecondaryAddressClaimed = FALSE;
10242 }
10243 }
10244 if(!WinVer_WDM_Model) {
10245 hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
10246 } else {
10247 // in WDM model things are different....
10248 hwInitializationData.comm.HwFindAdapter = (c == 0) ?
10249 UniataFindCompatBusMasterController1 : UniataFindCompatBusMasterController2;
10250 }
10251 hwInitializationData.comm.NumberOfAccessRanges = 6;
10252 hwInitializationData.comm.AdapterInterfaceType = Isa;
10253
10254 if(!WinVer_WDM_Model) {
10255 BMList[i].channel = (UCHAR)c;
10256 }
10257
10258 KdPrint2((PRINT_PREFIX "Try init channel %d, method %d\n", c, alt));
10259 newStatus = ScsiPortInitialize(DriverObject,
10260 Argument2,
10261 &hwInitializationData.comm,
10262 (PVOID)(i | (alt ? 0x80000000 : 0)));
10263 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
10264 if (newStatus < statusToReturn) {
10265 statusToReturn = newStatus;
10266 }
10267 if (newStatus == STATUS_SUCCESS) {
10268 if(WinVer_Id() < WinVer_2k) {
10269 // This should be done in HwInitialize under w2k+ to ensure that
10270 // channel is actually initialized
10271 BMList[i].ChanInitOk |= 0x01 << c;
10272 } else {
10273 if(BMList[i].ChanInitOk & (0x01 << c)) {
10274 KdPrint2((PRINT_PREFIX "HwInit passed\n"));
10275 }
10276 }
10277 /*
10278 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
10279 c = 1; // this will break our for()
10280 BMList[i].ChanInitOk |= 0x01 << c;
10281 }
10282 */
10283 }
10284 }
10285 /* if(WinVer_Id() >= WinVer_2k) {
10286 // the following didn't work under higher OSes,
10287 // until we move setting of FLAGS to HwInit
10288 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
10289 continue;
10290 }*/
10291 if(BMList[i].ChanInitOk & 0x03) {
10292 // Under NT we receive status immediately, so
10293 // we can omit alternative init method if STATUS_SUCCESS returned.
10294 // Under w2k+ we relay on flags, set in HwInitialize.
10295 KdPrint2((PRINT_PREFIX "Ok, no more retries required\n"));
10296 break;
10297 } else
10298 if(WinVer_Id() >= WinVer_2k) {
10299 // try AltInit if HwInit was not called immediately under w2k+
10300 KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n"));
10301 } else {
10302 // if (WinVer_Id() == WinVer_NT) and some error occured
10303 // try alternative init method
10304 KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n"));
10305 }
10306 } // for(alt...)
10307 if(g_opt_Verbose) {
10308 if(BMList[i].ChanInitOk & 0x03) {
10309 _PrintNtConsole(" OK\n");
10310 } else {
10311 _PrintNtConsole(" failed\n");
10312 }
10313 }
10314
10315 }
10316
10317 /* KeBugCheckEx(0xc000000e,
10318 (i << 16) | BMList[0].ChanInitOk,
10319 c,
10320 newStatus, statusToReturn);*/
10321
10322 // Look for PCI IDE controller
10323 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for PCI IDE controller\n"));
10324 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: i %d, BMListLen %d\n", i, BMListLen));
10325 for (; i <BMListLen; i++) {
10326
10327 if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreNativePci", 0)) {
10328 break;
10329 }
10330 /* if(BMList[i].MasterDev)
10331 continue;*/
10332 if(g_opt_Verbose) {
10333 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
10334 BMList[i].VendorId, BMList[i].DeviceId,
10335 BMList[i].busNumber,
10336 BMList[i].slotNumber % PCI_MAX_FUNCTION,
10337 (BMList[i].slotNumber / PCI_MAX_FUNCTION) % PCI_MAX_DEVICES);
10338 }
10339
10340 hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
10341 hwInitializationData.comm.NumberOfAccessRanges = 6;
10342 hwInitializationData.comm.AdapterInterfaceType = PCIBus;
10343
10344 hwInitializationData.comm.VendorId = (PVOID)BMList[i].VendorId;
10345 hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength;
10346 hwInitializationData.comm.DeviceId = (PVOID)BMList[i].DeviceId;
10347 hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength;
10348
10349 BMList[i].channel = 0/*(UCHAR)c*/;
10350
10351 KdPrint2((PRINT_PREFIX "Try init %4.4s %4.4s \n",
10352 hwInitializationData.comm.VendorId,
10353 hwInitializationData.comm.DeviceId));
10354 newStatus = ScsiPortInitialize(DriverObject,
10355 Argument2,
10356 &hwInitializationData.comm,
10357 (PVOID)i);
10358 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
10359 if(newStatus == (ULONG)STATUS_DEVICE_DOES_NOT_EXIST && BMList[i].NeedAltInit) {
10360 // Note: this is actually a BUG in scsiport.sys
10361 // It stops scanning PCI bus when reaches empty PCI Function inside Slot
10362 // However, this PCI Slot may have higher non-empty Functions
10363 // UniATA will perform all staff instead of ScsiPort under NT,
10364 // but for ReactOS it is better to patch ScsiPort.
10365 KdPrint2((PRINT_PREFIX "STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
10366 hwInitializationData.comm.AdapterInterfaceType = Isa;
10367 newStatus = ScsiPortInitialize(DriverObject,
10368 Argument2,
10369 &hwInitializationData.comm,
10370 (PVOID)(i | 0x80000000));
10371 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x (2)\n", newStatus));
10372 }
10373 if (newStatus < statusToReturn)
10374 statusToReturn = newStatus;
10375
10376 if(g_opt_Verbose) {
10377 if(newStatus == STATUS_SUCCESS) {
10378 _PrintNtConsole(" OK\n");
10379 } else {
10380 _PrintNtConsole(" failed\n");
10381 }
10382 }
10383
10384 }
10385
10386 /* KeBugCheckEx(0xc000000e,
10387 i,
10388 c,
10389 newStatus, statusToReturn);*/
10390
10391 // --------------
10392
10393 hwInitializationData.comm.VendorId = 0;
10394 hwInitializationData.comm.VendorIdLength = 0;
10395 hwInitializationData.comm.DeviceId = 0;
10396 hwInitializationData.comm.DeviceIdLength = 0;
10397
10398 if(!BMListLen) {
10399 hwInitializationData.comm.SrbExtensionSize = //FIELD_OFFSET(ATA_REQ, ata);
10400 sizeof(ATA_REQ);
10401 KdPrint2((PRINT_PREFIX "using AtaReq sz %x\n", hwInitializationData.comm.SrbExtensionSize));
10402 }
10403
10404 // The adapter count is used by the find adapter routine to track how
10405 // which adapter addresses have been tested.
10406
10407 // Indicate 2 access ranges and reset FindAdapter.
10408 hwInitializationData.comm.NumberOfAccessRanges = 2;
10409 hwInitializationData.comm.HwFindAdapter = AtapiFindController;
10410
10411 if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsa", 0)) {
10412 // Indicate ISA bustype.
10413 hwInitializationData.comm.AdapterInterfaceType = Isa;
10414 adapterCount = 0;
10415
10416 // Call initialization for ISA bustype.
10417 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for ISA Controllers\n"));
10418 newStatus = ScsiPortInitialize(DriverObject,
10419 Argument2,
10420 &hwInitializationData.comm,
10421 &adapterCount);
10422 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
10423 if (newStatus < statusToReturn)
10424 statusToReturn = newStatus;
10425 }
10426 if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreMca", 0)) {
10427 // Set up for MCA
10428 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for MCA Controllers\n"));
10429 hwInitializationData.comm.AdapterInterfaceType = MicroChannel;
10430 adapterCount = 0;
10431
10432 newStatus = ScsiPortInitialize(DriverObject,
10433 Argument2,
10434 &hwInitializationData.comm,
10435 &adapterCount);
10436 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
10437 if (newStatus < statusToReturn)
10438 statusToReturn = newStatus;
10439 }
10440 InDriverEntry = FALSE;
10441
10442 KdPrint2((PRINT_PREFIX "\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn));
10443
10444 return statusToReturn;
10445
10446 } // end DriverEntry()
10447
10448
10449 PSCSI_REQUEST_BLOCK
10450 NTAPI
10451 BuildMechanismStatusSrb(
10452 IN PVOID HwDeviceExtension,
10453 IN PSCSI_REQUEST_BLOCK Srb
10454 )
10455 {
10456 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10457 PSCSI_REQUEST_BLOCK srb;
10458 PCDB cdb;
10459 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
10460
10461 srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb);
10462
10463 RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
10464
10465 srb->PathId = (UCHAR)(Srb->PathId);
10466 srb->TargetId = (UCHAR)(Srb->TargetId);
10467 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
10468 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
10469
10470 // Set flags to disable synchronous negociation.
10471 srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
10472
10473 // Set timeout to 4 seconds.
10474 srb->TimeOutValue = 4;
10475
10476 srb->CdbLength = 6;
10477 srb->DataBuffer = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusData);
10478 srb->DataTransferLength = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
10479 srb->SrbExtension = AtaReq;
10480
10481 // Set CDB operation code.
10482 cdb = (PCDB)srb->Cdb;
10483 cdb->MECH_STATUS.OperationCode = SCSIOP_MECHANISM_STATUS;
10484 cdb->MECH_STATUS.AllocationLength[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
10485
10486 KdPrint2((PRINT_PREFIX " MechanismStatusSrb %#x\n", srb));
10487
10488 return srb;
10489 } // end BuildMechanismStatusSrb()
10490
10491 #endif //UNIATA_CORE
10492
10493 PSCSI_REQUEST_BLOCK
10494 NTAPI
10495 BuildRequestSenseSrb (
10496 IN PVOID HwDeviceExtension,
10497 IN PSCSI_REQUEST_BLOCK Srb
10498 )
10499 {
10500 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10501 PSCSI_REQUEST_BLOCK srb;
10502 PCDB cdb;
10503 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
10504
10505 srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb);
10506
10507 RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
10508
10509 srb->PathId = (UCHAR)(Srb->PathId);
10510 srb->TargetId = (UCHAR)(Srb->TargetId);
10511 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
10512 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
10513
10514 // Set flags to disable synchronous negociation.
10515 srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
10516
10517 // Set timeout to 2 seconds.
10518 srb->TimeOutValue = 4;
10519
10520 srb->CdbLength = 6;
10521 srb->DataBuffer = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusSense);
10522 srb->DataTransferLength = sizeof(SENSE_DATA);
10523 srb->SrbExtension = AtaReq;
10524
10525 // Set CDB operation code.
10526 cdb = (PCDB)srb->Cdb;
10527 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
10528 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
10529
10530 KdPrint2((PRINT_PREFIX " RequestSenseSrb %#x\n", srb));
10531
10532 return srb;
10533 } // end BuildRequestSenseSrb()
10534
10535 #ifndef UNIATA_CORE
10536
10537 ULONG
10538 NTAPI
10539 AtapiRegCheckDevLunValue(
10540 IN PVOID HwDeviceExtension,
10541 IN PCWCH NamePrefix,
10542 IN ULONG chan,
10543 IN ULONG dev,
10544 IN PCWSTR Name,
10545 IN ULONG Default
10546 )
10547 {
10548 WCHAR namex[160];
10549 ULONG val = Default;
10550
10551 val = AtapiRegCheckParameterValue(
10552 HwDeviceExtension, NamePrefix, Name, val);
10553
10554 if(chan != CHAN_NOT_SPECIFIED) {
10555 swprintf(namex, L"%s\\Chan_%1.1d", NamePrefix, chan);
10556 val = AtapiRegCheckParameterValue(
10557 HwDeviceExtension, namex, Name, val);
10558 if(dev != DEVNUM_NOT_SPECIFIED) {
10559 swprintf(namex, L"%s\\Chan_%1.1d\\%s", NamePrefix, chan, (dev & 0x01) ? L"Lun_1" : L"Lun_0");
10560 val = AtapiRegCheckParameterValue(
10561 HwDeviceExtension, namex, Name, val);
10562 }
10563 }
10564 return val;
10565 } // end AtapiRegCheckDevLunValue()
10566
10567 ULONG
10568 NTAPI
10569 EncodeVendorStr(
10570 OUT PWCHAR Buffer,
10571 IN PUCHAR Str,
10572 IN ULONG Length
10573 )
10574 {
10575 ULONG i,j;
10576 WCHAR a;
10577
10578 for(i=0, j=0; i<Length; i++, j++) {
10579 // fix byte-order
10580 a = Str[i ^ 0x01];
10581 if(!a) {
10582 Buffer[j] = 0;
10583 return j;
10584 } else
10585 if(a == ' ') {
10586 Buffer[j] = '_';
10587 } else
10588 if((a == '_') ||
10589 (a == '#') ||
10590 (a == '\\') ||
10591 (a == '\"') ||
10592 (a == '\'') ||
10593 (a < ' ') ||
10594 (a >= 127)) {
10595 Buffer[j] = '#';
10596 j++;
10597 swprintf(Buffer+j, L"%2.2x", a);
10598 j++;
10599 } else {
10600 Buffer[j] = a;
10601 }
10602 }
10603 Buffer[j] = 0;
10604 return j;
10605 } // end EncodeVendorStr()
10606
10607 ULONG
10608 NTAPI
10609 AtapiRegCheckDevValue(
10610 IN PVOID HwDeviceExtension,
10611 IN ULONG chan,
10612 IN ULONG dev,
10613 IN PCWSTR Name,
10614 IN ULONG Default
10615 )
10616 {
10617 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10618 // WCHAR name0[11];
10619 // WCHAR name1[11+4+5];
10620 // WCHAR name2[11+4+4+10];
10621 // WCHAR name3[11+4+4+5+20];
10622 // WCHAR name3[11+4+4+5+20+1];
10623 WCHAR namex[160];
10624
10625 WCHAR namev[16];
10626 WCHAR named[16];
10627 WCHAR names[20];
10628
10629 IN ULONG VendorID;
10630 IN ULONG DeviceID;
10631 IN ULONG SlotNumber;
10632
10633 ULONG val = Default;
10634
10635 KdPrint(( " Parameter %ws\n", Name));
10636
10637 if(deviceExtension) {
10638 VendorID = deviceExtension->DevID & 0xffff;
10639 DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
10640 SlotNumber = deviceExtension->slotNumber;
10641 } else {
10642 VendorID = 0xffff;
10643 DeviceID = 0xffff;
10644 SlotNumber = 0xffffffff;
10645 }
10646
10647 val = AtapiRegCheckDevLunValue(
10648 HwDeviceExtension, L"Parameters", chan, dev, Name, val);
10649
10650 if(deviceExtension) {
10651 if(deviceExtension->AdapterInterfaceType == PCIBus) {
10652 // PCI
10653 swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex);
10654 swprintf(namex, L"Parameters%s", namev);
10655 val = AtapiRegCheckDevLunValue(
10656 HwDeviceExtension, namex, chan, dev, Name, val);
10657
10658
10659 swprintf(namev, L"\\Ven_%4.4x", VendorID);
10660 swprintf(named, L"\\Dev_%4.4x", DeviceID);
10661 swprintf(names, L"\\Slot_%8.8x", SlotNumber);
10662
10663 swprintf(namex, L"Parameters%s", namev);
10664 val = AtapiRegCheckDevLunValue(
10665 HwDeviceExtension, namex, chan, dev, Name, val);
10666
10667 swprintf(namex, L"Parameters%s%s", namev, named);
10668 val = AtapiRegCheckDevLunValue(
10669 HwDeviceExtension, namex, chan, dev, Name, val);
10670
10671 swprintf(namex, L"Parameters%s%s%s", namev, named, names);
10672 val = AtapiRegCheckDevLunValue(
10673 HwDeviceExtension, namex, chan, dev, Name, val);
10674 } else
10675 if(deviceExtension->AdapterInterfaceType == Isa) {
10676 // Isa
10677 swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen);
10678 swprintf(namex, L"Parameters%s", namev);
10679 val = AtapiRegCheckDevLunValue(
10680 HwDeviceExtension, namex, chan, dev, Name, val);
10681
10682 swprintf(namev, L"\\ISA_%d", deviceExtension->DevIndex);
10683 swprintf(namex, L"Parameters%s", namev);
10684 val = AtapiRegCheckDevLunValue(
10685 HwDeviceExtension, namex, chan, dev, Name, val);
10686
10687 } else
10688 if(deviceExtension->AdapterInterfaceType == MicroChannel) {
10689 // MicroChannel
10690 swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen+IsaCount);
10691 swprintf(namex, L"Parameters%s", namev);
10692 val = AtapiRegCheckDevLunValue(
10693 HwDeviceExtension, namex, chan, dev, Name, val);
10694
10695 swprintf(namev, L"\\MCA_%d", deviceExtension->DevIndex);
10696 swprintf(namex, L"Parameters%s", namev);
10697 val = AtapiRegCheckDevLunValue(
10698 HwDeviceExtension, namex, chan, dev, Name, val);
10699
10700 }
10701 }
10702
10703 KdPrint(( " Parameter %ws = %#x\n", Name, val));
10704 return val;
10705
10706 } // end AtapiRegCheckDevValue()
10707
10708 /*
10709 The user must specify that Xxx is to run on the platform
10710 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
10711 Services\UniATA\Xxx:REG_DWORD:Zzz.
10712
10713 The user can override the global setting to enable or disable Xxx on a
10714 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
10715 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
10716
10717 If this registry value does not exist or contains the value zero then
10718 the timer to check for media change does not run.
10719
10720 Arguments:
10721
10722 RegistryPath - pointer to the unicode string inside
10723 ...\CurrentControlSet\Services\UniATA
10724 DeviceNumber - The number of the HBA device object
10725
10726 Returns: Registry Key value
10727 */
10728 ULONG
10729 NTAPI
10730 AtapiRegCheckParameterValue(
10731 IN PVOID HwDeviceExtension,
10732 IN PCWSTR PathSuffix,
10733 IN PCWSTR Name,
10734 IN ULONG Default
10735 )
10736 {
10737 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
10738
10739 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10740 NTSTATUS status;
10741 LONG zero = Default;
10742
10743 RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY];
10744
10745 // LONG tmp = 0;
10746 LONG doRun = Default;
10747
10748 PUNICODE_STRING RegistryPath = &SavedRegPath;
10749
10750 UNICODE_STRING paramPath;
10751
10752 // <SavedRegPath>\<PathSuffix> -> <Name>
10753 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
10754 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
10755
10756 paramPath.Length = 0;
10757 paramPath.MaximumLength = RegistryPath->Length +
10758 (wcslen(PathSuffix)+2)*sizeof(WCHAR);
10759 paramPath.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, paramPath.MaximumLength);
10760 if(!paramPath.Buffer) {
10761 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
10762 return Default;
10763 }
10764
10765 RtlZeroMemory(paramPath.Buffer, paramPath.MaximumLength);
10766 RtlAppendUnicodeToString(&paramPath, RegistryPath->Buffer);
10767 RtlAppendUnicodeToString(&paramPath, L"\\");
10768 RtlAppendUnicodeToString(&paramPath, REGRTL_STR_PTYPE PathSuffix);
10769
10770 // Check for the Xxx value.
10771 RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
10772
10773 parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
10774 parameters[0].Name = REGRTL_STR_PTYPE Name;
10775 parameters[0].EntryContext = &doRun;
10776 parameters[0].DefaultType = REG_DWORD;
10777 parameters[0].DefaultData = &zero;
10778 parameters[0].DefaultLength = sizeof(ULONG);
10779
10780 status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/,
10781 paramPath.Buffer, parameters, NULL, NULL);
10782 if(NT_SUCCESS(status)) {
10783 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun));
10784 }
10785
10786 ExFreePool(paramPath.Buffer);
10787
10788 if(!NT_SUCCESS(status)) {
10789 doRun = Default;
10790 }
10791
10792 return doRun;
10793
10794 #undef ITEMS_TO_QUERY
10795
10796 } // end AtapiRegCheckParameterValue()
10797
10798
10799 SCSI_ADAPTER_CONTROL_STATUS
10800 NTAPI
10801 AtapiAdapterControl(
10802 IN PVOID HwDeviceExtension,
10803 IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
10804 IN PVOID Parameters
10805 )
10806 {
10807 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10808 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList;
10809 ULONG numberChannels = deviceExtension->NumberChannels;
10810 ULONG c;
10811 NTSTATUS status;
10812
10813 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType));
10814
10815 switch(ControlType) {
10816 case ScsiQuerySupportedControlTypes: {
10817 BOOLEAN supportedTypes[ScsiAdapterControlMax] = {
10818 TRUE, // ScsiQuerySupportedControlTypes
10819 TRUE, // ScsiStopAdapter
10820 TRUE, // ScsiRestartAdapter
10821 FALSE, // ScsiSetBootConfig
10822 FALSE // ScsiSetRunningConfig
10823 };
10824
10825 ULONG lim = ScsiAdapterControlMax;
10826 ULONG i;
10827
10828 pControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST) Parameters;
10829
10830 if(pControlTypeList->MaxControlType < lim) {
10831 lim = pControlTypeList->MaxControlType;
10832 }
10833
10834 for(i = 0; i < lim; i++) {
10835 pControlTypeList->SupportedTypeList[i] = supportedTypes[i];
10836 }
10837
10838 break;
10839
10840 }
10841 case ScsiStopAdapter: {
10842
10843 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
10844 // Shut down all interrupts on the adapter. They'll get re-enabled
10845 // by the initialization routines.
10846 for (c = 0; c < numberChannels; c++) {
10847 AtapiResetController(deviceExtension, c);
10848 AtapiDisableInterrupts(deviceExtension, c);
10849 }
10850 if(deviceExtension->AdapterInterfaceType == PCIBus) {
10851 // we must never get here for non-PCI
10852 /*status =*/ UniataDisconnectIntr2(HwDeviceExtension);
10853 BMList[deviceExtension->DevIndex].Isr2Enable = FALSE;
10854 }
10855 break;
10856 }
10857 case ScsiRestartAdapter: {
10858
10859 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
10860 // Enable all the interrupts on the adapter while port driver call
10861 // for power up an HBA that was shut down for power management
10862
10863 AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
10864 status = UniataConnectIntr2(HwDeviceExtension);
10865 if(NT_SUCCESS(status)) {
10866 for (c = 0; c < numberChannels; c++) {
10867 AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, c);
10868 FindDevices(HwDeviceExtension, 0, c);
10869 AtapiEnableInterrupts(deviceExtension, c);
10870 AtapiHwInitialize__(deviceExtension, c);
10871 }
10872 if(deviceExtension->Isr2DevObj) {
10873 // we must never get here for non-PCI
10874 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
10875 }
10876 }
10877
10878 break;
10879 }
10880
10881 default: {
10882 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
10883 return ScsiAdapterControlUnsuccessful;
10884 }
10885 }
10886
10887 return ScsiAdapterControlSuccess;
10888 } // end AtapiAdapterControl()
10889
10890 #endif //UNIATA_CORE
10891
10892 extern "C"
10893 NTHALAPI
10894 VOID
10895 NTAPI
10896 HalDisplayString (
10897 PUCHAR String
10898 );
10899
10900 #define DEBUG_MSG_BUFFER_SIZE 512
10901
10902 extern "C"
10903 VOID
10904 _cdecl
10905 _PrintNtConsole(
10906 PCCH DebugMessage,
10907 ...
10908 )
10909 {
10910 //int len;
10911 UCHAR dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE];
10912 // UNICODE_STRING msgBuff;
10913 va_list ap;
10914 va_start(ap, DebugMessage);
10915
10916 /*len =*/ _vsnprintf((PCHAR)&dbg_print_tmp_buff[0], DEBUG_MSG_BUFFER_SIZE-1, DebugMessage, ap);
10917
10918 dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE-1] = 0;
10919
10920 //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro
10921 HalDisplayString(dbg_print_tmp_buff);
10922
10923 #ifdef _DEBUG
10924 if(g_LogToDisplay > 1) {
10925 AtapiStallExecution(g_LogToDisplay*1000);
10926 }
10927 #endif // _DEBUG
10928
10929 va_end(ap);
10930
10931 } // end PrintNtConsole()
10932