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