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