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