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