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