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