e62398539f2dbf668ad81e7e7791e01fb5d9b6a5
[reactos.git] / reactos / drivers / storage / ide / uniata / id_ata.cpp
1 /*++
2
3 Copyright (c) 2002-2008 Alexandr A. Telyatnikov (Alter)
4
5 Module Name:
6 id_ata.cpp
7
8 Abstract:
9 This is the miniport driver for ATA/ATAPI IDE controllers
10 with Busmaster DMA and Serial ATA support
11
12 Author:
13 Alexander A. Telyatnikov (Alter)
14
15 Environment:
16 kernel mode only
17
18 Notes:
19
20 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 Revision History:
32
33 The skeleton was taken from standard ATAPI.SYS from NT4 DDK by
34 Mike Glass (MGlass)
35 Chuck Park (ChuckP)
36
37 Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by
38 Søren Schmidt, Copyright (c) 1998-2007
39
40 All parts of code are greatly changed/updated by
41 Alter, Copyright (c) 2002-2007:
42
43 1. Internal command queueing/reordering
44 2. Drive identification
45 3. Support for 2 _independent_ channels in a single PCI device
46 4. Smart host<->drive transfer rate slowdown (for bad cable)
47 5. W2k support (binary compatibility)
48 6. HDD hot swap under NT4
49 7. XP support (binary compatibility)
50 8. Serial ATA (SATA/SATA2) support
51 9. NT 3.51 support (binary compatibility)
52
53 etc. (See todo.txt)
54
55
56 --*/
57
58 #include "stdafx.h"
59
60 #ifndef UNIATA_CORE
61
62 static const CHAR ver_string[] = "\n\nATAPI IDE MiniPort Driver (UniATA) v 0." UNIATA_VER_STR "\n";
63
64 static const CHAR uniata_comm_name[] = UNIATA_COMM_PORT_VENDOR_STR " \n";
65
66 UNICODE_STRING SavedRegPath;
67 WCHAR SavedRegPathBuffer[256];
68
69 #endif //UNIATA_CORE
70
71 UCHAR AtaCommands48[256];
72 UCHAR AtaCommandFlags[256];
73
74 ULONG SkipRaids = 1;
75 ULONG ForceSimplex = 0;
76
77 LONGLONG g_Perf = 0;
78 ULONG g_PerfDt = 0;
79
80 #ifdef _DEBUG
81 ULONG g_LogToDisplay = 0;
82 #endif //_DEBUG
83
84 ULONG g_WaitBusyInISR = 1;
85
86 BOOLEAN InDriverEntry = TRUE;
87
88 BOOLEAN g_opt_Verbose = 0;
89
90 BOOLEAN WinVer_WDM_Model = FALSE;
91 //UCHAR EnableDma = FALSE;
92 //UCHAR EnableReorder = FALSE;
93
94 UCHAR g_foo = 0;
95
96 BOOLEAN
97 DDKAPI
98 AtapiResetController__(
99 IN PVOID HwDeviceExtension,
100 IN ULONG PathId,
101 IN UCHAR CompleteType
102 );
103
104 VOID
105 NTAPI
106 AtapiHwInitialize__(
107 IN PHW_DEVICE_EXTENSION deviceExtension,
108 IN ULONG lChannel
109 );
110
111 #define RESET_COMPLETE_CURRENT 0x00
112 #define RESET_COMPLETE_ALL 0x01
113 #define RESET_COMPLETE_NONE 0x02
114
115 #ifndef UNIATA_CORE
116
117 VOID
118 DDKAPI
119 AtapiCallBack_X(
120 IN PVOID HwDeviceExtension
121 );
122
123 #ifdef UNIATA_USE_XXableInterrupts
124 #define RETTYPE_XXableInterrupts BOOLEAN
125 #define RETVAL_XXableInterrupts TRUE
126 #else
127 #define RETTYPE_XXableInterrupts VOID
128 #define RETVAL_XXableInterrupts
129 #endif
130
131 RETTYPE_XXableInterrupts
132 DDKAPI
133 AtapiInterruptDpc(
134 IN PVOID HwDeviceExtension
135 );
136
137 RETTYPE_XXableInterrupts
138 DDKAPI
139 AtapiEnableInterrupts__(
140 IN PVOID HwDeviceExtension
141 );
142
143 VOID
144 NTAPI
145 AtapiQueueTimerDpc(
146 IN PVOID HwDeviceExtension,
147 IN ULONG lChannel,
148 IN PHW_TIMER HwScsiTimer,
149 IN ULONG MiniportTimerValue
150 );
151
152 SCSI_ADAPTER_CONTROL_STATUS
153 DDKAPI
154 AtapiAdapterControl(
155 IN PVOID HwDeviceExtension,
156 IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
157 IN PVOID Parameters
158 );
159
160 #endif //UNIATA_CORE
161
162 BOOLEAN
163 NTAPI
164 AtapiCheckInterrupt__(
165 IN PVOID HwDeviceExtension,
166 IN UCHAR c
167 );
168
169
170 #ifndef UNIATA_CORE
171
172 BOOLEAN
173 NTAPI
174 AtapiRegGetStringParameterValue(
175 IN PWSTR RegistryPath,
176 IN PWSTR Name,
177 IN PWCHAR Str,
178 IN ULONG MaxLen
179 )
180 {
181 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
182 NTSTATUS status;
183 RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY];
184 UNICODE_STRING ustr;
185
186 ustr.Buffer = Str;
187 ustr.Length =
188 ustr.MaximumLength = (USHORT)MaxLen;
189 RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
190
191 parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
192 parameters[0].Name = Name;
193 parameters[0].EntryContext = &ustr;
194 parameters[0].DefaultType = REG_SZ;
195 parameters[0].DefaultData = Str;
196 parameters[0].DefaultLength = MaxLen;
197
198 status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/,
199 RegistryPath, parameters, NULL, NULL);
200
201 if(!NT_SUCCESS(status))
202 return FALSE;
203
204 return TRUE;
205
206 #undef ITEMS_TO_QUERY
207 } // end AtapiRegGetStringParameterValue()
208
209
210 #endif //UNIATA_CORE
211
212 VOID
213 DDKFASTAPI
214 UniataNanoSleep(
215 ULONG nano
216 )
217 {
218 LONGLONG t;
219 LARGE_INTEGER t0;
220
221 #ifdef NAVO_TEST
222 return;
223 #endif //NAVO_TEST
224
225 if(!nano || !g_Perf || !g_PerfDt)
226 return;
227 t = (g_Perf * nano) / g_PerfDt / 1000;
228 if(!t) {
229 t = 1;
230 }
231 do {
232 KeQuerySystemTime(&t0);
233 t--;
234 } while(t);
235 } // end UniataNanoSleep()
236
237
238 #define AtapiWritePortN_template(_type, _Type, sz) \
239 VOID \
240 DDKFASTAPI \
241 AtapiWritePort##sz( \
242 IN PHW_CHANNEL chan, \
243 IN ULONG _port, \
244 IN _type data \
245 ) \
246 { \
247 PIORES res; \
248 if(_port >= IDX_MAX_REG) { \
249 res = (PIORES)(_port); \
250 } else \
251 if(chan) { \
252 res = &chan->RegTranslation[_port]; \
253 } else { \
254 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
255 return; \
256 } \
257 if(!res->MemIo) { \
258 ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
259 } else { \
260 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
261 ScsiPortWriteRegister##_Type((_type*)(res->Addr), data); \
262 } \
263 return; \
264 }
265
266 AtapiWritePortN_template(ULONG, Ulong, 4);
267 AtapiWritePortN_template(USHORT, Ushort, 2);
268 AtapiWritePortN_template(UCHAR, Uchar, 1);
269
270 #define AtapiWritePortExN_template(_type, _Type, sz) \
271 VOID \
272 DDKFASTAPI \
273 AtapiWritePortEx##sz( \
274 IN PHW_CHANNEL chan, \
275 IN ULONG _port, \
276 IN ULONG offs, \
277 IN _type data \
278 ) \
279 { \
280 PIORES res; \
281 if(_port >= IDX_MAX_REG) { \
282 res = (PIORES)(_port); \
283 } else \
284 if(chan) { \
285 res = &chan->RegTranslation[_port]; \
286 } else { \
287 KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
288 return; \
289 } \
290 if(!res->MemIo) { \
291 ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
292 } else { \
293 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
294 ScsiPortWriteRegister##_Type((_type*)(res->Addr+offs), data); \
295 } \
296 return; \
297 }
298
299 AtapiWritePortExN_template(ULONG, Ulong, 4);
300 //AtapiWritePortExN_template(USHORT, Ushort, 2);
301 AtapiWritePortExN_template(UCHAR, Uchar, 1);
302
303 #define AtapiReadPortN_template(_type, _Type, sz) \
304 _type \
305 DDKFASTAPI \
306 AtapiReadPort##sz( \
307 IN PHW_CHANNEL chan, \
308 IN ULONG _port \
309 ) \
310 { \
311 PIORES res; \
312 if(_port >= IDX_MAX_REG) { \
313 res = (PIORES)(_port); \
314 } else \
315 if(chan) { \
316 res = &chan->RegTranslation[_port]; \
317 } else { \
318 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
319 return (_type)(-1); \
320 } \
321 if(!res->MemIo) { \
322 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
323 return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
324 } else { \
325 /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
326 return ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
327 } \
328 }
329
330 AtapiReadPortN_template(ULONG, Ulong, 4);
331 AtapiReadPortN_template(USHORT, Ushort, 2);
332 AtapiReadPortN_template(UCHAR, Uchar, 1);
333
334 #define AtapiReadPortExN_template(_type, _Type, sz) \
335 _type \
336 DDKFASTAPI \
337 AtapiReadPortEx##sz( \
338 IN PHW_CHANNEL chan, \
339 IN ULONG _port, \
340 IN ULONG offs \
341 ) \
342 { \
343 PIORES res; \
344 if(_port >= IDX_MAX_REG) { \
345 res = (PIORES)(_port); \
346 } else \
347 if(chan) { \
348 res = &chan->RegTranslation[_port]; \
349 } else { \
350 KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
351 return (_type)(-1); \
352 } \
353 if(!res->MemIo) { \
354 return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
355 } else { \
356 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
357 return ScsiPortReadRegister##_Type((_type*)(res->Addr+offs)); \
358 } \
359 }
360
361 AtapiReadPortExN_template(ULONG, Ulong, 4);
362 //AtapiReadPortExN_template(USHORT, Ushort, 2);
363 AtapiReadPortExN_template(UCHAR, Uchar, 1);
364
365 #define AtapiReadPortBufferN_template(_type, _Type, sz) \
366 VOID \
367 DDKFASTAPI \
368 AtapiReadBuffer##sz( \
369 IN PHW_CHANNEL chan, \
370 IN ULONG _port, \
371 IN PVOID Buffer, \
372 IN ULONG Count, \
373 IN ULONG Timing \
374 ) \
375 { \
376 PIORES res; \
377 \
378 if(Timing) { \
379 while(Count) { \
380 (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
381 Count--; \
382 Buffer = ((_type*)Buffer)+1; \
383 UniataNanoSleep(Timing); \
384 } \
385 return; \
386 } \
387 \
388 if(_port >= IDX_MAX_REG) { \
389 res = (PIORES)(_port); \
390 } else \
391 if(chan) { \
392 res = &chan->RegTranslation[_port]; \
393 } else { \
394 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
395 return; \
396 } \
397 if(!res->MemIo) { \
398 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
399 ScsiPortReadPortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
400 return; \
401 } \
402 while(Count) { \
403 (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
404 Count--; \
405 Buffer = ((_type*)Buffer)+1; \
406 } \
407 return; \
408 }
409
410 #define AtapiWritePortBufferN_template(_type, _Type, sz) \
411 VOID \
412 DDKFASTAPI \
413 AtapiWriteBuffer##sz( \
414 IN PHW_CHANNEL chan, \
415 IN ULONG _port, \
416 IN PVOID Buffer, \
417 IN ULONG Count, \
418 IN ULONG Timing \
419 ) \
420 { \
421 PIORES res; \
422 \
423 if(Timing) { \
424 while(Count) { \
425 AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
426 Buffer = ((_type*)Buffer)+1; \
427 Count--; \
428 UniataNanoSleep(Timing); \
429 } \
430 return; \
431 } \
432 \
433 if(_port >= IDX_MAX_REG) { \
434 res = (PIORES)(_port); \
435 } else \
436 if(chan) { \
437 res = &chan->RegTranslation[_port]; \
438 } else { \
439 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
440 return; \
441 } \
442 if(!res->MemIo) { \
443 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
444 ScsiPortWritePortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
445 return; \
446 } \
447 while(Count) { \
448 ScsiPortWriteRegister##_Type((_type*)(res->Addr), *((_type*)Buffer)); \
449 Count--; \
450 Buffer = ((_type*)Buffer)+1; \
451 } \
452 return; \
453 }
454
455 AtapiWritePortBufferN_template(ULONG, Ulong, 4);
456 AtapiWritePortBufferN_template(USHORT, Ushort, 2);
457
458 AtapiReadPortBufferN_template(ULONG, Ulong, 4);
459 AtapiReadPortBufferN_template(USHORT, Ushort, 2);
460
461
462 UCHAR
463 DDKFASTAPI
464 AtapiSuckPort2(
465 IN PHW_CHANNEL chan
466 )
467 {
468 UCHAR statusByte;
469 ULONG i;
470
471 WaitOnBusyLong(chan);
472 for (i = 0; i < 0x10000; i++) {
473
474 GetStatus(chan, statusByte);
475 if (statusByte & IDE_STATUS_DRQ) {
476 // Suck out any remaining bytes and throw away.
477 AtapiReadPort2(chan, IDX_IO1_i_Data);
478 } else {
479 break;
480 }
481 }
482 if(i) {
483 KdPrint2((PRINT_PREFIX "AtapiSuckPort2: overrun detected (%#x words)\n", i ));
484 }
485 return statusByte;
486 } // AtapiSuckPort2()
487
488 UCHAR
489 DDKFASTAPI
490 WaitOnBusy(
491 IN PHW_CHANNEL chan
492 )
493 {
494 ULONG i;
495 UCHAR Status;
496 for (i=0; i<200; i++) {
497 GetStatus(chan, Status);
498 if (Status & IDE_STATUS_BUSY) {
499 AtapiStallExecution(10);
500 continue;
501 } else {
502 break;
503 }
504 }
505 return Status;
506 } // end WaitOnBusy()
507
508 UCHAR
509 DDKFASTAPI
510 WaitOnBusyLong(
511 IN PHW_CHANNEL chan
512 )
513 {
514 ULONG i;
515 UCHAR Status;
516
517 Status = WaitOnBusy(chan);
518 if(!(Status & IDE_STATUS_BUSY))
519 return Status;
520 for (i=0; i<2000; i++) {
521 GetStatus(chan, Status);
522 if (Status & IDE_STATUS_BUSY) {
523 AtapiStallExecution(250);
524 continue;
525 } else {
526 break;
527 }
528 }
529 return Status;
530 } // end WaitOnBusyLong()
531
532 UCHAR
533 DDKFASTAPI
534 WaitOnBaseBusy(
535 IN PHW_CHANNEL chan
536 )
537 {
538 ULONG i;
539 UCHAR Status;
540 for (i=0; i<200; i++) {
541 GetBaseStatus(chan, Status);
542 if (Status & IDE_STATUS_BUSY) {
543 AtapiStallExecution(10);
544 continue;
545 } else {
546 break;
547 }
548 }
549 return Status;
550 } // end WaitOnBaseBusy()
551
552 UCHAR
553 DDKFASTAPI
554 WaitOnBaseBusyLong(
555 IN PHW_CHANNEL chan
556 )
557 {
558 ULONG i;
559 UCHAR Status;
560
561 Status = WaitOnBaseBusy(chan);
562 if(!(Status & IDE_STATUS_BUSY))
563 return Status;
564 for (i=0; i<2000; i++) {
565 GetBaseStatus(chan, Status);
566 if (Status & IDE_STATUS_BUSY) {
567 AtapiStallExecution(250);
568 continue;
569 } else {
570 break;
571 }
572 }
573 return Status;
574 } // end WaitOnBaseBusyLong()
575
576 UCHAR
577 DDKFASTAPI
578 UniataIsIdle(
579 IN struct _HW_DEVICE_EXTENSION* deviceExtension,
580 IN UCHAR Status
581 )
582 {
583 UCHAR Status2;
584
585 if(Status == 0xff) {
586 return 0xff;
587 }
588 if(Status & IDE_STATUS_BUSY) {
589 return Status;
590 }
591 // if(deviceExtension->HwFlags & UNIATA_SATA) {
592 if(UniataIsSATARangeAvailable(deviceExtension, 0)) {
593 if(Status & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
594 return Status;
595 }
596 } else {
597 Status2 = Status & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX);
598 if ((Status & IDE_STATUS_BUSY) ||
599 (Status2 != IDE_STATUS_IDLE && Status2 != IDE_STATUS_DRDY)) {
600 return Status;
601 }
602 }
603 return IDE_STATUS_IDLE;
604 } // end UniataIsIdle()
605
606 UCHAR
607 DDKFASTAPI
608 WaitForIdleLong(
609 IN PHW_CHANNEL chan
610 )
611 {
612 ULONG i;
613 UCHAR Status;
614 UCHAR Status2;
615 for (i=0; i<20000; i++) {
616 GetStatus(chan, Status);
617 Status2 = UniataIsIdle(chan->DeviceExtension, Status);
618 if(Status2 == 0xff) {
619 // no drive ?
620 break;
621 } else
622 if(Status2 & IDE_STATUS_BUSY) {
623 AtapiStallExecution(10);
624 continue;
625 } else {
626 break;
627 }
628 }
629 return Status;
630 } // end WaitForIdleLong()
631
632 UCHAR
633 DDKFASTAPI
634 WaitForDrq(
635 IN PHW_CHANNEL chan
636 )
637 {
638 ULONG i;
639 UCHAR Status;
640 for (i=0; i<1000; i++) {
641 GetStatus(chan, Status);
642 if (Status & IDE_STATUS_BUSY) {
643 AtapiStallExecution(10);
644 } else if (Status & IDE_STATUS_DRQ) {
645 break;
646 } else {
647 AtapiStallExecution(10);
648 }
649 }
650 return Status;
651 } // end WaitForDrq()
652
653 UCHAR
654 DDKFASTAPI
655 WaitShortForDrq(
656 IN PHW_CHANNEL chan
657 )
658 {
659 ULONG i;
660 UCHAR Status;
661 for (i=0; i<2; i++) {
662 GetStatus(chan, Status);
663 if (Status & IDE_STATUS_BUSY) {
664 AtapiStallExecution(10);
665 } else if (Status & IDE_STATUS_DRQ) {
666 break;
667 } else {
668 AtapiStallExecution(10);
669 }
670 }
671 return Status;
672 } // end WaitShortForDrq()
673
674 VOID
675 DDKFASTAPI
676 AtapiSoftReset(
677 IN PHW_CHANNEL chan,
678 ULONG DeviceNumber
679 )
680 {
681 //ULONG c = chan->lChannel;
682 ULONG i = 1000 * 1000;
683 UCHAR dma_status = 0;
684 KdPrint2((PRINT_PREFIX "AtapiSoftReset:\n"));
685 UCHAR statusByte2;
686
687 GetBaseStatus(chan, statusByte2);
688 KdPrint2((PRINT_PREFIX " statusByte2 %x:\n", statusByte2));
689 SelectDrive(chan, DeviceNumber);
690 AtapiStallExecution(10000);
691 AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
692 while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
693 i--)
694 {
695 AtapiStallExecution(30);
696 }
697 SelectDrive(chan, DeviceNumber);
698 WaitOnBusy(chan);
699 GetBaseStatus(chan, statusByte2);
700 AtapiStallExecution(500);
701
702 GetBaseStatus(chan, statusByte2);
703 if(chan && chan->DeviceExtension) {
704 dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
705 KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
706 } else {
707 KdPrint2((PRINT_PREFIX " can't get DMA status\n"));
708 }
709 if(dma_status & BM_STATUS_INTR) {
710 // bullshit, we have DMA interrupt, but had never initiate DMA operation
711 KdPrint2((PRINT_PREFIX " clear unexpected DMA intr on ATAPI reset\n"));
712 AtapiDmaDone(chan->DeviceExtension, DeviceNumber, chan->lChannel, NULL);
713 GetBaseStatus(chan, statusByte2);
714 }
715 if(chan->DeviceExtension->HwFlags & UNIATA_SATA) {
716 UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT);
717 }
718 return;
719
720 } // end AtapiSoftReset()
721
722 /*
723 Send command to device.
724 Translate to 48-Lba form if required
725 */
726 UCHAR
727 NTAPI
728 AtaCommand48(
729 IN PHW_DEVICE_EXTENSION deviceExtension,
730 IN ULONG DeviceNumber,
731 IN ULONG lChannel,
732 IN UCHAR command,
733 IN ULONGLONG lba,
734 IN USHORT count,
735 IN USHORT feature,
736 IN ULONG flags
737 )
738 {
739 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
740 UCHAR statusByte;
741 ULONG ldev = lChannel*2 + DeviceNumber;
742 ULONG i;
743 PUCHAR plba;
744
745 KdPrint2((PRINT_PREFIX "AtaCommand48: cntrlr %#x:%#x ldev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
746 deviceExtension->DevIndex, deviceExtension->Channel, ldev, command, lba, count, feature ));
747
748 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
749 SelectDrive(chan, DeviceNumber);
750
751 statusByte = WaitOnBusy(chan);
752
753 /* ready to issue command ? */
754 if (statusByte & IDE_STATUS_BUSY) {
755 KdPrint2((PRINT_PREFIX " Returning BUSY status\n"));
756 return statusByte;
757 }
758 //}
759 // !!! We should not check ERROR condition here
760 // ERROR bit may be asserted durring previous operation
761 // and not cleared after SELECT
762
763 //>>>>>> NV: 2006/08/03
764 if((AtaCommandFlags[command] & ATA_CMD_FLAG_LBAIOsupp) &&
765 CheckIfBadBlock(&(deviceExtension->lun[ldev]), lba, count)) {
766 KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count));
767 return IDE_STATUS_ERROR;
768 //return SRB_STATUS_ERROR;
769 }
770 //<<<<<< NV: 2006/08/03
771
772 /* only use 48bit addressing if needed because of the overhead */
773 if ((lba >= ATA_MAX_LBA28 || count > 256) &&
774 deviceExtension->lun[ldev].IdentifyData.FeaturesSupport.Address48) {
775
776 KdPrint2((PRINT_PREFIX " ldev %#x USE_LBA_48\n", ldev ));
777 /* translate command into 48bit version */
778 if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) {
779 command = AtaCommands48[command];
780 } else {
781 KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n"));
782 return (UCHAR)-1;
783 }
784
785 chan->ChannelCtrlFlags |= CTRFLAGS_LBA48;
786 plba = (PUCHAR)&lba;
787
788 AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)(feature>>8));
789 AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)feature);
790 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)(count>>8));
791 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)count);
792 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)(plba[3]));
793 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)(plba[0]));
794 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)(plba[4]));
795 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)(plba[1]));
796 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[5]));
797 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[2]));
798
799 //KdPrint2((PRINT_PREFIX "AtaCommand48: ldev %#x USE_LBA48 (2)\n", ldev ));
800 AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) );
801 } else {
802
803 plba = (PUCHAR)&lba; //ktp
804 chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48;
805
806 //if(feature ||
807 // (deviceExtension->lun[ldev].DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
808 AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)feature);
809 //}
810 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)count);
811 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)plba[0]);
812 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)plba[1]);
813 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)plba[2]);
814 if(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_LBA_ENABLED) {
815 //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_LBA\n", ldev ));
816 AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, (UCHAR)(plba[3] & 0xf) | IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
817 } else {
818 //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_CHS\n", ldev ));
819 AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, (UCHAR)(plba[3] & 0xf) | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
820 }
821 }
822
823 // write command code to device
824 AtapiWritePort1(chan, IDX_IO1_o_Command, command);
825
826 switch (flags) {
827 case ATA_WAIT_INTR:
828
829 // caller requested wait for interrupt
830 for(i=0;i<4;i++) {
831 WaitOnBusy(chan);
832 statusByte = WaitForDrq(chan);
833 if (statusByte & IDE_STATUS_DRQ)
834 break;
835 AtapiStallExecution(500);
836 KdPrint2((PRINT_PREFIX " retry waiting DRQ, status %#x\n", statusByte));
837 }
838
839 return statusByte;
840
841 case ATA_WAIT_IDLE:
842
843 // caller requested wait for entering Wait state
844 for (i=0; i<30 * 1000; i++) {
845
846 GetStatus(chan, statusByte);
847 statusByte = UniataIsIdle(deviceExtension, statusByte);
848 if(statusByte == 0xff) {
849 // no drive ?
850 break;
851 } else
852 if(statusByte & IDE_STATUS_ERROR) {
853 break;
854 } else
855 if(statusByte & IDE_STATUS_BUSY) {
856 AtapiStallExecution(100);
857 continue;
858 } else
859 if(statusByte == IDE_STATUS_IDLE) {
860 break;
861 } else {
862 //if(deviceExtension->HwFlags & UNIATA_SATA) {
863 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
864 break;
865 }
866 AtapiStallExecution(100);
867 }
868 }
869 //statusByte |= IDE_STATUS_BUSY;
870 break;
871
872 case ATA_WAIT_READY:
873 statusByte = WaitOnBusyLong(chan);
874 break;
875 case ATA_WAIT_BASE_READY:
876 statusByte = WaitOnBaseBusyLong(chan);
877 break;
878 case ATA_IMMEDIATE:
879 GetStatus(chan, statusByte);
880 if (statusByte & IDE_STATUS_ERROR) {
881 KdPrint2((PRINT_PREFIX " Warning: Immed Status %#x :(\n", statusByte));
882 if(statusByte == (IDE_STATUS_IDLE | IDE_STATUS_ERROR)) {
883 break;
884 }
885 KdPrint2((PRINT_PREFIX " try to continue\n"));
886 statusByte &= ~IDE_STATUS_ERROR;
887 }
888 chan->ExpectingInterrupt = TRUE;
889 // !!!!!
890 InterlockedExchange(&(chan->CheckIntr),
891 CHECK_INTR_IDLE);
892 statusByte = 0;
893 break;
894 }
895
896 KdPrint2((PRINT_PREFIX " Status %#x\n", statusByte));
897
898 return statusByte;
899 } // end AtaCommand48()
900
901 /*
902 Send command to device.
903 This is simply wrapper for AtaCommand48()
904 */
905 UCHAR
906 NTAPI
907 AtaCommand(
908 IN PHW_DEVICE_EXTENSION deviceExtension,
909 IN ULONG DeviceNumber,
910 IN ULONG lChannel,
911 IN UCHAR command,
912 IN USHORT cylinder,
913 IN UCHAR head,
914 IN UCHAR sector,
915 IN UCHAR count,
916 IN UCHAR feature,
917 IN ULONG flags
918 )
919 {
920 return AtaCommand48(deviceExtension, DeviceNumber, lChannel,
921 command,
922 (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
923 count, feature, flags);
924 } // end AtaCommand()
925
926 LONG
927 NTAPI
928 AtaPio2Mode(LONG pio)
929 {
930 switch (pio) {
931 default: return ATA_PIO;
932 case 0: return ATA_PIO0;
933 case 1: return ATA_PIO1;
934 case 2: return ATA_PIO2;
935 case 3: return ATA_PIO3;
936 case 4: return ATA_PIO4;
937 case 5: return ATA_PIO5;
938 }
939 } // end AtaPio2Mode()
940
941 LONG
942 NTAPI
943 AtaPioMode(PIDENTIFY_DATA2 ident)
944 {
945 if (ident->PioTimingsValid) {
946 if (ident->AdvancedPIOModes & AdvancedPIOModes_5)
947 return 5;
948 if (ident->AdvancedPIOModes & AdvancedPIOModes_4)
949 return 4;
950 if (ident->AdvancedPIOModes & AdvancedPIOModes_3)
951 return 3;
952 }
953 if (ident->PioCycleTimingMode == 2)
954 return 2;
955 if (ident->PioCycleTimingMode == 1)
956 return 1;
957 if (ident->PioCycleTimingMode == 0)
958 return 0;
959 return -1;
960 } // end AtaPioMode()
961
962 LONG
963 NTAPI
964 AtaWmode(PIDENTIFY_DATA2 ident)
965 {
966 if (ident->MultiWordDMASupport & 0x04)
967 return 2;
968 if (ident->MultiWordDMASupport & 0x02)
969 return 1;
970 if (ident->MultiWordDMASupport & 0x01)
971 return 0;
972 return -1;
973 } // end AtaWmode()
974
975 LONG
976 NTAPI
977 AtaUmode(PIDENTIFY_DATA2 ident)
978 {
979 if (!ident->UdmaModesValid)
980 return -1;
981 if (ident->UltraDMASupport & 0x40)
982 return 6;
983 if (ident->UltraDMASupport & 0x20)
984 return 5;
985 if (ident->UltraDMASupport & 0x10)
986 return 4;
987 if (ident->UltraDMASupport & 0x08)
988 return 3;
989 if (ident->UltraDMASupport & 0x04)
990 return 2;
991 if (ident->UltraDMASupport & 0x02)
992 return 1;
993 if (ident->UltraDMASupport & 0x01)
994 return 0;
995 return -1;
996 } // end AtaUmode()
997
998
999 #ifndef UNIATA_CORE
1000
1001 VOID
1002 DDKAPI
1003 AtapiTimerDpc(
1004 IN PVOID HwDeviceExtension
1005 )
1006 {
1007 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1008 PHW_TIMER HwScsiTimer;
1009 LARGE_INTEGER time;
1010 ULONG MiniportTimerValue;
1011 BOOLEAN recall = FALSE;
1012 ULONG lChannel;
1013 PHW_CHANNEL chan;
1014
1015 KdPrint2((PRINT_PREFIX "AtapiTimerDpc:\n"));
1016
1017 lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
1018 if(lChannel == CHAN_NOT_SPECIFIED) {
1019 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no items\n"));
1020 return;
1021 }
1022 chan = &deviceExtension->chan[lChannel];
1023
1024 while(TRUE) {
1025
1026 HwScsiTimer = chan->HwScsiTimer;
1027 chan->HwScsiTimer = NULL;
1028
1029 deviceExtension->FirstDpcChan = chan->NextDpcChan;
1030 if(deviceExtension->FirstDpcChan != CHAN_NOT_SPECIFIED) {
1031 recall = TRUE;
1032 }
1033
1034 HwScsiTimer(HwDeviceExtension);
1035
1036 chan->NextDpcChan = CHAN_NOT_SPECIFIED;
1037
1038 lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
1039 if(lChannel == CHAN_NOT_SPECIFIED) {
1040 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no more items\n"));
1041 deviceExtension->FirstDpcChan =
1042 deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
1043 return;
1044 }
1045
1046 KeQuerySystemTime(&time);
1047 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
1048
1049 chan = &deviceExtension->chan[lChannel];
1050 if(time.QuadPart >= chan->DpcTime - 10) {
1051 // call now
1052 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1053 (ULONG)(chan->DpcTime >> 32), (ULONG)(chan->DpcTime)));
1054 continue;
1055 }
1056 break;
1057 }
1058
1059 if(recall) {
1060 deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
1061 MiniportTimerValue = (ULONG)(time.QuadPart - chan->DpcTime)/10;
1062 if(!MiniportTimerValue)
1063 MiniportTimerValue = 1;
1064
1065 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: recall AtapiTimerDpc\n"));
1066 ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
1067 AtapiTimerDpc,
1068 MiniportTimerValue
1069 );
1070 }
1071 return;
1072
1073 } // end AtapiTimerDpc()
1074
1075 /*
1076 Wrapper for ScsiPort, that implements smart Dpc
1077 queueing. We need it to allow parallel functioning
1078 of IDE channles with shared interrupt. Standard Dpc mechanism
1079 cancels previous Dpc request (if any), but we need Dpc queue.
1080 */
1081 VOID
1082 NTAPI
1083 AtapiQueueTimerDpc(
1084 IN PVOID HwDeviceExtension,
1085 IN ULONG lChannel,
1086 IN PHW_TIMER HwScsiTimer,
1087 IN ULONG MiniportTimerValue
1088 )
1089 {
1090 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1091 LARGE_INTEGER time;
1092 LARGE_INTEGER time2;
1093 ULONG i;
1094 PHW_CHANNEL prev_chan;
1095 PHW_CHANNEL chan;
1096 // BOOLEAN UseRequestTimerCall = TRUE;
1097
1098 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
1099 KeQuerySystemTime(&time);
1100 time2 = time;
1101 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
1102 time.QuadPart += MiniportTimerValue*10;
1103 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time.HighPart, time.LowPart));
1104
1105 KdPrint2((PRINT_PREFIX " ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension->ActiveDpcChan, deviceExtension->FirstDpcChan));
1106
1107 i = deviceExtension->FirstDpcChan;
1108 chan = prev_chan = NULL;
1109 while(i != CHAN_NOT_SPECIFIED) {
1110 prev_chan = chan;
1111 chan = &deviceExtension->chan[i];
1112 if(chan->DpcTime > time.QuadPart) {
1113 break;
1114 }
1115 i = chan->NextDpcChan;
1116 }
1117 chan = &deviceExtension->chan[lChannel];
1118 if(!prev_chan) {
1119 deviceExtension->FirstDpcChan = lChannel;
1120 } else {
1121 prev_chan->NextDpcChan = lChannel;
1122 }
1123 chan->NextDpcChan = i;
1124 chan->HwScsiTimer = HwScsiTimer;
1125 chan->DpcTime = time.QuadPart;
1126
1127 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2.HighPart, time2.LowPart));
1128 if(time.QuadPart <= time2.QuadPart) {
1129 MiniportTimerValue = 1;
1130 } else {
1131 MiniportTimerValue = (ULONG)((time.QuadPart - time2.QuadPart) / 10);
1132 }
1133
1134 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
1135 ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
1136 AtapiTimerDpc,
1137 MiniportTimerValue);
1138
1139 } // end AtapiQueueTimerDpc()
1140
1141 #endif //UNIATA_CORE
1142
1143 VOID
1144 NTAPI
1145 UniataDumpATARegs(
1146 IN PHW_CHANNEL chan
1147 )
1148 {
1149 ULONG j;
1150 UCHAR statusByteAlt;
1151
1152 GetStatus(chan, statusByteAlt);
1153 KdPrint2((PRINT_PREFIX " AltStatus (%#x)\n", statusByteAlt));
1154
1155 for(j=1; j<IDX_IO1_SZ; j++) {
1156 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1157 KdPrint2((PRINT_PREFIX
1158 " Reg_%#x (%#x) = %#x\n",
1159 j,
1160 chan->RegTranslation[IDX_IO1+j].Addr,
1161 statusByteAlt));
1162 }
1163 for(j=0; j<IDX_BM_IO_SZ-1; j++) {
1164 statusByteAlt = AtapiReadPort1(chan, IDX_BM_IO+j);
1165 KdPrint2((PRINT_PREFIX
1166 " BM_%#x (%#x) = %#x\n",
1167 j,
1168 chan->RegTranslation[IDX_BM_IO+j].Addr,
1169 statusByteAlt));
1170 }
1171 return;
1172 } // end UniataDumpATARegs()
1173
1174 /*++
1175
1176 Routine Description:
1177
1178 Issue IDENTIFY command to a device.
1179
1180 Arguments:
1181
1182 HwDeviceExtension - HBA miniport driver's adapter data storage
1183 DeviceNumber - Indicates which device.
1184 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1185
1186 Return Value:
1187
1188 TRUE if all goes well.
1189
1190 --*/
1191 BOOLEAN
1192 NTAPI
1193 IssueIdentify(
1194 IN PVOID HwDeviceExtension,
1195 IN ULONG DeviceNumber,
1196 IN ULONG lChannel,
1197 IN UCHAR Command,
1198 IN BOOLEAN NoSetup
1199 )
1200 {
1201 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1202 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1203 ULONG waitCount = 50000;
1204 ULONG j;
1205 UCHAR statusByte;
1206 UCHAR statusByte2;
1207 UCHAR signatureLow,
1208 signatureHigh;
1209 BOOLEAN atapiDev = FALSE;
1210 ULONG ldev = (lChannel * 2) + DeviceNumber;
1211 PHW_LU_EXTENSION LunExt = &(deviceExtension->lun[ldev]);
1212
1213 if(DeviceNumber && (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
1214 KdPrint2((PRINT_PREFIX "IssueIdentify: NO SLAVE\n"));
1215 return FALSE;
1216 }
1217 if(LunExt->DeviceFlags & DFLAGS_HIDDEN) {
1218 KdPrint2((PRINT_PREFIX "IssueIdentify: HIDDEN\n"));
1219 return FALSE;
1220 }
1221
1222 SelectDrive(chan, DeviceNumber);
1223 AtapiStallExecution(10);
1224 statusByte = WaitOnBusyLong(chan);
1225 // Check that the status register makes sense.
1226 GetBaseStatus(chan, statusByte2);
1227
1228 UniataDumpATARegs(chan);
1229
1230 if (Command == IDE_COMMAND_IDENTIFY) {
1231 // Mask status byte ERROR bits.
1232 statusByte = UniataIsIdle(deviceExtension, statusByte & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX));
1233 KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte));
1234 // Check if register value is reasonable.
1235
1236 if(statusByte != IDE_STATUS_IDLE) {
1237
1238 // No reset here !!!
1239 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1240
1241 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1242 if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1243 SelectDrive(chan, DeviceNumber);
1244 WaitOnBusyLong(chan);
1245
1246 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1247 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1248
1249 if (signatureLow == ATAPI_MAGIC_LSB &&
1250 signatureHigh == ATAPI_MAGIC_MSB) {
1251 // Device is Atapi.
1252 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (ldev %d)\n", ldev));
1253 return FALSE;
1254 }
1255
1256 // We really should wait up to 31 seconds
1257 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1258 // (30 seconds for device 1)
1259 do {
1260 // Wait for Busy to drop.
1261 AtapiStallExecution(100);
1262 GetStatus(chan, statusByte);
1263
1264 } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
1265 GetBaseStatus(chan, statusByte2);
1266
1267 SelectDrive(chan, DeviceNumber);
1268 } else {
1269 GetBaseStatus(chan, statusByte2);
1270 }
1271 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1272 // a soft reset.
1273 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1274 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1275
1276 if (signatureLow == ATAPI_MAGIC_LSB &&
1277 signatureHigh == ATAPI_MAGIC_MSB) {
1278 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (2) (ldev %d)\n", ldev));
1279 // Device is Atapi.
1280 return FALSE;
1281 }
1282
1283 statusByte = UniataIsIdle(deviceExtension, statusByte) & ~IDE_STATUS_INDEX;
1284 if (statusByte != IDE_STATUS_IDLE) {
1285 // Give up on this.
1286 KdPrint2((PRINT_PREFIX "IssueIdentify: no dev (ldev %d)\n", ldev));
1287 return FALSE;
1288 }
1289 }
1290 } else {
1291 KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte));
1292 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1293 if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1294 statusByte = WaitForIdleLong(chan);
1295 KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte));
1296 }
1297 atapiDev = TRUE;
1298 }
1299
1300 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1301 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1302 j = 4;
1303 } else {
1304 j = 0;
1305 }
1306 for (; j < 4*2; j++) {
1307 // Send IDENTIFY command.
1308 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, Command, 0, 0, 0, (j >= 4) ? 0x200 : 0, 0, ATA_WAIT_INTR);
1309 // Clear interrupt
1310
1311 if (statusByte & IDE_STATUS_DRQ) {
1312 // Read status to acknowledge any interrupts generated.
1313 KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte));
1314 GetBaseStatus(chan, statusByte);
1315 // One last check for Atapi.
1316 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1317 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1318
1319 if (signatureLow == ATAPI_MAGIC_LSB &&
1320 signatureHigh == ATAPI_MAGIC_MSB) {
1321 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (3) (ldev %d)\n", ldev));
1322 // Device is Atapi.
1323 return FALSE;
1324 }
1325 break;
1326 } else {
1327 KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte));
1328 if (Command == IDE_COMMAND_IDENTIFY) {
1329 // Check the signature. If DRQ didn't come up it's likely Atapi.
1330 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1331 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1332
1333 if (signatureLow == ATAPI_MAGIC_LSB &&
1334 signatureHigh == ATAPI_MAGIC_MSB) {
1335 // Device is Atapi.
1336 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (4) (ldev %d)\n", ldev));
1337 return FALSE;
1338 }
1339 }
1340 // Device didn't respond correctly. It will be given one more chances.
1341 KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1342 statusByte, AtapiReadPort1(chan, IDX_IO1_i_Error)));
1343 GetBaseStatus(chan, statusByte);
1344 AtapiSoftReset(chan,DeviceNumber);
1345
1346 AtapiDisableInterrupts(deviceExtension, lChannel);
1347 AtapiEnableInterrupts(deviceExtension, lChannel);
1348
1349 GetBaseStatus(chan, statusByte);
1350 //GetStatus(chan, statusByte);
1351 KdPrint2((PRINT_PREFIX "IssueIdentify: Status after soft reset (%#x)\n", statusByte));
1352 }
1353 }
1354 // Check for error on really stupid master devices that assert random
1355 // patterns of bits in the status register at the slave address.
1356 if ((Command == IDE_COMMAND_IDENTIFY) && (statusByte & IDE_STATUS_ERROR)) {
1357 KdPrint2((PRINT_PREFIX "IssueIdentify: Exit on error (%#x)\n", statusByte));
1358 return FALSE;
1359 }
1360
1361 KdPrint2((PRINT_PREFIX "IssueIdentify: Status before read words %#x\n", statusByte));
1362 // Suck out 256 words. After waiting for one model that asserts busy
1363 // after receiving the Packet Identify command.
1364 statusByte = WaitForDrq(chan);
1365 statusByte = WaitOnBusyLong(chan);
1366 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1367
1368 if (!(statusByte & IDE_STATUS_DRQ)) {
1369 KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte));
1370 GetBaseStatus(chan, statusByte);
1371 return FALSE;
1372 }
1373 GetBaseStatus(chan, statusByte);
1374 KdPrint2((PRINT_PREFIX "IssueIdentify: BASE statusByte %#x\n", statusByte));
1375
1376 if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
1377
1378 KdPrint2((PRINT_PREFIX " use 16bit IO\n"));
1379 #if 0
1380 USHORT w;
1381 ULONG i;
1382 // ATI/SII chipsets with memory-mapped IO hangs when
1383 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1384 // Unfortunately, I don't know yet how to workaround it except the way you see below.
1385 KdPrint2((PRINT_PREFIX
1386 " IO_%#x (%#x), %s:\n",
1387 IDX_IO1_i_Data,
1388 chan->RegTranslation[IDX_IO1_i_Data].Addr,
1389 chan->RegTranslation[IDX_IO1_i_Data].MemIo ? "Mem" : "IO"));
1390 for(i=0; i<256; i++) {
1391 /*
1392 KdPrint2((PRINT_PREFIX
1393 " IO_%#x (%#x):\n",
1394 IDX_IO1_i_Data,
1395 chan->RegTranslation[IDX_IO1_i_Data].Addr));
1396 */
1397 w = AtapiReadPort2(chan, IDX_IO1_i_Data);
1398 KdPrint2((PRINT_PREFIX
1399 " %x\n", w));
1400 AtapiStallExecution(1);
1401 ((PUSHORT)&deviceExtension->FullIdentifyData)[i] = w;
1402 }
1403 #else
1404 ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
1405 #endif
1406 // Work around for some IDE and one model Atapi that will present more than
1407 // 256 bytes for the Identify data.
1408 KdPrint2((PRINT_PREFIX "IssueIdentify: suck data port\n", statusByte));
1409 statusByte = AtapiSuckPort2(chan);
1410 } else {
1411 KdPrint2((PRINT_PREFIX " use 32bit IO\n"));
1412 ReadBuffer2(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256/2, PIO0_TIMING);
1413 }
1414
1415 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1416 statusByte = WaitForDrq(chan);
1417 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1418 GetBaseStatus(chan, statusByte);
1419
1420 KdPrint2((PRINT_PREFIX "IssueIdentify: Status after read words %#x\n", statusByte));
1421
1422 if(NoSetup) {
1423 KdPrint2((PRINT_PREFIX "IssueIdentify: no setup, exiting\n"));
1424 return TRUE;
1425 }
1426
1427 KdPrint2((PRINT_PREFIX "Model: %20.20s\n", deviceExtension->FullIdentifyData.ModelNumber));
1428 KdPrint2((PRINT_PREFIX "FW: %4.4s\n", deviceExtension->FullIdentifyData.FirmwareRevision));
1429 KdPrint2((PRINT_PREFIX "S/N: %20.20s\n", deviceExtension->FullIdentifyData.SerialNumber));
1430 KdPrint2((PRINT_PREFIX "Pio: %x\n", deviceExtension->FullIdentifyData.PioCycleTimingMode));
1431 if(deviceExtension->FullIdentifyData.PioTimingsValid) {
1432 KdPrint2((PRINT_PREFIX "APio: %x\n", deviceExtension->FullIdentifyData.AdvancedPIOModes));
1433 }
1434 KdPrint2((PRINT_PREFIX "SWDMA: %x\n", deviceExtension->FullIdentifyData.SingleWordDMAActive));
1435 KdPrint2((PRINT_PREFIX "MWDMA: %x\n", deviceExtension->FullIdentifyData.MultiWordDMAActive));
1436 if(deviceExtension->FullIdentifyData.UdmaModesValid) {
1437 KdPrint2((PRINT_PREFIX "UDMA: %x\n", deviceExtension->FullIdentifyData.UltraDMAActive));
1438 }
1439 KdPrint2((PRINT_PREFIX "SATA: %x\n", deviceExtension->FullIdentifyData.SataEnable));
1440
1441 // Check out a few capabilities / limitations of the device.
1442 if (deviceExtension->FullIdentifyData.RemovableStatus & 1) {
1443 // Determine if this drive supports the MSN functions.
1444 KdPrint2((PRINT_PREFIX "IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1445 ldev,
1446 deviceExtension->FullIdentifyData.RemovableStatus));
1447 LunExt->DeviceFlags |= DFLAGS_REMOVABLE_DRIVE;
1448 }
1449 if (deviceExtension->FullIdentifyData.MaximumBlockTransfer) {
1450 // Determine max. block transfer for this device.
1451 LunExt->MaximumBlockXfer =
1452 (UCHAR)(deviceExtension->FullIdentifyData.MaximumBlockTransfer & 0xFF);
1453 }
1454 LunExt->NumOfSectors = 0;
1455 if (Command == IDE_COMMAND_IDENTIFY) {
1456 ULONGLONG NumOfSectors=0;
1457 ULONGLONG NativeNumOfSectors=0;
1458 ULONGLONG cylinders=0;
1459 ULONGLONG tmp_cylinders=0;
1460 // Read very-old-style drive geometry
1461 KdPrint2((PRINT_PREFIX "CHS %#x:%#x:%#x\n",
1462 deviceExtension->FullIdentifyData.NumberOfCylinders,
1463 deviceExtension->FullIdentifyData.NumberOfHeads,
1464 deviceExtension->FullIdentifyData.SectorsPerTrack
1465 ));
1466 NumOfSectors = deviceExtension->FullIdentifyData.NumberOfCylinders *
1467 deviceExtension->FullIdentifyData.NumberOfHeads *
1468 deviceExtension->FullIdentifyData.SectorsPerTrack;
1469 KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
1470 // Check for HDDs > 8Gb
1471 if ((deviceExtension->FullIdentifyData.NumberOfCylinders == 0x3fff) &&
1472 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1473 (NumOfSectors < deviceExtension->FullIdentifyData.UserAddressableSectors)) {
1474 KdPrint2((PRINT_PREFIX "NumberOfCylinders == 0x3fff\n"));
1475 cylinders =
1476 (deviceExtension->FullIdentifyData.UserAddressableSectors /
1477 (deviceExtension->FullIdentifyData.NumberOfHeads *
1478 deviceExtension->FullIdentifyData.SectorsPerTrack));
1479
1480 KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
1481
1482 NumOfSectors = cylinders *
1483 deviceExtension->FullIdentifyData.NumberOfHeads *
1484 deviceExtension->FullIdentifyData.SectorsPerTrack;
1485
1486 KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
1487 } else {
1488
1489 }
1490 // Check for LBA mode
1491 KdPrint2((PRINT_PREFIX "SupportLba flag %#x\n", deviceExtension->FullIdentifyData.SupportLba));
1492 KdPrint2((PRINT_PREFIX "MajorRevision %#x\n", deviceExtension->FullIdentifyData.MajorRevision));
1493 KdPrint2((PRINT_PREFIX "UserAddressableSectors %#x\n", deviceExtension->FullIdentifyData.UserAddressableSectors));
1494 if ( deviceExtension->FullIdentifyData.SupportLba
1495 ||
1496 (deviceExtension->FullIdentifyData.MajorRevision &&
1497 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1498 deviceExtension->FullIdentifyData.UserAddressableSectors)) {
1499 KdPrint2((PRINT_PREFIX "LBA mode\n"));
1500 LunExt->DeviceFlags |= DFLAGS_LBA_ENABLED;
1501 } else {
1502 KdPrint2((PRINT_PREFIX "Keep orig geometry\n"));
1503 LunExt->DeviceFlags |= DFLAGS_ORIG_GEOMETRY;
1504 goto skip_lba_staff;
1505 }
1506 // Check for LBA48 support
1507 if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
1508 if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48 &&
1509 deviceExtension->FullIdentifyData.FeaturesEnabled.Address48 &&
1510 (deviceExtension->FullIdentifyData.UserAddressableSectors48 > NumOfSectors)
1511 ) {
1512 KdPrint2((PRINT_PREFIX "LBA48\n"));
1513 cylinders =
1514 (deviceExtension->FullIdentifyData.UserAddressableSectors48 /
1515 (deviceExtension->FullIdentifyData.NumberOfHeads *
1516 deviceExtension->FullIdentifyData.SectorsPerTrack));
1517
1518 KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
1519
1520 NativeNumOfSectors = cylinders *
1521 deviceExtension->FullIdentifyData.NumberOfHeads *
1522 deviceExtension->FullIdentifyData.SectorsPerTrack;
1523
1524 KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
1525
1526 if(NativeNumOfSectors > NumOfSectors) {
1527 KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
1528 NumOfSectors = NativeNumOfSectors;
1529 }
1530 }
1531
1532 // Check drive capacity report for LBA48-capable drives.
1533 if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48) {
1534 ULONG hNativeNumOfSectors;
1535 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1536
1537 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
1538 IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY);
1539
1540 if(!(statusByte & IDE_STATUS_ERROR)) {
1541 NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
1542 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
1543 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) ;
1544
1545 AtapiWritePort1(chan, IDX_IO2_o_Control,
1546 IDE_DC_USE_HOB );
1547
1548 KdPrint2((PRINT_PREFIX "Read high order bytes\n"));
1549 NativeNumOfSectors |=
1550 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) << 24 );
1551 hNativeNumOfSectors=
1552 (ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) |
1553 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 8) ;
1554 ((PULONG)&NativeNumOfSectors)[1] = hNativeNumOfSectors;
1555
1556 KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
1557
1558 // Some drives report LBA48 capability while has capacity below 128Gb
1559 // Probably they support large block-counters.
1560 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
1561 // Here we check this
1562 if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
1563 KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!!\n"));
1564
1565 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
1566 IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY);
1567
1568 if(!(statusByte & IDE_STATUS_ERROR)) {
1569 NativeNumOfSectors = (ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
1570 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) << 24) |
1571 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8 ) |
1572 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 32) |
1573 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
1574 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 40)
1575 ;
1576 }
1577
1578 if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
1579 KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!! (2)\n"));
1580 NativeNumOfSectors = 0;
1581 }
1582 }
1583
1584 if(NumOfSectors <= ATA_MAX_LBA28 &&
1585 NativeNumOfSectors > NumOfSectors) {
1586
1587 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
1588 KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
1589
1590 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
1591 IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
1592 if(!(statusByte & IDE_STATUS_ERROR)) {
1593 NumOfSectors = NativeNumOfSectors;
1594 }
1595 }
1596 }
1597 }
1598
1599 if(NumOfSectors < 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
1600 // check for native LBA size
1601 // some drives report ~32Gb in Identify Block
1602 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
1603
1604 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_READ_NATIVE_SIZE,
1605 0, IDE_USE_LBA, 0, 0, 0, ATA_WAIT_READY);
1606
1607 if(!(statusByte & IDE_STATUS_ERROR)) {
1608 NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
1609 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
1610 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
1611 (((ULONG)AtapiReadPort1(chan, IDX_IO1_i_DriveSelect) & 0xf) << 24);
1612
1613 KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
1614
1615 if(NativeNumOfSectors > NumOfSectors) {
1616
1617 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
1618 KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
1619
1620 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
1621 IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
1622 if(!(statusByte & IDE_STATUS_ERROR)) {
1623 NumOfSectors = NativeNumOfSectors;
1624 }
1625 }
1626 }
1627 }
1628
1629 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
1630
1631 // fill IdentifyData with bogus geometry
1632 KdPrint2((PRINT_PREFIX "requested LunExt->GeomType=%x\n", LunExt->opt_GeomType));
1633 tmp_cylinders = NumOfSectors / (deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *
1634 deviceExtension->FullIdentifyData.NumberOfCurrentHeads);
1635 KdPrint2((PRINT_PREFIX "tmp_cylinders = %#I64x\n", tmp_cylinders));
1636 if((tmp_cylinders < 0xffff) || (LunExt->opt_GeomType == GEOM_ORIG)) {
1637 // ok, we can keep original values
1638 if(LunExt->opt_GeomType == GEOM_AUTO) {
1639 LunExt->opt_GeomType = GEOM_ORIG;
1640 }
1641 } else {
1642 tmp_cylinders = NumOfSectors / (255*63);
1643 if(tmp_cylinders < 0xffff) {
1644 // we can use generic values for H/S for generic geometry approach
1645 if(LunExt->opt_GeomType == GEOM_AUTO) {
1646 LunExt->opt_GeomType = GEOM_STD;
1647 }
1648 } else {
1649 // we should use UNIATA geometry approach
1650 if(LunExt->opt_GeomType == GEOM_AUTO) {
1651 LunExt->opt_GeomType = GEOM_UNIATA;
1652 }
1653 }
1654 }
1655 KdPrint2((PRINT_PREFIX "final LunExt->opt_GeomType=%x\n", LunExt->opt_GeomType));
1656
1657 if(LunExt->opt_GeomType == GEOM_STD) {
1658 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack =
1659 deviceExtension->FullIdentifyData.SectorsPerTrack = 63;
1660
1661 deviceExtension->FullIdentifyData.NumberOfCurrentHeads =
1662 deviceExtension->FullIdentifyData.NumberOfHeads = 255;
1663
1664 cylinders = NumOfSectors / (255*63);
1665 KdPrint2((PRINT_PREFIX "Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders, 255, 63));
1666 } else
1667 if(LunExt->opt_GeomType == GEOM_UNIATA) {
1668 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x80)) {
1669 cylinders /= 2;
1670 KdPrint2((PRINT_PREFIX "cylinders /= 2\n"));
1671 deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
1672 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
1673 }
1674 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x80)) {
1675 cylinders /= 2;
1676 KdPrint2((PRINT_PREFIX "cylinders /= 2 (2)\n"));
1677 deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
1678 deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
1679 }
1680 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x8000)) {
1681 cylinders /= 2;
1682 KdPrint2((PRINT_PREFIX "cylinders /= 2 (3)\n"));
1683 deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
1684 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
1685 }
1686 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x8000)) {
1687 cylinders /= 2;
1688 KdPrint2((PRINT_PREFIX "cylinders /= 2 (4)\n"));
1689 deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
1690 deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
1691 }
1692 KdPrint2((PRINT_PREFIX "Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders,
1693 deviceExtension->FullIdentifyData.NumberOfCurrentHeads,
1694 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack));
1695 }
1696 if(!cylinders) {
1697 KdPrint2((PRINT_PREFIX "cylinders = tmp_cylinders (%x = %x)\n", cylinders, tmp_cylinders));
1698 cylinders = tmp_cylinders;
1699 }
1700 deviceExtension->FullIdentifyData.NumberOfCurrentCylinders =
1701 deviceExtension->FullIdentifyData.NumberOfCylinders = (USHORT)cylinders;
1702
1703 skip_lba_staff:
1704
1705 KdPrint2((PRINT_PREFIX "Geometry: C %#x (%#x)\n",
1706 deviceExtension->FullIdentifyData.NumberOfCylinders,
1707 deviceExtension->FullIdentifyData.NumberOfCurrentCylinders
1708 ));
1709 KdPrint2((PRINT_PREFIX "Geometry: H %#x (%#x)\n",
1710 deviceExtension->FullIdentifyData.NumberOfHeads,
1711 deviceExtension->FullIdentifyData.NumberOfCurrentHeads
1712 ));
1713 KdPrint2((PRINT_PREFIX "Geometry: S %#x (%#x)\n",
1714 deviceExtension->FullIdentifyData.SectorsPerTrack,
1715 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack
1716 ));
1717
1718 if(NumOfSectors)
1719 LunExt->NumOfSectors = NumOfSectors;
1720 /* if(deviceExtension->FullIdentifyData.MajorRevision &&
1721 deviceExtension->FullIdentifyData.DoubleWordIo) {
1722 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
1723 }*/
1724 }
1725
1726 ScsiPortMoveMemory(&LunExt->IdentifyData,
1727 &deviceExtension->FullIdentifyData,sizeof(IDENTIFY_DATA2));
1728
1729 InitBadBlocks(LunExt);
1730
1731 if ((LunExt->IdentifyData.DrqType & ATAPI_DRQT_INTR) &&
1732 (Command != IDE_COMMAND_IDENTIFY)) {
1733
1734 // This device interrupts with the assertion of DRQ after receiving
1735 // Atapi Packet Command
1736 LunExt->DeviceFlags |= DFLAGS_INT_DRQ;
1737 KdPrint2((PRINT_PREFIX "IssueIdentify: Device interrupts on assertion of DRQ.\n"));
1738
1739 } else {
1740 KdPrint2((PRINT_PREFIX "IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
1741 }
1742
1743 if(Command != IDE_COMMAND_IDENTIFY) {
1744 // ATAPI branch
1745 if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_TAPE) {
1746 // This is a tape.
1747 LunExt->DeviceFlags |= DFLAGS_TAPE_DEVICE;
1748 KdPrint2((PRINT_PREFIX "IssueIdentify: Device is a tape drive.\n"));
1749 } else
1750 if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM ||
1751 LunExt->IdentifyData.DeviceType == ATAPI_TYPE_OPTICAL) {
1752 KdPrint2((PRINT_PREFIX "IssueIdentify: Device is CD/Optical drive.\n"));
1753 // set CD default costs
1754 LunExt->RwSwitchCost = REORDER_COST_SWITCH_RW_CD;
1755 LunExt->RwSwitchMCost = REORDER_MCOST_SWITCH_RW_CD;
1756 LunExt->SeekBackMCost = REORDER_MCOST_SEEK_BACK_CD;
1757 statusByte = WaitForDrq(chan);
1758 } else {
1759 KdPrint2((PRINT_PREFIX "IssueIdentify: ATAPI drive type %#x.\n",
1760 LunExt->IdentifyData.DeviceType));
1761 }
1762 } else {
1763 KdPrint2((PRINT_PREFIX "IssueIdentify: hard drive.\n"));
1764 }
1765
1766 GetBaseStatus(chan, statusByte);
1767 KdPrint2((PRINT_PREFIX "IssueIdentify: final Status on exit (%#x)\n", statusByte));
1768 return TRUE;
1769
1770 } // end IssueIdentify()
1771
1772
1773 /*++
1774
1775 Routine Description:
1776 Set drive parameters using the IDENTIFY data.
1777
1778 Arguments:
1779 HwDeviceExtension - HBA miniport driver's adapter data storage
1780 DeviceNumber - Indicates which device.
1781
1782 Return Value:
1783 TRUE if all goes well.
1784
1785 --*/
1786 BOOLEAN
1787 NTAPI
1788 SetDriveParameters(
1789 IN PVOID HwDeviceExtension,
1790 IN ULONG DeviceNumber,
1791 IN ULONG lChannel
1792 )
1793 {
1794 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1795 PIDENTIFY_DATA2 identifyData = &deviceExtension->lun[(lChannel * 2) + DeviceNumber].IdentifyData;
1796 // ULONG i;
1797 UCHAR statusByte;
1798 UCHAR errorByte;
1799
1800 if(deviceExtension->lun[(lChannel * 2) + DeviceNumber].DeviceFlags &
1801 (DFLAGS_LBA_ENABLED | DFLAGS_ORIG_GEOMETRY))
1802 return TRUE;
1803
1804 KdPrint2((PRINT_PREFIX "SetDriveParameters: Number of heads %#x\n", identifyData->NumberOfHeads));
1805 KdPrint2((PRINT_PREFIX "SetDriveParameters: Sectors per track %#x\n", identifyData->SectorsPerTrack));
1806
1807 // Send SET PARAMETER command.
1808 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
1809 IDE_COMMAND_SET_DRIVE_PARAMETERS, 0,
1810 (identifyData->NumberOfHeads - 1), 0,
1811 (UCHAR)identifyData->SectorsPerTrack, 0, ATA_WAIT_IDLE);
1812
1813 statusByte = UniataIsIdle(deviceExtension, statusByte);
1814 if(statusByte & IDE_STATUS_ERROR) {
1815 errorByte = AtapiReadPort1(&deviceExtension->chan[lChannel], IDX_IO1_i_Error);
1816 KdPrint2((PRINT_PREFIX "SetDriveParameters: Error bit set. Status %#x, error %#x\n",
1817 errorByte, statusByte));
1818 return FALSE;
1819 }
1820
1821 if(statusByte == IDE_STATUS_IDLE) {
1822 return TRUE;
1823 }
1824
1825 return FALSE;
1826
1827 } // end SetDriveParameters()
1828
1829 VOID
1830 NTAPI
1831 UniataForgetDevice(
1832 PHW_LU_EXTENSION LunExt
1833 )
1834 {
1835 LunExt->DeviceFlags &= DFLAGS_HIDDEN;
1836 } // end UniataForgetDevice()
1837
1838
1839 /*++
1840
1841 Routine Description:
1842 Reset IDE controller and/or Atapi device.
1843
1844 Arguments:
1845 HwDeviceExtension - HBA miniport driver's adapter data storage
1846
1847 Return Value:
1848 Nothing.
1849
1850
1851 --*/
1852 BOOLEAN
1853 DDKAPI
1854 AtapiResetController(
1855 IN PVOID HwDeviceExtension,
1856 IN ULONG PathId
1857 )
1858 {
1859 KdPrint2((PRINT_PREFIX "AtapiResetController()\n"));
1860 return AtapiResetController__(HwDeviceExtension, PathId, RESET_COMPLETE_ALL);
1861 } // end AtapiResetController()
1862
1863
1864 BOOLEAN
1865 NTAPI
1866 AtapiResetController__(
1867 IN PVOID HwDeviceExtension,
1868 IN ULONG PathId,
1869 IN BOOLEAN CompleteType
1870 )
1871 {
1872 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1873 ULONG numberChannels = deviceExtension->NumberChannels;
1874 PHW_CHANNEL chan = NULL;
1875 ULONG i,j;
1876 ULONG max_ldev;
1877 UCHAR statusByte;
1878 PSCSI_REQUEST_BLOCK CurSrb;
1879 ULONG ChannelCtrlFlags;
1880 UCHAR dma_status = 0;
1881
1882 ULONG slotNumber = deviceExtension->slotNumber;
1883 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
1884 ULONG VendorID = deviceExtension->DevID & 0xffff;
1885 #ifdef _DEBUG
1886 ULONG DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
1887 #endif
1888 //ULONG RevID = deviceExtension->RevID;
1889 ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
1890 UCHAR tmp8;
1891 UCHAR tmp16;
1892
1893 KdPrint2((PRINT_PREFIX "AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID, DeviceID, slotNumber));
1894
1895 if(!deviceExtension->simplexOnly && (PathId != CHAN_NOT_SPECIFIED)) {
1896 // we shall reset both channels on SimplexOnly devices,
1897 // It's not worth doing so on normal controllers
1898 j = PathId;
1899 numberChannels = min(j+1, deviceExtension->NumberChannels);
1900 } else {
1901 j=0;
1902 numberChannels = deviceExtension->NumberChannels;
1903 }
1904
1905 for (; j < numberChannels; j++) {
1906
1907 KdPrint2((PRINT_PREFIX "AtapiResetController: Reset channel %d\n", j));
1908 chan = &deviceExtension->chan[j];
1909 KdPrint2((PRINT_PREFIX " CompleteType %#x\n", CompleteType));
1910 max_ldev = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
1911 if(CompleteType != RESET_COMPLETE_NONE) {
1912 #ifndef UNIATA_CORE
1913 while((CurSrb = UniataGetCurRequest(chan))) {
1914
1915 PATA_REQ AtaReq = (PATA_REQ)(CurSrb->SrbExtension);
1916
1917 KdPrint2((PRINT_PREFIX "AtapiResetController: pending SRB %#x\n", CurSrb));
1918 // Check and see if we are processing an internal srb
1919 if (AtaReq->OriginalSrb) {
1920 KdPrint2((PRINT_PREFIX " restore original SRB %#x\n", AtaReq->OriginalSrb));
1921 AtaReq->Srb = AtaReq->OriginalSrb;
1922 AtaReq->OriginalSrb = NULL;
1923 // NOTE: internal SRB doesn't get to SRB queue !!!
1924 CurSrb = AtaReq->Srb;
1925 }
1926
1927 // Remove current request from queue
1928 UniataRemoveRequest(chan, CurSrb);
1929
1930 // Check if request is in progress.
1931 ASSERT(AtaReq->Srb == CurSrb);
1932 if (CurSrb) {
1933 // Complete outstanding request with SRB_STATUS_BUS_RESET.
1934 UCHAR PathId = CurSrb->PathId;
1935 UCHAR TargetId = CurSrb->TargetId;
1936 UCHAR Lun = CurSrb->Lun;
1937
1938 CurSrb->SrbStatus = ((CompleteType == RESET_COMPLETE_ALL) ? SRB_STATUS_BUS_RESET : SRB_STATUS_ABORTED) | SRB_STATUS_AUTOSENSE_VALID;
1939 CurSrb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
1940
1941 if (CurSrb->SenseInfoBuffer) {
1942
1943 PSENSE_DATA senseBuffer = (PSENSE_DATA)CurSrb->SenseInfoBuffer;
1944
1945 senseBuffer->ErrorCode = 0x70;
1946 senseBuffer->Valid = 1;
1947 senseBuffer->AdditionalSenseLength = 0xb;
1948 if(CompleteType == RESET_COMPLETE_ALL) {
1949 KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
1950 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
1951 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_BUS_RESET;
1952 senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_SCSI_BUS;
1953 } else {
1954 KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
1955 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
1956 senseBuffer->AdditionalSenseCode = 0;
1957 senseBuffer->AdditionalSenseCodeQualifier = 0;
1958 }
1959 }
1960
1961 // Clear request tracking fields.
1962 AtaReq->WordsLeft = 0;
1963 AtaReq->DataBuffer = NULL;
1964 AtaReq->TransferLength = 0;
1965
1966 ScsiPortNotification(RequestComplete,
1967 deviceExtension,
1968 CurSrb);
1969
1970 // Indicate ready for next request.
1971 ScsiPortNotification(NextLuRequest,
1972 deviceExtension,
1973 PathId,
1974 TargetId,
1975 Lun);
1976 }
1977 if(CompleteType != RESET_COMPLETE_ALL)
1978 break;
1979 } // end while()
1980 #endif //UNIATA_CORE
1981 } // end if (!CompleteType != RESET_COMPLETE_NONE)
1982
1983 // Save control flags
1984 ChannelCtrlFlags = chan->ChannelCtrlFlags;
1985 // Clear expecting interrupt flag.
1986 chan->ExpectingInterrupt = FALSE;
1987 chan->RDP = FALSE;
1988 chan->ChannelCtrlFlags = 0;
1989 InterlockedExchange(&(chan->CheckIntr),
1990 CHECK_INTR_IDLE);
1991
1992 // Reset controller
1993 KdPrint2((PRINT_PREFIX " disable intr (0)\n"));
1994 AtapiDisableInterrupts(deviceExtension, j);
1995 KdPrint2((PRINT_PREFIX " done\n"));
1996 switch(VendorID) {
1997 case ATA_INTEL_ID: {
1998 ULONG mask;
1999 ULONG timeout;
2000 if(!(ChipFlags & UNIATA_SATA))
2001 goto default_reset;
2002 if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
2003 goto default_reset;
2004 }
2005
2006 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2007 if(ChipFlags & UNIATA_AHCI) {
2008 mask = 0x0005 << j;
2009 } else {
2010 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2011 GetPciConfig1(0x90, tmp8);
2012 if(tmp8 & 0x04) {
2013 mask = 0x0003;
2014 } else {
2015 mask = 0x0001 << j;
2016 }
2017 }
2018 ChangePciConfig2(0x92, a & ~mask);
2019 AtapiStallExecution(10);
2020 ChangePciConfig2(0x92, a | mask);
2021 timeout = 100;
2022 while (timeout--) {
2023 AtapiStallExecution(10000);
2024 GetPciConfig2(0x92, tmp16);
2025 if ((tmp16 & (mask << 4)) == (mask << 4)) {
2026 AtapiStallExecution(10000);
2027 break;
2028 }
2029 }
2030 break; }
2031 case ATA_SIS_ID:
2032 case ATA_NVIDIA_ID: {
2033 KdPrint2((PRINT_PREFIX " SIS/nVidia\n"));
2034 if(!(ChipFlags & UNIATA_SATA))
2035 goto default_reset;
2036 break; }
2037 case ATA_SILICON_IMAGE_ID: {
2038 ULONG offset;
2039 ULONG Channel = deviceExtension->Channel + j;
2040 if(!(ChipFlags & UNIATA_SATA))
2041 goto default_reset;
2042 offset = ((Channel & 1) << 7) + ((Channel & 2) << 8);
2043 /* disable PHY state change interrupt */
2044 AtapiWritePortEx4(NULL, (ULONG)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + offset, 0);
2045
2046 UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT);
2047
2048 /* reset controller part for this channel */
2049 AtapiWritePortEx4(NULL, (ULONG)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
2050 AtapiReadPortEx4(NULL, (ULONG)(&deviceExtension->BaseIoAddressSATA_0), 0x48) | (0xc0 >> Channel));
2051 AtapiStallExecution(1000);
2052 AtapiWritePortEx4(NULL, (ULONG)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
2053 AtapiReadPortEx4(NULL, (ULONG)(&deviceExtension->BaseIoAddressSATA_0), 0x48) & ~(0xc0 >> Channel));
2054
2055
2056 break; }
2057 case ATA_PROMISE_ID: {
2058 break; }
2059 default:
2060 if(ChipFlags & UNIATA_SATA) {
2061 KdPrint2((PRINT_PREFIX " SATA generic reset\n"));
2062 UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT);
2063 }
2064 default_reset:
2065 KdPrint2((PRINT_PREFIX " send reset\n"));
2066 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS |
2067 IDE_DC_RESET_CONTROLLER );
2068 KdPrint2((PRINT_PREFIX " wait a little\n"));
2069 AtapiStallExecution(10000);
2070 // Disable interrupts
2071 KdPrint2((PRINT_PREFIX " disable intr\n"));
2072 AtapiDisableInterrupts(deviceExtension, j);
2073 AtapiStallExecution(100);
2074 KdPrint2((PRINT_PREFIX " re-enable intr\n"));
2075 AtapiEnableInterrupts(deviceExtension, j);
2076 KdPrint2((PRINT_PREFIX " wait a little (2)\n"));
2077 AtapiStallExecution(100000);
2078 KdPrint2((PRINT_PREFIX " done\n"));
2079
2080 break;
2081 }
2082
2083 //if(!(ChipFlags & UNIATA_SATA)) {
2084 if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
2085 // Reset DMA engine if active
2086 KdPrint2((PRINT_PREFIX " check DMA engine\n"));
2087 dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
2088 KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
2089 if((ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
2090 (dma_status & BM_STATUS_INTR)) {
2091 AtapiDmaDone(HwDeviceExtension, 0, j, NULL);
2092 }
2093 }
2094
2095 // all these shall be performed inside AtapiHwInitialize__() ?
2096 #if 1
2097 KdPrint2((PRINT_PREFIX " process connected devices\n"));
2098 // Do special processing for ATAPI and IDE disk devices.
2099 for (i = 0; i < max_ldev; i++) {
2100
2101 // Check if device present.
2102 if (!(deviceExtension->lun[i + (j * 2)].DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
2103 #ifdef NAVO_TEST
2104 continue;
2105 #else //NAVO_TEST
2106 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2107 if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
2108 continue;
2109 }
2110 if(!CheckDevice(HwDeviceExtension, j, i, TRUE)) {
2111 continue;
2112 }
2113 } else {
2114 if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
2115 KdPrint2((PRINT_PREFIX " device have gone\n"));
2116 UniataForgetDevice(&(deviceExtension->lun[i + (j * 2)]));
2117 }
2118 #endif //NAVO_TEST
2119 }
2120
2121 SelectDrive(chan, i);
2122 AtapiStallExecution(10);
2123 statusByte = WaitOnBusyLong(chan);
2124 statusByte = UniataIsIdle(deviceExtension, statusByte);
2125 if(statusByte == 0xff) {
2126 KdPrint2((PRINT_PREFIX
2127 "no drive, status %#x\n",
2128 statusByte));
2129 UniataForgetDevice(&(deviceExtension->lun[i + (j * 2)]));
2130 } else
2131 // Check for ATAPI disk.
2132 if (deviceExtension->lun[i + (j * 2)].DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2133 // Issue soft reset and issue identify.
2134 GetStatus(chan, statusByte);
2135 KdPrint2((PRINT_PREFIX "AtapiResetController: Status before Atapi reset (%#x).\n",
2136 statusByte));
2137
2138 AtapiDisableInterrupts(deviceExtension, j);
2139 AtapiSoftReset(chan, i);
2140 AtapiEnableInterrupts(deviceExtension, j);
2141
2142 GetStatus(chan, statusByte);
2143
2144 if(statusByte == IDE_STATUS_SUCCESS) {
2145
2146 IssueIdentify(HwDeviceExtension,
2147 i, j,
2148 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
2149 } else {
2150
2151 KdPrint2((PRINT_PREFIX
2152 "AtapiResetController: Status after soft reset %#x\n",
2153 statusByte));
2154 }
2155 GetBaseStatus(chan, statusByte);
2156
2157 } else {
2158 // Issue identify and reinit after channel reset.
2159
2160 if (statusByte != IDE_STATUS_IDLE &&
2161 statusByte != IDE_STATUS_SUCCESS &&
2162 statusByte != IDE_STATUS_DRDY) {
2163 // result2 = FALSE;
2164 KdPrint2((PRINT_PREFIX "AtapiResetController: IdeHardReset failed\n"));
2165 } else
2166 if(!IssueIdentify(HwDeviceExtension,
2167 i, j,
2168 IDE_COMMAND_IDENTIFY, FALSE)) {
2169 // result2 = FALSE;
2170 KdPrint2((PRINT_PREFIX "AtapiResetController: IDE IssueIdentify failed\n"));
2171 } else
2172 // Set disk geometry parameters.
2173 if (!SetDriveParameters(HwDeviceExtension, i, j)) {
2174 KdPrint2((PRINT_PREFIX "AtapiResetController: SetDriveParameters failed\n"));
2175 }
2176 GetBaseStatus(chan, statusByte);
2177 }
2178 // force DMA mode reinit
2179 deviceExtension->lun[i + (j * 2)].DeviceFlags |= DFLAGS_REINIT_DMA;
2180 }
2181 #endif //0
2182
2183 // Enable interrupts, note, the we can have here recursive disable
2184 AtapiStallExecution(10);
2185 KdPrint2((PRINT_PREFIX "AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2186 j,
2187 chan->DisableIntr));
2188 AtapiEnableInterrupts(deviceExtension, j);
2189
2190 // Call the HwInitialize routine to setup multi-block.
2191 AtapiHwInitialize__(deviceExtension, j);
2192 }
2193 ScsiPortNotification(NextRequest, deviceExtension, NULL);
2194
2195 return TRUE;
2196
2197 } // end AtapiResetController__()
2198
2199
2200 /*++
2201
2202 Routine Description:
2203 This routine maps ATAPI and IDE errors to specific SRB statuses.
2204
2205 Arguments:
2206 HwDeviceExtension - HBA miniport driver's adapter data storage
2207 Srb - IO request packet
2208
2209 Return Value:
2210 SRB status
2211
2212 --*/
2213 ULONG
2214 NTAPI
2215 MapError(
2216 IN PVOID HwDeviceExtension,
2217 IN PSCSI_REQUEST_BLOCK Srb
2218 )
2219 {
2220 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2221 ULONG lChannel = GET_CHANNEL(Srb);
2222 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
2223 // ULONG i;
2224 UCHAR errorByte;
2225 UCHAR srbStatus = SRB_STATUS_SUCCESS;
2226 UCHAR scsiStatus;
2227 ULONG ldev = GET_LDEV(Srb);
2228
2229 // Read the error register.
2230
2231 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
2232 KdPrint2((PRINT_PREFIX
2233 "MapError: Error register is %#x\n",
2234 errorByte));
2235
2236 if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2237
2238 switch (errorByte >> 4) {
2239 case SCSI_SENSE_NO_SENSE:
2240
2241 KdPrint2((PRINT_PREFIX
2242 "ATAPI: No sense information\n"));
2243 scsiStatus = SCSISTAT_CHECK_CONDITION;
2244 srbStatus = SRB_STATUS_ERROR;
2245 break;
2246
2247 case SCSI_SENSE_RECOVERED_ERROR:
2248
2249 KdPrint2((PRINT_PREFIX
2250 "ATAPI: Recovered error\n"));
2251 scsiStatus = 0;
2252 srbStatus = SRB_STATUS_SUCCESS;
2253 break;
2254
2255 case SCSI_SENSE_NOT_READY:
2256
2257 KdPrint2((PRINT_PREFIX
2258 "ATAPI: Device not ready\n"));
2259 scsiStatus = SCSISTAT_CHECK_CONDITION;
2260 srbStatus = SRB_STATUS_ERROR;
2261 break;
2262
2263 case SCSI_SENSE_MEDIUM_ERROR:
2264
2265 KdPrint2((PRINT_PREFIX
2266 "ATAPI: Media error\n"));
2267 scsiStatus = SCSISTAT_CHECK_CONDITION;
2268 srbStatus = SRB_STATUS_ERROR;
2269 break;
2270
2271 case SCSI_SENSE_HARDWARE_ERROR:
2272
2273 KdPrint2((PRINT_PREFIX
2274 "ATAPI: Hardware error\n"));
2275 scsiStatus = SCSISTAT_CHECK_CONDITION;
2276 srbStatus = SRB_STATUS_ERROR;
2277 break;
2278
2279 case SCSI_SENSE_ILLEGAL_REQUEST:
2280
2281 KdPrint2((PRINT_PREFIX
2282 "ATAPI: Illegal request\n"));
2283 scsiStatus = SCSISTAT_CHECK_CONDITION;
2284 srbStatus = SRB_STATUS_ERROR;
2285 break;
2286
2287 case SCSI_SENSE_UNIT_ATTENTION:
2288
2289 KdPrint2((PRINT_PREFIX
2290 "ATAPI: Unit attention\n"));
2291 scsiStatus = SCSISTAT_CHECK_CONDITION;
2292 srbStatus = SRB_STATUS_ERROR;
2293 break;
2294
2295 case SCSI_SENSE_DATA_PROTECT:
2296
2297 KdPrint2((PRINT_PREFIX
2298 "ATAPI: Data protect\n"));
2299 scsiStatus = SCSISTAT_CHECK_CONDITION;
2300 srbStatus = SRB_STATUS_ERROR;
2301 break;
2302
2303 case SCSI_SENSE_BLANK_CHECK:
2304
2305 KdPrint2((PRINT_PREFIX
2306 "ATAPI: Blank check\n"));
2307 scsiStatus = SCSISTAT_CHECK_CONDITION;
2308 srbStatus = SRB_STATUS_ERROR;
2309 break;
2310
2311 case SCSI_SENSE_ABORTED_COMMAND:
2312 KdPrint2((PRINT_PREFIX
2313 "Atapi: Command Aborted\n"));
2314 scsiStatus = SCSISTAT_CHECK_CONDITION;
2315 srbStatus = SRB_STATUS_ERROR;
2316 break;
2317
2318 default:
2319
2320 KdPrint2((PRINT_PREFIX
2321 "ATAPI: Invalid sense information\n"));
2322 scsiStatus = 0;
2323 srbStatus = SRB_STATUS_ERROR;
2324 break;
2325 }
2326
2327 } else {
2328
2329 scsiStatus = 0;
2330
2331 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
2332 chan->ReturningMediaStatus = errorByte;
2333
2334 if (errorByte & IDE_ERROR_MEDIA_CHANGE_REQ) {
2335 KdPrint2((PRINT_PREFIX
2336 "IDE: Media change\n"));
2337 scsiStatus = SCSISTAT_CHECK_CONDITION;
2338 srbStatus = SRB_STATUS_ERROR;
2339
2340 if (Srb->SenseInfoBuffer) {
2341
2342 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2343
2344 senseBuffer->ErrorCode = 0x70;
2345 senseBuffer->Valid = 1;
2346 senseBuffer->AdditionalSenseLength = 0xb;
2347 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
2348 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
2349 senseBuffer->AdditionalSenseCodeQualifier = 0;
2350
2351 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2352 }
2353
2354 } else if (errorByte & IDE_ERROR_COMMAND_ABORTED) {
2355 KdPrint2((PRINT_PREFIX
2356 "IDE: Command abort\n"));
2357 srbStatus = SRB_STATUS_ABORTED;
2358 scsiStatus = SCSISTAT_CHECK_CONDITION;
2359
2360 if (Srb->SenseInfoBuffer) {
2361
2362 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2363
2364 senseBuffer->ErrorCode = 0x70;
2365 senseBuffer->Valid = 1;
2366 senseBuffer->AdditionalSenseLength = 0xb;
2367 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
2368 senseBuffer->AdditionalSenseCode = 0;
2369 senseBuffer->AdditionalSenseCodeQualifier = 0;
2370
2371 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2372 }
2373
2374 deviceExtension->lun[ldev].ErrorCount++;
2375
2376 } else if (errorByte & IDE_ERROR_END_OF_MEDIA) {
2377
2378 KdPrint2((PRINT_PREFIX
2379 "IDE: End of media\n"));
2380 scsiStatus = SCSISTAT_CHECK_CONDITION;
2381 srbStatus = SRB_STATUS_ERROR;
2382
2383 if (Srb->SenseInfoBuffer) {
2384
2385 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2386
2387 senseBuffer->ErrorCode = 0x70;
2388 senseBuffer->Valid = 1;
2389 senseBuffer->AdditionalSenseLength = 0xb;
2390 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
2391 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIA_STATE;
2392 senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_END_OF_MEDIUM;
2393 senseBuffer->EndOfMedia = 1;
2394
2395 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2396 }
2397
2398 if (!(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
2399 deviceExtension->lun[ldev].ErrorCount++;
2400 }
2401
2402 } else if (errorByte & IDE_ERROR_ILLEGAL_LENGTH) {
2403
2404 KdPrint2((PRINT_PREFIX
2405 "IDE: Illegal length\n"));
2406 srbStatus = SRB_STATUS_INVALID_REQUEST;
2407
2408 if (Srb->SenseInfoBuffer) {
2409
2410 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2411
2412 senseBuffer->ErrorCode = 0x70;
2413 senseBuffer->Valid = 1;
2414 senseBuffer->AdditionalSenseLength = 0xb;
2415 senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST;
2416 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_VALUE;
2417 senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_PARAM_INVALID_VALUE;
2418 senseBuffer->IncorrectLength = 1;
2419
2420 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2421 }
2422
2423 } else if (errorByte & IDE_ERROR_BAD_BLOCK) {
2424
2425 KdPrint2((PRINT_PREFIX
2426 "IDE: Bad block\n"));
2427 srbStatus = SRB_STATUS_ERROR;
2428 scsiStatus = SCSISTAT_CHECK_CONDITION;
2429 if (Srb->SenseInfoBuffer) {
2430
2431 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2432
2433 senseBuffer->ErrorCode = 0x70;
2434 senseBuffer->Valid = 1;
2435 senseBuffer->AdditionalSenseLength = 0xb;
2436 senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
2437 senseBuffer->AdditionalSenseCode = 0;
2438 senseBuffer->AdditionalSenseCodeQualifier = 0;
2439
2440 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2441 }
2442
2443 } else if (errorByte & IDE_ERROR_ID_NOT_FOUND) {
2444
2445 KdPrint2((PRINT_PREFIX
2446 "IDE: Id not found\n"));
2447 srbStatus = SRB_STATUS_ERROR;
2448 scsiStatus = SCSISTAT_CHECK_CONDITION;
2449
2450 if (Srb->SenseInfoBuffer) {
2451
2452 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2453
2454 senseBuffer->ErrorCode = 0x70;
2455 senseBuffer->Valid = 1;
2456 senseBuffer->AdditionalSenseLength = 0xb;
2457 senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
2458 senseBuffer->AdditionalSenseCode = 0;
2459 senseBuffer->AdditionalSenseCodeQualifier = 0;
2460
2461 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2462 }
2463
2464 deviceExtension->lun[ldev].ErrorCount++;
2465
2466 } else if (errorByte & IDE_ERROR_MEDIA_CHANGE) {
2467
2468 KdPrint2((PRINT_PREFIX
2469 "IDE: Media change\n"));
2470 scsiStatus = SCSISTAT_CHECK_CONDITION;
2471 srbStatus = SRB_STATUS_ERROR;
2472
2473 if (Srb->SenseInfoBuffer) {
2474
2475 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2476
2477 senseBuffer->ErrorCode = 0x70;
2478 senseBuffer->Valid = 1;
2479 senseBuffer->AdditionalSenseLength = 0xb;
2480 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
2481 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
2482 senseBuffer->AdditionalSenseCodeQualifier = 0;
2483
2484 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2485 }
2486
2487 } else if (errorByte & IDE_ERROR_DATA_ERROR) {
2488
2489 KdPrint2((PRINT_PREFIX
2490 "IDE: Data error\n"));
2491 scsiStatus = SCSISTAT_CHECK_CONDITION;
2492 srbStatus = SRB_STATUS_ERROR;
2493
2494 if (!(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
2495 deviceExtension->lun[ldev].ErrorCount++;
2496 }
2497
2498 // Build sense buffer
2499 if (Srb->SenseInfoBuffer) {
2500
2501 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2502
2503 senseBuffer->ErrorCode = 0x70;
2504 senseBuffer->Valid = 1;
2505 senseBuffer->AdditionalSenseLength = 0xb;
2506 senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
2507 senseBuffer->AdditionalSenseCode = 0;
2508 senseBuffer->AdditionalSenseCodeQualifier = 0;
2509
2510 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2511 }
2512 }
2513
2514 if (deviceExtension->lun[ldev].ErrorCount >= MAX_ERRORS) {
2515 // deviceExtension->DWordIO = FALSE;
2516
2517 KdPrint2((PRINT_PREFIX
2518 "MapError: ErrorCount >= MAX_ERRORS\n"));
2519
2520 deviceExtension->lun[ldev].DeviceFlags &= ~DFLAGS_DWORDIO_ENABLED;
2521 deviceExtension->lun[ldev].MaximumBlockXfer = 0;
2522 BrutePoint();
2523
2524 KdPrint2((PRINT_PREFIX
2525 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
2526
2527 // Log the error.
2528 KdPrint2((PRINT_PREFIX
2529 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
2530 HwDeviceExtension,
2531 Srb,
2532 Srb->PathId,
2533 Srb->TargetId,
2534 Srb->Lun,
2535 SP_BAD_FW_WARNING,
2536 4
2537 ));
2538 ScsiPortLogError( HwDeviceExtension,
2539 Srb,
2540 Srb->PathId,
2541 Srb->TargetId,
2542 Srb->Lun,
2543 SP_BAD_FW_WARNING,
2544 4);
2545
2546 // Reprogram to not use Multi-sector.
2547 UCHAR statusByte;
2548
2549 if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT &&
2550 !(deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
2551
2552 statusByte = AtaCommand(deviceExtension, ldev & 0x1, lChannel, IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY);
2553
2554 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2555 // command was aborted.
2556 if (statusByte & IDE_STATUS_ERROR) {
2557
2558 // Read the error register.
2559 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
2560
2561 KdPrint2((PRINT_PREFIX "MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
2562 statusByte,
2563 errorByte));
2564
2565 // Adjust the devExt. value, if necessary.
2566 deviceExtension->lun[ldev].MaximumBlockXfer = 0;
2567 BrutePoint();
2568
2569 }
2570 }
2571 }
2572 }
2573
2574 // Set SCSI status to indicate a check condition.
2575 Srb->ScsiStatus = scsiStatus;
2576
2577 return srbStatus;
2578
2579 } // end MapError()
2580
2581
2582 /*++
2583
2584 Routine Description:
2585
2586 Arguments:
2587 HwDeviceExtension - HBA miniport driver's adapter data storage
2588
2589 Return Value:
2590 TRUE - if initialization successful.
2591 FALSE - if initialization unsuccessful.
2592
2593 --*/
2594 BOOLEAN
2595 DDKAPI
2596 AtapiHwInitialize(
2597 IN PVOID HwDeviceExtension
2598 )
2599 {
2600 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2601 ULONG numberChannels = deviceExtension->NumberChannels;
2602 ULONG c;
2603
2604 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base)\n"));
2605
2606 if(WinVer_WDM_Model) {
2607 AtapiResetController__(HwDeviceExtension, CHAN_NOT_SPECIFIED, RESET_COMPLETE_ALL);
2608 }
2609
2610 /* do extra chipset specific setups */
2611 AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
2612 /*
2613 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
2614 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
2615 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
2616 }
2617 */
2618 for (c = 0; c < numberChannels; c++) {
2619 AtapiHwInitialize__(deviceExtension, c);
2620 }
2621 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base) done\n"));
2622 return TRUE;
2623 } // end AtapiHwInitialize()
2624
2625 VOID
2626 NTAPI
2627 AtapiHwInitialize__(
2628 IN PHW_DEVICE_EXTENSION deviceExtension,
2629 IN ULONG lChannel
2630 )
2631 {
2632 ULONG i;
2633 UCHAR statusByte, errorByte;
2634 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
2635 PHW_LU_EXTENSION LunExt;
2636 // ULONG tmp32;
2637 ULONG PreferedMode = 0xffffffff;
2638
2639 AtapiChipInit(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel);
2640 FindDevices(deviceExtension, 0, lChannel);
2641
2642 for (i = lChannel*2; i < (lChannel+1)*2; i++) {
2643
2644 KdPrint3((PRINT_PREFIX "AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel, i));
2645
2646 LunExt = &(deviceExtension->lun[i]);
2647 // skip empty slots
2648 if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
2649 continue;
2650 }
2651
2652 AtapiDisableInterrupts(deviceExtension, lChannel);
2653 AtapiStallExecution(1);
2654
2655 if (!(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
2656
2657 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: IDE branch\n"));
2658 // Enable media status notification
2659 IdeMediaStatus(TRUE,deviceExtension,(UCHAR)i);
2660
2661 // If supported, setup Multi-block transfers.
2662 statusByte = AtaCommand(deviceExtension, i & 1, lChannel,
2663 IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
2664 LunExt->MaximumBlockXfer, 0, ATA_WAIT_BASE_READY);
2665
2666 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2667 // command was aborted.
2668 if (statusByte & IDE_STATUS_ERROR) {
2669
2670 // Read the error register.
2671 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
2672
2673 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
2674 statusByte,
2675 errorByte));
2676
2677 statusByte = AtaCommand(deviceExtension, i & 1, lChannel,
2678 IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
2679 LunExt->MaximumBlockXfer, 0, ATA_WAIT_BASE_READY);
2680
2681 if (statusByte & IDE_STATUS_ERROR) {
2682 // Read the error register.
2683 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
2684
2685 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
2686 statusByte,
2687 errorByte));
2688 }
2689 // Adjust the devExt. value, if necessary.
2690 LunExt->MaximumBlockXfer = 0;
2691
2692 } else {
2693 KdPrint2((PRINT_PREFIX
2694 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
2695 i,
2696 LunExt->MaximumBlockXfer));
2697 }
2698
2699 if(LunExt->IdentifyData.MajorRevision) {
2700
2701 if(LunExt->opt_ReadCacheEnable) {
2702 KdPrint2((PRINT_PREFIX " Try Enable Read Cache\n"));
2703 // If supported, setup read/write cacheing
2704 statusByte = AtaCommand(deviceExtension, i & 1, lChannel,
2705 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
2706 0, ATA_C_F_ENAB_RCACHE, ATA_WAIT_BASE_READY);
2707
2708 // Check for errors.
2709 if (statusByte & IDE_STATUS_ERROR) {
2710 KdPrint2((PRINT_PREFIX
2711 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
2712 i));
2713 LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
2714 } else {
2715 LunExt->DeviceFlags |= DFLAGS_RCACHE_ENABLED;
2716 }
2717 } else {
2718 KdPrint2((PRINT_PREFIX " Disable Read Cache\n"));
2719 statusByte = AtaCommand(deviceExtension, i & 1, lChannel,
2720 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
2721 0, ATA_C_F_DIS_RCACHE, ATA_WAIT_BASE_READY);
2722 LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
2723 }
2724 if(LunExt->opt_WriteCacheEnable) {
2725 KdPrint2((PRINT_PREFIX " Try Enable Write Cache\n"));
2726 // If supported & allowed, setup write cacheing
2727 statusByte = AtaCommand(deviceExtension, i & 1, lChannel,
2728 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
2729 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
2730 // Check for errors.
2731 if (statusByte & IDE_STATUS_ERROR) {
2732 KdPrint2((PRINT_PREFIX
2733 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
2734 i));
2735 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
2736 } else {
2737 LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED;
2738 }
2739 } else {
2740 KdPrint2((PRINT_PREFIX " Disable Write Cache\n"));
2741 statusByte = AtaCommand(deviceExtension, i & 1, lChannel,
2742 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
2743 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
2744 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
2745 }
2746 }
2747
2748 } else if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)){
2749
2750 ULONG j;
2751 BOOLEAN isSanyo = FALSE;
2752 CCHAR vendorId[26];
2753
2754 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: ATAPI/Changer branch\n"));
2755
2756 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
2757 for (j = 0; j < 26; j += 2) {
2758
2759 // Build a buffer based on the identify data.
2760 MOV_DW_SWP(vendorId[j], ((PUCHAR)LunExt->IdentifyData.ModelNumber)[j]);
2761 }
2762
2763 if (!AtapiStringCmp (vendorId, "CD-ROM CDR", 11)) {
2764
2765 // Inquiry string for older model had a '-', newer is '_'
2766 if (vendorId[12] == 'C') {
2767
2768 // Torisan changer. Set the bit. This will be used in several places
2769 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
2770 LunExt->DeviceFlags |= (DFLAGS_CHANGER_INITED | DFLAGS_SANYO_ATAPI_CHANGER);
2771 LunExt->DiscsPresent = 3;
2772 isSanyo = TRUE;
2773 }
2774 }
2775 }
2776
2777 PreferedMode = LunExt->opt_MaxTransferMode;
2778 if(PreferedMode == 0xffffffff) {
2779 KdPrint2((PRINT_PREFIX "MaxTransferMode (overriden): %#x\n", chan->MaxTransferMode));
2780 PreferedMode = chan->MaxTransferMode;
2781 }
2782
2783 if(LunExt->opt_PreferedTransferMode != 0xffffffff) {
2784 KdPrint2((PRINT_PREFIX "PreferedTransferMode: %#x\n", PreferedMode));
2785 PreferedMode = min(LunExt->opt_PreferedTransferMode, PreferedMode);
2786 }
2787
2788 KdPrint2((PRINT_PREFIX " try mode %#x\n", PreferedMode));
2789 LunExt->OrigTransferMode =
2790 LunExt->LimitedTransferMode =
2791 LunExt->TransferMode =
2792 (CHAR)PreferedMode;
2793
2794 AtapiDmaInit__(deviceExtension, i);
2795
2796 LunExt->OrigTransferMode =
2797 LunExt->LimitedTransferMode =
2798 LunExt->TransferMode;
2799 KdPrint2((PRINT_PREFIX "Using %#x mode\n", LunExt->TransferMode));
2800
2801 // We need to get our device ready for action before
2802 // returning from this function
2803
2804 // According to the atapi spec 2.5 or 2.6, an atapi device
2805 // clears its status BSY bit when it is ready for atapi commands.
2806 // However, some devices (Panasonic SQ-TC500N) are still
2807 // not ready even when the status BSY is clear. They don't react
2808 // to atapi commands.
2809 //
2810 // Since there is really no other indication that tells us
2811 // the drive is really ready for action. We are going to check BSY
2812 // is clear and then just wait for an arbitrary amount of time!
2813 //
2814 if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2815 ULONG waitCount;
2816
2817 // have to get out of the loop sometime!
2818 // 10000 * 100us = 1000,000us = 1000ms = 1s
2819 waitCount = 10000;
2820 GetStatus(chan, statusByte);
2821 while ((statusByte & IDE_STATUS_BUSY) && waitCount) {
2822
2823 KdPrint2((PRINT_PREFIX "Wait for ATAPI (status %x\n)", statusByte));
2824 // Wait for Busy to drop.
2825 AtapiStallExecution(100);
2826 GetStatus(chan, statusByte);
2827 waitCount--;
2828 }
2829
2830 // 5000 * 100us = 500,000us = 500ms = 0.5s
2831 waitCount = 5000;
2832 do {
2833 AtapiStallExecution(100);
2834 } while (waitCount--);
2835 }
2836 GetBaseStatus(chan, statusByte);
2837 AtapiEnableInterrupts(deviceExtension, lChannel);
2838 AtapiStallExecution(10);
2839 }
2840
2841 return;
2842
2843 } // end AtapiHwInitialize()
2844
2845
2846 #ifndef UNIATA_CORE
2847
2848 VOID
2849 NTAPI
2850 AtapiHwInitializeChanger(
2851 IN PVOID HwDeviceExtension,
2852 IN PSCSI_REQUEST_BLOCK Srb,
2853 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus)
2854 {
2855 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2856 ULONG ldev = GET_LDEV(Srb);
2857
2858 if (MechanismStatus) {
2859 deviceExtension->lun[ldev].DiscsPresent = MechanismStatus->NumberAvailableSlots;
2860 if (deviceExtension->lun[ldev].DiscsPresent > 1) {
2861 deviceExtension->lun[ldev].DeviceFlags |= DFLAGS_ATAPI_CHANGER;
2862 }
2863 }
2864 return;
2865 } // end AtapiHwInitializeChanger()
2866
2867
2868 /*++
2869
2870 Routine Description:
2871 This routine will parse the string for a match on the keyword, then
2872 calculate the value for the keyword and return it to the caller.
2873
2874 Arguments:
2875 String - The ASCII string to parse.
2876 KeyWord - The keyword for the value desired.
2877
2878 Return Values:
2879 Zero if value not found
2880 Value converted from ASCII to binary.
2881
2882 --*/
2883 ULONG
2884 NTAPI
2885 AtapiParseArgumentString(
2886 IN PCCH String,
2887 IN PCCH KeyWord
2888 )
2889 {
2890 PCCH cptr;
2891 PCCH kptr;
2892 ULONG value;
2893 ULONG stringLength = 0;
2894 ULONG keyWordLength = 0;
2895 ULONG index;
2896
2897 if (!String) {
2898 return 0;
2899 }
2900 if (!KeyWord) {
2901 return 0;
2902 }
2903
2904 // Calculate the string length.
2905 cptr = String;
2906 while (*cptr++) {
2907 stringLength++;
2908 }
2909
2910 // Calculate the keyword length.
2911 kptr = KeyWord;
2912 while (*kptr++) {
2913 keyWordLength++;
2914 }
2915
2916 if (keyWordLength > stringLength) {
2917
2918 // Can't possibly have a match.
2919 return 0;
2920 }
2921
2922 // Now setup and start the compare.
2923 cptr = String;
2924
2925 ContinueSearch:
2926
2927 // The input string may start with white space. Skip it.
2928 while (*cptr == ' ' || *cptr == '\t') {
2929 cptr++;
2930 }
2931
2932 if (*cptr == '\0') {
2933 // end of string.
2934 return 0;
2935 }
2936
2937 kptr = KeyWord;
2938 while ((*cptr == *kptr) ||
2939 (*cptr <= 'Z' && *cptr + ('a' - 'A') == *kptr) ||
2940 (*cptr >= 'a' && *cptr - ('a' - 'A') == *kptr)) {
2941 cptr++;
2942 kptr++;
2943
2944 if (*cptr == '\0') {
2945 // end of string
2946 return 0;
2947 }
2948 }
2949
2950 if (*kptr == '\0') {
2951
2952 // May have a match backup and check for blank or equals.
2953 while (*cptr == ' ' || *cptr == '\t') {
2954 cptr++;
2955 }
2956
2957 // Found a match. Make sure there is an equals.
2958 if (*cptr != '=') {
2959
2960 // Not a match so move to the next semicolon.
2961 while (*cptr) {
2962 if (*cptr++ == ';') {
2963 goto ContinueSearch;
2964 }
2965 }
2966 return 0;
2967 }
2968 // Skip the equals sign.
2969 cptr++;
2970
2971 // Skip white space.
2972 while ((*cptr == ' ') || (*cptr == '\t')) {
2973 cptr++;
2974 }
2975
2976 if (*cptr == '\0') {
2977 // Early end of string, return not found
2978 return 0;
2979 }
2980
2981 if (*cptr == ';') {
2982 // This isn't it either.
2983 cptr++;
2984 goto ContinueSearch;
2985 }
2986
2987 value = 0;
2988 if ((*cptr == '0') && ((*(cptr + 1) == 'x') || (*(cptr + 1) == 'X'))) {
2989 // Value is in Hex. Skip the "0x"
2990 cptr += 2;
2991 for (index = 0; *(cptr + index); index++) {
2992
2993 if (*(cptr + index) == ' ' ||
2994 *(cptr + index) == '\t' ||
2995 *(cptr + index) == ';') {
2996 break;
2997 }
2998
2999 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
3000 value = (16 * value) + (*(cptr + index) - '0');
3001 } else {
3002 if ((*(cptr + index) >= 'a') && (*(cptr + index) <= 'f')) {
3003 value = (16 * value) + (*(cptr + index) - 'a' + 10);
3004 } else if ((*(cptr + index) >= 'A') && (*(cptr + index) <= 'F')) {
3005 value = (16 * value) + (*(cptr + index) - 'A' + 10);
3006 } else {
3007 // Syntax error, return not found.
3008 return 0;
3009 }
3010 }
3011 }
3012 } else {
3013
3014 // Value is in Decimal.
3015 for (index = 0; *(cptr + index); index++) {
3016
3017 if (*(cptr + index) == ' ' ||
3018 *(cptr + index) == '\t' ||
3019 *(cptr + index) == ';') {
3020 break;
3021 }
3022
3023 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
3024 value = (10 * value) + (*(cptr + index) - '0');
3025 } else {
3026
3027 // Syntax error return not found.
3028 return 0;
3029 }
3030 }
3031 }
3032
3033 return value;
3034 } else {
3035
3036 // Not a match check for ';' to continue search.
3037 while (*cptr) {
3038 if (*cptr++ == ';') {
3039 goto ContinueSearch;
3040 }
3041 }
3042
3043 return 0;
3044 }
3045 } // end AtapiParseArgumentString()_
3046
3047 /*
3048 Timer callback
3049 */
3050 VOID
3051 NTAPI
3052 AtapiCallBack__(
3053 IN PVOID HwDeviceExtension,
3054 IN UCHAR lChannel
3055 )
3056 {
3057
3058 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3059 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
3060 ULONG c, _c;
3061
3062 PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
3063 UCHAR statusByte;
3064
3065 KdPrint2((PRINT_PREFIX "AtapiCallBack:\n"));
3066 // If the last command was DSC restrictive, see if it's set. If so, the device is
3067 // ready for a new request. Otherwise, reset the timer and come back to here later.
3068
3069 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3070 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3071 // we shall have no problem with interrupt handler.
3072 if (!srb || chan->ExpectingInterrupt) {
3073 KdPrint2((PRINT_PREFIX "AtapiCallBack: Calling ISR directly due to BUSY\n"));
3074 chan->DpcState = DPC_STATE_TIMER;
3075 if(!AtapiInterrupt__(HwDeviceExtension, lChannel)) {
3076 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
3077 KdPrint2((PRINT_PREFIX "AtapiCallBack: What's fucking this ???\n"));
3078 }
3079 goto ReturnCallback;
3080 }
3081
3082 #if DBG
3083 if (!IS_RDP((srb->Cdb[0]))) {
3084 KdPrint2((PRINT_PREFIX "AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb->Cdb[0]));
3085 }
3086 #endif
3087 if(!(chan->RDP)) {
3088 goto ReturnEnableIntr;
3089 }
3090 GetStatus(chan, statusByte);
3091 if (statusByte & IDE_STATUS_DSC) {
3092
3093 UCHAR PathId = srb->PathId;
3094 UCHAR TargetId = srb->TargetId;
3095 UCHAR Lun = srb->Lun;
3096
3097 KdPrint2((PRINT_PREFIX "AtapiCallBack: Found DSC for RDP - %#x\n", srb->Cdb[0]));
3098 AtapiDmaDBSync(chan, srb);
3099 UniataRemoveRequest(chan, srb);
3100 ScsiPortNotification(RequestComplete, deviceExtension, srb);
3101 // Clear current SRB.
3102 if(!deviceExtension->simplexOnly) {
3103 srb = UniataGetCurRequest(chan);
3104 } else {
3105 srb = NULL;
3106 }
3107 chan->RDP = FALSE;
3108
3109 // Ask for next request.
3110 ScsiPortNotification(NextLuRequest,
3111 deviceExtension,
3112 PathId,
3113 TargetId,
3114 Lun);
3115 ScsiPortNotification(NextRequest, deviceExtension, NULL);
3116
3117 if(srb) {
3118 AtapiStartIo__(HwDeviceExtension, srb, FALSE);
3119 }
3120
3121 } else {
3122 KdPrint2((PRINT_PREFIX "AtapiCallBack: Requesting another timer for Op %#x\n",
3123 srb->Cdb[0]));
3124
3125 AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
3126 AtapiCallBack_X,
3127 1000);
3128
3129 goto ReturnCallback;
3130 }
3131
3132 ReturnEnableIntr:
3133
3134 if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) {
3135 KdPrint2((PRINT_PREFIX "AtapiCallBack: CallDisableInterrupts\n"));
3136 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3137 #ifdef UNIATA_USE_XXableInterrupts
3138 chan->ChannelCtrlFlags |= CTRFLAGS_ENABLE_INTR_REQ;
3139 // must be called on DISPATCH_LEVEL
3140 ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension,
3141 AtapiEnableInterrupts__);
3142 #else
3143 AtapiEnableInterrupts(HwDeviceExtension, lChannel);
3144 InterlockedExchange(&(chan->CheckIntr),
3145 CHECK_INTR_IDLE);
3146 // Will raise IRQL to DIRQL
3147 AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
3148 AtapiEnableInterrupts__,
3149 1);
3150 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
3151 #endif // UNIATA_USE_XXableInterrupts
3152 } else {
3153 //ASSERT(!deviceExtension->simplexOnly);
3154 }
3155
3156 ReturnCallback:
3157
3158 // Check other channel
3159 // In simplex mode no interrupts must appear on other channels
3160 for(_c=0; _c<deviceExtension->NumberChannels-1; _c++) {
3161 c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
3162
3163 chan = &(deviceExtension->chan[c]);
3164
3165 if((ULONG)InterlockedCompareExchange(&chan->CheckIntr,
3166 CHECK_INTR_ACTIVE,
3167 CHECK_INTR_DETECTED) == CHECK_INTR_DETECTED) {
3168 //ASSERT(!deviceExtension->simplexOnly);
3169 chan->DpcState = DPC_STATE_ISR;
3170 if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
3171 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
3172 }
3173 }
3174 }
3175 KdPrint2((PRINT_PREFIX "AtapiCallBack: return\n"));
3176 return;
3177
3178 } // end AtapiCallBack__()
3179
3180 VOID
3181 NTAPI
3182 AtapiCallBack_X(
3183 IN PVOID HwDeviceExtension
3184 )
3185 {
3186 AtapiCallBack__(HwDeviceExtension, (UCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->ActiveDpcChan);
3187 }
3188
3189 #endif //UNIATA_CORE
3190
3191 /*++
3192
3193 Routine Description:
3194
3195 This is the interrupt service routine for ATAPI IDE miniport driver.
3196
3197 Arguments:
3198
3199 HwDeviceExtension - HBA miniport driver's adapter data storage
3200
3201 Return Value:
3202
3203 TRUE if expecting an interrupt.
3204
3205 --*/
3206 BOOLEAN
3207 DDKAPI
3208 AtapiInterrupt(
3209 IN PVOID HwDeviceExtension
3210 )
3211 {
3212 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3213 ULONG c, _c;
3214 BOOLEAN status = FALSE;
3215 ULONG c_state;
3216 ULONG i_res = 0;
3217 ULONG pass;
3218 BOOLEAN checked[AHCI_MAX_PORT];
3219
3220 KdPrint2((PRINT_PREFIX "Intr: VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
3221
3222 for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
3223 checked[_c] = FALSE;
3224 }
3225 // fc =
3226 // atapiDev = (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
3227 for(pass=0; pass<2; pass++) {
3228 for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
3229
3230 c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
3231 //non_empty_chan = (deviceExtension->lun[c*2].DeviceFlags | deviceExtension->lun[c*2+1].DeviceFlags)
3232 // & DFLAGS_DEVICE_PRESENT;
3233
3234 if(checked[c])
3235 continue;
3236
3237 // check non-empty and expecting interrupt channels first
3238 if(!pass && !deviceExtension->chan[c].ExpectingInterrupt)
3239 continue;
3240
3241 checked[c] = TRUE;
3242
3243 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
3244
3245 if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
3246 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): disabled INTR on ch %d\n", c));
3247 continue;
3248 }
3249 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
3250 do {
3251 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): try lock\n"));
3252 // c_state = deviceExtension->chan[c].CheckIntr;
3253 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
3254 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
3255 // }
3256 c_state = (ULONG)InterlockedCompareExchange(&(deviceExtension->chan[c].CheckIntr),
3257 CHECK_INTR_ACTIVE,
3258 CHECK_INTR_DETECTED);
3259 if(c_state == CHECK_INTR_IDLE) {
3260 // c_state = deviceExtension->chan[c].CheckIntr;
3261 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
3262 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
3263 // }
3264 c_state = (ULONG)InterlockedCompareExchange(&(deviceExtension->chan[c].CheckIntr),
3265 CHECK_INTR_ACTIVE,
3266 CHECK_INTR_IDLE);
3267 }
3268 } while(c_state == CHECK_INTR_CHECK);
3269 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): locked\n"));
3270 // check if already serviced
3271 if(c_state == CHECK_INTR_ACTIVE) {
3272 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
3273 continue;
3274 }
3275
3276 if((c_state == CHECK_INTR_DETECTED) ||
3277 (i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
3278
3279 if(i_res == 2) {
3280 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): Catch unexpected\n"));
3281 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
3282 return TRUE;
3283 }
3284 // disable interrupts on other channel of legacy mode
3285 // ISA-bridged onboard controller
3286 if(deviceExtension->simplexOnly /*||
3287 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3288 AtapiDisableInterrupts(deviceExtension, !c);
3289 }
3290
3291 deviceExtension->chan[c].DpcState = DPC_STATE_ISR;
3292 if(AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
3293 deviceExtension->LastInterruptedChannel = (UCHAR)c;
3294 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): return status TRUE\n"));
3295 status = TRUE;
3296 } else {
3297 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
3298 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
3299 }
3300
3301 // re-enable interrupts on other channel
3302 if(deviceExtension->simplexOnly /*||
3303 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3304 AtapiEnableInterrupts(deviceExtension, !c);
3305 }
3306
3307 } else {
3308 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
3309 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
3310 }
3311
3312 }
3313 }
3314 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): exit with status %#x\n", status));
3315 if(status) {
3316 deviceExtension->FirstChannelToCheck++;
3317 if(deviceExtension->FirstChannelToCheck >= deviceExtension->NumberChannels)
3318 deviceExtension->FirstChannelToCheck = 0;
3319 }
3320 return status;
3321 } // end AtapiInterrupt()
3322
3323 //ULONG i2c = 0;
3324 #ifndef UNIATA_CORE
3325
3326 BOOLEAN
3327 NTAPI
3328 AtapiInterrupt2(
3329 IN PKINTERRUPT Interrupt,
3330 IN PVOID Isr2HwDeviceExtension
3331 )
3332 {
3333
3334 PISR2_DEVICE_EXTENSION Isr2DeviceExtension = (PISR2_DEVICE_EXTENSION)Isr2HwDeviceExtension;
3335 PHW_DEVICE_EXTENSION deviceExtension = Isr2DeviceExtension->HwDeviceExtension;
3336 ULONG c;
3337 BOOLEAN status = FALSE;
3338 ULONG c_count = 0;
3339 ULONG i_res;
3340
3341 // we should never get here for ISA/MCA
3342 if(!BMList[deviceExtension->DevIndex].Isr2Enable) {
3343 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension->DevIndex, deviceExtension->Channel));
3344 return FALSE;
3345 }
3346
3347 for(c=0; c<deviceExtension->NumberChannels; c++) {
3348 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
3349
3350 if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
3351 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: disabled INTR\n"));
3352 continue;
3353 }
3354
3355 if((ULONG)CrNtInterlockedCompareExchange(&(deviceExtension->chan[c].CheckIntr),
3356 CHECK_INTR_CHECK,
3357 CHECK_INTR_IDLE) != CHECK_INTR_IDLE) {
3358 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
3359 // hunt on unexpected intr (Some devices generate double interrupts,
3360 // some controllers (at least CMD649) interrupt twice with small delay.
3361 // If interrupts are disabled, they queue interrupt and re-issue it later,
3362 // when we do not expect it.
3363 continue;
3364 }
3365
3366 c_count++;
3367 if((i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
3368
3369 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: intr\n"));
3370 if(i_res == 2) {
3371 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: Catch unexpected\n"));
3372 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
3373 return TRUE;
3374 }
3375
3376 status = TRUE;
3377 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_DETECTED);
3378 } else {
3379 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
3380 }
3381 }
3382 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: status %d, c_count %d\n", status, c_count));
3383 if(status && (c_count != deviceExtension->NumberChannels)) {
3384 // there is an active ISR/DPC for one channel, but
3385 // we have an interrupt from another one
3386 // Lets inform current ISR/DPC about new interrupt
3387 InterlockedExchange(&(deviceExtension->ReCheckIntr), CHECK_INTR_DETECTED);
3388 } else {
3389 status = FALSE;
3390 }
3391 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: return %d\n", status));
3392 return status;
3393
3394 } // end AtapiInterrupt2()
3395
3396 RETTYPE_XXableInterrupts
3397 DDKAPI
3398 AtapiInterruptDpc(
3399 IN PVOID HwDeviceExtension
3400 )
3401 {
3402 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3403 ULONG c;
3404
3405 for(c=0; c<deviceExtension->NumberChannels; c++) {
3406 KdPrint2((PRINT_PREFIX "AtapiInterruptDpc: %#x\n",c));
3407
3408 if(!(deviceExtension->chan[c].ChannelCtrlFlags & CTRFLAGS_DPC_REQ)) {
3409
3410 if((ULONG)InterlockedCompareExchange(&(deviceExtension->chan[c].CheckIntr),
3411 CHECK_INTR_ACTIVE,
3412 CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED) {
3413 continue;
3414 }
3415
3416 } else {
3417 deviceExtension->chan[c].ChannelCtrlFlags &= ~CTRFLAGS_DPC_REQ;
3418 }
3419 /*
3420 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
3421 AtapiDisableInterrupts(deviceExtension, lChannel);
3422 }
3423 */
3424 deviceExtension->chan[c].DpcState = DPC_STATE_DPC;
3425 if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
3426 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
3427 }
3428 }
3429 return RETVAL_XXableInterrupts;
3430 } // end AtapiInterruptDpc()
3431
3432
3433 RETTYPE_XXableInterrupts
3434 DDKAPI
3435 AtapiEnableInterrupts__(
3436 IN PVOID HwDeviceExtension
3437 )
3438 {
3439 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3440 KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__():\n"));
3441 ULONG c;
3442 PHW_CHANNEL chan = NULL;
3443
3444 for(c=0; c<deviceExtension->NumberChannels; c++) {
3445 KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__(2): %#x\n",c));
3446 chan = &(deviceExtension->chan[c]);
3447
3448 if(chan->ChannelCtrlFlags & CTRFLAGS_ENABLE_INTR_REQ) {
3449 // enable intrs on requested channel
3450 chan->ChannelCtrlFlags &= ~CTRFLAGS_ENABLE_INTR_REQ;
3451 AtapiEnableInterrupts(HwDeviceExtension, c);
3452 InterlockedExchange(&(chan->CheckIntr),
3453 CHECK_INTR_IDLE);
3454
3455 // check if current or other channel(s) interrupted
3456 //AtapiInterrupt(HwDeviceExtension);
3457
3458 if(deviceExtension->simplexOnly) {
3459 break;
3460 }
3461 } else {
3462 // check if other channel(s) interrupted
3463 // must do nothing in simplex mode
3464 if((ULONG)CrNtInterlockedCompareExchange(&(chan->CheckIntr),
3465 CHECK_INTR_ACTIVE,
3466 CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED) {
3467 continue;
3468 }
3469 //ASSERT(!deviceExtension->simplexOnly);
3470 chan->DpcState = DPC_STATE_ISR;
3471 if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
3472 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
3473 }
3474 }
3475 }
3476 // In simplex mode next command must be sent to device here
3477 if(deviceExtension->simplexOnly && chan) {
3478 PSCSI_REQUEST_BLOCK srb;
3479 chan = UniataGetNextChannel(chan);
3480 if(chan) {
3481 srb = UniataGetCurRequest(chan);
3482 } else {
3483 srb = NULL;
3484 }
3485 if(srb) {
3486 AtapiStartIo__(HwDeviceExtension, srb, FALSE);
3487 }
3488 }
3489
3490 return RETVAL_XXableInterrupts;
3491
3492 } // end AtapiEnableInterrupts__()
3493
3494 #endif //UNIATA_CORE
3495
3496
3497 VOID
3498 NTAPI
3499 AtapiEnableInterrupts(
3500 IN PVOID HwDeviceExtension,
3501 IN ULONG c
3502 )
3503 {
3504 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3505 KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: %d\n",c, deviceExtension->chan[c].DisableIntr));
3506 if(c >= deviceExtension->NumberChannels) {
3507 return;
3508 }
3509 if(!InterlockedDecrement(&deviceExtension->chan[c].DisableIntr)) {
3510 AtapiWritePort1(&deviceExtension->chan[c], IDX_IO2_o_Control,
3511 IDE_DC_A_4BIT );
3512 deviceExtension->chan[c].ChannelCtrlFlags &= ~CTRFLAGS_INTR_DISABLED;
3513 } else {
3514 AtapiWritePort1(&deviceExtension->chan[c], IDX_IO2_o_Control,
3515 IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
3516 }
3517 return;
3518 } // end AtapiEnableInterrupts()
3519
3520 VOID
3521 NTAPI
3522 AtapiDisableInterrupts(
3523 IN PVOID HwDeviceExtension,
3524 IN ULONG c
3525 )
3526 {
3527 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3528 KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: %d\n",c, deviceExtension->chan[c].DisableIntr));
3529 // mark channel as busy
3530 if(c >= deviceExtension->NumberChannels) {
3531 return;
3532 }
3533 if(InterlockedIncrement(&deviceExtension->chan[c].DisableIntr)) {
3534 AtapiWritePort1(&deviceExtension->chan[c], IDX_IO2_o_Control,
3535 IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
3536 deviceExtension->chan[c].ChannelCtrlFlags |= CTRFLAGS_INTR_DISABLED;
3537 }
3538
3539 return;
3540 } // end AtapiDisableInterrupts()
3541
3542
3543 /*
3544 Check hardware for interrupt state
3545 */
3546 BOOLEAN
3547 NTAPI
3548 AtapiCheckInterrupt__(
3549 IN PVOID HwDeviceExtension,
3550 IN UCHAR c // logical channel
3551 )
3552 {
3553 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3554 PHW_CHANNEL chan = &(deviceExtension->chan[c]);
3555 PHW_LU_EXTENSION LunExt;
3556
3557 ULONG VendorID = deviceExtension->DevID & 0xffff;
3558 ULONG ChipType = deviceExtension->HwFlags & CHIPTYPE_MASK;
3559
3560 ULONG status;
3561 ULONG pr_status = 0;
3562 UCHAR dma_status = 0;
3563 UCHAR reg8 = 0;
3564 ULONG reg32 = 0;
3565 UCHAR statusByte;
3566 ULONG slotNumber = deviceExtension->slotNumber;
3567 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
3568 ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
3569 UCHAR Channel;
3570 UCHAR lChannel;
3571 BOOLEAN DmaTransfer = FALSE;
3572 BOOLEAN OurInterrupt = FALSE;
3573 // ULONG k;