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