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