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