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