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