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