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