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