[UNIATA]: Sync to 0.43f5.
[reactos.git] / reactos / 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_SATA) {
6980 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (ahci)\n"));
6981 use_dma = TRUE;
6982 goto setup_dma;
6983 } else
6984 if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
6985 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
6986 } else
6987 if(AtaReq->TransferLength) {
6988 // try use DMA
6989 switch(Srb->Cdb[0]) {
6990 case SCSIOP_WRITE:
6991 case SCSIOP_WRITE12:
6992 case SCSIOP_WRITE16:
6993 case SCSIOP_SEND:
6994 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO)
6995 break;
6996 /* FALLTHROUGH */
6997 case SCSIOP_RECEIVE:
6998 case SCSIOP_READ:
6999 case SCSIOP_READ12:
7000 case SCSIOP_READ16:
7001
7002 if(deviceExtension->opt_AtapiDmaReadWrite) {
7003 call_dma_setup:
7004 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7005 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n"));
7006 use_dma = TRUE;
7007 } else
7008 if(AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
7009 (PUCHAR)(AtaReq->DataBuffer),
7010 Srb->DataTransferLength
7011 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
7012 )) {
7013 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n"));
7014 use_dma = TRUE;
7015 }
7016 }
7017 break;
7018 case SCSIOP_READ_CD:
7019 if(deviceExtension->opt_AtapiDmaRawRead)
7020 goto call_dma_setup;
7021 break;
7022 default:
7023
7024 if(deviceExtension->opt_AtapiDmaControlCmd) {
7025 if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
7026 // read operation
7027 use_dma = TRUE;
7028 } else {
7029 // write operation
7030 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO) {
7031 KdPrint2((PRINT_PREFIX "dma RO\n"));
7032 use_dma = FALSE;
7033 } else {
7034 use_dma = TRUE;
7035 }
7036 }
7037 }
7038 break;
7039 }
7040 // try setup DMA
7041 setup_dma:
7042 if(use_dma) {
7043 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7044 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n"));
7045 //use_dma = TRUE;
7046 } else
7047 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
7048 (PUCHAR)(AtaReq->DataBuffer),
7049 Srb->DataTransferLength)) {
7050 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma\n"));
7051 use_dma = FALSE;
7052 } else {
7053 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n"));
7054 }
7055 }
7056 } else {
7057 KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer, no DMA setup\n"));
7058 }
7059
7060
7061 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7062
7063 UniataAhciSetupCmdPtr(AtaReq);
7064
7065 if(!Srb->DataTransferLength) {
7066 KdPrint2((PRINT_PREFIX "zero-transfer\n"));
7067 use_dma = FALSE;
7068 } else
7069 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
7070 (PUCHAR)(AtaReq->DataBuffer),
7071 Srb->DataTransferLength)) {
7072 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no AHCI dma!\n"));
7073 return SRB_STATUS_ERROR;
7074 }
7075 if(!use_dma) {
7076 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7077 } else {
7078 FeatureReg |= ATA_F_DMA;
7079 if(LunExt->IdentifyData.AtapiDMA.DMADirRequired &&
7080 (Srb->SrbFlags & SRB_FLAGS_DATA_IN)) {
7081 FeatureReg |= ATA_F_DMAREAD;
7082 }
7083 }
7084
7085 KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n"));
7086 // this is done in UniataAhciSetupFIS_H2D()
7087 //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
7088 RtlCopyMemory(&(AtaReq->ahci.ahci_cmd_ptr->acmd), Srb->Cdb, Srb->CdbLength);
7089
7090 fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
7091 &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]),
7092 IDE_COMMAND_ATAPI_PACKET /* command */,
7093 0 /* lba */,
7094 (Srb->DataTransferLength >= 0x10000) ? (USHORT)(0xffff) : (USHORT)(Srb->DataTransferLength),
7095 FeatureReg/* feature */
7096 );
7097
7098 if(!fis_size) {
7099 KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n"));
7100 return SRB_STATUS_ERROR;
7101 }
7102
7103 AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0,
7104 ((Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) ? ATA_AHCI_CMD_WRITE : 0) |
7105 (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH),
7106 fis_size, DeviceNumber);
7107
7108 KdPrint2((PRINT_PREFIX "AtapiSendCommand ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags));
7109 }
7110
7111 } else {
7112 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
7113 // if this is queued request, reinit DMA and check
7114 // if DMA mode is still available
7115 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() (1)\n"));
7116 AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7117 if (/*EnableDma &&*/
7118 (LunExt->TransferMode >= ATA_DMA)) {
7119 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (2)\n"));
7120 use_dma = TRUE;
7121 } else {
7122 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7123 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma (2)\n"));
7124 use_dma = FALSE;
7125 }
7126 dma_reinited = TRUE;
7127 }
7128 }
7129
7130 if(!(CmdAction & CMD_ACTION_EXEC)) {
7131 KdPrint2((PRINT_PREFIX "AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
7132 return SRB_STATUS_PENDING;
7133 }
7134 KdPrint3((PRINT_PREFIX "AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma, Srb->Cdb[0]));
7135 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
7136 KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n"));
7137 }
7138
7139 if((Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) && !(deviceExtension->HwFlags & UNIATA_SATA)) {
7140 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
7141 use_dma = FALSE;
7142 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7143 AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7144 } if(AtaReq->TransferLength) {
7145 if(!dma_reinited) {
7146 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit()\n"));
7147 AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7148 if (/*EnableDma &&*/
7149 (LunExt->TransferMode >= ATA_DMA)) {
7150 use_dma = TRUE;
7151 } else {
7152 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7153 use_dma = FALSE;
7154 }
7155 }
7156 } else {
7157 KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer\n"));
7158 use_dma = FALSE;
7159 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7160 if(!deviceExtension->opt_AtapiDmaZeroTransfer && !(deviceExtension->HwFlags & UNIATA_SATA)) {
7161 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
7162 AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7163 }
7164 }
7165 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use_dma=%d\n", use_dma));
7166 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
7167 KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n"));
7168 }
7169
7170 KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_EXEC\n"));
7171
7172 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
7173 &(Srb->Cdb), Srb->Cdb[0], Srb->TargetId, Srb->Lun));
7174
7175 // Make sure command is to ATAPI device.
7176 flags = LunExt->DeviceFlags;
7177 if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
7178 if((Srb->Lun) > (LunExt->DiscsPresent - 1)) {
7179
7180 // Indicate no device found at this address.
7181 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7182 return SRB_STATUS_SELECTION_TIMEOUT;
7183 }
7184 } else if(Srb->Lun > 0) {
7185 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7186 return SRB_STATUS_SELECTION_TIMEOUT;
7187 }
7188
7189 if(!(flags & DFLAGS_ATAPI_DEVICE)) {
7190 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7191 return SRB_STATUS_SELECTION_TIMEOUT;
7192 }
7193 retry:
7194 // Select device 0 or 1. Or more for PM
7195 SelectDrive(chan, DeviceNumber);
7196
7197 // Verify that controller is ready for next command.
7198 GetStatus(chan, statusByte);
7199 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status %#x\n", statusByte));
7200
7201 if(statusByte == IDE_STATUS_WRONG) {
7202 KdPrint2((PRINT_PREFIX "AtapiSendCommand: bad status 0xff on entry\n"));
7203 goto make_reset;
7204 }
7205 if(statusByte & IDE_STATUS_BUSY) {
7206 if(statusByte & IDE_STATUS_DSC) {
7207 KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte));
7208 } else {
7209 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte));
7210 // We have to make reset here, since we are expecting device to be available
7211 //return SRB_STATUS_BUSY; // this cause queue freeze
7212 goto make_reset;
7213 }
7214 }
7215 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7216 ULONG CI;
7217 // Check if command list is free
7218 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
7219 if(CI) {
7220 // controller is busy, however we expect it to be free
7221 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI));
7222 goto make_reset;
7223 }
7224 }
7225 if(statusByte & IDE_STATUS_ERROR) {
7226 if (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
7227
7228 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on entry: (%#x)\n", statusByte));
7229 // Read the error reg. to clear it and fail this request.
7230 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7231 return MapError(deviceExtension, Srb);
7232 } else {
7233 KdPrint2((PRINT_PREFIX " continue with SCSIOP_REQUEST_SENSE\n", statusByte));
7234 }
7235 }
7236 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
7237 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
7238 if((!(statusByte & IDE_STATUS_DSC)) &&
7239 (flags & (DFLAGS_TAPE_DEVICE | DFLAGS_ATAPI_DEVICE)) && chan->RDP) {
7240
7241 AtapiStallExecution(200);
7242 KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte));
7243 AtaReq->ReqState = REQ_STATE_QUEUED;
7244 return SRB_STATUS_PENDING;
7245 }
7246
7247 if(IS_RDP(Srb->Cdb[0])) {
7248 chan->RDP = TRUE;
7249 KdPrint2((PRINT_PREFIX "AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb->Cdb[0]));
7250 } else {
7251 chan->RDP = FALSE;
7252 }
7253 if(statusByte & IDE_STATUS_DRQ) {
7254
7255 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
7256 statusByte));
7257 // Try to drain the data that one preliminary device thinks that it has
7258 // to transfer. Hopefully this random assertion of DRQ will not be present
7259 // in production devices.
7260 statusByte = AtapiSuckPort2(chan);
7261 /*
7262 for (i = 0; i < 0x10000; i++) {
7263 GetStatus(chan, statusByte);
7264 if(statusByte & IDE_STATUS_DRQ) {
7265 AtapiReadPort2(chan, IDX_IO1_i_Data);
7266 } else {
7267 break;
7268 }
7269 }
7270 */
7271 if (statusByte & IDE_STATUS_DRQ) {
7272 make_reset:
7273 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte));
7274
7275 AtapiDisableInterrupts(deviceExtension, lChannel);
7276
7277 AtapiSoftReset(chan, DeviceNumber);
7278
7279 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Issued soft reset to Atapi device. \n"));
7280 // Re-initialize Atapi device.
7281 CheckDevice(HwDeviceExtension, GET_CHANNEL(Srb), DeviceNumber, TRUE);
7282 /*
7283 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
7284 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
7285 */
7286 // Inform the port driver that the bus has been reset.
7287 ScsiPortNotification(ResetDetected, HwDeviceExtension, 0);
7288 // Clean up device extension fields that AtapiStartIo won't.
7289 UniataExpectChannelInterrupt(chan, FALSE);
7290 chan->RDP = FALSE;
7291 InterlockedExchange(&(deviceExtension->chan[GET_CHANNEL(Srb)].CheckIntr),
7292 CHECK_INTR_IDLE);
7293
7294 AtapiEnableInterrupts(deviceExtension, lChannel);
7295 /*
7296 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7297 return SRB_STATUS_BUS_RESET;
7298 */
7299 if(!retried) {
7300 KdPrint3((PRINT_PREFIX "AtapiSendCommand: retry after reset.\n"));
7301 retried = TRUE;
7302 goto retry;
7303 }
7304 KdPrint3((PRINT_PREFIX "AtapiSendCommand: selection timeout.\n"));
7305 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7306 return SRB_STATUS_SELECTION_TIMEOUT;
7307 }
7308 }
7309
7310 if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
7311 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
7312 Srb->Cdb[1] &= ~0xE0;
7313 if((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY) && (flags & DFLAGS_SANYO_ATAPI_CHANGER)) {
7314 // Torisan changer. TUR's are overloaded to be platter switches.
7315 Srb->Cdb[7] = Srb->Lun;
7316 }
7317 }
7318
7319 // SETUP DMA !!!!!
7320
7321 if(use_dma) {
7322 chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
7323 } else {
7324 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
7325 }
7326
7327 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7328 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AHCI, begin transaction\n"));
7329 //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
7330 UniataExpectChannelInterrupt(chan, TRUE);
7331 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
7332 return SRB_STATUS_PENDING;
7333 }
7334
7335 statusByte = WaitOnBusy(chan);
7336 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entry Status (%#x)\n",
7337 statusByte));
7338
7339 if(use_dma) {
7340 FeatureReg |= ATA_F_DMA;
7341 if(LunExt->IdentifyData.AtapiDMA.DMADirRequired &&
7342 (Srb->SrbFlags & SRB_FLAGS_DATA_IN)) {
7343 FeatureReg |= ATA_F_DMAREAD;
7344 }
7345 }
7346
7347 AtapiWritePort1(chan, IDX_IO1_o_Feature, FeatureReg);
7348
7349 // Write transfer byte count to registers.
7350 byteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF);
7351 byteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8);
7352
7353 if (Srb->DataTransferLength >= 0x10000) {
7354 byteCountLow = byteCountHigh = 0xFF;
7355 }
7356
7357 AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountLow, byteCountLow);
7358 AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh, byteCountHigh);
7359
7360 if (flags & DFLAGS_INT_DRQ) {
7361
7362 // This device interrupts when ready to receive the packet.
7363
7364 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
7365 statusByte));
7366
7367 UniataExpectChannelInterrupt(chan, TRUE);
7368 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_CMD_INTR;
7369 InterlockedExchange(&(chan->CheckIntr),
7370 CHECK_INTR_IDLE);
7371
7372 // Write ATAPI packet command.
7373 AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
7374
7375 KdPrint3((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
7376 return SRB_STATUS_PENDING;
7377
7378 }
7379
7380 // This device quickly sets DRQ when ready to receive the packet.
7381
7382 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
7383 statusByte));
7384
7385 UniataExpectChannelInterrupt(chan, TRUE);
7386 AtaReq->ReqState = REQ_STATE_ATAPI_DO_NOTHING_INTR;
7387 InterlockedExchange(&(chan->CheckIntr),
7388 CHECK_INTR_IDLE);
7389
7390 if(g_opt_AtapiSendDisableIntr) {
7391 AtapiDisableInterrupts(deviceExtension, lChannel);
7392 }
7393
7394 // Write ATAPI packet command.
7395 AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
7396
7397 // Wait for DRQ.
7398 WaitOnBusy(chan);
7399 statusByte = WaitForDrq(chan);
7400
7401 // Need to read status register and clear interrupt (if any)
7402 GetBaseStatus(chan, statusByte);
7403
7404 if (!(statusByte & IDE_STATUS_DRQ)) {
7405
7406 if(g_opt_AtapiSendDisableIntr) {
7407 AtapiEnableInterrupts(deviceExtension, lChannel);
7408 }
7409 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte));
7410 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7411 return SRB_STATUS_ERROR;
7412 }
7413
7414 GetStatus(chan, statusByte);
7415 KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte));
7416
7417 // Send CDB to device.
7418 statusByte = WaitOnBaseBusy(chan);
7419
7420 // Indicate expecting an interrupt and wait for it.
7421 UniataExpectChannelInterrupt(chan, TRUE);
7422 InterlockedExchange(&(chan->CheckIntr),
7423 CHECK_INTR_IDLE);
7424 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
7425
7426 GetBaseStatus(chan, statusByte);
7427
7428 if(g_opt_AtapiSendDisableIntr) {
7429 AtapiEnableInterrupts(deviceExtension, lChannel);
7430 }
7431
7432 WriteBuffer(chan,
7433 (PUSHORT)Srb->Cdb,
7434 LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
7435 0);
7436
7437 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
7438 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
7439 }
7440
7441 KdPrint3((PRINT_PREFIX "AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan->ExpectingInterrupt));
7442
7443 KdPrint2((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
7444 return SRB_STATUS_PENDING;
7445
7446 } // end AtapiSendCommand()
7447
7448
7449 #ifndef UNIATA_CORE
7450
7451 /*++
7452
7453 Routine Description:
7454 Program ATA registers for IDE disk transfer.
7455
7456 Arguments:
7457 HwDeviceExtension - ATAPI driver storage.
7458 Srb - System request block.
7459
7460 Return Value:
7461 SRB status (pending if all goes well).
7462
7463 --*/
7464
7465 #ifdef _DEBUG
7466 ULONG check_point = 0;
7467 #define SetCheckPoint(cp) { check_point = (cp) ; }
7468 #else
7469 #define SetCheckPoint(cp)
7470 #endif
7471
7472 ULONG
7473 NTAPI
7474 IdeSendCommand(
7475 IN PVOID HwDeviceExtension,
7476 IN PSCSI_REQUEST_BLOCK Srb,
7477 IN ULONG CmdAction
7478 )
7479 {
7480 SetCheckPoint(1);
7481 KdPrint2((PRINT_PREFIX "** Ide: Command: entryway\n"));
7482 SetCheckPoint(2);
7483
7484 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
7485 SetCheckPoint(3);
7486 UCHAR lChannel;
7487 PHW_CHANNEL chan;
7488 PCDB cdb;
7489 PHW_LU_EXTENSION LunExt;
7490
7491 SetCheckPoint(4);
7492
7493 UCHAR statusByte,errorByte;
7494 ULONG status = SRB_STATUS_INVALID_REQUEST;
7495 ULONG i;
7496 ULONGLONG lba;
7497 PMODE_PARAMETER_HEADER modeData;
7498 //ULONG ldev;
7499 ULONG DeviceNumber;
7500 PATA_REQ AtaReq;
7501 UCHAR command;
7502
7503 SetCheckPoint(5);
7504 //ULONG __ebp__ = 0;
7505
7506 SetCheckPoint(0x20);
7507 KdPrint2((PRINT_PREFIX "** Ide: Command:\n\n"));
7508 /* __asm {
7509 mov eax,ebp
7510 mov __ebp__, eax
7511 }*/
7512 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
7513 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
7514 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
7515 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
7516 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
7517 Srb));
7518 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
7519 Srb->SrbExtension));
7520 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
7521 Srb->TargetId));*/
7522
7523 SetCheckPoint(0x30);
7524 AtaReq = (PATA_REQ)(Srb->SrbExtension);
7525
7526 KdPrint2((PRINT_PREFIX "** Ide: Command &AtaReq %#x\n",
7527 &AtaReq));
7528 KdPrint2((PRINT_PREFIX "** Ide: Command AtaReq %#x\n",
7529 AtaReq));
7530 KdPrint2((PRINT_PREFIX "** --- **\n"));
7531
7532 lChannel = GET_CHANNEL(Srb);
7533 chan = &(deviceExtension->chan[lChannel]);
7534 //ldev = GET_LDEV(Srb);
7535 DeviceNumber = GET_CDEV(Srb);
7536 LunExt = chan->lun[DeviceNumber];
7537
7538 SetCheckPoint(0x40);
7539 if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
7540 AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER;
7541
7542 cdb = (PCDB)(Srb->Cdb);
7543
7544 if(CmdAction == CMD_ACTION_PREPARE) {
7545 switch (Srb->Cdb[0]) {
7546 case SCSIOP_SERVICE_ACTION16:
7547 if( cdb->SERVICE_ACTION16.ServiceAction==SCSIOP_SA_READ_CAPACITY16 ) {
7548 // ok
7549 } else {
7550 goto default_no_prep;
7551 }
7552 #ifdef NAVO_TEST
7553 case SCSIOP_INQUIRY: // now it requires device access
7554 #endif //NAVO_TEST
7555 case SCSIOP_READ_CAPACITY:
7556 case SCSIOP_READ:
7557 case SCSIOP_WRITE:
7558 case SCSIOP_READ12:
7559 case SCSIOP_WRITE12:
7560 case SCSIOP_READ16:
7561 case SCSIOP_WRITE16:
7562 case SCSIOP_REQUEST_SENSE:
7563 // all right
7564 KdPrint2((PRINT_PREFIX "** Ide: Command continue prep\n"));
7565 SetCheckPoint(50);
7566 break;
7567 default:
7568 default_no_prep:
7569 SetCheckPoint(0);
7570 KdPrint2((PRINT_PREFIX "** Ide: Command break prep\n"));
7571 return SRB_STATUS_BUSY;
7572 }
7573 }
7574
7575 SetCheckPoint(0x100 | Srb->Cdb[0]);
7576 switch (Srb->Cdb[0]) {
7577 case SCSIOP_INQUIRY:
7578
7579 KdPrint2((PRINT_PREFIX
7580 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
7581 Srb->PathId, Srb->Lun, Srb->TargetId));
7582 // Filter out wrong TIDs.
7583 if ((Srb->Lun != 0) ||
7584 (Srb->PathId >= deviceExtension->NumberChannels) ||
7585 (Srb->TargetId >= deviceExtension->NumberLuns)) {
7586
7587 KdPrint2((PRINT_PREFIX
7588 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
7589 // Indicate no device found at this address.
7590 status = SRB_STATUS_SELECTION_TIMEOUT;
7591 break;
7592
7593 } else {
7594
7595 KdPrint2((PRINT_PREFIX
7596 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
7597 PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer);
7598 PIDENTIFY_DATA2 identifyData = &(LunExt->IdentifyData);
7599
7600 if (!(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
7601
7602 if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
7603 KdPrint2((PRINT_PREFIX
7604 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
7605 // Indicate no device found at this address.
7606 #ifndef NAVO_TEST
7607 status = SRB_STATUS_SELECTION_TIMEOUT;
7608 break;
7609 }
7610 } else {
7611 if(!UniataAnybodyHome(HwDeviceExtension, lChannel, DeviceNumber)) {
7612 KdPrint2((PRINT_PREFIX
7613 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
7614 // Indicate no device found at this address.
7615 UniataForgetDevice(chan->lun[DeviceNumber]);
7616 #endif //NAVO_TEST
7617 status = SRB_STATUS_SELECTION_TIMEOUT;
7618 break;
7619 }
7620 }
7621
7622 // Zero INQUIRY data structure.
7623 RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength);
7624
7625 // Standard IDE interface only supports disks.
7626 inquiryData->DeviceType = DIRECT_ACCESS_DEVICE;
7627
7628 // Set the removable bit, if applicable.
7629 if (LunExt->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) {
7630 KdPrint2((PRINT_PREFIX
7631 "RemovableMedia\n"));
7632 inquiryData->RemovableMedia = 1;
7633 }
7634 // Set the Relative Addressing (LBA) bit, if applicable.
7635 if (LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
7636 inquiryData->RelativeAddressing = 1;
7637 KdPrint2((PRINT_PREFIX
7638 "RelativeAddressing\n"));
7639 }
7640 // Set the CommandQueue bit
7641 inquiryData->CommandQueue = 1;
7642
7643 // Fill in vendor identification fields.
7644 for (i = 0; i < 24; i += 2) {
7645 MOV_DW_SWP(inquiryData->VendorId[i], ((PUCHAR)identifyData->ModelNumber)[i]);
7646 }
7647 /*
7648 // Initialize unused portion of product id.
7649 for (i = 0; i < 4; i++) {
7650 inquiryData->ProductId[12+i] = ' ';
7651 }
7652 */
7653 // Move firmware revision from IDENTIFY data to
7654 // product revision in INQUIRY data.
7655 for (i = 0; i < 4; i += 2) {
7656 MOV_DW_SWP(inquiryData->ProductRevisionLevel[i], ((PUCHAR)identifyData->FirmwareRevision)[i]);
7657 }
7658
7659 status = SRB_STATUS_SUCCESS;
7660 }
7661
7662 break;
7663
7664 case SCSIOP_REPORT_LUNS: {
7665
7666 ULONG alen;
7667 PREPORT_LUNS_INFO_HDR LunInfo;
7668
7669 KdPrint2((PRINT_PREFIX
7670 "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
7671 Srb->PathId, Srb->Lun, Srb->TargetId));
7672
7673 MOV_DD_SWP(alen, cdb->REPORT_LUNS.AllocationLength);
7674
7675 if(alen < 16) {
7676 goto invalid_cdb;
7677 }
7678 alen = 8;
7679
7680 LunInfo = (PREPORT_LUNS_INFO_HDR)(Srb->DataBuffer);
7681 RtlZeroMemory(LunInfo, 16);
7682
7683 MOV_DD_SWP( LunInfo->ListLength, alen );
7684 Srb->DataTransferLength = 16;
7685 status = SRB_STATUS_SUCCESS;
7686
7687 break; }
7688
7689 case SCSIOP_MODE_SENSE:
7690
7691 KdPrint2((PRINT_PREFIX
7692 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
7693 Srb->PathId, Srb->Lun, Srb->TargetId));
7694
7695 if(cdb->MODE_SENSE.PageCode == MODE_PAGE_POWER_CONDITION) {
7696 PMODE_POWER_CONDITION_PAGE modeData;
7697
7698 KdPrint2((PRINT_PREFIX "MODE_PAGE_POWER_CONDITION\n"));
7699 modeData = (PMODE_POWER_CONDITION_PAGE)(Srb->DataBuffer);
7700 if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_POWER_CONDITION_PAGE)) {
7701 status = SRB_STATUS_DATA_OVERRUN;
7702 } else {
7703 RtlZeroMemory(modeData, sizeof(MODE_POWER_CONDITION_PAGE));
7704 modeData->PageCode = MODE_PAGE_POWER_CONDITION;
7705 modeData->PageLength = sizeof(MODE_PAGE_POWER_CONDITION)-sizeof(MODE_PARAMETER_HEADER);
7706 modeData->Byte3.Fields.Idle = LunExt->PowerState <= StartStop_Power_Idle;
7707 modeData->Byte3.Fields.Standby = LunExt->PowerState == StartStop_Power_Standby;
7708 Srb->DataTransferLength = sizeof(MODE_POWER_CONDITION_PAGE);
7709 status = SRB_STATUS_SUCCESS;
7710 }
7711 } else
7712 if(cdb->MODE_SENSE.PageCode == MODE_PAGE_CACHING) {
7713 PMODE_CACHING_PAGE modeData;
7714
7715 KdPrint2((PRINT_PREFIX "MODE_PAGE_CACHING\n"));
7716 modeData = (PMODE_CACHING_PAGE)(Srb->DataBuffer);
7717 if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_CACHING_PAGE)) {
7718 status = SRB_STATUS_DATA_OVERRUN;
7719 } else {
7720 RtlZeroMemory(modeData, sizeof(MODE_CACHING_PAGE));
7721 modeData->PageCode = MODE_PAGE_CACHING;
7722 modeData->PageLength = sizeof(MODE_CACHING_PAGE)-sizeof(MODE_PARAMETER_HEADER);
7723 modeData->ReadDisableCache = (LunExt->DeviceFlags & DFLAGS_RCACHE_ENABLED) ? 0 : 1;
7724 modeData->WriteCacheEnable = (LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) ? 1 : 0;
7725 Srb->DataTransferLength = sizeof(MODE_CACHING_PAGE);
7726 status = SRB_STATUS_SUCCESS;
7727 }
7728 } else
7729 if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
7730
7731 // This is used to determine if the media is write-protected.
7732 // Since IDE does not support mode sense then we will modify just the portion we need
7733 // so the higher level driver can determine if media is protected.
7734
7735 //SelectDrive(chan, DeviceNumber);
7736 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7737 //statusByte = WaitOnBusy(chan);
7738 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY);
7739
7740 if (!(statusByte & IDE_STATUS_ERROR)) {
7741
7742 // no error occured return success, media is not protected
7743 UniataExpectChannelInterrupt(chan, FALSE);
7744 InterlockedExchange(&(chan->CheckIntr),
7745 CHECK_INTR_IDLE);
7746 status = SRB_STATUS_SUCCESS;
7747
7748 } else {
7749
7750 // error occured, handle it locally, clear interrupt
7751 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7752
7753 GetBaseStatus(chan, statusByte);
7754 UniataExpectChannelInterrupt(chan, FALSE);
7755 InterlockedExchange(&(chan->CheckIntr),
7756 CHECK_INTR_IDLE);
7757 status = SRB_STATUS_SUCCESS;
7758
7759 if (errorByte & IDE_ERROR_DATA_ERROR) {
7760
7761 //media is write-protected, set bit in mode sense buffer
7762 modeData = (PMODE_PARAMETER_HEADER)Srb->DataBuffer;
7763
7764 Srb->DataTransferLength = sizeof(MODE_PARAMETER_HEADER);
7765 modeData->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
7766 }
7767 }
7768 status = SRB_STATUS_SUCCESS;
7769 } else {
7770 status = SRB_STATUS_INVALID_REQUEST;
7771 }
7772 break;
7773
7774 case SCSIOP_TEST_UNIT_READY:
7775
7776 KdPrint2((PRINT_PREFIX
7777 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
7778 Srb->PathId, Srb->Lun, Srb->TargetId));
7779 if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
7780
7781 // Select device 0 or 1.
7782 //SelectDrive(chan, DeviceNumber);
7783 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7784 // Wait for busy. If media has not changed, return success
7785 //statusByte = WaitOnBusy(chan);
7786 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY);
7787
7788 if (!(statusByte & IDE_STATUS_ERROR)){
7789 UniataExpectChannelInterrupt(chan, FALSE);
7790 InterlockedExchange(&(chan->CheckIntr),
7791 CHECK_INTR_IDLE);
7792 status = SRB_STATUS_SUCCESS;
7793 } else {
7794 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7795 if (errorByte == IDE_ERROR_DATA_ERROR){
7796
7797 // Special case: If current media is write-protected,
7798 // the 0xDA command will always fail since the write-protect bit
7799 // is sticky,so we can ignore this error
7800 GetBaseStatus(chan, statusByte);
7801 UniataExpectChannelInterrupt(chan, FALSE);
7802 InterlockedExchange(&(chan->CheckIntr),
7803 CHECK_INTR_IDLE);
7804 status = SRB_STATUS_SUCCESS;
7805
7806 } else {
7807
7808 // Request sense buffer to be build
7809 UniataExpectChannelInterrupt(chan, TRUE);
7810 InterlockedExchange(&(chan->CheckIntr),
7811 CHECK_INTR_IDLE);
7812 status = SRB_STATUS_PENDING;
7813 }
7814 }
7815 } else {
7816 status = SRB_STATUS_SUCCESS;
7817 }
7818
7819 break;
7820
7821 case SCSIOP_READ_CAPACITY:
7822
7823 KdPrint2((PRINT_PREFIX
7824 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7825 Srb->PathId, Srb->Lun, Srb->TargetId));
7826 // Claim 512 byte blocks (big-endian).
7827 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7828 i = DEV_BSIZE;
7829 RtlZeroMemory(Srb->DataBuffer, sizeof(READ_CAPACITY_DATA));
7830 MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock, i );
7831
7832 // Calculate last sector.
7833 if(!(i = (ULONG)LunExt->NumOfSectors)) {
7834 i = LunExt->IdentifyData.SectorsPerTrack *
7835 LunExt->IdentifyData.NumberOfHeads *
7836 LunExt->IdentifyData.NumberOfCylinders;
7837 }
7838 i--;
7839
7840 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
7841 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
7842 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
7843
7844 MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress, i );
7845
7846 KdPrint2((PRINT_PREFIX
7847 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
7848 Srb->TargetId,
7849 LunExt->IdentifyData.SectorsPerTrack,
7850 LunExt->IdentifyData.NumberOfHeads,
7851 LunExt->IdentifyData.NumberOfCylinders));
7852
7853
7854 status = SRB_STATUS_SUCCESS;
7855 break;
7856
7857 case SCSIOP_SERVICE_ACTION16:
7858
7859 if( cdb->SERVICE_ACTION16.ServiceAction==SCSIOP_SA_READ_CAPACITY16 ) {
7860 KdPrint2((PRINT_PREFIX
7861 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7862 Srb->PathId, Srb->Lun, Srb->TargetId));
7863 // Claim 512 byte blocks (big-endian).
7864 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7865 i = DEV_BSIZE;
7866 RtlZeroMemory(Srb->DataBuffer, sizeof(READ_CAPACITY16_DATA));
7867 MOV_DD_SWP( ((PREAD_CAPACITY16_DATA)Srb->DataBuffer)->BytesPerBlock, i );
7868
7869 // Calculate last sector.
7870 if(!(lba = LunExt->NumOfSectors)) {
7871 lba = LunExt->IdentifyData.SectorsPerTrack *
7872 LunExt->IdentifyData.NumberOfHeads *
7873 LunExt->IdentifyData.NumberOfCylinders;
7874 }
7875 lba--;
7876 MOV_QD_SWP( ((PREAD_CAPACITY16_DATA)Srb->DataBuffer)->LogicalBlockAddress, lba );
7877
7878 KdPrint2((PRINT_PREFIX
7879 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n",
7880 Srb->TargetId,
7881 LunExt->IdentifyData.SectorsPerTrack,
7882 LunExt->IdentifyData.NumberOfHeads,
7883 LunExt->IdentifyData.NumberOfCylinders));
7884
7885 status = SRB_STATUS_SUCCESS;
7886 } else {
7887 goto default_abort;
7888 }
7889 break;
7890
7891 case SCSIOP_VERIFY:
7892 case SCSIOP_VERIFY12:
7893 case SCSIOP_VERIFY16:
7894
7895 KdPrint2((PRINT_PREFIX
7896 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
7897 Srb->PathId, Srb->Lun, Srb->TargetId));
7898 status = IdeVerify(HwDeviceExtension,Srb);
7899
7900 break;
7901
7902 case SCSIOP_READ:
7903 case SCSIOP_WRITE:
7904 case SCSIOP_READ12:
7905 case SCSIOP_WRITE12:
7906 case SCSIOP_READ16:
7907 case SCSIOP_WRITE16:
7908
7909 KdPrint2((PRINT_PREFIX
7910 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
7911 (Srb->Cdb[0] == SCSIOP_WRITE) ? "WRITE" : "READ",
7912 Srb->PathId, Srb->Lun, Srb->TargetId));
7913 AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
7914 AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE ||
7915 Srb->Cdb[0] == SCSIOP_WRITE12 ||
7916 Srb->Cdb[0] == SCSIOP_WRITE16) ? REQ_FLAG_WRITE : REQ_FLAG_READ;
7917 status = IdeReadWrite(HwDeviceExtension,
7918 Srb, CmdAction);
7919 break;
7920
7921 case SCSIOP_START_STOP_UNIT:
7922
7923 KdPrint2((PRINT_PREFIX
7924 "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
7925 cdb->START_STOP.Immediate, Srb->PathId, Srb->Lun, Srb->TargetId));
7926 //Determine what type of operation we should perform
7927
7928 command = 0;
7929
7930 if(cdb->START_STOP.FL ||
7931 cdb->START_STOP.FormatLayerNumber ||
7932 cdb->START_STOP.Reserved2 ||
7933 cdb->START_STOP.Reserved2_2 ||
7934 cdb->START_STOP.Reserved3 ||
7935 FALSE) {
7936 goto invalid_cdb;
7937 }
7938
7939 if (cdb->START_STOP.PowerConditions) {
7940 KdPrint2((PRINT_PREFIX "START_STOP Power %d\n", cdb->START_STOP.PowerConditions));
7941 switch(cdb->START_STOP.PowerConditions) {
7942 case StartStop_Power_Idle:
7943 command = IDE_COMMAND_IDLE_IMMED;
7944 break;
7945 case StartStop_Power_Standby:
7946 command = IDE_COMMAND_STANDBY_IMMED;
7947 break;
7948 case StartStop_Power_Sleep:
7949 // TODO: we should save power state in order to know
7950 // that RESET sould be issued to revert device into
7951 // operable state
7952
7953 command = IDE_COMMAND_SLEEP;
7954 break;
7955 default:
7956 goto invalid_cdb;
7957 }
7958 LunExt->PowerState = cdb->START_STOP.PowerConditions;
7959 } else
7960 if (cdb->START_STOP.LoadEject == 1) {
7961 KdPrint2((PRINT_PREFIX "START_STOP eject\n"));
7962 // Eject media,
7963 // first select device 0 or 1.
7964 //SelectDrive(chan, DeviceNumber);
7965 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
7966 command = IDE_COMMAND_MEDIA_EJECT;
7967 } else
7968 if (cdb->START_STOP.Start == 0) {
7969 KdPrint2((PRINT_PREFIX "START_STOP standby\n"));
7970 command = IDE_COMMAND_STANDBY_IMMED;
7971 } else {
7972 // TODO: we may need to perform hard reset (after sleep) or
7973 // issue IDE_COMMAND_IDLE_IMMED in order to activate device
7974 KdPrint2((PRINT_PREFIX "START_STOP activate\n"));
7975
7976 if(LunExt->PowerState == StartStop_Power_Sleep) {
7977 UniataUserDeviceReset(deviceExtension, LunExt, lChannel);
7978 status = SRB_STATUS_SUCCESS;
7979 break;
7980 } else
7981 if(LunExt->PowerState > StartStop_Power_Idle) {
7982 KdPrint2((PRINT_PREFIX " issue IDLE\n"));
7983 command = IDE_COMMAND_IDLE_IMMED;
7984 } else {
7985 KdPrint2((PRINT_PREFIX " do nothing\n"));
7986 status = SRB_STATUS_SUCCESS;
7987 break;
7988 }
7989 }
7990 if(command) {
7991 statusByte = WaitOnBaseBusy(chan);
7992 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, command, 0, 0, 0, 0, 0,
7993 cdb->START_STOP.Immediate ? ATA_IMMEDIATE : ATA_WAIT_READY);
7994 status = (statusByte & IDE_STATUS_ERROR) ? SRB_STATUS_ERROR : SRB_STATUS_SUCCESS;
7995 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
7996
7997 } else {
7998 invalid_cdb:
7999 KdPrint2((PRINT_PREFIX "START_STOP invalid\n"));
8000 if (Srb->SenseInfoBuffer) {
8001
8002 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
8003
8004 senseBuffer->ErrorCode = 0x70;
8005 senseBuffer->Valid = 1;
8006 senseBuffer->AdditionalSenseLength = 0xb;
8007 senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST;
8008 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_CDB;
8009 senseBuffer->AdditionalSenseCodeQualifier = 0;
8010
8011 Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID;
8012 Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
8013 }
8014 status = SRB_STATUS_ERROR;
8015 }
8016 break;
8017
8018 case SCSIOP_MEDIUM_REMOVAL:
8019
8020 cdb = (PCDB)Srb->Cdb;
8021
8022 if(LunExt->IdentifyData.Removable) {
8023 statusByte = WaitOnBaseBusy(chan);
8024
8025 //SelectDrive(chan, DeviceNumber);
8026 if (cdb->MEDIA_REMOVAL.Prevent == TRUE) {
8027 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
8028 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_LOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
8029 } else {
8030 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
8031 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_UNLOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
8032 }
8033 status = SRB_STATUS_SUCCESS;
8034 } else {
8035 status = SRB_STATUS_INVALID_REQUEST;
8036 }
8037 break;
8038
8039 #if 0
8040 // Note: I don't implement this, because NTFS driver too often issues this command
8041 // It causes awful performance degrade. However, if somebody wants, I will implement
8042 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
8043 case SCSIOP_FLUSH_BUFFER:
8044 case SCSIOP_SYNCHRONIZE_CACHE:
8045
8046 SelectDrive(chan, DeviceNumber);
8047 AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_FLUSH_CACHE);
8048 status = SRB_STATUS_SUCCESS;
8049 // status = SRB_STATUS_PENDING;
8050 statusByte = WaitOnBusy(chan);
8051 break;
8052 #endif
8053
8054 case SCSIOP_REQUEST_SENSE:
8055 // this function makes sense buffers to report the results
8056 // of the original GET_MEDIA_STATUS command
8057
8058 KdPrint2((PRINT_PREFIX
8059 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8060 Srb->PathId, Srb->Lun, Srb->TargetId));
8061 if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
8062 status = IdeBuildSenseBuffer(HwDeviceExtension,Srb);
8063 break;
8064 }
8065 status = SRB_STATUS_INVALID_REQUEST;
8066 break;
8067
8068 // ATA_PASSTHORUGH
8069 case SCSIOP_ATA_PASSTHROUGH:
8070 {
8071 PIDEREGS_EX regs;
8072 BOOLEAN use_dma = FALSE;
8073 ULONG to_lim;
8074
8075 regs = (PIDEREGS_EX) &(Srb->Cdb[2]);
8076
8077 if(chan->DeviceExtension->HwFlags & UNIATA_SATA) {
8078 //lChannel = Srb->TargetId >> 1;
8079 } else {
8080 DeviceNumber = max(DeviceNumber, 1);
8081 regs->bDriveHeadReg &= 0x0f;
8082 regs->bDriveHeadReg |= (UCHAR) (((DeviceNumber & 0x1) << 4) | 0xA0);
8083 }
8084
8085 if((regs->bOpFlags & 1) == 0) { // execute ATA command
8086
8087 KdPrint2((PRINT_PREFIX
8088 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
8089 Srb->PathId, Srb->Lun, Srb->TargetId));
8090
8091 if((regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) == UNIATA_SPTI_EX_SPEC_TO) {
8092 to_lim = Srb->TimeOutValue;
8093 } else {
8094 if(Srb->TimeOutValue <= 2) {
8095 to_lim = Srb->TimeOutValue*900;
8096 } else {
8097 to_lim = (Srb->TimeOutValue*999) - 500;
8098 }
8099 }
8100
8101 AtapiDisableInterrupts(deviceExtension, lChannel);
8102
8103 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
8104 // AHCI
8105 statusByte = UniataAhciSendPIOCommandDirect(
8106 deviceExtension,
8107 lChannel,
8108 DeviceNumber,
8109 Srb,
8110 regs,
8111 ATA_WAIT_INTR,
8112 to_lim
8113 );
8114 if(statusByte == IDE_STATUS_WRONG) {
8115 goto passthrough_err;
8116 }
8117 if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
8118 UniataAhciAbortOperation(chan);
8119 goto passthrough_err;
8120 }
8121 goto passthrough_done;
8122 }
8123
8124 // SATA/PATA
8125 if((AtaCommandFlags[regs->bCommandReg] & ATA_CMD_FLAG_DMA) || (regs->bOpFlags & UNIATA_SPTI_EX_USE_DMA)) {
8126 if((chan->lun[DeviceNumber]->LimitedTransferMode >= ATA_DMA)) {
8127 use_dma = TRUE;
8128 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
8129 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
8130 (PUCHAR)(Srb->DataBuffer),
8131 ((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1)))) {
8132 use_dma = FALSE;
8133 }
8134 }
8135 }
8136
8137 AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, regs->bDriveHeadReg);
8138 AtapiStallExecution(10);
8139
8140 if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { // execute ATA command
8141 AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesReg);
8142 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountReg);
8143 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberReg);
8144 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowReg);
8145 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg);
8146 } else {
8147 AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesRegH);
8148 AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesReg);
8149 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountRegH);
8150 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountReg);
8151 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberRegH);
8152 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberReg);
8153 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowRegH);
8154 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowReg);
8155 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighRegH);
8156 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg);
8157 }
8158 AtapiWritePort1(chan, IDX_IO1_o_Command, regs->bCommandReg);
8159
8160 if(use_dma) {
8161 GetBaseStatus(chan, statusByte);
8162 if(statusByte & IDE_STATUS_ERROR) {
8163 goto passthrough_err;
8164 }
8165 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
8166 }
8167
8168 ScsiPortStallExecution(1); // wait for busy to be set
8169
8170 for(i=0; i<to_lim;i+=2) { // 2 msec from WaitOnBaseBusy()
8171 statusByte = WaitOnBaseBusy(chan); // wait for busy to be clear, up to 2 msec
8172 GetBaseStatus(chan, statusByte);
8173 if(statusByte & IDE_STATUS_ERROR) {
8174 break;
8175 }
8176 if(!(statusByte & IDE_STATUS_BUSY)) {
8177 break;
8178 }
8179 }
8180 if(i >= to_lim) {
8181 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
8182 //}
8183 AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_NONE);
8184 goto passthrough_err;
8185 }
8186
8187 if(use_dma) {
8188 AtapiCheckInterrupt__(deviceExtension, (UCHAR)lChannel);
8189 }
8190 AtapiDmaDone(deviceExtension, DeviceNumber, lChannel, NULL);
8191 GetBaseStatus(chan, statusByte);
8192
8193 if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
8194 AtapiSuckPort2(chan);
8195 passthrough_err:
8196 if (Srb->SenseInfoBuffer) {
8197
8198 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
8199
8200 senseBuffer->ErrorCode = 0x70;
8201 senseBuffer->Valid = 1;
8202 senseBuffer->AdditionalSenseLength = 0xb;
8203 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
8204 senseBuffer->AdditionalSenseCode = 0;
8205 senseBuffer->AdditionalSenseCodeQualifier = 0;
8206
8207 Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID;
8208 Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
8209 }
8210 status = SRB_STATUS_ERROR;
8211 } else {
8212
8213 if(!use_dma) {
8214 if (statusByte & IDE_STATUS_DRQ) {
8215 if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
8216 ReadBuffer(chan,
8217 (PUSHORT) Srb->DataBuffer,
8218 Srb->DataTransferLength / 2,
8219 0);
8220 } else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
8221 WriteBuffer(chan,
8222 (PUSHORT) Srb->DataBuffer,
8223 Srb->DataTransferLength / 2,
8224 0);
8225 }
8226 }
8227 }
8228 status = SRB_STATUS_SUCCESS;
8229 }
8230 passthrough_done:;
8231 AtapiEnableInterrupts(deviceExtension, lChannel);
8232
8233 } else { // read task register
8234
8235 BOOLEAN use48;
8236 regs = (PIDEREGS_EX) Srb->DataBuffer;
8237
8238 KdPrint2((PRINT_PREFIX
8239 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
8240 Srb->PathId, Srb->Lun, Srb->TargetId));
8241
8242 if((Srb->DataTransferLength >= sizeof(IDEREGS_EX)) &&
8243 (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND)) {
8244 use48 = TRUE;
8245 } else
8246 if(Srb->DataTransferLength >= sizeof(IDEREGS)) {
8247 use48 = FALSE;
8248 } else {
8249 KdPrint2((PRINT_PREFIX " buffer too small \n"));
8250 status = SRB_STATUS_DATA_OVERRUN;
8251 break;
8252 }
8253 RtlZeroMemory(regs, use48 ? sizeof(IDEREGS_EX) : sizeof(IDEREGS));
8254 regs->bOpFlags = use48 ? ATA_FLAGS_48BIT_COMMAND : 0;
8255 UniataSnapAtaRegs(chan, 0, regs);
8256
8257 status = SRB_STATUS_SUCCESS;
8258 }
8259 break;
8260 }
8261
8262 default:
8263 default_abort:
8264 KdPrint2((PRINT_PREFIX
8265 "IdeSendCommand: Unsupported command %#x\n",
8266 Srb->Cdb[0]));
8267
8268 status = SRB_STATUS_INVALID_REQUEST;
8269
8270 } // end switch
8271
8272 if(status == SRB_STATUS_PENDING) {
8273 KdPrint2((PRINT_PREFIX "IdeSendCommand: SRB_STATUS_PENDING\n"));
8274 if(CmdAction & CMD_ACTION_EXEC) {
8275 KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
8276 AtaReq->ReqState = REQ_STATE_EXPECTING_INTR;
8277 }
8278 } else {
8279 KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
8280 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
8281 }
8282
8283 return status;
8284
8285 } // end IdeSendCommand()
8286
8287
8288 /*++
8289
8290 Routine Description:
8291 Enables disables media status notification
8292
8293 Arguments:
8294 HwDeviceExtension - ATAPI driver storage.
8295
8296 --*/
8297 VOID
8298 NTAPI
8299 IdeMediaStatus(
8300 BOOLEAN EnableMSN,
8301 IN PVOID HwDeviceExtension,
8302 IN ULONG lChannel,
8303 IN ULONG DeviceNumber
8304 )
8305 {
8306 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
8307 PHW_CHANNEL chan;
8308 UCHAR statusByte,errorByte;
8309
8310 chan = &(deviceExtension->chan[lChannel]);
8311 SelectDrive(chan, DeviceNumber);
8312
8313 if (EnableMSN == TRUE){
8314
8315 // If supported enable Media Status Notification support
8316 if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_REMOVABLE_DRIVE)) {
8317
8318 // enable
8319 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
8320 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
8321 0, ATA_C_F_ENAB_MEDIASTAT, ATA_WAIT_BASE_READY);
8322
8323 if (statusByte & IDE_STATUS_ERROR) {
8324 // Read the error register.
8325 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
8326
8327 KdPrint2((PRINT_PREFIX
8328 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
8329 statusByte,
8330 errorByte));
8331 } else {
8332 chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_MEDIA_STATUS_ENABLED;
8333 KdPrint2((PRINT_PREFIX "IdeMediaStatus: Media Status Notification Supported\n"));
8334 chan->ReturningMediaStatus = 0;
8335
8336 }
8337
8338 }
8339 } else { // end if EnableMSN == TRUE
8340
8341 // disable if previously enabled
8342 if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)) {
8343
8344 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
8345 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
8346 0, ATA_C_F_DIS_MEDIASTAT, ATA_WAIT_BASE_READY);
8347 chan->lun[DeviceNumber]->DeviceFlags &= ~DFLAGS_MEDIA_STATUS_ENABLED;
8348 }
8349
8350
8351 }
8352
8353
8354 } // end IdeMediaStatus()
8355
8356
8357 /*++
8358
8359 Routine Description:
8360
8361 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
8362 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
8363 Arguments:
8364
8365 HwDeviceExtension - ATAPI driver storage.
8366 Srb - System request block.
8367
8368 Return Value:
8369
8370 SRB status (ALWAYS SUCCESS).
8371
8372 --*/
8373 ULONG
8374 NTAPI
8375 IdeBuildSenseBuffer(
8376 IN PVOID HwDeviceExtension,
8377 IN PSCSI_REQUEST_BLOCK Srb
8378 )
8379 {
8380 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
8381 // ULONG status;
8382 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->DataBuffer;
8383 UCHAR ReturningMediaStatus = deviceExtension->chan[GET_CHANNEL(Srb)].ReturningMediaStatus;
8384
8385 if (senseBuffer){
8386
8387 if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE) {
8388
8389 senseBuffer->ErrorCode = 0x70;
8390 senseBuffer->Valid = 1;
8391 senseBuffer->AdditionalSenseLength = 0xb;
8392 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
8393 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
8394 senseBuffer->AdditionalSenseCodeQualifier = 0;
8395 } else if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE_REQ) {
8396
8397 senseBuffer->ErrorCode = 0x70;
8398 senseBuffer->Valid = 1;
8399 senseBuffer->AdditionalSenseLength = 0xb;
8400 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
8401 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
8402 senseBuffer->AdditionalSenseCodeQualifier = 0;
8403 } else if(ReturningMediaStatus & IDE_ERROR_END_OF_MEDIA) {
8404
8405 senseBuffer->ErrorCode = 0x70;
8406 senseBuffer->Valid = 1;
8407 senseBuffer->AdditionalSenseLength = 0xb;
8408 senseBuffer->SenseKey = SCSI_SENSE_NOT_READY;
8409 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
8410 senseBuffer->AdditionalSenseCodeQualifier = 0;
8411 } else if(ReturningMediaStatus & IDE_ERROR_DATA_ERROR) {
8412
8413 senseBuffer->ErrorCode = 0x70;
8414 senseBuffer->Valid = 1;
8415 senseBuffer->AdditionalSenseLength = 0xb;
8416 senseBuffer->SenseKey = SCSI_SENSE_DATA_PROTECT;
8417 senseBuffer->AdditionalSenseCode = 0;
8418 senseBuffer->AdditionalSenseCodeQualifier = 0;
8419 }
8420 return SRB_STATUS_SUCCESS;
8421 }
8422 return SRB_STATUS_ERROR;
8423
8424 }// End of IdeBuildSenseBuffer
8425
8426 VOID
8427 NTAPI
8428 UniataUserDeviceReset(
8429 PHW_DEVICE_EXTENSION deviceExtension,
8430 PHW_LU_EXTENSION LunExt,
8431 ULONG lChannel
8432 )
8433 {
8434 ULONG i;
8435 AtapiDisableInterrupts(deviceExtension, lChannel);
8436 if ((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
8437 (LunExt->PowerState != StartStop_Power_Sleep)) {
8438 KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset ATAPI\n"));
8439 AtapiSoftReset(&(deviceExtension->chan[lChannel]), LunExt->Lun);
8440 } else {
8441 KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
8442 AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_NONE);
8443 for(i=0; i<deviceExtension->NumberLuns; i++) {
8444 deviceExtension->chan[lChannel].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
8445 }
8446 }
8447 LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit
8448 AtapiEnableInterrupts(deviceExtension, lChannel);
8449 return;
8450 } // end UniataUserDeviceReset()
8451
8452 BOOLEAN
8453 NTAPI
8454 UniataNeedQueueing(
8455 PHW_DEVICE_EXTENSION deviceExtension,
8456 PHW_CHANNEL chan,
8457 BOOLEAN TopLevel
8458 )
8459 {
8460 BOOLEAN PostReq = FALSE;
8461 if(TopLevel) {
8462 KdPrint3((PRINT_PREFIX "UniataNeedQueueing: TopLevel, qd=%x\n", chan->queue_depth));
8463 if(chan->queue_depth > 0) {
8464 #if 0
8465 if(atapiDev &&
8466 ((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY)/* ||
8467 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
8468 KdPrint2((PRINT_PREFIX "spec: SCSIOP_TEST_UNIT_READY\n"));
8469 //PostReq = FALSE;
8470 status = SRB_STATUS_BUSY;
8471 goto skip_exec;
8472 } else {
8473 PostReq = TRUE;
8474 }
8475 #else
8476 PostReq = TRUE;
8477 #endif
8478 } else
8479 if(deviceExtension->simplexOnly && deviceExtension->queue_depth > 0) {
8480 PostReq = TRUE;
8481 }
8482 } else {
8483 KdPrint3((PRINT_PREFIX "UniataNeedQueueing: qd=%x\n", chan->queue_depth));
8484 }
8485 return PostReq;
8486 } // end UniataNeedQueueing()
8487
8488 /*++
8489
8490 Routine Description:
8491
8492 This routine is called from the SCSI port driver synchronized
8493 with the kernel to start an IO request.
8494 ->HwStartIo
8495
8496 Arguments:
8497
8498 HwDeviceExtension - HBA miniport driver's adapter data storage
8499 Srb - IO request packet
8500
8501 Return Value:
8502
8503 TRUE
8504
8505 --*/
8506 BOOLEAN
8507 NTAPI
8508 AtapiStartIo(
8509 IN PVOID HwDeviceExtension,
8510 IN PSCSI_REQUEST_BLOCK Srb
8511 )
8512 {
8513 return AtapiStartIo__(HwDeviceExtension, Srb, TRUE);
8514 } // end AtapiStartIo()
8515
8516 BOOLEAN
8517 NTAPI
8518 AtapiStartIo__(
8519 IN PVOID HwDeviceExtension,
8520 IN PSCSI_REQUEST_BLOCK Srb,
8521 IN BOOLEAN TopLevel
8522 )
8523 {
8524 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
8525 UCHAR lChannel;
8526 PHW_CHANNEL chan;
8527 PHW_LU_EXTENSION LunExt;
8528 ULONG status;
8529 //ULONG ldev;
8530 ULONG DeviceNumber;
8531 UCHAR PathId;
8532 UCHAR TargetId;
8533 UCHAR Lun;
8534 PATA_REQ AtaReq;
8535 PSCSI_REQUEST_BLOCK tmpSrb;
8536 BOOLEAN PostReq = FALSE;
8537 BOOLEAN atapiDev;
8538 BOOLEAN commPort = FALSE;
8539
8540 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
8541 if(deviceExtension->Isr2DevObj && !BMList[deviceExtension->DevIndex].Isr2Enable) {
8542 KdPrint2((PRINT_PREFIX "Isr2Enable -> 1\n"));
8543 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
8544 }
8545 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
8546
8547 /* KeBugCheckEx(0xc000000e,
8548 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8549 Srb->Function,
8550 TopLevel, 0x80000001);
8551 */
8552 if(TopLevel && Srb && Srb->SrbExtension) {
8553 KdPrint2((PRINT_PREFIX "TopLevel\n"));
8554 //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
8555 UniAtaClearAtaReq(Srb->SrbExtension);
8556 }
8557
8558 do { // fetch all queued commands for the channel (if valid)
8559
8560 lChannel = GET_CHANNEL(Srb);
8561 //ldev = GET_LDEV(Srb);
8562 chan = NULL;
8563 LunExt = NULL;
8564 DeviceNumber = GET_CDEV(Srb);
8565 commPort = FALSE;
8566
8567 //ASSERT(deviceExtension);
8568 //ASSERT(chan);
8569
8570 KdPrint2((PRINT_PREFIX
8571 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8572 Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId));
8573 KdPrint2((PRINT_PREFIX " VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
8574
8575 if(lChannel == deviceExtension->NumberChannels &&
8576 !Srb->Lun && !Srb->TargetId &&
8577 ((Srb->Function == SRB_FUNCTION_IO_CONTROL) ||
8578 (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI && Srb->Cdb[0] == SCSIOP_INQUIRY))
8579 ) {
8580 // This is our virtual device
8581 KdPrint2((PRINT_PREFIX
8582 "AtapiStartIo: Communication port\n"));
8583 if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
8584
8585 if(Srb->DataTransferLength < sizeof(PINQUIRYDATA)) {
8586 KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", Srb->DataTransferLength,
8587 sizeof(PINQUIRYDATA) ));
8588 wrong_buffer_size:
8589 status = SRB_STATUS_DATA_OVERRUN;
8590 goto complete_req;
8591 }
8592
8593 PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer);
8594
8595 KdPrint2((PRINT_PREFIX
8596 " INQUIRY\n"));
8597 // Zero INQUIRY data structure.
8598 RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength);
8599
8600 inquiryData->DeviceType = COMMUNICATION_DEVICE;
8601
8602 // Fill in vendor identification fields.
8603 RtlCopyMemory(&inquiryData->VendorId, &uniata_comm_name, 28);
8604
8605 status = SRB_STATUS_SUCCESS;
8606 goto complete_req;
8607 }
8608 commPort = TRUE;
8609 /* Pass IOCTL request down */
8610 } else
8611 if(lChannel >= deviceExtension->NumberChannels ||
8612 Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns ||
8613 Srb->Lun) {
8614
8615 if(lChannel >= deviceExtension->NumberChannels) {
8616 chan = NULL;
8617 }
8618
8619 reject_srb:
8620 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8621 KdPrint3((PRINT_PREFIX
8622 "AtapiStartIo: SRB rejected\n"));
8623 // Indicate no device found at this address.
8624 KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
8625 status = SRB_STATUS_SELECTION_TIMEOUT;
8626 goto complete_req;
8627 //}
8628 } else
8629 if((deviceExtension->HwFlags & UNIATA_AHCI) &&
8630 !UniataAhciChanImplemented(deviceExtension, lChannel)) {
8631 chan = NULL;
8632 }
8633
8634 if(!commPort) {
8635 chan = &(deviceExtension->chan[lChannel]);
8636 LunExt = chan->lun[DeviceNumber];
8637 if(!LunExt) {
8638 goto reject_srb;
8639 }
8640 atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
8641 } else {
8642 atapiDev = FALSE;
8643 }
8644
8645 #ifdef _DEBUG
8646 if(!commPort && !LunExt) {
8647 #if 0
8648 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
8649 deviceExtension,
8650 chan, DeviceNumber,
8651 deviceExtension->NumberChannels);
8652 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
8653 lChannel, GET_CDEV(Srb), deviceExtension->chan[0].lun[0]);
8654 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8655 Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId);
8656 #endif //0
8657 /*
8658 int i;
8659 for(i=0; i<1000; i++) {
8660 AtapiStallExecution(3*1000);
8661 }
8662 */
8663 goto reject_srb;
8664 }
8665 #endif //_DEBUG
8666
8667 // Determine which function.
8668 switch (Srb->Function) {
8669
8670 case SRB_FUNCTION_EXECUTE_SCSI:
8671
8672 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
8673 if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) {
8674 // let passthrough go
8675 } else
8676 if(Srb->Cdb[0] == SCSIOP_INQUIRY) {
8677 // let INQUIRY go
8678 } else {
8679
8680 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8681 KdPrint2((PRINT_PREFIX
8682 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
8683 // Indicate no device found at this address.
8684 KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
8685 status = SRB_STATUS_SELECTION_TIMEOUT;
8686 break;
8687 //}
8688 }
8689 } else {
8690 KdPrint2((PRINT_PREFIX
8691 " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb, &(Srb->Cdb), Srb->SrbExtension, Srb->Cdb[0]));
8692 }
8693 /*
8694 __try {
8695 if(Srb->DataTransferLength) {
8696 UCHAR a;
8697 a = ((PUCHAR)(Srb->DataBuffer))[0];
8698 g_foo += a;
8699 }
8700 } __except(EXCEPTION_EXECUTE_HANDLER) {
8701 KdPrint3((PRINT_PREFIX
8702 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
8703 // Indicate no device found at this address.
8704 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
8705 status = SRB_STATUS_ERROR;
8706 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
8707 ASSERT(FALSE);
8708 break;
8709 }
8710 */
8711 PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
8712
8713 if(PostReq) {
8714
8715 KdPrint3((PRINT_PREFIX "Non-empty queue\n"));
8716 if (atapiDev &&
8717 (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) {
8718 KdPrint3((PRINT_PREFIX "Try ATAPI prepare\n"));
8719
8720 status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE);
8721 } else {
8722 KdPrint2((PRINT_PREFIX "Try IDE prepare\n"));
8723 status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE);
8724 }
8725 /*KeBugCheckEx(0xc000000e,
8726 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8727 Srb->Function,
8728 status, 0x80000001);*/
8729 if(status == SRB_STATUS_BUSY)
8730 status = SRB_STATUS_PENDING;
8731 // Insert requests AFTER they have been initialized on
8732 // CMD_ACTION_PREPARE stage
8733 // we should not check TopLevel here (it is always TRUE)
8734 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8735 UniataQueueRequest(chan, Srb);
8736
8737 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
8738
8739 } else {
8740
8741 // Send command to device.
8742 KdPrint2((PRINT_PREFIX "Send to device %x\n", Srb->Cdb[0]));
8743 if(TopLevel) {
8744 KdPrint2((PRINT_PREFIX "TopLevel (2), srb %#x\n", Srb));
8745 AtaReq = (PATA_REQ)(Srb->SrbExtension);
8746 KdPrint2((PRINT_PREFIX "TopLevel (3), AtaReq %#x\n", AtaReq));
8747 //ASSERT(!AtaReq->Flags);
8748 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8749 UniataQueueRequest(chan, Srb);
8750 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
8751 //ASSERT(!AtaReq->Flags);
8752 AtaReq->ReqState = REQ_STATE_QUEUED;
8753 //ASSERT(!AtaReq->Flags);
8754 }
8755
8756 #ifndef NAVO_TEST
8757 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
8758 if(!LunExt) {
8759 goto reject_srb;
8760 }
8761 if(Srb->Cdb[0] == SCSIOP_INQUIRY) {
8762 if(UniataAnybodyHome(deviceExtension, chan->lChannel, DeviceNumber)) {
8763 if(!CheckDevice(HwDeviceExtension, chan->lChannel, DeviceNumber, TRUE)) {
8764 goto reject_srb;
8765 }
8766 }
8767 if(!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
8768 goto reject_srb;
8769 }
8770 } else
8771 if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) {
8772 // allow
8773 } else {
8774 goto reject_srb;
8775 }
8776 }
8777 #endif //NAVO_TEST
8778
8779 if(atapiDev &&
8780 (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)/* &&
8781 (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
8782 KdPrint3((PRINT_PREFIX "Try ATAPI send %x\n", Srb->Cdb[0]));
8783 status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
8784 } else {
8785 KdPrint2((PRINT_PREFIX "Try IDE send\n"));
8786 /* {
8787 ULONG __ebp__ = 0;
8788 ULONG __esp__ = 0;
8789
8790 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
8791 __asm {
8792 mov eax,ebp
8793 mov __ebp__, eax
8794 mov eax,esp
8795 mov __esp__, eax
8796 }
8797 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
8798 }*/
8799 status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
8800 }
8801 /* KeBugCheckEx(0xc000000e,
8802 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8803 Srb->Function,
8804 status, 0x80000002);*/
8805
8806 }
8807 //skip_exec:
8808 TopLevel = FALSE;
8809
8810 break;
8811
8812 case SRB_FUNCTION_ABORT_COMMAND:
8813
8814 tmpSrb = ScsiPortGetSrb(HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun,
8815 Srb->QueueTag);
8816 // Verify that SRB to abort is still outstanding.
8817 if((tmpSrb != Srb->NextSrb) ||
8818 !chan->queue_depth) {
8819
8820 KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB to abort already completed\n"));
8821
8822 // Complete abort SRB.
8823 status = SRB_STATUS_ABORT_FAILED;
8824 break;
8825 }
8826
8827 AtaReq = (PATA_REQ)(tmpSrb->SrbExtension);
8828 if(AtaReq->ReqState > REQ_STATE_READY_TO_TRANSFER) {
8829 if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_CURRENT)) {
8830 KdPrint2((PRINT_PREFIX "AtapiStartIo: Abort command failed\n"));
8831 // Log reset failure.
8832 KdPrint3((PRINT_PREFIX
8833 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
8834 HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
8835 ));
8836 ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8);
8837 status = SRB_STATUS_ERROR;
8838
8839 } else {
8840 status = SRB_STATUS_SUCCESS;
8841 }
8842 } else {
8843 KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove aborted srb %#x\n", tmpSrb));
8844 if (tmpSrb->SenseInfoBuffer &&
8845 tmpSrb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) {
8846
8847 PSENSE_DATA senseBuffer = (PSENSE_DATA)tmpSrb->SenseInfoBuffer;
8848
8849 senseBuffer->ErrorCode = 0;
8850 senseBuffer->Valid = 1;
8851 senseBuffer->AdditionalSenseLength = 0xb;
8852 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
8853 senseBuffer->AdditionalSenseCode = 0;
8854 senseBuffer->AdditionalSenseCodeQualifier = 0;
8855
8856 tmpSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
8857 }
8858 AtapiDmaDBSync(chan, tmpSrb);
8859 UniataRemoveRequest(chan, tmpSrb);
8860 // Indicate command complete.
8861 ScsiPortNotification(RequestComplete,
8862 deviceExtension,
8863 tmpSrb);
8864 status = SRB_STATUS_SUCCESS;
8865 }
8866 break;
8867
8868 // Abort function indicates that a request timed out.
8869 // Call reset routine. Card will only be reset if
8870 // status indicates something is wrong.
8871 // Fall through to reset code.
8872
8873 case SRB_FUNCTION_RESET_DEVICE:
8874 case SRB_FUNCTION_RESET_LOGICAL_UNIT:
8875
8876 // Reset single device.
8877 // For now we support only Lun=0
8878
8879 // Note: reset is immediate command, it cannot be queued since it is usually used to
8880 // revert not-responding device to operational state
8881 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device request received\n"));
8882 UniataUserDeviceReset(deviceExtension, LunExt, lChannel);
8883 status = SRB_STATUS_SUCCESS;
8884 break;
8885
8886 case SRB_FUNCTION_RESET_BUS:
8887 do_bus_reset:
8888 // Reset Atapi and SCSI bus.
8889
8890 // Note: reset is immediate command, it cannot be queued since it is usually used to
8891 // revert not- responding device to operational state
8892 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus request received\n"));
8893 if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_ALL)) {
8894 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus failed\n"));
8895 // Log reset failure.
8896 KdPrint3((PRINT_PREFIX
8897 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
8898 HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
8899 ));
8900 ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8);
8901 status = SRB_STATUS_ERROR;
8902
8903 } else {
8904 status = SRB_STATUS_SUCCESS;
8905 }
8906
8907 break;
8908
8909 case SRB_FUNCTION_SHUTDOWN:
8910
8911 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown\n"));
8912 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
8913 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - no such device\n"));
8914 } else
8915 if(atapiDev) {
8916 // FLUSH ATAPI device - do nothing
8917 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - ATAPI device\n"));
8918 } else {
8919 // FLUSH IDE/ATA device
8920 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - IDE device\n"));
8921 AtapiDisableInterrupts(deviceExtension, lChannel);
8922 status = AtaCommand(deviceExtension, DeviceNumber, GET_CHANNEL(Srb),
8923 IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_IDLE);
8924 // If supported & allowed, reset write cacheing
8925 if(LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) {
8926
8927 // Disable write cache
8928 status = AtaCommand(deviceExtension, DeviceNumber, lChannel,
8929 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
8930 0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY);
8931 // Check for errors.
8932 if (status & IDE_STATUS_ERROR) {
8933 KdPrint2((PRINT_PREFIX
8934 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
8935 DeviceNumber));
8936 }
8937 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
8938
8939 // Re-enable write cache
8940 status = AtaCommand(deviceExtension, DeviceNumber, lChannel,
8941 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
8942 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
8943 // Check for errors.
8944 if (status & IDE_STATUS_ERROR) {
8945 KdPrint2((PRINT_PREFIX
8946 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
8947 DeviceNumber));
8948 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
8949 } else {
8950 LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED;
8951 }
8952 }
8953
8954 AtapiEnableInterrupts(deviceExtension, lChannel);
8955 }
8956 status = SRB_STATUS_SUCCESS;
8957
8958 break;
8959
8960 case SRB_FUNCTION_FLUSH:
8961
8962 KdPrint2((PRINT_PREFIX "AtapiStartIo: Flush (do nothing)\n"));
8963 status = SRB_STATUS_SUCCESS;
8964 break;
8965
8966 case SRB_FUNCTION_IO_CONTROL: {
8967
8968 ULONG len;
8969
8970 KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
8971
8972 len = Srb->DataTransferLength;
8973
8974 if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
8975
8976 ULONG targetId = (ULONG)(-1);
8977
8978 if(len < sizeof(SRB_IO_CONTROL)) {
8979 goto wrong_buffer_size;
8980 }
8981
8982 // extract bogus bus address
8983 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
8984 case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
8985 PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
8986
8987 if(len < sizeof(SRB_IO_CONTROL)+sizeof(GETVERSIONINPARAMS)) {
8988 goto wrong_buffer_size;
8989 }
8990
8991 targetId = versionParameters->bIDEDeviceMap;
8992 KdPrint2((PRINT_PREFIX "targetId (smart ver) %d\n", targetId));
8993 break; }
8994 case IOCTL_SCSI_MINIPORT_IDENTIFY:
8995 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
8996 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
8997 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
8998 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
8999 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9000 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9001 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9002 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9003 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE:
9004 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG:
9005 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG:
9006 {
9007 PSENDCMDINPARAMS cmdInParameters = (PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9008
9009 if(len < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDINPARAMS) - 1) {
9010 goto wrong_buffer_size;
9011 }
9012
9013 targetId = cmdInParameters->bDriveNumber;
9014 KdPrint2((PRINT_PREFIX "targetId (smart/ident) %d\n", targetId));
9015 break; }
9016 default:
9017 invalid_request:
9018 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9019 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9020 status = SRB_STATUS_INVALID_REQUEST;
9021 goto complete_req;
9022 } // end switch()
9023
9024 // adjust (if necessary) bus address
9025 if(targetId != (ULONG)(-1)) {
9026
9027 // This is done because of how the IOCTL_SCSI_MINIPORT
9028 // determines 'targetid's'. Disk.sys places the real target id value
9029 // in the DeviceMap field. Once we do some parameter checking, the value passed
9030 // back to the application will be determined.
9031
9032 if (deviceExtension->NumberChannels == 1) {
9033 // do this for legacy controllers and legacy callers
9034 KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call\n"));
9035 DeviceNumber = (targetId & 0x01);
9036 lChannel = 0;
9037 } else
9038 if(commPort) {
9039 // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
9040 // due to DISK.SYS design bug, we have invalid SCSI address in SRB
9041 KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call (2)\n"));
9042 if(deviceExtension->HwFlags & UNIATA_AHCI) {
9043 lChannel = (UCHAR)targetId / 2;
9044 DeviceNumber = 0;
9045 } else {
9046 lChannel = (UCHAR)(targetId / 2);
9047 DeviceNumber = targetId & 0x01;
9048 }
9049 } else {
9050 // otherwise assume lChannel and DeviceNumber from Srb are ok
9051 }
9052 if(lChannel >= deviceExtension->NumberChannels ||
9053 DeviceNumber >= deviceExtension->NumberLuns) {
9054 KdPrint2((PRINT_PREFIX
9055 "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
9056 targetId));
9057 // Indicate no device found at this address.
9058 goto reject_srb;
9059 }
9060 targetId = lChannel*deviceExtension->NumberLuns+DeviceNumber;
9061 chan = &(deviceExtension->chan[lChannel]);
9062 LunExt = chan->lun[DeviceNumber];
9063 if(!LunExt) {
9064 goto reject_srb;
9065 }
9066 atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
9067
9068 if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
9069 goto reject_srb;
9070 }
9071 }
9072
9073 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
9074 case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
9075
9076 PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9077 UCHAR deviceNumberMap;
9078
9079 KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
9080
9081 // Version and revision per SMART 1.03
9082
9083 versionParameters->bVersion = 1;
9084 versionParameters->bRevision = 1;
9085 versionParameters->bReserved = 0;
9086
9087 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
9088 versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD);
9089
9090 if (atapiDev) {
9091 goto invalid_request;
9092 }
9093
9094 // NOTE: This will only set the bit
9095 // corresponding to this drive's target id.
9096 // The bit mask is as follows:
9097 //
9098 // -Sec Pri
9099 // S M S M
9100 // 3 2 1 0
9101
9102 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
9103 deviceNumberMap = 1 << lChannel;
9104 DeviceNumber = 0;
9105 } else
9106 if (deviceExtension->NumberChannels == 1) {
9107 if (chan->PrimaryAddress) {
9108 deviceNumberMap = 1 << DeviceNumber;
9109 } else {
9110 deviceNumberMap = 4 << DeviceNumber;
9111 }
9112 } else {
9113 deviceNumberMap = 1 << (DeviceNumber+lChannel*2);
9114 }
9115
9116 versionParameters->bIDEDeviceMap = deviceNumberMap;
9117
9118 status = SRB_STATUS_SUCCESS;
9119 break;
9120 }
9121
9122 case IOCTL_SCSI_MINIPORT_IDENTIFY: {
9123
9124 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9125 SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9126
9127 KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
9128 // Extract the target.
9129 KdPrint2((PRINT_PREFIX "targetId %d\n", targetId));
9130
9131 switch(cmdInParameters.irDriveRegs.bCommandReg) {
9132 case ID_CMD:
9133 if(atapiDev) {
9134 KdPrint2((PRINT_PREFIX "Error: ID_CMD for ATAPI\n"));
9135 goto invalid_request;
9136 }
9137 /* FALL THROUGH */
9138 case ATAPI_ID_CMD:
9139
9140 if(!atapiDev &&
9141 (cmdInParameters.irDriveRegs.bCommandReg == ATAPI_ID_CMD)) {
9142 KdPrint2((PRINT_PREFIX "Error: ATAPI_ID_CMD for non-ATAPI\n"));
9143 goto invalid_request;
9144 }
9145
9146 len = min(len, sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE);
9147 // Zero the output buffer
9148 RtlZeroMemory(cmdOutParameters, len);
9149 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
9150 ((PUCHAR)cmdOutParameters)[i] = 0;
9151 }*/
9152
9153 // Build status block.
9154 cmdOutParameters->cBufferSize = min(IDENTIFY_BUFFER_SIZE, len - sizeof(SENDCMDOUTPARAMS) + 1);
9155 cmdOutParameters->DriverStatus.bDriverError = 0;
9156 cmdOutParameters->DriverStatus.bIDEError = 0;
9157
9158 // Extract the identify data from the device extension.
9159 ScsiPortMoveMemory (cmdOutParameters->bBuffer, &(LunExt->IdentifyData),
9160 cmdOutParameters->cBufferSize);
9161
9162 if((cmdOutParameters->cBufferSize == IDENTIFY_BUFFER_SIZE) &&
9163 (LunExt->IdentifyData.ChecksumValid == ATA_ChecksumValid)) {
9164 // adjust checksum if it is possible
9165 CHAR csum = 0;
9166 ULONG i;
9167
9168 for(i=0; i < IDENTIFY_BUFFER_SIZE-1; i++) {
9169 csum += (CHAR)(cmdOutParameters->bBuffer[i]);
9170 }
9171 cmdOutParameters->bBuffer[i] = -csum;
9172 KdPrint2((PRINT_PREFIX "AtapiStartIo: adjust checksum %d\n"));
9173 }
9174 KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
9175
9176 status = SRB_STATUS_SUCCESS;
9177
9178 break;
9179 default:
9180 KdPrint2((PRINT_PREFIX "AtapiStartIo: not supported ID code %x\n",
9181 cmdInParameters.irDriveRegs.bCommandReg));
9182 status = SRB_STATUS_INVALID_REQUEST;
9183 break;
9184 }
9185 break;
9186 }
9187 /*
9188 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9189 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9190 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9191 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9192 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9193 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9194 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9195 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9196 */
9197 default:
9198 // *all* IOCTLs here are SMART
9199 if(commPort) {
9200 KdPrint2((PRINT_PREFIX
9201 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
9202 }
9203 if (atapiDev) {
9204 goto invalid_request;
9205 }
9206
9207 PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
9208
9209 if(PostReq || TopLevel) {
9210 UniataQueueRequest(chan, Srb);
9211 AtaReq = (PATA_REQ)(Srb->SrbExtension);
9212 AtaReq->ReqState = REQ_STATE_QUEUED;
9213 }
9214
9215 if(PostReq) {
9216
9217 KdPrint2((PRINT_PREFIX "Non-empty queue (SMART)\n"));
9218 status = SRB_STATUS_PENDING;
9219
9220 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
9221 } else {
9222
9223 status = IdeSendSmartCommand(HwDeviceExtension, Srb, targetId);
9224 }
9225 break;
9226
9227 // we should not get here, checked above
9228 /* default :
9229 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9230 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9231 status = SRB_STATUS_INVALID_REQUEST;
9232 break;
9233 */
9234 }
9235 } else
9236 if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"-UNIATA-", sizeof("-UNIATA-")-1)) {
9237
9238 PUNIATA_CTL AtaCtl = (PUNIATA_CTL)(Srb->DataBuffer);
9239 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
9240 ULONG DeviceNumber = AtaCtl->addr.TargetId;
9241 BOOLEAN bad_ldev;
9242 ULONG i, pos;
9243
9244 pos = FIELD_OFFSET(UNIATA_CTL, RawData);
9245 //chan = &(deviceExtension->chan[lChannel]);
9246 if(len < pos) {
9247 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9248 FIELD_OFFSET(UNIATA_CTL, RawData) ));
9249 goto wrong_buffer_size;
9250 }
9251
9252 if(AtaCtl->addr.Lun ||
9253 AtaCtl->addr.TargetId >= deviceExtension->NumberLuns ||
9254 AtaCtl->addr.PathId >= deviceExtension->NumberChannels) {
9255
9256 chan = NULL;
9257 bad_ldev = TRUE;
9258 LunExt = NULL;
9259
9260 } else {
9261 bad_ldev = FALSE;
9262 lChannel = AtaCtl->addr.PathId;
9263 chan = &(deviceExtension->chan[lChannel]);
9264 LunExt = chan->lun[DeviceNumber];
9265 }
9266
9267 KdPrint2((PRINT_PREFIX "AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl->hdr.ControlCode, DeviceNumber));
9268
9269 /* check for valid LUN */
9270 switch (AtaCtl->hdr.ControlCode) {
9271 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
9272 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE:
9273 // this would be BUS reset
9274 if(bad_ldev &&
9275 (AtaCtl->addr.PathId >= deviceExtension->NumberChannels ||
9276 AtaCtl->addr.TargetId != 0xff ||
9277 AtaCtl->addr.Lun != 0
9278 )) {
9279 if(AtaCtl->hdr.ControlCode == IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES &&
9280 DeviceNumber < deviceExtension->NumberLuns) { // AtaCtl->addr.TargetId != 0xff
9281 lChannel = AtaCtl->addr.PathId;
9282 chan = &(deviceExtension->chan[lChannel]);
9283 LunExt = chan->lun[DeviceNumber];
9284 // OK
9285 } else {
9286 goto handle_bad_ldev;
9287 }
9288 } else {
9289 lChannel = AtaCtl->addr.PathId;
9290 chan = &(deviceExtension->chan[lChannel]);
9291 }
9292 break;
9293 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE:
9294 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
9295 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE:
9296 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB:
9297 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
9298 if(bad_ldev) {
9299 handle_bad_ldev:
9300 KdPrint2((PRINT_PREFIX
9301 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
9302 // Indicate no device found at this address.
9303 goto reject_srb;
9304 }
9305 }
9306
9307 /* check if queueing is necessary */
9308 switch (AtaCtl->hdr.ControlCode) {
9309 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB:
9310 if(!LunExt->nBadBlocks) {
9311 break;
9312 }
9313 goto uata_ctl_queue;
9314 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
9315 if(len < pos+sizeof(AtaCtl->SetMode)) {
9316 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9317 pos+sizeof(AtaCtl->SetMode) ));
9318 goto wrong_buffer_size;
9319 }
9320 if(!AtaCtl->SetMode.ApplyImmediately) {
9321 break;
9322 }
9323 goto uata_ctl_queue;
9324 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
9325 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
9326 uata_ctl_queue:
9327 KdPrint2((PRINT_PREFIX "put to queue (UNIATA)\n"));
9328 PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
9329
9330 if(PostReq || TopLevel) {
9331 UniataQueueRequest(chan, Srb);
9332 AtaReq = (PATA_REQ)(Srb->SrbExtension);
9333 AtaReq->ReqState = REQ_STATE_QUEUED;
9334 }
9335 if(PostReq) {
9336 KdPrint2((PRINT_PREFIX "Non-empty queue (UNIATA)\n"));
9337 status = SRB_STATUS_PENDING;
9338
9339 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
9340 goto complete_req;
9341 }
9342 } // end switch (AtaCtl->hdr.ControlCode)
9343
9344 /* process request */
9345 switch (AtaCtl->hdr.ControlCode) {
9346 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
9347
9348 KdPrint2((PRINT_PREFIX "AtapiStartIo: rescan bus\n"));
9349
9350 if(len < pos+sizeof(AtaCtl->FindDelDev)) {
9351 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9352 pos+sizeof(AtaCtl->FindDelDev) ));
9353 goto wrong_buffer_size;
9354 }
9355 if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) {
9356 KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n"));
9357 if(AtaCtl->addr.TargetId != 0xff) {
9358 LunExt->DeviceFlags &= ~DFLAGS_HIDDEN;
9359 } else {
9360 }
9361 }
9362
9363 for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
9364 AtapiStallExecution(1000 * 1000);
9365 }
9366
9367 FindDevices(HwDeviceExtension,
9368 ((AtaCtl->addr.TargetId == 0xff) && (AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE))
9369 ? UNIATA_FIND_DEV_UNHIDE : 0,
9370 AtaCtl->addr.PathId);
9371 status = SRB_STATUS_SUCCESS;
9372
9373 break;
9374
9375 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE: {
9376
9377 KdPrint2((PRINT_PREFIX "AtapiStartIo: remove %#x:%#x\n", AtaCtl->addr.PathId, AtaCtl->addr.TargetId));
9378
9379 if(len < pos+sizeof(AtaCtl->FindDelDev)) {
9380 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9381 pos+sizeof(AtaCtl->FindDelDev) ));
9382 goto wrong_buffer_size;
9383 }
9384 LunExt->DeviceFlags = 0;
9385 if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) {
9386 KdPrint2((PRINT_PREFIX "AtapiStartIo: hide from further detection\n"));
9387 //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
9388 UniataForgetDevice(LunExt);
9389 }
9390
9391 for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
9392 AtapiStallExecution(1000 * 1000);
9393 }
9394
9395 status = SRB_STATUS_SUCCESS;
9396 break;
9397 }
9398 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE: {
9399
9400 KdPrint2((PRINT_PREFIX "AtapiStartIo: Set transfer mode\n"));
9401
9402 if(len < pos+sizeof(AtaCtl->SetMode)) {
9403 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9404 pos+sizeof(AtaCtl->SetMode) ));
9405 goto wrong_buffer_size;
9406 }
9407 if(AtaCtl->SetMode.OrigMode != IOMODE_NOT_SPECIFIED) {
9408 LunExt->OrigTransferMode = (UCHAR)(AtaCtl->SetMode.OrigMode);
9409 }
9410 if(AtaCtl->SetMode.MaxMode != IOMODE_NOT_SPECIFIED) {
9411 LunExt->LimitedTransferMode = (UCHAR)(AtaCtl->SetMode.MaxMode);
9412 if(LunExt->LimitedTransferMode >
9413 LunExt->OrigTransferMode) {
9414 // check for incorrect value
9415 LunExt->LimitedTransferMode =
9416 LunExt->OrigTransferMode;
9417 }
9418 }
9419 LunExt->TransferMode = min(LunExt->LimitedTransferMode, LunExt->OrigTransferMode);
9420
9421 LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit
9422 if(AtaCtl->SetMode.ApplyImmediately) {
9423 AtapiDmaInit__(deviceExtension, LunExt);
9424 }
9425 /* LunExt->TransferMode =
9426 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
9427 status = SRB_STATUS_SUCCESS;
9428 break;
9429 }
9430 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE: {
9431
9432 KdPrint2((PRINT_PREFIX "AtapiStartIo: Get transfer mode\n"));
9433
9434 if(len < pos+sizeof(AtaCtl->GetMode)) {
9435 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9436 pos+sizeof(AtaCtl->GetMode) ));
9437 goto wrong_buffer_size;
9438 }
9439 AtaCtl->GetMode.OrigMode = LunExt->OrigTransferMode;
9440 AtaCtl->GetMode.MaxMode = LunExt->LimitedTransferMode;
9441 AtaCtl->GetMode.CurrentMode = LunExt->TransferMode;
9442 AtaCtl->GetMode.PhyMode = LunExt->PhyTransferMode;
9443
9444 status = SRB_STATUS_SUCCESS;
9445 break;
9446 }
9447 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION: {
9448
9449 KdPrint2((PRINT_PREFIX "AtapiStartIo: Get version\n"));
9450
9451 if(len < pos+sizeof(AtaCtl->Version)) {
9452 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9453 pos+sizeof(AtaCtl->Version) ));
9454 goto wrong_buffer_size;
9455 }
9456 AtaCtl->Version.Length = sizeof(GETDRVVERSION);
9457 AtaCtl->Version.VersionMj = UNIATA_VER_MJ;
9458 AtaCtl->Version.VersionMn = UNIATA_VER_MN;
9459 AtaCtl->Version.SubVerMj = UNIATA_VER_SUB_MJ;
9460 AtaCtl->Version.SubVerMn = UNIATA_VER_SUB_MN;
9461
9462 status = SRB_STATUS_SUCCESS;
9463 break;
9464 }
9465 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO: {
9466
9467 KdPrint2((PRINT_PREFIX "AtapiStartIo: Get adapter info\n"));
9468
9469 if(len < pos+sizeof(AtaCtl->AdapterInfo)) {
9470 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9471 pos+sizeof(AtaCtl->AdapterInfo) ));
9472 goto wrong_buffer_size;
9473 }
9474 AtaCtl->AdapterInfo.HeaderLength = sizeof(ADAPTERINFO);
9475
9476 AtaCtl->AdapterInfo.DevID = deviceExtension->DevID;
9477 AtaCtl->AdapterInfo.RevID = deviceExtension->RevID;
9478 AtaCtl->AdapterInfo.slotNumber = deviceExtension->slotNumber;
9479 AtaCtl->AdapterInfo.SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
9480 AtaCtl->AdapterInfo.DevIndex = deviceExtension->DevIndex;
9481 AtaCtl->AdapterInfo.Channel = deviceExtension->Channel;
9482 AtaCtl->AdapterInfo.HbaCtrlFlags = deviceExtension->HbaCtrlFlags;
9483 AtaCtl->AdapterInfo.simplexOnly= deviceExtension->simplexOnly;
9484 AtaCtl->AdapterInfo.MemIo = FALSE;/*deviceExtension->MemIo;*/
9485 AtaCtl->AdapterInfo.UnknownDev = deviceExtension->UnknownDev;
9486 AtaCtl->AdapterInfo.MasterDev = deviceExtension->MasterDev;
9487 AtaCtl->AdapterInfo.MaxTransferMode = deviceExtension->MaxTransferMode;
9488 AtaCtl->AdapterInfo.HwFlags = deviceExtension->HwFlags;
9489 AtaCtl->AdapterInfo.OrigAdapterInterfaceType = deviceExtension->OrigAdapterInterfaceType;
9490 AtaCtl->AdapterInfo.BusInterruptLevel = deviceExtension->BusInterruptLevel;
9491 AtaCtl->AdapterInfo.InterruptMode = deviceExtension->InterruptMode;
9492 AtaCtl->AdapterInfo.BusInterruptVector = deviceExtension->BusInterruptVector;
9493 AtaCtl->AdapterInfo.NumberChannels = deviceExtension->NumberChannels;
9494 AtaCtl->AdapterInfo.NumberLuns = (UCHAR)deviceExtension->NumberLuns;
9495 AtaCtl->AdapterInfo.AdapterInterfaceType = deviceExtension->AdapterInterfaceType;
9496 if(deviceExtension->FullDevName) {
9497 strncpy(AtaCtl->AdapterInfo.DeviceName, deviceExtension->FullDevName, 64);
9498 }
9499 AtaCtl->AdapterInfo.ChanInfoValid = FALSE;
9500 AtaCtl->AdapterInfo.LunInfoValid = FALSE;
9501 AtaCtl->AdapterInfo.ChanHeaderLengthValid = TRUE;
9502
9503 pos += AtaCtl->AdapterInfo.HeaderLength;
9504
9505 // zero tail
9506 RtlZeroMemory(((PCHAR)AtaCtl)+pos,
9507 len-pos);
9508
9509 if(len >= pos+AtaCtl->AdapterInfo.NumberChannels*sizeof(CHANINFO)) {
9510 PCHANINFO ChanInfo = (PCHANINFO)( ((PCHAR)AtaCtl)+pos );
9511 PHW_CHANNEL cur_chan;
9512 KdPrint2((PRINT_PREFIX "AtapiStartIo: Fill channel info\n"));
9513 for(i=0;i<AtaCtl->AdapterInfo.NumberChannels;i++) {
9514 KdPrint2((PRINT_PREFIX "chan[%d] %x\n", i, cur_chan));
9515 cur_chan = &(deviceExtension->chan[i]);
9516 ChanInfo->MaxTransferMode = cur_chan->MaxTransferMode;
9517 ChanInfo->ChannelCtrlFlags = cur_chan->ChannelCtrlFlags;
9518 RtlCopyMemory(&(ChanInfo->QueueStat), &(cur_chan->QueueStat), sizeof(ChanInfo->QueueStat));
9519 ChanInfo->ReorderCount = cur_chan->ReorderCount;
9520 ChanInfo->IntersectCount = cur_chan->IntersectCount;
9521 ChanInfo->TryReorderCount = cur_chan->TryReorderCount;
9522 ChanInfo->TryReorderHeadCount = cur_chan->TryReorderHeadCount;
9523 ChanInfo->TryReorderTailCount = cur_chan->TryReorderTailCount;
9524 //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
9525 ChanInfo++;
9526 }
9527 AtaCtl->AdapterInfo.ChanInfoValid = TRUE;
9528 AtaCtl->AdapterInfo.ChanHeaderLength = sizeof(*ChanInfo);
9529 }
9530
9531 status = SRB_STATUS_SUCCESS;
9532 break;
9533 }
9534 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB: {
9535
9536 KdPrint2((PRINT_PREFIX "AtapiStartIo: Forget BB list\n"));
9537
9538 ForgetBadBlocks(LunExt);
9539
9540 status = SRB_STATUS_SUCCESS;
9541 break;
9542 }
9543 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: {
9544
9545 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device\n"));
9546
9547 if(bad_ldev) {
9548 goto do_bus_reset;
9549 } else {
9550 UniataUserDeviceReset(deviceExtension, LunExt, AtaCtl->addr.PathId);
9551 }
9552
9553 status = SRB_STATUS_SUCCESS;
9554 break;
9555 }
9556 default :
9557 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
9558 AtaCtl->hdr.ControlCode ));
9559 status = SRB_STATUS_INVALID_REQUEST;
9560 break;
9561 }
9562
9563 } else {
9564 KdPrint2((PRINT_PREFIX "AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
9565 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature,
9566 "SCSIDISK", "-UNIATA-"));
9567
9568 status = SRB_STATUS_INVALID_REQUEST;
9569 break;
9570 }
9571
9572 break;
9573 } // end SRB_FUNCTION_IO_CONTROL
9574 default:
9575
9576 KdPrint2((PRINT_PREFIX "AtapiStartIo: Unknown IOCTL\n"));
9577 // Indicate unsupported command.
9578 status = SRB_STATUS_INVALID_REQUEST;
9579
9580 // break;
9581
9582 } // end switch
9583
9584 complete_req:
9585
9586 PathId = Srb->PathId;
9587 TargetId = Srb->TargetId;
9588 Lun = Srb->Lun;
9589
9590 if (status != SRB_STATUS_PENDING) {
9591
9592 KdPrint2((PRINT_PREFIX
9593 "AtapiStartIo: Srb %#x complete with status %#x\n",
9594 Srb,
9595 status));
9596
9597 // Set status in SRB.
9598 Srb->SrbStatus = (UCHAR)status;
9599
9600 if(chan && Srb) {
9601 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan, Srb));
9602 AtapiDmaDBSync(chan, Srb);
9603 }
9604 KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan, Srb));
9605 UniataRemoveRequest(chan, Srb);
9606 // Indicate command complete.
9607 KdPrint2((PRINT_PREFIX "AtapiStartIo: ScsiPortNotification\n"));
9608 ScsiPortNotification(RequestComplete,
9609 deviceExtension,
9610 Srb);
9611
9612 KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataGetCurRequest\n"));
9613 // Remove current Srb & get next one
9614 if((Srb = UniataGetCurRequest(chan))) {
9615 AtaReq = (PATA_REQ)(Srb->SrbExtension);
9616 if(AtaReq->ReqState > REQ_STATE_QUEUED) {
9617 // current request is under precessing, thus
9618 // we should do nothing here
9619 Srb = NULL;
9620 }
9621 }
9622 KdPrint2((PRINT_PREFIX "AtapiStartIo: chan %x, Src %x\n", chan, Srb));
9623 if(!chan) {
9624 //ASSERT(TopLevel);
9625 }
9626 }
9627 KdPrint2((PRINT_PREFIX "AtapiStartIo: next Srb %x\n", Srb));
9628
9629 } while (Srb && (status != SRB_STATUS_PENDING));
9630
9631 KdPrint2((PRINT_PREFIX "AtapiStartIo: query PORT for next request\n"));
9632 // Indicate ready for next request.
9633 ScsiPortNotification(NextRequest,
9634 deviceExtension,
9635 NULL);
9636
9637 ScsiPortNotification(NextLuRequest,
9638 deviceExtension,
9639 PathId,
9640 TargetId,
9641 Lun);
9642
9643 return TRUE;
9644
9645 } // end AtapiStartIo__()
9646
9647
9648 void
9649 NTAPI
9650 UniataInitAtaCommands()
9651 {
9652 int i;
9653 UCHAR command;
9654 UCHAR flags;
9655
9656 KdPrint2((PRINT_PREFIX "UniataInitAtaCommands:\n"));
9657
9658 for(i=0; i<256; i++) {
9659
9660 flags = 0;
9661 command = i;
9662
9663 //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
9664
9665 switch(command) {
9666 case IDE_COMMAND_READ_DMA48:
9667 case IDE_COMMAND_READ_DMA_Q48:
9668 case IDE_COMMAND_READ_STREAM_DMA48:
9669 case IDE_COMMAND_READ_STREAM48:
9670 case IDE_COMMAND_WRITE_DMA48:
9671 case IDE_COMMAND_WRITE_DMA_Q48:
9672 case IDE_COMMAND_READ_DMA_Q:
9673 case IDE_COMMAND_READ_DMA:
9674 case IDE_COMMAND_WRITE_DMA:
9675 case IDE_COMMAND_WRITE_DMA_Q:
9676 case IDE_COMMAND_WRITE_STREAM_DMA48:
9677 case IDE_COMMAND_WRITE_STREAM48:
9678 case IDE_COMMAND_WRITE_FUA_DMA48:
9679 case IDE_COMMAND_WRITE_FUA_DMA_Q48:
9680 case IDE_COMMAND_READ_LOG_DMA48:
9681 case IDE_COMMAND_WRITE_LOG_DMA48:
9682 case IDE_COMMAND_TRUSTED_RCV_DMA:
9683 case IDE_COMMAND_TRUSTED_SEND_DMA:
9684 case IDE_COMMAND_DATA_SET_MGMT:
9685 //KdPrint2((PRINT_PREFIX "DMA "));
9686 flags |= ATA_CMD_FLAG_DMA;
9687 }
9688
9689 switch(command) {
9690 case IDE_COMMAND_WRITE_FUA_DMA48:
9691 case IDE_COMMAND_WRITE_FUA_DMA_Q48:
9692 case IDE_COMMAND_WRITE_MUL_FUA48:
9693
9694 flags |= ATA_CMD_FLAG_FUA;
9695 /* FALL THROUGH */
9696
9697 case IDE_COMMAND_READ48:
9698 case IDE_COMMAND_READ_DMA48:
9699 case IDE_COMMAND_READ_DMA_Q48:
9700 case IDE_COMMAND_READ_MUL48:
9701 case IDE_COMMAND_READ_STREAM_DMA48:
9702 case IDE_COMMAND_READ_STREAM48:
9703 case IDE_COMMAND_WRITE48:
9704 case IDE_COMMAND_WRITE_DMA48:
9705 case IDE_COMMAND_WRITE_DMA_Q48:
9706 case IDE_COMMAND_WRITE_MUL48:
9707 case IDE_COMMAND_WRITE_STREAM_DMA48:
9708 case IDE_COMMAND_WRITE_STREAM48:
9709 case IDE_COMMAND_FLUSH_CACHE48:
9710 case IDE_COMMAND_VERIFY48:
9711
9712 //KdPrint2((PRINT_PREFIX "48 "));
9713 flags |= ATA_CMD_FLAG_48;
9714 /* FALL THROUGH */
9715
9716 case IDE_COMMAND_READ:
9717 case IDE_COMMAND_READ_MULTIPLE:
9718 case IDE_COMMAND_READ_DMA:
9719 case IDE_COMMAND_READ_DMA_Q:
9720 case IDE_COMMAND_WRITE:
9721 case IDE_COMMAND_WRITE_MULTIPLE:
9722 case IDE_COMMAND_WRITE_DMA:
9723 case IDE_COMMAND_WRITE_DMA_Q:
9724 case IDE_COMMAND_FLUSH_CACHE:
9725 case IDE_COMMAND_VERIFY:
9726
9727 //KdPrint2((PRINT_PREFIX "LBA "));
9728 flags |= ATA_CMD_FLAG_LBAIOsupp;
9729 }
9730
9731 switch(command) {
9732 case IDE_COMMAND_READ_NATIVE_SIZE48:
9733 case IDE_COMMAND_SET_NATIVE_SIZE48:
9734 // we cannot set LBA flag for these commands to avoid BadBlock handling
9735 //flags |= ATA_CMD_FLAG_LBAIOsupp;
9736 flags |= ATA_CMD_FLAG_48;
9737
9738 case IDE_COMMAND_READ_NATIVE_SIZE:
9739 case IDE_COMMAND_SET_NATIVE_SIZE:
9740
9741 flags |= ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_FUA;
9742 }
9743
9744 flags |= ATA_CMD_FLAG_48supp;
9745
9746 switch (command) {
9747 case IDE_COMMAND_READ:
9748 command = IDE_COMMAND_READ48; break;
9749 case IDE_COMMAND_READ_MULTIPLE:
9750 command = IDE_COMMAND_READ_MUL48; break;
9751 case IDE_COMMAND_READ_DMA:
9752 command = IDE_COMMAND_READ_DMA48; break;
9753 case IDE_COMMAND_READ_DMA_Q:
9754 command = IDE_COMMAND_READ_DMA_Q48; break;
9755 case IDE_COMMAND_WRITE:
9756 command = IDE_COMMAND_WRITE48; break;
9757 case IDE_COMMAND_WRITE_MULTIPLE:
9758 command = IDE_COMMAND_WRITE_MUL48; break;
9759 case IDE_COMMAND_WRITE_DMA:
9760 command = IDE_COMMAND_WRITE_DMA48; break;
9761 case IDE_COMMAND_WRITE_DMA_Q:
9762 command = IDE_COMMAND_WRITE_DMA_Q48; break;
9763 case IDE_COMMAND_FLUSH_CACHE:
9764 command = IDE_COMMAND_FLUSH_CACHE48; break;
9765 // case IDE_COMMAND_READ_NATIVE_SIZE:
9766 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
9767 case IDE_COMMAND_SET_NATIVE_SIZE:
9768 command = IDE_COMMAND_SET_NATIVE_SIZE48; break;
9769 case IDE_COMMAND_VERIFY:
9770 command = IDE_COMMAND_VERIFY48; break;
9771 default:
9772 //KdPrint2((PRINT_PREFIX "!28->48 "));
9773 flags &= ~ATA_CMD_FLAG_48supp;
9774 }
9775
9776 switch (command) {
9777 case IDE_COMMAND_READ:
9778 case IDE_COMMAND_READ_MULTIPLE:
9779 case IDE_COMMAND_READ_DMA48:
9780 case IDE_COMMAND_READ_DMA_Q48:
9781 case IDE_COMMAND_READ_STREAM_DMA48:
9782 case IDE_COMMAND_READ_STREAM48:
9783 case IDE_COMMAND_READ_DMA_Q:
9784 case IDE_COMMAND_READ_DMA:
9785 case IDE_COMMAND_READ_LOG_DMA48:
9786 case IDE_COMMAND_TRUSTED_RCV_DMA:
9787 case IDE_COMMAND_IDENTIFY:
9788 case IDE_COMMAND_ATAPI_IDENTIFY:
9789 //KdPrint2((PRINT_PREFIX "RD "));
9790 flags |= ATA_CMD_FLAG_In;
9791 break;
9792 case IDE_COMMAND_WRITE:
9793 case IDE_COMMAND_WRITE_MULTIPLE:
9794 case IDE_COMMAND_WRITE_DMA48:
9795 case IDE_COMMAND_WRITE_DMA_Q48:
9796 case IDE_COMMAND_WRITE_DMA:
9797 case IDE_COMMAND_WRITE_DMA_Q:
9798 case IDE_COMMAND_WRITE_STREAM_DMA48:
9799 case IDE_COMMAND_WRITE_STREAM48:
9800 case IDE_COMMAND_WRITE_FUA_DMA48:
9801 case IDE_COMMAND_WRITE_FUA_DMA_Q48:
9802 //KdPrint2((PRINT_PREFIX "WR "));
9803 flags |= ATA_CMD_FLAG_Out;
9804 break;
9805 }
9806
9807 //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
9808 AtaCommands48[i] = command;
9809 AtaCommandFlags[i] = flags;
9810 }
9811 } // end UniataInitAtaCommands()
9812
9813 /*++
9814
9815 Routine Description:
9816
9817 Installable driver initialization entry point for system.
9818
9819 Arguments:
9820
9821 Driver Object
9822
9823 Return Value:
9824
9825 Status from ScsiPortInitialize()
9826
9827 --*/
9828 extern "C"
9829 ULONG
9830 NTAPI
9831 DriverEntry(
9832 IN PVOID DriverObject,
9833 IN PVOID Argument2
9834 )
9835 {
9836 HW_INITIALIZATION_DATA_COMMON hwInitializationData;
9837 ULONG adapterCount;
9838 ULONG i, c, alt;
9839 ULONG statusToReturn, newStatus;
9840 PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
9841 BOOLEAN ReEnter = FALSE;
9842 WCHAR a;
9843 #ifndef USE_REACTOS_DDK
9844 NTSTATUS status;
9845 #endif
9846
9847 PCONFIGURATION_INFORMATION GlobalConfig = IoGetConfigurationInformation();
9848 BOOLEAN PrimaryClaimed = FALSE;
9849 BOOLEAN SecondaryClaimed = FALSE;
9850
9851 LARGE_INTEGER t0, t1;
9852
9853 Connect_DbgPrint();
9854 KdPrint2((PRINT_PREFIX "%s", (PCCHAR)ver_string));
9855 a = (WCHAR)strlen(ver_string);
9856
9857 g_opt_Verbose = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PrintLogo", 0);
9858 if(g_opt_Verbose) {
9859 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR "\n");
9860 }
9861
9862 if(!SavedDriverObject) {
9863 SavedDriverObject = (PDRIVER_OBJECT)DriverObject;
9864 #ifdef USE_REACTOS_DDK
9865 KdPrint(("UniATA Init: OS should be ReactOS\n"));
9866 MajorVersion=0x04;
9867 MinorVersion=0x01;
9868 BuildNumber=1;
9869 #else
9870 // we are here for the 1st time
9871 // init CrossNT and get OS version
9872 if(!NT_SUCCESS(status = CrNtInit(SavedDriverObject, RegistryPath))) {
9873 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status));
9874 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
9875 return status;
9876 }
9877 #endif // USE_REACTOS_DDK
9878 KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion, MinorVersion, BuildNumber, KeNumberProcessors));
9879
9880 KeQuerySystemTime(&t0);
9881 do {
9882 KeQuerySystemTime(&t1);
9883 } while(t0.QuadPart == t1.QuadPart);
9884 t0=t1;
9885 g_Perf=0;
9886 do {
9887 KeQuerySystemTime(&t1);
9888 g_Perf++;
9889 } while(t0.QuadPart == t1.QuadPart);
9890 g_PerfDt = (ULONG)((t1.QuadPart - t0.QuadPart)/10);
9891 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt, g_Perf ));
9892 } else {
9893 KdPrint(("UniATA Init: ReEnter\n"));
9894 ReEnter = TRUE;
9895 }
9896
9897 // (re)read bad block list
9898 InitBadBlocks(NULL);
9899
9900 if(!ReEnter) {
9901 // init ATA command translation table
9902 UniataInitAtaCommands();
9903 // get registry path to settings
9904 RtlCopyMemory(&SavedRegPath, RegistryPath, sizeof(UNICODE_STRING));
9905 SavedRegPath.Buffer = (PWCHAR)&SavedRegPathBuffer;
9906 SavedRegPath.Length = min(RegistryPath->Length, 255*sizeof(WCHAR));
9907 SavedRegPath.MaximumLength = 255*sizeof(WCHAR);
9908 RtlCopyMemory(SavedRegPath.Buffer, RegistryPath->Buffer, SavedRegPath.Length);
9909 SavedRegPath.Buffer[SavedRegPath.Length/sizeof(WCHAR)] = 0;
9910 }
9911
9912 if(WinVer_Id() >= WinVer_2k) {
9913 if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"1", 0)) {
9914 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
9915 WinVer_WDM_Model = TRUE;
9916 }
9917 if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"5", 0)) {
9918 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
9919 WinVer_WDM_Model = TRUE;
9920 }
9921 }
9922
9923 SkipRaids = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"SkipRaids", 1);
9924 ForceSimplex = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"ForceSimplex", 0);
9925 #ifdef _DEBUG
9926 g_LogToDisplay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"LogToDisplay", 0);
9927 #endif //_DEBUG
9928
9929 statusToReturn = 0xffffffff;
9930
9931 // Zero out structure.
9932 RtlZeroMemory(((PCHAR)&hwInitializationData), sizeof(hwInitializationData));
9933
9934 // Set size of hwInitializationData.
9935 hwInitializationData.comm.HwInitializationDataSize =
9936 sizeof(hwInitializationData.comm) +
9937 // sizeof(hwInitializationData.nt4) +
9938 ((WinVer_Id() <= WinVer_NT) ? 0 : sizeof(hwInitializationData.w2k));
9939 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData.comm.HwInitializationDataSize));
9940
9941 // Set entry points.
9942 hwInitializationData.comm.HwInitialize = (PHW_INITIALIZE)AtapiHwInitialize;
9943 hwInitializationData.comm.HwResetBus = (PHW_RESET_BUS)AtapiResetController;
9944 hwInitializationData.comm.HwStartIo = (PHW_STARTIO)AtapiStartIo;
9945 hwInitializationData.comm.HwInterrupt = (PHW_INTERRUPT)AtapiInterrupt;
9946
9947 // Specify size of extensions.
9948 hwInitializationData.comm.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
9949 hwInitializationData.comm.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION);
9950 hwInitializationData.comm.SrbExtensionSize = sizeof(ATA_REQ);
9951
9952 // Indicate PIO device.
9953 hwInitializationData.comm.MapBuffers = TRUE;
9954 // Set PnP-specific API
9955 if(WinVer_Id() > WinVer_NT) {
9956 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
9957 hwInitializationData.comm.NeedPhysicalAddresses = TRUE;
9958 KdPrint(("set AtapiAdapterControl() ptr\n"));
9959 hwInitializationData.w2k.HwAdapterControl = (PHW_ADAPTER_CONTROL)AtapiAdapterControl;
9960 }
9961
9962 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE enum supported BusMaster Devices\n"));
9963
9964 if(!ReEnter) {
9965
9966 g_opt_VirtualMachine = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualMachineType", g_opt_VirtualMachine);
9967 if(g_opt_VirtualMachine > VM_MAX_KNOWN) {
9968 g_opt_VirtualMachine = 0;
9969 }
9970 if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualBox", (g_opt_VirtualMachine == VM_VBOX))) {
9971 g_opt_VirtualMachine = VM_VBOX;
9972 }
9973 // Pre-scan PCI bus, also check if we are under VM
9974 UniataEnumBusMasterController(DriverObject, Argument2);
9975
9976 switch(g_opt_VirtualMachine) {
9977 case VM_VBOX:
9978 KdPrint2((PRINT_PREFIX "adjust options for VirtualBox\n"));
9979 // adjust options for VirtualBox
9980 g_opt_WaitBusyCount = 20000;
9981 g_opt_WaitBusyDelay = 150;
9982 g_opt_WaitDrqDelay = 100;
9983 g_opt_WaitBusyLongCount = 20000;
9984 g_opt_MaxIsrWait = 200;
9985 g_opt_AtapiSendDisableIntr = 0;
9986 g_opt_AtapiDmaRawRead = FALSE;
9987 break;
9988 }
9989
9990 if(!hasPCI) {
9991 KdPrint2((PRINT_PREFIX "old slow machine, adjust timings\n"));
9992 // old slow machine, adjust timings
9993 g_opt_WaitBusyCount = 20000;
9994 g_opt_WaitBusyDelay = 150;
9995 g_opt_WaitDrqDelay = 100;
9996 g_opt_WaitBusyLongCount = 20000;
9997 g_opt_MaxIsrWait = 200;
9998 }
9999
10000 g_opt_WaitBusyCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyCount", g_opt_WaitBusyCount); // 200 vs 20000
10001 g_opt_WaitBusyDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyDelay", g_opt_WaitBusyDelay); // 10 vs 150
10002 g_opt_WaitDrqDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitDrqDelay", g_opt_WaitDrqDelay); // 10 vs 100
10003 g_opt_WaitBusyLongCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongCount", g_opt_WaitBusyLongCount); // 2000 vs 20000
10004 g_opt_WaitBusyLongDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongDelay", g_opt_WaitBusyLongDelay); // 250 vs 250
10005 g_opt_AtapiSendDisableIntr = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr); // 1 vs 0
10006 g_opt_AtapiDmaRawRead = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiDmaRawRead", g_opt_AtapiDmaRawRead); // 1 vs 0
10007 g_opt_MaxIsrWait = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"MaxIsrWait", g_opt_MaxIsrWait); // 40 vs xxx
10008 }
10009
10010 // Look for legacy ISA-bridged PCI IDE controller (onboard)
10011 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
10012 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: BMListLen %d\n", BMListLen));
10013 for (i=0; i <BMListLen; i++) {
10014
10015 if(!BMList[i].MasterDev) {
10016 KdPrint2((PRINT_PREFIX "!BMList[i].MasterDev\n"));
10017 break;
10018 }
10019 if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) {
10020 break;
10021 }
10022 if(ReEnter) {
10023 KdPrint2((PRINT_PREFIX "ReEnter, skip it\n"));
10024 if(BMList[i].ChanInitOk & 0x03) {
10025 KdPrint2((PRINT_PREFIX "Already initialized, skip it\n"));
10026 statusToReturn =
10027 newStatus = STATUS_SUCCESS;
10028 }
10029 continue;
10030 }
10031 //BMList[i].AltInitMasterDev = (UCHAR)0xff;
10032
10033 if(GlobalConfig->AtDiskPrimaryAddressClaimed)
10034 PrimaryClaimed = TRUE;
10035 if(GlobalConfig->AtDiskSecondaryAddressClaimed)
10036 SecondaryClaimed = TRUE;
10037
10038 if(!WinVer_WDM_Model && !PrimaryClaimed && !SecondaryClaimed &&
10039 !(BMList[i].ChanInitOk & 0x80)) {
10040 newStatus = UniataClaimLegacyPCIIDE(i);
10041 if(newStatus != STATUS_SUCCESS) {
10042 KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
10043 break;
10044 }
10045 }
10046
10047 if(g_opt_Verbose) {
10048 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
10049 }
10050
10051
10052 for(alt = 0; alt < (ULONG)(WinVer_WDM_Model ? 1 : 2) ; alt++) {
10053
10054 for(c=0; c<2; c++) {
10055
10056 if(AtapiRegCheckDevValue(NULL, c, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) {
10057 break;
10058 }
10059 if(c==0) {
10060 if(PrimaryClaimed) {
10061 KdPrint2((PRINT_PREFIX "Primary already claimed\n"));
10062 continue;
10063 }
10064 } else
10065 if(c==1) {
10066 if(SecondaryClaimed) {
10067 KdPrint2((PRINT_PREFIX "Secondary already claimed\n"));
10068 continue;
10069 }
10070 }
10071
10072 if((WinVer_Id() < WinVer_2k)) {
10073 // do not even try if already claimed
10074 if(c==0) {
10075 GlobalConfig->AtDiskPrimaryAddressClaimed = FALSE;
10076 } else
10077 if(c==1) {
10078 GlobalConfig->AtDiskSecondaryAddressClaimed = FALSE;
10079 }
10080 }
10081 if(!WinVer_WDM_Model) {
10082 hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
10083 } else {
10084 // in WDM model things are different....
10085 hwInitializationData.comm.HwFindAdapter = (c == 0) ?
10086 UniataFindCompatBusMasterController1 : UniataFindCompatBusMasterController2;
10087 }
10088 hwInitializationData.comm.NumberOfAccessRanges = 6;
10089 hwInitializationData.comm.AdapterInterfaceType = Isa;
10090
10091 if(!WinVer_WDM_Model) {
10092 BMList[i].channel = (UCHAR)c;
10093 }
10094
10095 KdPrint2((PRINT_PREFIX "Try init channel %d, method %d\n", c, alt));
10096 newStatus = ScsiPortInitialize(DriverObject,
10097 Argument2,
10098 &hwInitializationData.comm,
10099 (PVOID)(i | (alt ? 0x80000000 : 0)));
10100 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
10101 if (newStatus < statusToReturn) {
10102 statusToReturn = newStatus;
10103 }
10104 if (newStatus == STATUS_SUCCESS) {
10105 if(WinVer_Id() < WinVer_2k) {
10106 // This should be done in HwInitialize under w2k+ to ensure that
10107 // channel is actually initialized
10108 BMList[i].ChanInitOk |= 0x01 << c;
10109 } else {
10110 if(BMList[i].ChanInitOk & (0x01 << c)) {
10111 KdPrint2((PRINT_PREFIX "HwInit passed\n"));
10112 }
10113 }
10114 /*
10115 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
10116 c = 1; // this will break our for()
10117 BMList[i].ChanInitOk |= 0x01 << c;
10118 }
10119 */
10120 }
10121 }
10122 /* if(WinVer_Id() >= WinVer_2k) {
10123 // the following didn't work under higher OSes,
10124 // until we move setting of FLAGS to HwInit
10125 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
10126 continue;
10127 }*/
10128 if(BMList[i].ChanInitOk & 0x03) {
10129 // Under NT we receive status immediately, so
10130 // we can omit alternative init method if STATUS_SUCCESS returned.
10131 // Under w2k+ we relay on flags, set in HwInitialize.
10132 KdPrint2((PRINT_PREFIX "Ok, no more retries required\n"));
10133 break;
10134 } else
10135 if(WinVer_Id() >= WinVer_2k) {
10136 // try AltInit if HwInit was not called immediately under w2k+
10137 KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n"));
10138 } else {
10139 // if (WinVer_Id() == WinVer_NT) and some error occured
10140 // try alternative init method
10141 KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n"));
10142 }
10143 } // for(alt...)
10144 if(g_opt_Verbose) {
10145 if(BMList[i].ChanInitOk & 0x03) {
10146 _PrintNtConsole(" OK\n");
10147 } else {
10148 _PrintNtConsole(" failed\n");
10149 }
10150 }
10151
10152 }
10153
10154 /* KeBugCheckEx(0xc000000e,
10155 (i << 16) | BMList[0].ChanInitOk,
10156 c,
10157 newStatus, statusToReturn);*/
10158
10159 // Look for PCI IDE controller
10160 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for PCI IDE controller\n"));
10161 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: i %d, BMListLen %d\n", i, BMListLen));
10162 for (; i <BMListLen; i++) {
10163
10164 if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreNativePci", 0)) {
10165 break;
10166 }
10167 /* if(BMList[i].MasterDev)
10168 continue;*/
10169 if(g_opt_Verbose) {
10170 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
10171 BMList[i].VendorId, BMList[i].DeviceId,
10172 BMList[i].busNumber,
10173 BMList[i].slotNumber % PCI_MAX_FUNCTION,
10174 (BMList[i].slotNumber / PCI_MAX_FUNCTION) % PCI_MAX_DEVICES);
10175 }
10176
10177 hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
10178 hwInitializationData.comm.NumberOfAccessRanges = 6;
10179 hwInitializationData.comm.AdapterInterfaceType = PCIBus;
10180
10181 hwInitializationData.comm.VendorId = (PVOID)BMList[i].VendorId;
10182 hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength;
10183 hwInitializationData.comm.DeviceId = (PVOID)BMList[i].DeviceId;
10184 hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength;
10185
10186 BMList[i].channel = 0/*(UCHAR)c*/;
10187
10188 KdPrint2((PRINT_PREFIX "Try init %4.4s %4.4s \n",
10189 hwInitializationData.comm.VendorId,
10190 hwInitializationData.comm.DeviceId));
10191 newStatus = ScsiPortInitialize(DriverObject,
10192 Argument2,
10193 &hwInitializationData.comm,
10194 (PVOID)i);
10195 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
10196 if(newStatus == (ULONG)STATUS_DEVICE_DOES_NOT_EXIST && BMList[i].NeedAltInit) {
10197 // Note: this is actually a BUG in scsiport.sys
10198 // It stops scanning PCI bus when reaches empty PCI Function inside Slot
10199 // However, this PCI Slot may have higher non-empty Functions
10200 // UniATA will perform all staff instead of ScsiPort under NT,
10201 // but for ReactOS it is better to patch ScsiPort.
10202 KdPrint2((PRINT_PREFIX "STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
10203 hwInitializationData.comm.AdapterInterfaceType = Isa;
10204 newStatus = ScsiPortInitialize(DriverObject,
10205 Argument2,
10206 &hwInitializationData.comm,
10207 (PVOID)(i | 0x80000000));
10208 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x (2)\n", newStatus));
10209 }
10210 if (newStatus < statusToReturn)
10211 statusToReturn = newStatus;
10212
10213 if(g_opt_Verbose) {
10214 if(newStatus == STATUS_SUCCESS) {
10215 _PrintNtConsole(" OK\n");
10216 } else {
10217 _PrintNtConsole(" failed\n");
10218 }
10219 }
10220
10221 }
10222
10223 /* KeBugCheckEx(0xc000000e,
10224 i,
10225 c,
10226 newStatus, statusToReturn);*/
10227
10228 // --------------
10229
10230 hwInitializationData.comm.VendorId = 0;
10231 hwInitializationData.comm.VendorIdLength = 0;
10232 hwInitializationData.comm.DeviceId = 0;
10233 hwInitializationData.comm.DeviceIdLength = 0;
10234
10235 if(!BMListLen) {
10236 hwInitializationData.comm.SrbExtensionSize = //FIELD_OFFSET(ATA_REQ, ata);
10237 sizeof(ATA_REQ);
10238 KdPrint2((PRINT_PREFIX "using AtaReq sz %x\n", hwInitializationData.comm.SrbExtensionSize));
10239 }
10240
10241 // The adapter count is used by the find adapter routine to track how
10242 // which adapter addresses have been tested.
10243
10244 // Indicate 2 access ranges and reset FindAdapter.
10245 hwInitializationData.comm.NumberOfAccessRanges = 2;
10246 hwInitializationData.comm.HwFindAdapter = AtapiFindController;
10247
10248 if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsa", 0)) {
10249 // Indicate ISA bustype.
10250 hwInitializationData.comm.AdapterInterfaceType = Isa;
10251 adapterCount = 0;
10252
10253 // Call initialization for ISA bustype.
10254 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for ISA Controllers\n"));
10255 newStatus = ScsiPortInitialize(DriverObject,
10256 Argument2,
10257 &hwInitializationData.comm,
10258 &adapterCount);
10259 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
10260 if (newStatus < statusToReturn)
10261 statusToReturn = newStatus;
10262 }
10263 if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreMca", 0)) {
10264 // Set up for MCA
10265 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for MCA Controllers\n"));
10266 hwInitializationData.comm.AdapterInterfaceType = MicroChannel;
10267 adapterCount = 0;
10268
10269 newStatus = ScsiPortInitialize(DriverObject,
10270 Argument2,
10271 &hwInitializationData.comm,
10272 &adapterCount);
10273 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
10274 if (newStatus < statusToReturn)
10275 statusToReturn = newStatus;
10276 }
10277 InDriverEntry = FALSE;
10278
10279 KdPrint2((PRINT_PREFIX "\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn));
10280
10281 return statusToReturn;
10282
10283 } // end DriverEntry()
10284
10285
10286 PSCSI_REQUEST_BLOCK
10287 NTAPI
10288 BuildMechanismStatusSrb(
10289 IN PVOID HwDeviceExtension,
10290 IN PSCSI_REQUEST_BLOCK Srb
10291 )
10292 {
10293 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10294 PSCSI_REQUEST_BLOCK srb;
10295 PCDB cdb;
10296 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
10297
10298 srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb);
10299
10300 RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
10301
10302 srb->PathId = (UCHAR)(Srb->PathId);
10303 srb->TargetId = (UCHAR)(Srb->TargetId);
10304 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
10305 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
10306
10307 // Set flags to disable synchronous negociation.
10308 srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
10309
10310 // Set timeout to 4 seconds.
10311 srb->TimeOutValue = 4;
10312
10313 srb->CdbLength = 6;
10314 srb->DataBuffer = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusData);
10315 srb->DataTransferLength = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
10316 srb->SrbExtension = AtaReq;
10317
10318 // Set CDB operation code.
10319 cdb = (PCDB)srb->Cdb;
10320 cdb->MECH_STATUS.OperationCode = SCSIOP_MECHANISM_STATUS;
10321 cdb->MECH_STATUS.AllocationLength[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
10322
10323 KdPrint2((PRINT_PREFIX " MechanismStatusSrb %#x\n", srb));
10324
10325 return srb;
10326 } // end BuildMechanismStatusSrb()
10327
10328 #endif //UNIATA_CORE
10329
10330 PSCSI_REQUEST_BLOCK
10331 NTAPI
10332 BuildRequestSenseSrb (
10333 IN PVOID HwDeviceExtension,
10334 IN PSCSI_REQUEST_BLOCK Srb
10335 )
10336 {
10337 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10338 PSCSI_REQUEST_BLOCK srb;
10339 PCDB cdb;
10340 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
10341
10342 srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb);
10343
10344 RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
10345
10346 srb->PathId = (UCHAR)(Srb->PathId);
10347 srb->TargetId = (UCHAR)(Srb->TargetId);
10348 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
10349 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
10350
10351 // Set flags to disable synchronous negociation.
10352 srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
10353
10354 // Set timeout to 2 seconds.
10355 srb->TimeOutValue = 4;
10356
10357 srb->CdbLength = 6;
10358 srb->DataBuffer = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusSense);
10359 srb->DataTransferLength = sizeof(SENSE_DATA);
10360 srb->SrbExtension = AtaReq;
10361
10362 // Set CDB operation code.
10363 cdb = (PCDB)srb->Cdb;
10364 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
10365 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
10366
10367 KdPrint2((PRINT_PREFIX " RequestSenseSrb %#x\n", srb));
10368
10369 return srb;
10370 } // end BuildRequestSenseSrb()
10371
10372 #ifndef UNIATA_CORE
10373
10374 ULONG
10375 NTAPI
10376 AtapiRegCheckDevLunValue(
10377 IN PVOID HwDeviceExtension,
10378 IN PCWCH NamePrefix,
10379 IN ULONG chan,
10380 IN ULONG dev,
10381 IN PCWSTR Name,
10382 IN ULONG Default
10383 )
10384 {
10385 WCHAR namex[160];
10386 ULONG val = Default;
10387
10388 val = AtapiRegCheckParameterValue(
10389 HwDeviceExtension, NamePrefix, Name, val);
10390
10391 if(chan != CHAN_NOT_SPECIFIED) {
10392 swprintf(namex, L"%s\\Chan_%1.1d", NamePrefix, chan);
10393 val = AtapiRegCheckParameterValue(
10394 HwDeviceExtension, namex, Name, val);
10395 if(dev != DEVNUM_NOT_SPECIFIED) {
10396 swprintf(namex, L"%s\\Chan_%1.1d\\%s", NamePrefix, chan, (dev & 0x01) ? L"Lun_1" : L"Lun_0");
10397 val = AtapiRegCheckParameterValue(
10398 HwDeviceExtension, namex, Name, val);
10399 }
10400 }
10401 return val;
10402 } // end AtapiRegCheckDevLunValue()
10403
10404 ULONG
10405 NTAPI
10406 EncodeVendorStr(
10407 OUT PWCHAR Buffer,
10408 IN PUCHAR Str,
10409 IN ULONG Length
10410 )
10411 {
10412 ULONG i,j;
10413 WCHAR a;
10414
10415 for(i=0, j=0; i<Length; i++, j++) {
10416 // fix byte-order
10417 a = Str[i ^ 0x01];
10418 if(!a) {
10419 Buffer[j] = 0;
10420 return j;
10421 } else
10422 if(a == ' ') {
10423 Buffer[j] = '_';
10424 } else
10425 if((a == '_') ||
10426 (a == '#') ||
10427 (a == '\\') ||
10428 (a == '\"') ||
10429 (a == '\'') ||
10430 (a < ' ') ||
10431 (a >= 127)) {
10432 Buffer[j] = '#';
10433 j++;
10434 swprintf(Buffer+j, L"%2.2x", a);
10435 j++;
10436 } else {
10437 Buffer[j] = a;
10438 }
10439 }
10440 Buffer[j] = 0;
10441 return j;
10442 } // end EncodeVendorStr()
10443
10444 ULONG
10445 NTAPI
10446 AtapiRegCheckDevValue(
10447 IN PVOID HwDeviceExtension,
10448 IN ULONG chan,
10449 IN ULONG dev,
10450 IN PCWSTR Name,
10451 IN ULONG Default
10452 )
10453 {
10454 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10455 // WCHAR name0[11];
10456 // WCHAR name1[11+4+5];
10457 // WCHAR name2[11+4+4+10];
10458 // WCHAR name3[11+4+4+5+20];
10459 // WCHAR name3[11+4+4+5+20+1];
10460 WCHAR namex[160];
10461
10462 WCHAR namev[16];
10463 WCHAR named[16];
10464 WCHAR names[20];
10465
10466 IN ULONG VendorID;
10467 IN ULONG DeviceID;
10468 IN ULONG SlotNumber;
10469
10470 ULONG val = Default;
10471
10472 KdPrint(( " Parameter %ws\n", Name));
10473
10474 if(deviceExtension) {
10475 VendorID = deviceExtension->DevID & 0xffff;
10476 DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
10477 SlotNumber = deviceExtension->slotNumber;
10478 } else {
10479 VendorID = 0xffff;
10480 DeviceID = 0xffff;
10481 SlotNumber = 0xffffffff;
10482 }
10483
10484 val = AtapiRegCheckDevLunValue(
10485 HwDeviceExtension, L"Parameters", chan, dev, Name, val);
10486
10487 if(deviceExtension) {
10488 if(deviceExtension->AdapterInterfaceType == PCIBus) {
10489 // PCI
10490 swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex);
10491 swprintf(namex, L"Parameters%s", namev);
10492 val = AtapiRegCheckDevLunValue(
10493 HwDeviceExtension, namex, chan, dev, Name, val);
10494
10495
10496 swprintf(namev, L"\\Ven_%4.4x", VendorID);
10497 swprintf(named, L"\\Dev_%4.4x", DeviceID);
10498 swprintf(names, L"\\Slot_%8.8x", SlotNumber);
10499
10500 swprintf(namex, L"Parameters%s", namev);
10501 val = AtapiRegCheckDevLunValue(
10502 HwDeviceExtension, namex, chan, dev, Name, val);
10503
10504 swprintf(namex, L"Parameters%s%s", namev, named);
10505 val = AtapiRegCheckDevLunValue(
10506 HwDeviceExtension, namex, chan, dev, Name, val);
10507
10508 swprintf(namex, L"Parameters%s%s%s", namev, named, names);
10509 val = AtapiRegCheckDevLunValue(
10510 HwDeviceExtension, namex, chan, dev, Name, val);
10511 } else
10512 if(deviceExtension->AdapterInterfaceType == Isa) {
10513 // Isa
10514 swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen);
10515 swprintf(namex, L"Parameters%s", namev);
10516 val = AtapiRegCheckDevLunValue(
10517 HwDeviceExtension, namex, chan, dev, Name, val);
10518
10519 swprintf(namev, L"\\ISA_%d", deviceExtension->DevIndex);
10520 swprintf(namex, L"Parameters%s", namev);
10521 val = AtapiRegCheckDevLunValue(
10522 HwDeviceExtension, namex, chan, dev, Name, val);
10523
10524 } else
10525 if(deviceExtension->AdapterInterfaceType == MicroChannel) {
10526 // MicroChannel
10527 swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen+IsaCount);
10528 swprintf(namex, L"Parameters%s", namev);
10529 val = AtapiRegCheckDevLunValue(
10530 HwDeviceExtension, namex, chan, dev, Name, val);
10531
10532 swprintf(namev, L"\\MCA_%d", deviceExtension->DevIndex);
10533 swprintf(namex, L"Parameters%s", namev);
10534 val = AtapiRegCheckDevLunValue(
10535 HwDeviceExtension, namex, chan, dev, Name, val);
10536
10537 }
10538 }
10539
10540 KdPrint(( " Parameter %ws = %#x\n", Name, val));
10541 return val;
10542
10543 } // end AtapiRegCheckDevValue()
10544
10545 /*
10546 The user must specify that Xxx is to run on the platform
10547 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
10548 Services\UniATA\Xxx:REG_DWORD:Zzz.
10549
10550 The user can override the global setting to enable or disable Xxx on a
10551 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
10552 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
10553
10554 If this registry value does not exist or contains the value zero then
10555 the timer to check for media change does not run.
10556
10557 Arguments:
10558
10559 RegistryPath - pointer to the unicode string inside
10560 ...\CurrentControlSet\Services\UniATA
10561 DeviceNumber - The number of the HBA device object
10562
10563 Returns: Registry Key value
10564 */
10565 ULONG
10566 NTAPI
10567 AtapiRegCheckParameterValue(
10568 IN PVOID HwDeviceExtension,
10569 IN PCWSTR PathSuffix,
10570 IN PCWSTR Name,
10571 IN ULONG Default
10572 )
10573 {
10574 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
10575
10576 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10577 NTSTATUS status;
10578 LONG zero = Default;
10579
10580 RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY];
10581
10582 // LONG tmp = 0;
10583 LONG doRun = Default;
10584
10585 PUNICODE_STRING RegistryPath = &SavedRegPath;
10586
10587 UNICODE_STRING paramPath;
10588
10589 // <SavedRegPath>\<PathSuffix> -> <Name>
10590 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
10591 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
10592
10593 paramPath.Length = 0;
10594 paramPath.MaximumLength = RegistryPath->Length +
10595 (wcslen(PathSuffix)+2)*sizeof(WCHAR);
10596 paramPath.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, paramPath.MaximumLength);
10597 if(!paramPath.Buffer) {
10598 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
10599 return Default;
10600 }
10601
10602 RtlZeroMemory(paramPath.Buffer, paramPath.MaximumLength);
10603 RtlAppendUnicodeToString(&paramPath, RegistryPath->Buffer);
10604 RtlAppendUnicodeToString(&paramPath, L"\\");
10605 RtlAppendUnicodeToString(&paramPath, REGRTL_STR_PTYPE PathSuffix);
10606
10607 // Check for the Xxx value.
10608 RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
10609
10610 parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
10611 parameters[0].Name = REGRTL_STR_PTYPE Name;
10612 parameters[0].EntryContext = &doRun;
10613 parameters[0].DefaultType = REG_DWORD;
10614 parameters[0].DefaultData = &zero;
10615 parameters[0].DefaultLength = sizeof(ULONG);
10616
10617 status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/,
10618 paramPath.Buffer, parameters, NULL, NULL);
10619 if(NT_SUCCESS(status)) {
10620 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun));
10621 }
10622
10623 ExFreePool(paramPath.Buffer);
10624
10625 if(!NT_SUCCESS(status)) {
10626 doRun = Default;
10627 }
10628
10629 return doRun;
10630
10631 #undef ITEMS_TO_QUERY
10632
10633 } // end AtapiRegCheckParameterValue()
10634
10635
10636 SCSI_ADAPTER_CONTROL_STATUS
10637 NTAPI
10638 AtapiAdapterControl(
10639 IN PVOID HwDeviceExtension,
10640 IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
10641 IN PVOID Parameters
10642 )
10643 {
10644 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10645 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList;
10646 ULONG numberChannels = deviceExtension->NumberChannels;
10647 ULONG c;
10648 NTSTATUS status;
10649
10650 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType));
10651
10652 switch(ControlType) {
10653 case ScsiQuerySupportedControlTypes: {
10654 BOOLEAN supportedTypes[ScsiAdapterControlMax] = {
10655 TRUE, // ScsiQuerySupportedControlTypes
10656 TRUE, // ScsiStopAdapter
10657 TRUE, // ScsiRestartAdapter
10658 FALSE, // ScsiSetBootConfig
10659 FALSE // ScsiSetRunningConfig
10660 };
10661
10662 ULONG lim = ScsiAdapterControlMax;
10663 ULONG i;
10664
10665 pControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST) Parameters;
10666
10667 if(pControlTypeList->MaxControlType < lim) {
10668 lim = pControlTypeList->MaxControlType;
10669 }
10670
10671 for(i = 0; i < lim; i++) {
10672 pControlTypeList->SupportedTypeList[i] = supportedTypes[i];
10673 }
10674
10675 break;
10676
10677 }
10678 case ScsiStopAdapter: {
10679
10680 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
10681 // Shut down all interrupts on the adapter. They'll get re-enabled
10682 // by the initialization routines.
10683 for (c = 0; c < numberChannels; c++) {
10684 AtapiResetController(deviceExtension, c);
10685 AtapiDisableInterrupts(deviceExtension, c);
10686 }
10687 if(deviceExtension->AdapterInterfaceType == PCIBus) {
10688 // we must never get here for non-PCI
10689 status = UniataDisconnectIntr2(HwDeviceExtension);
10690 BMList[deviceExtension->DevIndex].Isr2Enable = FALSE;
10691 }
10692 break;
10693 }
10694 case ScsiRestartAdapter: {
10695
10696 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
10697 // Enable all the interrupts on the adapter while port driver call
10698 // for power up an HBA that was shut down for power management
10699
10700 AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
10701 status = UniataConnectIntr2(HwDeviceExtension);
10702 for (c = 0; c < numberChannels; c++) {
10703 AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, c);
10704 FindDevices(HwDeviceExtension, 0, c);
10705 AtapiEnableInterrupts(deviceExtension, c);
10706 AtapiHwInitialize__(deviceExtension, c);
10707 }
10708 if(deviceExtension->Isr2DevObj) {
10709 // we must never get here for non-PCI
10710 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
10711 }
10712
10713 break;
10714 }
10715
10716 default: {
10717 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
10718 return ScsiAdapterControlUnsuccessful;
10719 }
10720 }
10721
10722 return ScsiAdapterControlSuccess;
10723 } // end AtapiAdapterControl()
10724
10725 #endif //UNIATA_CORE
10726
10727 extern "C"
10728 NTHALAPI
10729 VOID
10730 NTAPI
10731 HalDisplayString (
10732 PUCHAR String
10733 );
10734
10735 extern "C"
10736 VOID
10737 _cdecl
10738 _PrintNtConsole(
10739 PCCH DebugMessage,
10740 ...
10741 )
10742 {
10743 int len;
10744 UCHAR dbg_print_tmp_buff[512];
10745 // UNICODE_STRING msgBuff;
10746 va_list ap;
10747 va_start(ap, DebugMessage);
10748
10749 len = _vsnprintf((PCHAR)&dbg_print_tmp_buff[0], 511, DebugMessage, ap);
10750
10751 dbg_print_tmp_buff[511] = 0;
10752
10753 KdPrint(((PCHAR)&(dbg_print_tmp_buff[0])));
10754 HalDisplayString(dbg_print_tmp_buff);
10755
10756 va_end(ap);
10757
10758 } // end PrintNtConsole()
10759