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