ReactOS 0.4.16-dev-329-g9223134
id_ata.cpp
Go to the documentation of this file.
1/*++
2
3Copyright (c) 2002-2018 Alexandr A. Telyatnikov (Alter)
4
5Module Name:
6 id_ata.cpp
7
8Abstract:
9 This is the miniport driver for ATA/ATAPI IDE/SATA/AHCI controllers
10 with Busmaster DMA and Serial ATA support
11
12Author:
13 Alexander A. Telyatnikov (Alter)
14
15Environment:
16 kernel mode only
17
18Notes:
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
31Revision History:
32
33 The skeleton was taken from standard ATAPI.SYS from NT4 DDK by
34 Mike Glass (MGlass)
35 Chuck Park (ChuckP)
36
37 Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by
38 Søren Schmidt, Copyright (c) 1998-2007
39
40 All parts of code are significantly changed/updated by
41 Alter, Copyright (c) 2002-2014:
42
43 1. Internal command queueing/reordering
44 2. Drive identification
45 3. Support for 2 _independent_ channels in a single PCI device
46 4. Smart host<->drive transfer rate slowdown (for bad cable)
47 5. W2k support (binary compatibility)
48 6. HDD hot swap under NT4
49 7. XP support (binary compatibility)
50 8. Serial ATA (SATA/SATA2/SATA3) support
51 9. NT 3.51 support (binary compatibility)
52 10. AHCI support
53
54 etc. (See todo.txt)
55
56Licence:
57 GPLv2
58
59--*/
60
61#include "stdafx.h"
62
63#ifndef UNIATA_CORE
64
65static const CHAR ver_string[] = "\n\nATAPI IDE MiniPort Driver (UniATA) v 0." UNIATA_VER_STR "\n";
66
68
71
72#endif //UNIATA_CORE
73
74//UCHAR AtaCommands48[256];
75//UCHAR AtaCommandFlags[256];
76
79
82
83#ifdef _DEBUG
85#endif //_DEBUG
86
88
96
98
104
106
109
111
114
115//UCHAR EnableDma = FALSE;
116//UCHAR EnableReorder = FALSE;
117
119
121NTAPI
123 IN PVOID HwDeviceExtension,
125 IN UCHAR CompleteType
126 );
127
128VOID
129NTAPI
131 IN PHW_DEVICE_EXTENSION deviceExtension,
132 IN ULONG lChannel
133 );
134
135VOID
136NTAPI
138 PHW_DEVICE_EXTENSION deviceExtension,
139 PHW_LU_EXTENSION LunExt,
140 ULONG lChannel
141 );
142
143#define RESET_COMPLETE_CURRENT 0x00
144#define RESET_COMPLETE_ALL 0x01
145#define RESET_COMPLETE_NONE 0x02
146
147#ifndef UNIATA_CORE
148
149VOID
150NTAPI
152 IN PVOID HwDeviceExtension
153 );
154
155#ifdef UNIATA_USE_XXableInterrupts
156 #define RETTYPE_XXableInterrupts BOOLEAN
157 #define RETVAL_XXableInterrupts TRUE
158#else
159 #define RETTYPE_XXableInterrupts VOID
160 #define RETVAL_XXableInterrupts
161#endif
162
164NTAPI
166 IN PVOID HwDeviceExtension
167 );
168
170NTAPI
172 IN PVOID HwDeviceExtension
173 );
174
175VOID
176NTAPI
178 IN PVOID HwDeviceExtension,
179 IN ULONG lChannel,
180 IN PHW_TIMER HwScsiTimer,
181 IN ULONG MiniportTimerValue
182 );
183
185NTAPI
187 IN PVOID HwDeviceExtension,
188 IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
190 );
191
192#endif //UNIATA_CORE
193
194#ifndef UNIATA_CORE
195
197NTAPI
200 IN PWSTR Name,
201 IN PWCHAR Str,
202 IN ULONG MaxLen
203 )
204{
205#define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
208 UNICODE_STRING ustr;
209
210 ustr.Buffer = Str;
211 ustr.Length =
212 ustr.MaximumLength = (USHORT)MaxLen;
214
215 parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
216 parameters[0].Name = Name;
217 parameters[0].EntryContext = &ustr;
218 parameters[0].DefaultType = REG_SZ;
219 parameters[0].DefaultData = Str;
220 parameters[0].DefaultLength = MaxLen;
221
222 status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/,
223 RegistryPath, parameters, NULL, NULL);
224
225 if(!NT_SUCCESS(status))
226 return FALSE;
227
228 return TRUE;
229
230#undef ITEMS_TO_QUERY
231} // end AtapiRegGetStringParameterValue()
232
233
234#endif //UNIATA_CORE
235
236VOID
239 ULONG nano
240 )
241{
242 LONGLONG t;
243 LARGE_INTEGER t0;
244
245#ifdef NAVO_TEST
246 return;
247#endif //NAVO_TEST
248
249 if(!nano || !g_Perf || !g_PerfDt)
250 return;
251 t = (g_Perf * nano) / g_PerfDt / 1000;
252 if(!t) {
253 t = 1;
254 }
255 do {
257 t--;
258 } while(t);
259} // end UniataNanoSleep()
260
261#define AtapiWritePortN_template(_type, _Type, sz) \
262VOID \
263DDKFASTAPI \
264AtapiWritePort##sz( \
265 IN PHW_CHANNEL chan, \
266 IN ULONGIO_PTR _port, \
267 IN _type data \
268 ) \
269{ \
270 PIORES res; \
271 if(_port >= IDX_MAX_REG) { \
272 res = (PIORES)(_port); \
273 } else \
274 if(chan) { \
275 res = &chan->RegTranslation[_port]; \
276 } else { \
277 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
278 return; \
279 } \
280 if(res->Proc) { \
281 KdPrint(("PROC io write request @ ch %x, res* %x\n", chan, _port)); \
282 ASSERT(FALSE); /* We should never get here */ \
283 } \
284 if(!res->MemIo) { \
285 ScsiPortWritePort##_Type((_type*)(ULONGIO_PTR)(res->Addr), data); \
286 } else { \
287 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
288 ScsiPortWriteRegister##_Type((_type*)(ULONG_PTR)(res->Addr), data); \
289 } \
290 return; \
291}
292
296
297#define AtapiWritePortExN_template(_type, _Type, sz) \
298VOID \
299DDKFASTAPI \
300AtapiWritePortEx##sz( \
301 IN PHW_CHANNEL chan, \
302 IN ULONGIO_PTR _port, \
303 IN ULONG offs, \
304 IN _type data \
305 ) \
306{ \
307 PIORES res; \
308 if(_port >= IDX_MAX_REG) { \
309 res = (PIORES)(_port); \
310 } else \
311 if(chan) { \
312 res = &chan->RegTranslation[_port]; \
313 } else { \
314 KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
315 return; \
316 } \
317 if(res->Proc) { \
318 KdPrint(("PROC io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
319 ASSERT(FALSE); /* We should never get here */ \
320 } \
321 if(!res->MemIo) { \
322 ScsiPortWritePort##_Type((_type*)(ULONGIO_PTR)(res->Addr+offs), data); \
323 } else { \
324 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
325 ScsiPortWriteRegister##_Type((_type*)(ULONG_PTR)(res->Addr+offs), data); \
326 } \
327 return; \
328}
329
331//AtapiWritePortExN_template(USHORT, Ushort, 2);
333
334#define AtapiReadPortN_template(_type, _Type, sz) \
335_type \
336DDKFASTAPI \
337AtapiReadPort##sz( \
338 IN PHW_CHANNEL chan, \
339 IN ULONGIO_PTR _port \
340 ) \
341{ \
342 PIORES res; \
343 if(_port >= IDX_MAX_REG) { \
344 res = (PIORES)(_port); \
345 } else \
346 if(chan) { \
347 res = &chan->RegTranslation[_port]; \
348 } else { \
349 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
350 return (_type)(-1); \
351 } \
352 if(res->Proc) { \
353 KdPrint(("PROC io read request @ ch %x, res* %x\n", chan, _port)); \
354 ASSERT(FALSE); /* We should never get here */ \
355 } \
356 if(!res->MemIo) { \
357 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
358 return ScsiPortReadPort##_Type((_type*)(ULONGIO_PTR)(res->Addr)); \
359 } else { \
360 /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
361 return ScsiPortReadRegister##_Type((_type*)(ULONG_PTR)(res->Addr)); \
362 } \
363}
364
368
369#define AtapiReadPortExN_template(_type, _Type, sz) \
370_type \
371DDKFASTAPI \
372AtapiReadPortEx##sz( \
373 IN PHW_CHANNEL chan, \
374 IN ULONGIO_PTR _port, \
375 IN ULONG offs \
376 ) \
377{ \
378 PIORES res; \
379 if(_port >= IDX_MAX_REG) { \
380 res = (PIORES)(_port); \
381 } else \
382 if(chan) { \
383 res = &chan->RegTranslation[_port]; \
384 } else { \
385 KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
386 return (_type)(-1); \
387 } \
388 if(res->Proc) { \
389 KdPrint(("PROC io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
390 ASSERT(FALSE); /* We should never get here */ \
391 } \
392 if(!res->MemIo) { \
393 return ScsiPortReadPort##_Type((_type*)(ULONGIO_PTR)(res->Addr+offs)); \
394 } else { \
395 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
396 return ScsiPortReadRegister##_Type((_type*)(ULONG_PTR)(res->Addr+offs)); \
397 } \
398}
399
401//AtapiReadPortExN_template(USHORT, Ushort, 2);
403
404#define AtapiReadPortBufferN_template(_type, _Type, sz) \
405VOID \
406DDKFASTAPI \
407AtapiReadBuffer##sz( \
408 IN PHW_CHANNEL chan, \
409 IN ULONGIO_PTR _port, \
410 IN PVOID Buffer, \
411 IN ULONG Count, \
412 IN ULONG Timing \
413 ) \
414{ \
415 PIORES res; \
416 \
417 if(Timing) { \
418 while(Count) { \
419 (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
420 Count--; \
421 Buffer = ((_type*)Buffer)+1; \
422 UniataNanoSleep(Timing); \
423 } \
424 return; \
425 } \
426 \
427 if(_port >= IDX_MAX_REG) { \
428 res = (PIORES)(_port); \
429 } else \
430 if(chan) { \
431 res = &chan->RegTranslation[_port]; \
432 } else { \
433 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
434 return; \
435 } \
436 if(!res->MemIo) { \
437 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
438 ScsiPortReadPortBuffer##_Type((_type*)(ULONGIO_PTR)(res->Addr), (_type*)Buffer, Count); \
439 return; \
440 } \
441 while(Count) { \
442 (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(ULONG_PTR)(res->Addr)); \
443 Count--; \
444 Buffer = ((_type*)Buffer)+1; \
445 } \
446 return; \
447}
448
449#define AtapiWritePortBufferN_template(_type, _Type, sz) \
450VOID \
451DDKFASTAPI \
452AtapiWriteBuffer##sz( \
453 IN PHW_CHANNEL chan, \
454 IN ULONGIO_PTR _port, \
455 IN PVOID Buffer, \
456 IN ULONG Count, \
457 IN ULONG Timing \
458 ) \
459{ \
460 PIORES res; \
461 \
462 if(Timing) { \
463 while(Count) { \
464 AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
465 Buffer = ((_type*)Buffer)+1; \
466 Count--; \
467 UniataNanoSleep(Timing); \
468 } \
469 return; \
470 } \
471 \
472 if(_port >= IDX_MAX_REG) { \
473 res = (PIORES)(_port); \
474 } else \
475 if(chan) { \
476 res = &chan->RegTranslation[_port]; \
477 } else { \
478 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
479 return; \
480 } \
481 if(!res->MemIo) { \
482 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
483 ScsiPortWritePortBuffer##_Type((_type*)(ULONGIO_PTR)(res->Addr), (_type*)Buffer, Count); \
484 return; \
485 } \
486 while(Count) { \
487 ScsiPortWriteRegister##_Type((_type*)(ULONG_PTR)(res->Addr), *((_type*)Buffer)); \
488 Count--; \
489 Buffer = ((_type*)Buffer)+1; \
490 } \
491 return; \
492}
493
496
499
500
501UCHAR
504 IN PHW_CHANNEL chan
505 )
506{
507 UCHAR statusByte;
508 ULONG i;
509
510 // Assume, proper drive is already seleted
511 WaitOnBusyLong(chan);
512 for (i = 0; i < 0x10000; i++) {
513
514 GetStatus(chan, statusByte);
515 if (statusByte & IDE_STATUS_DRQ) {
516 // Suck out any remaining bytes and throw away.
519 } else {
520 break;
521 }
522 }
523 if(i) {
524 KdPrint2((PRINT_PREFIX "AtapiSuckPort2: overrun detected (%#x words)\n", i ));
525 }
526 return statusByte;
527} // AtapiSuckPort2()
528
529ULONG
532 IN PHW_CHANNEL chan,
535 )
536{
537 UCHAR statusByte;
538 ULONG i;
539 USHORT data;
540 BOOLEAN retry = FALSE;
541
542 // Assume, proper drive is already seleted
543 WaitOnBusyLong(chan);
544 for (i = 0; i < Count; i++) {
545
546 GetStatus(chan, statusByte);
547 if (statusByte & IDE_STATUS_DRQ) {
548 // Suck out any remaining bytes and throw away.
550 (*Buffer) = data;
551 Count--;
552 Buffer++;
554 retry = FALSE;
555 } else {
556 if(i<Count && !retry) {
557 KdPrint2((PRINT_PREFIX " wait...\n"));
558 WaitForDrq(chan);
559 retry = TRUE;
560 }
561 break;
562 }
563 }
564 if(i) {
565 KdPrint2((PRINT_PREFIX "AtapiSuckPortBuffer2: %#x words\n", i ));
566 if(i==Count) {
567 AtapiSuckPort2(chan);
568 }
569 }
570 return i;
571} // AtapiSuckPortBuffer2()
572
573#ifdef __REACTOS__
574VOID
576FillDeviceIdentificationString(
577 IN OUT PINQUIRYDATA InquiryData,
578 IN PIDENTIFY_DATA2 IdentifyData)
579{
580 ULONG i;
581 ULONG IdentifierLen, FirstWordLen;
582
583 /* We need to copy a field which is 20 chars long to two fields which are 8+16 bytes long (VendorId + ProductId)
584 * Note that a space will be added between those fields when displaying them.
585 * => Try to split identifier on space char.
586 */
587
588#define IDENTIFIER_LETTER(Identifier, i) (((PUCHAR)Identifier)[(i) ^ 1])
589
590 for (IdentifierLen = 20; IdentifierLen > 0 && IDENTIFIER_LETTER(IdentifyData->ModelNumber, IdentifierLen - 1) == ' '; IdentifierLen--)
591 ;
592
593 /* Strategy 1: copy first word to VendorId if len <= 8. Copy other chars to ProductId */
594 for (FirstWordLen = 0; IDENTIFIER_LETTER(IdentifyData->ModelNumber, FirstWordLen) != ' ' && FirstWordLen < IdentifierLen; FirstWordLen++)
595 ;
596 if (FirstWordLen <= 8)
597 {
598 for (i = 0; i < FirstWordLen; i++)
599 InquiryData->VendorId[i] = IDENTIFIER_LETTER(IdentifyData->ModelNumber, i);
600 for (i = FirstWordLen + 1; i < IdentifierLen; i++)
601 InquiryData->ProductId[i - FirstWordLen - 1] = IDENTIFIER_LETTER(IdentifyData->ModelNumber, i);
602 return;
603 }
604
605 /* Strategy 2: copy everything to ProductId */
606 if (IdentifierLen <= 16)
607 {
608 for (i = 0; i < IdentifierLen; i++)
609 InquiryData->ProductId[i] = IDENTIFIER_LETTER(IdentifyData->ModelNumber, i);
610 return;
611 }
612
613 /* Strategy 3: copy first to VendorId, then to ProductId */
614 for (i = 0; i < 24; i += 2)
615 MOV_DW_SWP(InquiryData->DeviceIdentificationString[i], ((PUCHAR)IdentifyData->ModelNumber)[i]);
616}
617#endif
618
619UCHAR
622 IN PHW_CHANNEL chan,
624 )
625{
626 if(!chan) {
627 return 0;
628 }
629/*
630 if(chan->lun[DeviceNumber] &&
631 (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_CHANGER)) {
632 KdPrint3((" Select %d\n", DeviceNumber));
633 }
634*/
635 if(chan->last_devsel == DeviceNumber) {
636 //KdPrint3((" Selected %d\n", DeviceNumber));
637 return 1;
638 }
640 chan->last_devsel = DeviceNumber ? 1 : 0;
642 //KdPrint3((" Select %d\n", DeviceNumber));
643 return 2;
644 }
645 //KdPrint3((" Select %d (%d ns)\n", DeviceNumber, g_opt_DriveSelectNanoDelay));
647 return 2;
648} // end SelectDrive()
649
650UCHAR
653 IN PHW_CHANNEL chan
654 )
655{
656 ULONG i;
658
659 GetStatus(chan, Status);
660 for (i=0; i<g_opt_WaitBusyCount; i++) {
661 if (Status & IDE_STATUS_BUSY) {
663 GetStatus(chan, Status);
664 continue;
665 } else {
666 break;
667 }
668 }
669 return Status;
670} // end WaitOnBusy()
671
672UCHAR
675 IN PHW_CHANNEL chan
676 )
677{
678 ULONG i;
680
681 Status = WaitOnBusy(chan);
682 if(!(Status & IDE_STATUS_BUSY))
683 return Status;
684 for (i=0; i<g_opt_WaitBusyLongCount; i++) {
685 GetStatus(chan, Status);
686 if (Status & IDE_STATUS_BUSY) {
688 continue;
689 } else {
690 break;
691 }
692 }
693 return Status;
694} // end WaitOnBusyLong()
695
696UCHAR
699 IN PHW_CHANNEL chan
700 )
701{
702 ULONG i;
704 for (i=0; i<g_opt_WaitBusyCount; i++) {
705 GetBaseStatus(chan, Status);
706 if (Status & IDE_STATUS_BUSY) {
708 continue;
709 } else {
710 break;
711 }
712 }
713 return Status;
714} // end WaitOnBaseBusy()
715
716UCHAR
719 IN PHW_CHANNEL chan
720 )
721{
722 ULONG i;
724
725 Status = WaitOnBaseBusy(chan);
726 if(!(Status & IDE_STATUS_BUSY))
727 return Status;
728 for (i=0; i<2000; i++) {
729 GetBaseStatus(chan, Status);
730 if (Status & IDE_STATUS_BUSY) {
732 continue;
733 } else {
734 break;
735 }
736 }
737 return Status;
738} // end WaitOnBaseBusyLong()
739
740UCHAR
743 IN struct _HW_DEVICE_EXTENSION* deviceExtension,
745 )
746{
747 UCHAR Status2;
748
749 if(Status == IDE_STATUS_WRONG) {
750 return IDE_STATUS_WRONG;
751 }
752 if(Status & IDE_STATUS_BUSY) {
753 return Status;
754 }
755// if(deviceExtension->HwFlags & UNIATA_SATA) {
756 if(UniataIsSATARangeAvailable(deviceExtension, 0)) {
758 return Status;
759 }
760 } else {
762 if ((Status & IDE_STATUS_BUSY) ||
763 (Status2 != IDE_STATUS_IDLE && Status2 != IDE_STATUS_DRDY)) {
764 return Status;
765 }
766 }
767 return IDE_STATUS_IDLE;
768} // end UniataIsIdle()
769
770UCHAR
773 IN PHW_CHANNEL chan
774 )
775{
776 ULONG i;
778 UCHAR Status2;
779 for (i=0; i<20000; i++) {
780 GetStatus(chan, Status);
781 Status2 = UniataIsIdle(chan->DeviceExtension, Status);
782 if(Status2 == IDE_STATUS_WRONG) {
783 // no drive ?
784 break;
785 } else
786 if(Status2 & IDE_STATUS_BUSY) {
788 continue;
789 } else {
790 break;
791 }
792 }
793 return Status;
794} // end WaitForIdleLong()
795
796UCHAR
799 IN PHW_CHANNEL chan
800 )
801{
802 ULONG i;
804 for (i=0; i<1000; i++) {
805 GetStatus(chan, Status);
806 if (Status & IDE_STATUS_BUSY) {
808 } else if (Status & IDE_STATUS_DRQ) {
809 break;
810 } else {
812 }
813 }
814 return Status;
815} // end WaitForDrq()
816
817UCHAR
820 IN PHW_CHANNEL chan
821 )
822{
823 ULONG i;
825 for (i=0; i<2; i++) {
826 GetStatus(chan, Status);
827 if (Status & IDE_STATUS_BUSY) {
829 } else if (Status & IDE_STATUS_DRQ) {
830 break;
831 } else {
833 }
834 }
835 return Status;
836} // end WaitShortForDrq()
837
838VOID
841 IN PHW_CHANNEL chan,
843 )
844{
845 //ULONG c = chan->lChannel;
846 ULONG i = 30 * 1000;
847 UCHAR dma_status = 0;
848 KdPrint2((PRINT_PREFIX "AtapiSoftReset:\n"));
849 UCHAR statusByte0, statusByte2;
850
851 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
852 UniataAhciSoftReset(chan->DeviceExtension, chan->lChannel, DeviceNumber);
853 return;
854 }
855
856 GetBaseStatus(chan, statusByte2);
857 KdPrint2((PRINT_PREFIX " statusByte2 %x:\n", statusByte2));
859 if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MANUAL_CHS) {
860 // For ESDI/MFM
861 KdPrint2((PRINT_PREFIX " ESDI/MFM\n"));
862 AtapiStallExecution(10000);
863 for (i = 0; i < 1000; i++) {
865 }
866/* } else
867 // Seems to be unnecessary, verified by KtP
868 if(!hasPCI) {
869 // original atapi.sys behavior for old ISA-only hardware
870 AtapiStallExecution(10000);
871 AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
872 for (i = 0; i < 1000; i++) {
873 AtapiStallExecution(999);
874 } */
875 } else {
877 GetBaseStatus(chan, statusByte2);
878 statusByte0 = statusByte2;
880
881 // Do not wait for BUSY assertion if it was initially set, jump to
882 // BUSY release wait loop
883 if(!(statusByte0 & IDE_STATUS_BUSY)) {
884 // Wait for BUSY assertion, in some cases delay may occure
885 // 100ms should be enough
887 i = 100;
888 } else {
889 i = 10*1000;
890 }
891 statusByte2 = AtapiReadPort1(chan, IDX_IO1_i_Status);
892 while (!(statusByte2 & IDE_STATUS_BUSY) &&
893 i--)
894 {
895 if(!(statusByte0 & IDE_STATUS_ERROR) && (statusByte2 & IDE_STATUS_ERROR)) {
896 KdPrint2((PRINT_PREFIX " Command aborted, statusByte2 %x:\n", statusByte2));
897 break;
898 }
900 }
901 }
902
903 i = 30 * 1000;
904 // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
905 // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
906 // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
907 // implementation. (which is around 1 second)
909 i--)
910 {
912 }
913 KdPrint2((PRINT_PREFIX " set DFLAGS_REINIT_DMA\n"));
914 chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_REINIT_DMA;
915 }
916
917 chan->last_devsel = -1; // make sure proper drive would be selected
919 WaitOnBusy(chan);
920 GetBaseStatus(chan, statusByte2);
922
923 GetBaseStatus(chan, statusByte2);
924 if(chan && chan->DeviceExtension) {
925 dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
926 KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
927 } else {
928 KdPrint2((PRINT_PREFIX " can't get DMA status\n"));
929 }
930 if(dma_status & BM_STATUS_INTR) {
931 // bullshit, we have DMA interrupt, but had never initiate DMA operation
932 KdPrint2((PRINT_PREFIX " clear unexpected DMA intr on ATAPI reset\n"));
933 AtapiDmaDone(chan->DeviceExtension, DeviceNumber, chan->lChannel, NULL);
934 GetBaseStatus(chan, statusByte2);
935 }
936 if(chan->DeviceExtension->HwFlags & UNIATA_SATA) {
937 UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, DeviceNumber);
938/* if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
939 UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1);
940 }*/
941 }
942 return;
943
944} // end AtapiSoftReset()
945
946VOID
949 IN struct _HW_CHANNEL* chan,
950 IN BOOLEAN DisableInterrupts,
951 IN ULONG Delay
952 )
953{
954 KdPrint2((PRINT_PREFIX "AtapiHardReset: %d, dis=%d\n", Delay, DisableInterrupts));
956 (DisableInterrupts ? IDE_DC_DISABLE_INTERRUPTS : 0));
957 chan->last_devsel = -1;
958 AtapiStallExecution(Delay);
960} // end AtapiHardReset()
961
962/*
963 Send command to device.
964 Translate to 48-Lba form if required
965*/
966UCHAR
967NTAPI
969 IN PHW_DEVICE_EXTENSION deviceExtension,
971 IN ULONG lChannel,
976 IN ULONG wait_flags
977 )
978{
979 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
980 UCHAR statusByte;
981 ULONG i;
982 PUCHAR plba;
983
984 KdPrint2((PRINT_PREFIX "AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
985 deviceExtension->DevIndex, deviceExtension->Channel, DeviceNumber, command, lba, count, feature ));
986
987 if(deviceExtension->HwFlags & UNIATA_AHCI) {
988 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
989
990 KdPrint3((" (ahci)\n"));
991
992 statusByte = UniataAhciSendPIOCommand(deviceExtension, lChannel, DeviceNumber,
994 NULL,
995 0,
996 command,
997 lba, count,
998 feature,
999 0 /* ahci flags */ ,
1000 wait_flags,
1001 1000 /* timeout 1 sec */
1002 );
1003
1004 return statusByte;
1005 }
1006
1008
1009 statusByte = WaitOnBusy(chan);
1010
1011 /* ready to issue command ? */
1012 if (statusByte & IDE_STATUS_BUSY) {
1013 KdPrint2((PRINT_PREFIX " Returning BUSY status\n"));
1014 return statusByte;
1015 }
1016 // !!! We should not check ERROR condition here
1017 // ERROR bit may be asserted durring previous operation
1018 // and not cleared after SELECT
1019
1020 //>>>>>> NV: 2006/08/03
1023 KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count));
1024 return IDE_STATUS_ERROR;
1025 //return SRB_STATUS_ERROR;
1026 }
1027 //<<<<<< NV: 2006/08/03
1028
1029 /* only use 48bit addressing if needed because of the overhead */
1031 chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48)) {
1032
1033 KdPrint2((PRINT_PREFIX " dev %#x USE_LBA_48\n", DeviceNumber ));
1034 /* translate command into 48bit version */
1037 } else {
1038 KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n"));
1039 return (UCHAR)-1;
1040 }
1041
1043 plba = (PUCHAR)&lba;
1044
1049 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)(plba[3]));
1050 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)(plba[0]));
1051 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)(plba[4]));
1052 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)(plba[1]));
1053 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[5]));
1054 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[2]));
1055
1056 //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber ));
1058 } else {
1059
1060 plba = (PUCHAR)&lba; //ktp
1061 chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48;
1062
1063 //if(feature ||
1064 // (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
1066 //}
1071 if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_LBA_ENABLED) {
1072 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber ));
1074 } else {
1075 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber ));
1077 }
1078 }
1079
1080 // write command code to device
1082
1083 switch (wait_flags) {
1084 case ATA_WAIT_INTR:
1085
1086 // caller requested wait for interrupt
1087 for(i=0;i<4;i++) {
1088 WaitOnBusy(chan);
1089 statusByte = WaitForDrq(chan);
1090 if (statusByte & IDE_STATUS_DRQ)
1091 break;
1093 KdPrint2((PRINT_PREFIX " retry waiting DRQ, status %#x\n", statusByte));
1094 }
1095
1096 return statusByte;
1097
1098 case ATA_WAIT_IDLE:
1099
1100 // caller requested wait for entering Wait state
1101 for (i=0; i<30 * 1000; i++) {
1102
1103 GetStatus(chan, statusByte);
1104 statusByte = UniataIsIdle(deviceExtension, statusByte);
1105 if(statusByte == IDE_STATUS_WRONG) {
1106 // no drive ?
1107 break;
1108 } else
1109 if(statusByte & IDE_STATUS_ERROR) {
1110 break;
1111 } else
1112 if(statusByte & IDE_STATUS_BUSY) {
1114 continue;
1115 } else
1116 if((statusByte & ~IDE_STATUS_INDEX) == IDE_STATUS_IDLE) {
1117 break;
1118 } else {
1119 //if(deviceExtension->HwFlags & UNIATA_SATA) {
1120 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1121 break;
1122 }
1124 }
1125 }
1126 //statusByte |= IDE_STATUS_BUSY;
1127 break;
1128
1129 case ATA_WAIT_READY:
1130 statusByte = WaitOnBusyLong(chan);
1131 break;
1133 statusByte = WaitOnBaseBusyLong(chan);
1134 break;
1135 case ATA_IMMEDIATE:
1136 GetStatus(chan, statusByte);
1137 if (statusByte & IDE_STATUS_ERROR) {
1138 KdPrint2((PRINT_PREFIX " Warning: Immed Status %#x :(\n", statusByte));
1139 if(statusByte == (IDE_STATUS_IDLE | IDE_STATUS_ERROR)) {
1140 break;
1141 }
1142 KdPrint2((PRINT_PREFIX " try to continue\n"));
1143 statusByte &= ~IDE_STATUS_ERROR;
1144
1145 } else {
1146 //KdPrint2((PRINT_PREFIX " send Status %#x\n", statusByte));
1147 }
1149 // !!!!!
1152
1153 statusByte = IDE_STATUS_SUCCESS;
1154 break;
1155 }
1156
1157 //KdPrint2((PRINT_PREFIX " Status %#x\n", statusByte));
1158
1159 return statusByte;
1160} // end AtaCommand48()
1161
1162/*
1163 Send command to device.
1164 This is simply wrapper for AtaCommand48()
1165*/
1166UCHAR
1167NTAPI
1169 IN PHW_DEVICE_EXTENSION deviceExtension,
1171 IN ULONG lChannel,
1174 IN UCHAR head,
1175 IN UCHAR sector,
1176 IN UCHAR count,
1178 IN ULONG wait_flags
1179 )
1180{
1181 if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
1182 return AtaCommand48(deviceExtension, DeviceNumber, lChannel,
1183 command,
1184 (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
1185 count, feature, wait_flags);
1186 } else {
1187 return UniataAhciSendPIOCommand(deviceExtension, lChannel, DeviceNumber,
1189 NULL,
1190 0,
1191 command,
1192 (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
1193 count,
1194 feature,
1195 0 /* ahci flags */ ,
1196 wait_flags,
1197 1000 /* timeout 1 sec */
1198 );
1199
1200 }
1201} // end AtaCommand()
1202
1203LONG
1204NTAPI
1206{
1207 switch (pio) {
1208 default: return ATA_PIO;
1209 case 0: return ATA_PIO0;
1210 case 1: return ATA_PIO1;
1211 case 2: return ATA_PIO2;
1212 case 3: return ATA_PIO3;
1213 case 4: return ATA_PIO4;
1214 case 5: return ATA_PIO5;
1215 }
1216} // end AtaPio2Mode()
1217
1218LONG
1219NTAPI
1221{
1222 if (ident->PioTimingsValid) {
1223 if (ident->AdvancedPIOModes & AdvancedPIOModes_5)
1224 return 5;
1225 if (ident->AdvancedPIOModes & AdvancedPIOModes_4)
1226 return 4;
1227 if (ident->AdvancedPIOModes & AdvancedPIOModes_3)
1228 return 3;
1229 }
1230 if (ident->PioCycleTimingMode == 2)
1231 return 2;
1232 if (ident->PioCycleTimingMode == 1)
1233 return 1;
1234 if (ident->PioCycleTimingMode == 0)
1235 return 0;
1236 return IOMODE_NOT_SPECIFIED;
1237} // end AtaPioMode()
1238
1239LONG
1240NTAPI
1242{
1243 if (ident->MultiWordDMASupport & 0x04)
1244 return 2;
1245 if (ident->MultiWordDMASupport & 0x02)
1246 return 1;
1247 if (ident->MultiWordDMASupport & 0x01)
1248 return 0;
1249 return IOMODE_NOT_SPECIFIED;
1250} // end AtaWmode()
1251
1252LONG
1253NTAPI
1255{
1256 if (!ident->UdmaModesValid)
1257 return IOMODE_NOT_SPECIFIED;
1258 if (ident->UltraDMASupport & 0x40)
1259 return 6;
1260 if (ident->UltraDMASupport & 0x20)
1261 return 5;
1262 if (ident->UltraDMASupport & 0x10)
1263 return 4;
1264 if (ident->UltraDMASupport & 0x08)
1265 return 3;
1266 if (ident->UltraDMASupport & 0x04)
1267 return 2;
1268 if (ident->UltraDMASupport & 0x02)
1269 return 1;
1270 if (ident->UltraDMASupport & 0x01)
1271 return 0;
1272 return IOMODE_NOT_SPECIFIED;
1273} // end AtaUmode()
1274
1275LONG
1276NTAPI
1278 if(!ident->SataCapabilities ||
1279 ident->SataCapabilities == 0xffff) {
1280 return IOMODE_NOT_SPECIFIED;
1281 }
1282 if(ident->SataCapabilities & ATA_SATA_GEN3) {
1283 return ATA_SA600;
1284 } else
1285 if(ident->SataCapabilities & ATA_SATA_GEN2) {
1286 return ATA_SA300;
1287 } else
1288 if(ident->SataCapabilities & ATA_SATA_GEN1) {
1289 return ATA_SA150;
1290 }
1291 return IOMODE_NOT_SPECIFIED;
1292} // end AtaSAmode()
1293
1294#ifndef UNIATA_CORE
1295
1296VOID
1297NTAPI
1299 IN PVOID HwDeviceExtension
1300 )
1301{
1302 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1303 PHW_TIMER HwScsiTimer;
1305 ULONG MiniportTimerValue;
1306 BOOLEAN recall = FALSE;
1307 ULONG lChannel;
1308 PHW_CHANNEL chan;
1309
1310 KdPrint2((PRINT_PREFIX "AtapiTimerDpc:\n"));
1311
1312 lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
1313 if(lChannel == CHAN_NOT_SPECIFIED) {
1314 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no items\n"));
1315 return;
1316 }
1317 chan = &(deviceExtension->chan[lChannel]);
1318
1319 while(TRUE) {
1320
1321 HwScsiTimer = chan->HwScsiTimer;
1322 chan->HwScsiTimer = NULL;
1323
1324 deviceExtension->FirstDpcChan = chan->NextDpcChan;
1325 if(deviceExtension->FirstDpcChan != CHAN_NOT_SPECIFIED) {
1326 recall = TRUE;
1327 }
1328
1329 HwScsiTimer(HwDeviceExtension);
1330
1332
1333 lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
1334 if(lChannel == CHAN_NOT_SPECIFIED) {
1335 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no more items\n"));
1336 deviceExtension->FirstDpcChan =
1337 deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
1338 return;
1339 }
1340
1342 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
1343
1344 chan = &deviceExtension->chan[lChannel];
1345 if(time.QuadPart >= chan->DpcTime - 10) {
1346 // call now
1347 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1348 (ULONG)(chan->DpcTime >> 32), (ULONG)(chan->DpcTime)));
1349 continue;
1350 }
1351 break;
1352 }
1353
1354 if(recall) {
1355 deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
1356 MiniportTimerValue = (ULONG)(time.QuadPart - chan->DpcTime)/10;
1357 if(!MiniportTimerValue)
1358 MiniportTimerValue = 1;
1359
1360 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: recall AtapiTimerDpc\n"));
1361 ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
1363 MiniportTimerValue
1364 );
1365 }
1366 return;
1367
1368} // end AtapiTimerDpc()
1369
1370/*
1371 Wrapper for ScsiPort, that implements smart Dpc
1372 queueing. We need it to allow parallel functioning
1373 of IDE channels with shared interrupt. Standard Dpc mechanism
1374 cancels previous Dpc request (if any), but we need Dpc queue.
1375*/
1376VOID
1377NTAPI
1379 IN PVOID HwDeviceExtension,
1380 IN ULONG lChannel,
1381 IN PHW_TIMER HwScsiTimer,
1382 IN ULONG MiniportTimerValue
1383 )
1384{
1385 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1387 LARGE_INTEGER time2;
1388 ULONG i;
1389 PHW_CHANNEL prev_chan;
1390 PHW_CHANNEL chan;
1391// BOOLEAN UseRequestTimerCall = TRUE;
1392
1393 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
1395 time2 = time;
1396 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
1397 time.QuadPart += MiniportTimerValue*10;
1398 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time.HighPart, time.LowPart));
1399
1400 KdPrint2((PRINT_PREFIX " ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension->ActiveDpcChan, deviceExtension->FirstDpcChan));
1401
1402 i = deviceExtension->FirstDpcChan;
1403 chan = prev_chan = NULL;
1404 while(i != CHAN_NOT_SPECIFIED) {
1405 prev_chan = chan;
1406 chan = &(deviceExtension->chan[i]);
1407 if(chan->DpcTime > time.QuadPart) {
1408 break;
1409 }
1410 i = chan->NextDpcChan;
1411 }
1412 chan = &(deviceExtension->chan[lChannel]);
1413 if(!prev_chan) {
1414 deviceExtension->FirstDpcChan = lChannel;
1415 } else {
1416 prev_chan->NextDpcChan = lChannel;
1417 }
1418 chan->NextDpcChan = i;
1419 chan->HwScsiTimer = HwScsiTimer;
1420 chan->DpcTime = time.QuadPart;
1421
1422 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2.HighPart, time2.LowPart));
1423 if(time.QuadPart <= time2.QuadPart) {
1424 MiniportTimerValue = 1;
1425 } else {
1426 MiniportTimerValue = (ULONG)((time.QuadPart - time2.QuadPart) / 10);
1427 }
1428
1429 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
1430 ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
1432 MiniportTimerValue);
1433
1434} // end AtapiQueueTimerDpc()
1435
1436#endif //UNIATA_CORE
1437
1438#ifdef _DEBUG
1439VOID
1440NTAPI
1442 IN PHW_CHANNEL chan
1443 )
1444{
1445 ULONG j;
1446 UCHAR statusByteAlt;
1447
1448 GetStatus(chan, statusByteAlt);
1449 KdPrint2((PRINT_PREFIX " AltStatus (%#x)\n", statusByteAlt));
1450
1451 for(j=1; j<IDX_IO1_SZ; j++) {
1452 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1454 " Reg_%#x (%#x) = %#x\n",
1455 j,
1456 chan->RegTranslation[IDX_IO1+j].Addr,
1457 statusByteAlt));
1458 }
1459 if(!chan->RegTranslation[IDX_BM_IO].Addr) {
1460 return;
1461 }
1462 for(j=0; j<IDX_BM_IO_SZ-1; j++) {
1463 statusByteAlt = AtapiReadPort1(chan, IDX_BM_IO+j);
1465 " BM_%#x (%#x) = %#x\n",
1466 j,
1467 chan->RegTranslation[IDX_BM_IO+j].Addr,
1468 statusByteAlt));
1469 }
1470 return;
1471} // end UniataDumpATARegs()
1472#endif //_DEBUG
1473
1474VOID
1475NTAPI
1477 IN PHW_CHANNEL chan,
1480 )
1481{
1482 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
1483 // AHCI
1485 } else {
1486 // SATA/PATA, assume drive is selected
1487 ULONG j;
1488 UCHAR statusByteAlt;
1489
1490 if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) {
1492 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1493 ((PUCHAR)regs)[j-1] = statusByteAlt;
1494 }
1495 regs->bOpFlags = 0;
1496 } else {
1497 regs->bDriveHeadReg = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect);
1499 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1500 ((PUCHAR)regs)[j-1] = statusByteAlt;
1501 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1502 ((PUCHAR)regs)[j+8-1] = statusByteAlt;
1503 }
1504 regs->bCommandReg = AtapiReadPort1(chan, IDX_IO1_i_Status);
1505 }
1506 }
1507 return;
1508} // end UniataSnapAtaRegs()
1509
1510/*++
1511
1512Routine Description:
1513
1514 Issue IDENTIFY command to a device.
1515
1516Arguments:
1517
1518 HwDeviceExtension - HBA miniport driver's adapter data storage
1519 DeviceNumber - Indicates which device.
1520 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1521
1522Return Value:
1523
1524 TRUE if all goes well.
1525
1526--*/
1527BOOLEAN
1528NTAPI
1530 IN PVOID HwDeviceExtension,
1532 IN ULONG lChannel,
1534 IN BOOLEAN NoSetup
1535 )
1536{
1537 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1538 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
1539 ULONG waitCount = 50000;
1540 ULONG j;
1541 UCHAR statusByte;
1542 //UCHAR statusByte2;
1543 UCHAR signatureLow,
1544 signatureHigh;
1545 BOOLEAN atapiDev = FALSE;
1546 BOOLEAN use_ahci = FALSE;
1547 PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
1548
1549 use_ahci = UniataIsSATARangeAvailable(deviceExtension, lChannel) &&
1550 (deviceExtension->HwFlags & UNIATA_AHCI);
1551
1553 if(chan->PmLunMap & (1 << DeviceNumber)) {
1554 // OK
1555 } else {
1556 KdPrint2((PRINT_PREFIX "IssueIdentify: PM empty port\n"));
1557 return FALSE;
1558 }
1559 } else
1561 KdPrint2((PRINT_PREFIX "IssueIdentify: NO SLAVE\n"));
1562 return FALSE;
1563 }
1564 if(LunExt->DeviceFlags & DFLAGS_HIDDEN) {
1565 KdPrint2((PRINT_PREFIX "IssueIdentify: HIDDEN\n"));
1566 return FALSE;
1567 }
1568
1569 if(use_ahci) {
1570 statusByte = WaitOnBusyLong(chan);
1571#ifdef _DEBUG
1572 if(!chan->AhciInternalAtaReq) {
1573 KdPrint2((PRINT_PREFIX "!AhciInternalAtaReq\n"));
1574 }
1575#endif
1576 } else {
1579 statusByte = WaitOnBusyLong(chan);
1580 // Check that the status register makes sense.
1581 GetBaseStatus(chan, statusByte);
1582 /*
1583 // unnecessary
1584 if(!hasPCI) {
1585 // original atapi.sys behavior for old ISA-only hardware
1586 AtapiStallExecution(100);
1587 }
1588 */
1589 }
1590
1592 // Mask status byte ERROR bits.
1593 statusByte = UniataIsIdle(deviceExtension, statusByte & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX));
1594 KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte));
1595 // Check if register value is reasonable.
1596
1597 if(statusByte != IDE_STATUS_IDLE) {
1598
1599 // No reset here !!!
1600 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1601
1602 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1603 if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1605 WaitOnBusyLong(chan);
1606
1607 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1608 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1609
1610 if (signatureLow == ATAPI_MAGIC_LSB &&
1611 signatureHigh == ATAPI_MAGIC_MSB) {
1612 // Device is Atapi.
1613 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber));
1614 return FALSE;
1615 }
1616
1617 // We really should wait up to 31 seconds
1618 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1619 // (30 seconds for device 1)
1620 do {
1621 // Wait for Busy to drop.
1623 GetStatus(chan, statusByte);
1624 if(statusByte == IDE_STATUS_WRONG) {
1625 KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_WRONG (dev %d)\n", DeviceNumber));
1626 return FALSE;
1627 }
1628
1629 } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
1630 GetBaseStatus(chan, statusByte);
1631
1633 } else {
1634 GetBaseStatus(chan, statusByte);
1635 }
1636 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1637 // a soft reset.
1638 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1639 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1640
1641 if (signatureLow == ATAPI_MAGIC_LSB &&
1642 signatureHigh == ATAPI_MAGIC_MSB) {
1643 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber));
1644 // Device is Atapi.
1645 return FALSE;
1646 }
1647
1648 statusByte = UniataIsIdle(deviceExtension, statusByte) & ~IDE_STATUS_INDEX;
1649 if (statusByte != IDE_STATUS_IDLE) {
1650 // Give up on this.
1651 KdPrint2((PRINT_PREFIX "IssueIdentify: no dev (dev %d)\n", DeviceNumber));
1652 return FALSE;
1653 }
1654 }
1655 } else {
1656 KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte));
1657 if(statusByte == IDE_STATUS_WRONG) {
1658 return FALSE;
1659 }
1660 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1661 if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1662 statusByte = WaitForIdleLong(chan);
1663 KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte));
1664 }
1665 atapiDev = TRUE;
1666 }
1667
1668// if(deviceExtension->HwFlags & UNIATA_SATA) {
1669 if(use_ahci) {
1670 statusByte = UniataAhciSendPIOCommand(HwDeviceExtension, lChannel, DeviceNumber,
1672 (PUCHAR)(&deviceExtension->FullIdentifyData),
1673 DEV_BSIZE,
1674 Command,
1675 0, 0,
1676 0,
1677 0 /* ahci flags */ ,
1679 1000 /* timeout 1 sec */
1680 );
1681 j = 9; // AHCI is rather different, skip loop at all
1682 } else
1683 if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) {
1684 j = 9; // don't send IDENTIFY, assume it is not supported
1685 KdPrint2((PRINT_PREFIX "IssueIdentify: Manual CHS\n"));
1686 RtlZeroMemory(&(deviceExtension->FullIdentifyData), sizeof(deviceExtension->FullIdentifyData));
1687 RtlCopyMemory(&(deviceExtension->FullIdentifyData), &(LunExt->IdentifyData), sizeof(LunExt->IdentifyData));
1688 } else
1689 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1690 j = 4; // skip old-style checks
1691 } else {
1692 j = 0;
1693 }
1694 for (; j < 4*2; j++) {
1695 // Send IDENTIFY command.
1696
1697 // Load CylinderHigh and CylinderLow with number bytes to transfer for old devices, use 0 for newer.
1698
1699 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, Command, (j < 4) ? DEV_BSIZE : 0 /* cyl */, 0, 0, 0, 0, ATA_WAIT_INTR);
1700 // Clear interrupt
1701
1702 if (!statusByte) {
1703 KdPrint2((PRINT_PREFIX "IssueIdentify: 0-status, not present\n"));
1704 return FALSE;
1705 } else
1706 if (statusByte & IDE_STATUS_DRQ) {
1707 // Read status to acknowledge any interrupts generated.
1708 KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte));
1709 GetBaseStatus(chan, statusByte);
1710 // One last check for Atapi.
1712 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1713 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1714
1715 if (signatureLow == ATAPI_MAGIC_LSB &&
1716 signatureHigh == ATAPI_MAGIC_MSB) {
1717 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber));
1718 // Device is Atapi.
1719 return FALSE;
1720 }
1721 }
1722 break;
1723 } else {
1724 KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte));
1726 // Check the signature. If DRQ didn't come up it's likely Atapi.
1727 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1728 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1729
1730 if (signatureLow == ATAPI_MAGIC_LSB &&
1731 signatureHigh == ATAPI_MAGIC_MSB) {
1732 // Device is Atapi.
1733 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber));
1734 return FALSE;
1735 }
1736 } else {
1737 if(!(statusByte & IDE_STATUS_ERROR) && (statusByte & IDE_STATUS_BUSY)) {
1738 KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n"));
1739 break;
1740 }
1741 }
1742 // Device didn't respond correctly. It will be given one more chance.
1743 KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1744 statusByte, AtapiReadPort1(chan, IDX_IO1_i_Error)));
1745 GetBaseStatus(chan, statusByte);
1747
1748 AtapiDisableInterrupts(deviceExtension, lChannel);
1749 AtapiEnableInterrupts(deviceExtension, lChannel);
1750
1751 GetBaseStatus(chan, statusByte);
1752 //GetStatus(chan, statusByte);
1753 KdPrint2((PRINT_PREFIX "IssueIdentify: Status after soft reset (%#x)\n", statusByte));
1754 }
1755 }
1756 // Check for error on really stupid master devices that assert random
1757 // patterns of bits in the status register at the slave address.
1758 if ((Command == IDE_COMMAND_IDENTIFY) && (statusByte & IDE_STATUS_ERROR)) {
1759 KdPrint2((PRINT_PREFIX "IssueIdentify: Exit on error (%#x)\n", statusByte));
1760 return FALSE;
1761 }
1762
1763 if(use_ahci) {
1764 // everything should already be done by controller
1765 } else
1766 if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) {
1767 j = 9; // don't send IDENTIFY, assume it is not supported
1768 KdPrint2((PRINT_PREFIX "IssueIdentify: Manual CHS (2)\n"));
1769 statusByte = WaitForDrq(chan);
1770 statusByte = WaitOnBusyLong(chan);
1771 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1772 GetBaseStatus(chan, statusByte);
1773 } else {
1774
1775 KdPrint2((PRINT_PREFIX "IssueIdentify: Status before read words %#x\n", statusByte));
1776 // Suck out 256 words. After waiting for one model that asserts busy
1777 // after receiving the Packet Identify command.
1778 statusByte = WaitForDrq(chan);
1779 statusByte = WaitOnBusyLong(chan);
1780 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1781
1782 if (!(statusByte & IDE_STATUS_DRQ)) {
1783 KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte));
1784 GetBaseStatus(chan, statusByte);
1785 return FALSE;
1786 }
1787 GetBaseStatus(chan, statusByte);
1788 KdPrint2((PRINT_PREFIX "IssueIdentify: BASE statusByte %#x\n", statusByte));
1789
1790#ifdef _DEBUG
1791 if(atapiDev) {
1793 KdPrint3((PRINT_PREFIX "IssueIdentify: iReason %x\n", j));
1794
1795 j =
1797
1798 j |=
1800 KdPrint3((PRINT_PREFIX "IssueIdentify: wCount %x\n", j));
1801
1802 }
1803#endif //_DEBUG
1804
1805 if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) ) {
1806
1807 KdPrint2((PRINT_PREFIX " use 16bit IO\n"));
1808 // ATI/SII chipsets with memory-mapped IO hangs when
1809 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1810 // Unfortunately, I don't know yet how to workaround it except
1811 // spacifying manual delay in the way you see below.
1812 ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
1813
1814 // Work around for some IDE and one model Atapi that will present more than
1815 // 256 bytes for the Identify data.
1816 KdPrint2((PRINT_PREFIX "IssueIdentify: suck data port\n", statusByte));
1817 statusByte = AtapiSuckPort2(chan);
1818 } else {
1819 KdPrint2((PRINT_PREFIX " use 32bit IO\n"));
1820 ReadBuffer2(chan, (PULONG)&deviceExtension->FullIdentifyData, 256/2, PIO0_TIMING);
1821 }
1822
1823 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1824 statusByte = WaitForDrq(chan);
1825 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1826 GetBaseStatus(chan, statusByte);
1827 }
1828 KdPrint2((PRINT_PREFIX "IssueIdentify: Status after read words %#x\n", statusByte));
1829
1830 if(NoSetup) {
1831 KdPrint2((PRINT_PREFIX "IssueIdentify: no setup, exiting\n"));
1832 return TRUE;
1833 }
1834
1835 KdPrint2((PRINT_PREFIX "Model: %20.20s\n", deviceExtension->FullIdentifyData.ModelNumber));
1836 KdPrint2((PRINT_PREFIX "FW: %4.4s\n", deviceExtension->FullIdentifyData.FirmwareRevision));
1837 KdPrint2((PRINT_PREFIX "S/N: %20.20s\n", deviceExtension->FullIdentifyData.SerialNumber));
1839 if((deviceExtension->FullIdentifyData.FirmwareRevision[0] == 0 ||
1840 deviceExtension->FullIdentifyData.FirmwareRevision[0] == ' ') &&
1841 (deviceExtension->FullIdentifyData.FirmwareRevision[1] == 0 ||
1842 deviceExtension->FullIdentifyData.FirmwareRevision[1] == ' ')) {
1843 // Check for BOCHS VM signature. If no additional PCI devices (e.g. VGA)
1844 // are declared BOCHS looks like regular PC
1845 if (!atapiDev && !AtapiStringCmp ((PCCHAR)(deviceExtension->FullIdentifyData.SerialNumber), "XBDH00", 6)) {
1846 KdPrint2((PRINT_PREFIX "IssueIdentify: BOCHS HDD\n"));
1848 } else
1849 if (atapiDev && !AtapiStringCmp ((PCCHAR)(deviceExtension->FullIdentifyData.SerialNumber), "XBDC00", 6)) {
1850 KdPrint2((PRINT_PREFIX "IssueIdentify: BOCHS CD\n"));
1852 }
1853 }
1854 }
1855
1856 KdPrint2((PRINT_PREFIX "Pio: %x\n", deviceExtension->FullIdentifyData.PioCycleTimingMode));
1857 if(deviceExtension->FullIdentifyData.PioTimingsValid) {
1858 KdPrint2((PRINT_PREFIX "APio: %x\n", deviceExtension->FullIdentifyData.AdvancedPIOModes));
1859 }
1860 KdPrint2((PRINT_PREFIX "SWDMA: %x\n", deviceExtension->FullIdentifyData.SingleWordDMAActive));
1861 KdPrint2((PRINT_PREFIX "MWDMA: %x\n", deviceExtension->FullIdentifyData.MultiWordDMAActive));
1862 if(deviceExtension->FullIdentifyData.UdmaModesValid) {
1863 KdPrint2((PRINT_PREFIX "UDMA: %x/%x\n", deviceExtension->FullIdentifyData.UltraDMAActive, deviceExtension->FullIdentifyData.UltraDMASupport));
1864 }
1865 KdPrint2((PRINT_PREFIX "SATA: %x\n", deviceExtension->FullIdentifyData.SataEnable));
1866 KdPrint2((PRINT_PREFIX "SATA support: %x, CAPs %#x\n",
1867 deviceExtension->FullIdentifyData.SataSupport,
1868 deviceExtension->FullIdentifyData.SataCapabilities));
1869
1870 LunExt->LimitedTransferMode =
1871 LunExt->OrigTransferMode =
1873 LunExt->TransferMode =
1875
1876 KdPrint2((PRINT_PREFIX "OrigTransferMode: %x, Active: %x\n", LunExt->OrigTransferMode, LunExt->TransferMode));
1877 KdPrint2((PRINT_PREFIX "Accoustic %d, cur %d\n",
1878 deviceExtension->FullIdentifyData.VendorAcoustic,
1879 deviceExtension->FullIdentifyData.CurrentAcoustic
1880 ));
1881 KdPrint2((PRINT_PREFIX "AdvPowerMode %d\n",
1882 deviceExtension->FullIdentifyData.CfAdvPowerMode
1883 ));
1884
1885 KdPrint2((PRINT_PREFIX "PowerMngt %d/%d, APM %d/%d\n",
1886 deviceExtension->FullIdentifyData.FeaturesEnabled.PowerMngt,
1887 deviceExtension->FullIdentifyData.FeaturesSupport.PowerMngt,
1888 deviceExtension->FullIdentifyData.FeaturesEnabled.APM,
1889 deviceExtension->FullIdentifyData.FeaturesSupport.APM
1890 ));
1891
1892 // Check out a few capabilities / limitations of the device.
1893 if (deviceExtension->FullIdentifyData.RemovableStatus & 1) {
1894 // Determine if this drive supports the MSN functions.
1895 KdPrint2((PRINT_PREFIX "IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1897 deviceExtension->FullIdentifyData.RemovableStatus));
1899 }
1900 if(use_ahci) {
1901 // AHCI doesn't recommend using PIO and multiblock
1902 LunExt->MaximumBlockXfer = 0;
1903 } else
1904 if (deviceExtension->FullIdentifyData.MaximumBlockTransfer) {
1905 // Determine max. block transfer for this device.
1906 LunExt->MaximumBlockXfer =
1907 (UCHAR)(deviceExtension->FullIdentifyData.MaximumBlockTransfer & 0xFF);
1908 }
1909 LunExt->NumOfSectors = 0;
1911 ULONGLONG NumOfSectors=0;
1912 ULONGLONG NativeNumOfSectors=0;
1913 ULONGLONG cylinders=0;
1914 ULONGLONG tmp_cylinders=0;
1915
1916 KdPrint2((PRINT_PREFIX "PhysLogSectorSize %#x, %#x, offset %#x\n",
1917 deviceExtension->FullIdentifyData.PhysLogSectorSize,
1918 deviceExtension->FullIdentifyData.LargeSectorSize,
1919 deviceExtension->FullIdentifyData.LogicalSectorOffset
1920 ));
1921
1922 KdPrint2((PRINT_PREFIX "NV PM_Sup %d, PM_En %d, En %d, PM ver %#x ver %#x\n",
1923 deviceExtension->FullIdentifyData.NVCache_PM_Supported,
1924 deviceExtension->FullIdentifyData.NVCache_PM_Enabled,
1925 deviceExtension->FullIdentifyData.NVCache_Enabled,
1926 deviceExtension->FullIdentifyData.NVCache_PM_Version,
1927 deviceExtension->FullIdentifyData.NVCache_Version
1928 ));
1929
1930 KdPrint2((PRINT_PREFIX "R-rate %d\n",
1932 ));
1933 KdPrint2((PRINT_PREFIX "WC %d/%d, LA %d/%d, WB %d/%d, RB %d/%d, Q %d/%d\n",
1934 deviceExtension->FullIdentifyData.FeaturesEnabled.WriteCache,
1935 deviceExtension->FullIdentifyData.FeaturesSupport.WriteCache,
1936 deviceExtension->FullIdentifyData.FeaturesEnabled.LookAhead,
1937 deviceExtension->FullIdentifyData.FeaturesSupport.LookAhead,
1938 deviceExtension->FullIdentifyData.FeaturesEnabled.WriteBuffer,
1939 deviceExtension->FullIdentifyData.FeaturesSupport.WriteBuffer,
1940 deviceExtension->FullIdentifyData.FeaturesEnabled.ReadBuffer,
1941 deviceExtension->FullIdentifyData.FeaturesSupport.ReadBuffer,
1942 deviceExtension->FullIdentifyData.FeaturesEnabled.Queued,
1943 deviceExtension->FullIdentifyData.FeaturesSupport.Queued
1944 ));
1945
1946 KdPrint2((PRINT_PREFIX "Protected %d/%d status %#x, rev %#x\n",
1947 deviceExtension->FullIdentifyData.FeaturesEnabled.Protected,
1948 deviceExtension->FullIdentifyData.FeaturesSupport.Protected,
1949 deviceExtension->FullIdentifyData.SecurityStatus,
1950 deviceExtension->FullIdentifyData.MasterPasswdRevision
1951 ));
1952
1953 // Read very-old-style drive geometry
1954 KdPrint2((PRINT_PREFIX "CHS %#x:%#x:%#x\n",
1955 deviceExtension->FullIdentifyData.NumberOfCylinders,
1956 deviceExtension->FullIdentifyData.NumberOfHeads,
1957 deviceExtension->FullIdentifyData.SectorsPerTrack
1958 ));
1959 NumOfSectors = deviceExtension->FullIdentifyData.NumberOfCylinders *
1960 deviceExtension->FullIdentifyData.NumberOfHeads *
1961 deviceExtension->FullIdentifyData.SectorsPerTrack;
1962 KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
1963 // Check for HDDs > 8Gb
1964 if ((deviceExtension->FullIdentifyData.NumberOfCylinders == 0x3fff) &&
1965/* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1966 deviceExtension->FullIdentifyData.NumberOfHeads &&
1967 deviceExtension->FullIdentifyData.SectorsPerTrack &&
1968 (NumOfSectors < deviceExtension->FullIdentifyData.UserAddressableSectors)) {
1969 KdPrint2((PRINT_PREFIX "NumberOfCylinders == 0x3fff\n"));
1970 cylinders =
1971 (deviceExtension->FullIdentifyData.UserAddressableSectors /
1972 (deviceExtension->FullIdentifyData.NumberOfHeads *
1973 deviceExtension->FullIdentifyData.SectorsPerTrack));
1974
1975 KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
1976
1977 NumOfSectors = cylinders *
1978 deviceExtension->FullIdentifyData.NumberOfHeads *
1979 deviceExtension->FullIdentifyData.SectorsPerTrack;
1980
1981 KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
1982 } else {
1983
1984 }
1985 // Check for LBA mode
1986 KdPrint2((PRINT_PREFIX "SupportLba flag %#x\n", deviceExtension->FullIdentifyData.SupportLba));
1987 KdPrint2((PRINT_PREFIX "SupportDMA flag %#x\n", deviceExtension->FullIdentifyData.SupportDma));
1988 KdPrint2((PRINT_PREFIX "SoftReset %#x\n", deviceExtension->FullIdentifyData.SoftReset));
1989 KdPrint2((PRINT_PREFIX "SupportIordy %#x, DisableIordy %#x\n",
1990 deviceExtension->FullIdentifyData.SupportIordy,
1991 deviceExtension->FullIdentifyData.DisableIordy
1992 ));
1993 KdPrint2((PRINT_PREFIX "MajorRevision %#x\n", deviceExtension->FullIdentifyData.MajorRevision));
1994 KdPrint2((PRINT_PREFIX "UserAddressableSectors %#x\n", deviceExtension->FullIdentifyData.UserAddressableSectors));
1995 if ( deviceExtension->FullIdentifyData.SupportLba
1996 ||
1997 (deviceExtension->FullIdentifyData.MajorRevision &&
1998/* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1999 deviceExtension->FullIdentifyData.UserAddressableSectors)) {
2000 KdPrint2((PRINT_PREFIX "LBA mode\n"));
2002 } else {
2003 KdPrint2((PRINT_PREFIX "Keep orig geometry\n"));
2005 goto skip_lba_staff;
2006 }
2007 // Check for LBA48 support
2008 if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
2009 if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48 &&
2010 deviceExtension->FullIdentifyData.FeaturesEnabled.Address48 &&
2011 deviceExtension->FullIdentifyData.NumberOfHeads &&
2012 deviceExtension->FullIdentifyData.SectorsPerTrack &&
2013 (deviceExtension->FullIdentifyData.UserAddressableSectors48 > NumOfSectors)
2014 ) {
2015 KdPrint2((PRINT_PREFIX "LBA48\n"));
2016 cylinders =
2017 (deviceExtension->FullIdentifyData.UserAddressableSectors48 /
2018 (deviceExtension->FullIdentifyData.NumberOfHeads *
2019 deviceExtension->FullIdentifyData.SectorsPerTrack));
2020
2021 KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
2022
2023 NativeNumOfSectors = cylinders *
2024 deviceExtension->FullIdentifyData.NumberOfHeads *
2025 deviceExtension->FullIdentifyData.SectorsPerTrack;
2026
2027 KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
2028
2029 if(NativeNumOfSectors > NumOfSectors) {
2030 KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
2031 NumOfSectors = NativeNumOfSectors;
2032 }
2033 }
2034
2035 // Check drive capacity report for LBA48-capable drives.
2036 if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48) {
2037 ULONG hNativeNumOfSectors;
2038 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
2039
2040 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
2042
2043 if(!(statusByte & IDE_STATUS_ERROR)) {
2044 if(use_ahci) {
2045 NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
2046 } else {
2047 NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
2050
2053
2054 KdPrint2((PRINT_PREFIX "Read high order bytes\n"));
2055 NativeNumOfSectors |=
2057 hNativeNumOfSectors=
2060 ((PULONG)&NativeNumOfSectors)[1] = hNativeNumOfSectors;
2061 }
2062 KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
2063
2064 // Some drives report LBA48 capability while has capacity below 128Gb
2065 // Probably they support large block-counters.
2066 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
2067 // Here we check this
2068 if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
2069 KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!!\n"));
2070
2071 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
2073
2074 if(!(statusByte & IDE_STATUS_ERROR)) {
2075 if(use_ahci) {
2076 NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
2077 } else {
2078 NativeNumOfSectors = (ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
2084 ;
2085 }
2086 }
2087
2088 if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
2089 KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!! (2)\n"));
2090 NativeNumOfSectors = 0;
2091 }
2092 }
2093
2094 if(NumOfSectors <= ATA_MAX_LBA28 &&
2095 NativeNumOfSectors > NumOfSectors) {
2096
2097 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
2098 KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
2099
2100 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
2101 IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
2102 if(!(statusByte & IDE_STATUS_ERROR)) {
2103 NumOfSectors = NativeNumOfSectors;
2104 }
2105 }
2106 } // !error
2107 }
2108
2109 if(NumOfSectors < 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
2110 // check for native LBA size
2111 // some drives report ~32Gb in Identify Block
2112 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
2113
2114 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_READ_NATIVE_SIZE,
2115 0, IDE_USE_LBA, 0, 0, 0, ATA_WAIT_READY);
2116
2117 if(!(statusByte & IDE_STATUS_ERROR)) {
2118 if(use_ahci) {
2119 NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
2120 } else {
2121 NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
2124 (((ULONG)AtapiReadPort1(chan, IDX_IO1_i_DriveSelect) & 0xf) << 24);
2125 }
2126 KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
2127
2128 if(NativeNumOfSectors > NumOfSectors) {
2129
2130 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
2131 KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
2132
2133 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
2134 IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
2135 if(!(statusByte & IDE_STATUS_ERROR)) {
2136 NumOfSectors = NativeNumOfSectors;
2137 }
2138 }
2139 }
2140 }
2141
2142 if(NumOfSectors > ATA_MAX_IOLBA28) {
2143 KdPrint2((PRINT_PREFIX "2TB threshold, force LBA64 WRITE requirement\n"));
2144 LunExt->DeviceFlags |= DFLAGS_LBA32plus;
2145 }
2146 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
2147
2148 // fill IdentifyData with bogus geometry
2149 KdPrint2((PRINT_PREFIX "requested LunExt->GeomType=%x\n", LunExt->opt_GeomType));
2150 if(deviceExtension->FullIdentifyData.CurrentSectorsPerTrack &&
2151 deviceExtension->FullIdentifyData.NumberOfCurrentHeads) {
2152 tmp_cylinders = NumOfSectors / (deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *
2153 deviceExtension->FullIdentifyData.NumberOfCurrentHeads);
2154 } else
2155 if(deviceExtension->FullIdentifyData.SectorsPerTrack &&
2156 deviceExtension->FullIdentifyData.NumberOfHeads) {
2157 KdPrint2((PRINT_PREFIX "Current C/H = %#I64x/%#I64x\n",
2159 deviceExtension->FullIdentifyData.NumberOfCurrentHeads));
2160 tmp_cylinders = NumOfSectors / (deviceExtension->FullIdentifyData.SectorsPerTrack *
2161 deviceExtension->FullIdentifyData.NumberOfHeads);
2162 } else {
2163 tmp_cylinders = 0;
2164 }
2165 KdPrint2((PRINT_PREFIX "tmp_cylinders = %#I64x\n", tmp_cylinders));
2166 if((tmp_cylinders < 0xffff) || (LunExt->opt_GeomType == GEOM_ORIG)) {
2167 // ok, we can keep original values
2168 if(LunExt->opt_GeomType == GEOM_AUTO) {
2169 LunExt->opt_GeomType = GEOM_ORIG;
2170 }
2171 } else {
2172 tmp_cylinders = NumOfSectors / (255*63);
2173 if(tmp_cylinders < 0xffff) {
2174 // we can use generic values for H/S for generic geometry approach
2175 if(LunExt->opt_GeomType == GEOM_AUTO) {
2176 LunExt->opt_GeomType = GEOM_STD;
2177 }
2178 } else {
2179 // we should use UNIATA geometry approach
2180 if(LunExt->opt_GeomType == GEOM_AUTO) {
2181 LunExt->opt_GeomType = GEOM_UNIATA;
2182 }
2183 }
2184 }
2185
2186 if(!deviceExtension->FullIdentifyData.SectorsPerTrack ||
2187 !deviceExtension->FullIdentifyData.NumberOfHeads) {
2188 KdPrint2((PRINT_PREFIX "Zero S/H -> Force Use GEOM_STD\n"));
2189 }
2190
2191 if(LunExt->opt_GeomType == GEOM_STD) {
2192 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack =
2193 deviceExtension->FullIdentifyData.SectorsPerTrack = 63;
2194
2195 deviceExtension->FullIdentifyData.NumberOfCurrentHeads =
2196 deviceExtension->FullIdentifyData.NumberOfHeads = 255;
2197
2198 cylinders = NumOfSectors / (255*63);
2199 KdPrint2((PRINT_PREFIX "Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders, 255, 63));
2200 } else
2201 if(LunExt->opt_GeomType == GEOM_UNIATA) {
2202 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x80)) {
2203 cylinders /= 2;
2204 KdPrint2((PRINT_PREFIX "cylinders /= 2\n"));
2205 deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
2206 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
2207 }
2208 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x80)) {
2209 cylinders /= 2;
2210 KdPrint2((PRINT_PREFIX "cylinders /= 2 (2)\n"));
2211 deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
2212 deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
2213 }
2214 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x8000)) {
2215 cylinders /= 2;
2216 KdPrint2((PRINT_PREFIX "cylinders /= 2 (3)\n"));
2217 deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
2218 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
2219 }
2220 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x8000)) {
2221 cylinders /= 2;
2222 KdPrint2((PRINT_PREFIX "cylinders /= 2 (4)\n"));
2223 deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
2224 deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
2225 }
2226 KdPrint2((PRINT_PREFIX "Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders,
2227 deviceExtension->FullIdentifyData.NumberOfCurrentHeads,
2228 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack));
2229 }
2230 if(!cylinders) {
2231 KdPrint2((PRINT_PREFIX "cylinders = tmp_cylinders (%x = %x)\n", cylinders, tmp_cylinders));
2232 cylinders = tmp_cylinders;
2233 }
2235 deviceExtension->FullIdentifyData.NumberOfCylinders = (USHORT)cylinders;
2236
2237skip_lba_staff:
2238
2239 KdPrint2((PRINT_PREFIX "Geometry: C %#x (%#x)\n",
2240 deviceExtension->FullIdentifyData.NumberOfCylinders,
2242 ));
2243 KdPrint2((PRINT_PREFIX "Geometry: H %#x (%#x)\n",
2244 deviceExtension->FullIdentifyData.NumberOfHeads,
2245 deviceExtension->FullIdentifyData.NumberOfCurrentHeads
2246 ));
2247 KdPrint2((PRINT_PREFIX "Geometry: S %#x (%#x)\n",
2248 deviceExtension->FullIdentifyData.SectorsPerTrack,
2250 ));
2251
2252 if(NumOfSectors) {
2253 LunExt->NumOfSectors = NumOfSectors;
2254 }
2255 if(deviceExtension->FullIdentifyData.MajorRevision &&
2256 deviceExtension->FullIdentifyData.DoubleWordIo) {
2258 KdPrint2((PRINT_PREFIX "IssueIdentify: DWORDIO supported\n"));
2259 }
2260 } else {
2261 // ATAPI
2262 if(deviceExtension->FullIdentifyData.MajorRevision &&
2263 deviceExtension->FullIdentifyData.DoubleWordIo) {
2265 KdPrint2((PRINT_PREFIX "IssueIdentify: DFLAGS_DWORDIO_ENABLED.\n"));
2266 }
2267 if(deviceExtension->FullIdentifyData.AtapiDMA.DMADirRequired) {
2268 KdPrint2((PRINT_PREFIX "DMADirRequired.\n"));
2269 }
2270 if(deviceExtension->FullIdentifyData.AtapiByteCount0) {
2271 KdPrint2((PRINT_PREFIX "AtapiByteCount0=%x\n", deviceExtension->FullIdentifyData.AtapiByteCount0));
2272 }
2273 }
2274
2276 &deviceExtension->FullIdentifyData,sizeof(IDENTIFY_DATA2));
2277
2278 InitBadBlocks(LunExt);
2279
2280 if ((LunExt->IdentifyData.DrqType & ATAPI_DRQT_INTR) &&
2282
2283 // This device interrupts with the assertion of DRQ after receiving
2284 // Atapi Packet Command
2285 LunExt->DeviceFlags |= DFLAGS_INT_DRQ;
2286 KdPrint2((PRINT_PREFIX "IssueIdentify: Device interrupts on assertion of DRQ.\n"));
2287
2288 } else {
2289 KdPrint2((PRINT_PREFIX "IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
2290 }
2291
2293 // ATAPI branch
2294 if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_TAPE) {
2295 // This is a tape.
2297 KdPrint2((PRINT_PREFIX "IssueIdentify: Device is a tape drive.\n"));
2298 } else
2299 if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM ||
2300 LunExt->IdentifyData.DeviceType == ATAPI_TYPE_OPTICAL) {
2301 KdPrint2((PRINT_PREFIX "IssueIdentify: Device is CD/Optical drive.\n"));
2302 // set CD default costs
2306 statusByte = WaitForDrq(chan);
2307 } else {
2308 KdPrint2((PRINT_PREFIX "IssueIdentify: ATAPI drive type %#x.\n",
2309 LunExt->IdentifyData.DeviceType));
2310 }
2311 KdPrint2((PRINT_PREFIX "IssueIdentify: AtapiCmdSize %#x\n", deviceExtension->FullIdentifyData.AtapiCmdSize));
2312 } else {
2313 KdPrint2((PRINT_PREFIX "IssueIdentify: hard drive.\n"));
2314 }
2315
2316 GetBaseStatus(chan, statusByte);
2317 KdPrint2((PRINT_PREFIX "IssueIdentify: final Status on exit (%#x)\n", statusByte));
2318 return TRUE;
2319
2320} // end IssueIdentify()
2321
2322
2323/*++
2324
2325Routine Description:
2326 Set drive parameters using the IDENTIFY data.
2327
2328Arguments:
2329 HwDeviceExtension - HBA miniport driver's adapter data storage
2330 DeviceNumber - Indicates which device.
2331
2332Return Value:
2333 TRUE if all goes well.
2334
2335--*/
2336BOOLEAN
2337NTAPI
2339 IN PVOID HwDeviceExtension,
2341 IN ULONG lChannel
2342 )
2343{
2344 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2345 PIDENTIFY_DATA2 identifyData;
2346 PHW_LU_EXTENSION LunExt;
2347// ULONG i;
2348 UCHAR statusByte;
2349 UCHAR errorByte;
2350
2351 LunExt = deviceExtension->chan[lChannel].lun[DeviceNumber];
2352 identifyData = &(LunExt->IdentifyData);
2353
2354 if(LunExt->DeviceFlags &
2356 return TRUE;
2357
2358 KdPrint2((PRINT_PREFIX "SetDriveParameters: Number of heads %#x\n", identifyData->NumberOfHeads));
2359 KdPrint2((PRINT_PREFIX "SetDriveParameters: Sectors per track %#x\n", identifyData->SectorsPerTrack));
2360
2361 // Send SET PARAMETER command.
2362 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
2364 (identifyData->NumberOfHeads - 1), 0,
2365 (UCHAR)identifyData->SectorsPerTrack, 0, ATA_WAIT_IDLE);
2366
2367 statusByte = UniataIsIdle(deviceExtension, statusByte);
2368 if(statusByte & IDE_STATUS_ERROR) {
2369 errorByte = AtapiReadPort1(&deviceExtension->chan[lChannel], IDX_IO1_i_Error);
2370 KdPrint2((PRINT_PREFIX "SetDriveParameters: Error bit set. Status %#x, error %#x\n",
2371 errorByte, statusByte));
2372 return FALSE;
2373 }
2374
2375 if(statusByte == IDE_STATUS_IDLE) {
2376 return TRUE;
2377 }
2378
2379 return FALSE;
2380
2381} // end SetDriveParameters()
2382
2383VOID
2384NTAPI
2386 PHW_LU_EXTENSION LunExt
2387 )
2388{
2389 // keep only DFLAGS_HIDDEN flag
2390 LunExt->DeviceFlags &= DFLAGS_HIDDEN;
2391 LunExt->AtapiReadyWaitDelay = 0;
2392} // end UniataForgetDevice()
2393
2394
2395/*++
2396
2397Routine Description:
2398 Reset IDE controller and/or Atapi device.
2399 ->HwResetBus
2400
2401Arguments:
2402 HwDeviceExtension - HBA miniport driver's adapter data storage
2403
2404Return Value:
2405 Nothing.
2406
2407
2408--*/
2409BOOLEAN
2410NTAPI
2412 IN PVOID HwDeviceExtension,
2414 )
2415{
2416 KdPrint2((PRINT_PREFIX "AtapiResetController(%x)\n", PathId));
2417 return AtapiResetController__(HwDeviceExtension, PathId, RESET_COMPLETE_ALL);
2418} // end AtapiResetController()
2419
2420BOOLEAN
2421NTAPI
2423 IN PVOID HwDeviceExtension,
2424 IN ULONG PathId,
2425 IN BOOLEAN CompleteType
2426 )
2427{
2428 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2429 ULONG numberChannels = deviceExtension->NumberChannels;
2430 PHW_CHANNEL chan = NULL;
2431 ULONG i,j;
2432 ULONG MaxLuns;
2433 UCHAR statusByte;
2434 PSCSI_REQUEST_BLOCK CurSrb;
2435 ULONG ChannelCtrlFlags;
2436 UCHAR dma_status = 0;
2437
2438 ULONG slotNumber = deviceExtension->slotNumber;
2439 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
2440 ULONG VendorID = deviceExtension->DevID & 0xffff;
2441#ifdef _DEBUG
2442 ULONG DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
2443#endif
2444 //ULONG RevID = deviceExtension->RevID;
2445 ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
2446 //UCHAR tmp8;
2447 USHORT tmp16;
2448
2449 KdPrint2((PRINT_PREFIX "AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID, DeviceID, slotNumber));
2450 KdPrint2((PRINT_PREFIX "simplexOnly %d, VM %x\n", deviceExtension->simplexOnly, g_opt_VirtualMachine));
2451
2452 if(!deviceExtension->simplexOnly && (PathId != CHAN_NOT_SPECIFIED)) {
2453 // we shall reset both channels on SimplexOnly devices,
2454 // It's not worth doing so on normal controllers
2455 j = PathId;
2456 numberChannels = min(j+1, deviceExtension->NumberChannels);
2457 } else {
2458 j=0;
2459 numberChannels = deviceExtension->NumberChannels;
2460 }
2461
2462 for (; j < numberChannels; j++) {
2463
2464 KdPrint2((PRINT_PREFIX "AtapiResetController: Reset lchannel %d[%d]\n", j, deviceExtension->Channel));
2465 chan = &(deviceExtension->chan[j]);
2466 MaxLuns = chan->NumberLuns;
2467 // Save control flags
2468 ChannelCtrlFlags = chan->ChannelCtrlFlags;
2469 KdPrint2((PRINT_PREFIX " CompleteType %#x, Luns %d, chan %#x, sptr %#x, flags %#x\n", CompleteType, MaxLuns, chan, &chan, ChannelCtrlFlags));
2470 //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
2471 if(CompleteType != RESET_COMPLETE_NONE) {
2472#ifndef UNIATA_CORE
2473 while((CurSrb = UniataGetCurRequest(chan))) {
2474
2475 PHW_LU_EXTENSION LunExt;
2476 PATA_REQ AtaReq = (PATA_REQ)(CurSrb->SrbExtension);
2477
2478 i = GET_CDEV(CurSrb);
2479 KdPrint2((PRINT_PREFIX " Lun %x\n", i));
2480 LunExt = chan->lun[i];
2481
2482 KdPrint2((PRINT_PREFIX "AtapiResetController: pending SRB %#x, chan %#x\n", CurSrb, chan));
2483 if(CurSrb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
2484 KdPrint2((PRINT_PREFIX " was MechStatus\n"));
2485
2486 if(!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)) {
2488 KdPrint2((PRINT_PREFIX " set DFLAGS_CHANGER_INITED\n"));
2489 }
2490 }
2491 // Check and see if we are processing an internal srb
2492 if (AtaReq->OriginalSrb) {
2493 KdPrint2((PRINT_PREFIX " restore original SRB %#x\n", AtaReq->OriginalSrb));
2494 AtaReq->Srb = AtaReq->OriginalSrb;
2495 CurSrb->SrbExtension = NULL;
2496 AtaReq->OriginalSrb = NULL;
2497 // NOTE: internal SRB doesn't get to SRB queue !!!
2498 CurSrb = AtaReq->Srb;
2499 }
2500
2501 // Remove current request from queue
2502 UniataRemoveRequest(chan, CurSrb);
2503
2504 // Check if request is in progress.
2505 ASSERT(AtaReq->Srb == CurSrb);
2506 if (CurSrb) {
2507 // Complete outstanding request with SRB_STATUS_BUS_RESET.
2508 UCHAR CurPathId = CurSrb->PathId;
2509 UCHAR TargetId = CurSrb->TargetId;
2510 UCHAR Lun = CurSrb->Lun;
2511
2514
2515 if (CurSrb->SenseInfoBuffer) {
2516
2517 PSENSE_DATA senseBuffer = (PSENSE_DATA)CurSrb->SenseInfoBuffer;
2518 KdPrint2((PRINT_PREFIX " senseBuffer %#x, chan %#x, ReqFlags %#x\n", senseBuffer, chan, AtaReq->Flags));
2519
2520 senseBuffer->ErrorCode = 0x70;
2521 senseBuffer->Valid = 1;
2522 senseBuffer->AdditionalSenseLength = 0xb;
2523 if(CompleteType == RESET_COMPLETE_ALL) {
2524 KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
2525 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
2528 } else {
2529 KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
2530 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
2531 senseBuffer->AdditionalSenseCode = 0;
2532 senseBuffer->AdditionalSenseCodeQualifier = 0;
2533 }
2534 }
2535
2536 if(!ATAPI_DEVICE(chan, i) && AtaReq->bcount && AtaReq->retry < MAX_RETRIES) {
2537 KdPrint2((PRINT_PREFIX "Save IDE retry status %d\n", AtaReq->retry));
2538 LunExt->errLastLba = AtaReq->lba;
2539 LunExt->errBCount = AtaReq->bcount;
2540 LunExt->errRetry = AtaReq->retry+1;
2541 //KdPrint2((PRINT_PREFIX "AtaReq->Flags & REQ_FLAG_RW_MASK = %x (%x)\n", (AtaReq->Flags & REQ_FLAG_RW_MASK), REQ_FLAG_READ));
2542 //KdPrint2((PRINT_PREFIX "ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION = %x (%x)\n", ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE, CTRFLAGS_DMA_OPERATION));
2543 //KdPrint2((PRINT_PREFIX "g_opt_VirtualMachine = %x (%x)\n", g_opt_VirtualMachine, VM_BOCHS));
2544 if(((AtaReq->Flags & REQ_FLAG_RW_MASK) == REQ_FLAG_READ) &&
2545 (ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) &&
2547 KdPrint2((PRINT_PREFIX "set CTRFLAGS_DMA_BEFORE_R on BOCHS\n"));
2550 } else {
2551 KdPrint2((PRINT_PREFIX "do nothing\n"));
2552 }
2553 } else
2554 if(ATAPI_DEVICE(chan, i) && AtaReq->bcount && !AtaReq->retry) {
2555 KdPrint2((PRINT_PREFIX "Save ATAPI retry status %d\n", AtaReq->retry));
2556 LunExt->errLastLba = AtaReq->lba;
2557 LunExt->errBCount = AtaReq->bcount;
2558 LunExt->errRetry = AtaReq->retry+1;
2559 if(((AtaReq->Flags & REQ_FLAG_RW_MASK) == REQ_FLAG_READ) &&
2560 (ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) &&
2562 KdPrint2((PRINT_PREFIX "set CTRFLAGS_DMA_BEFORE_R on BOCHS ATAPI\n"));
2563 //g_opt_BochsDmaReadWorkaround = TRUE;
2565 } else {
2566 KdPrint2((PRINT_PREFIX "do nothing\n"));
2567 }
2568 } else {
2569 LunExt->errRetry = 0;
2570 }
2571
2572 // Clear request tracking fields.
2573 AtaReq->WordsLeft = 0;
2574 AtaReq->DataBuffer = NULL;
2575 AtaReq->TransferLength = 0;
2576 KdPrint2((PRINT_PREFIX "chan %#x\n", chan));
2577
2579 deviceExtension,
2580 CurSrb);
2581
2582 // Indicate ready for next request.
2584 deviceExtension,
2585 CurPathId,
2586 TargetId,
2587 Lun);
2588 }
2589 if(CompleteType != RESET_COMPLETE_ALL)
2590 break;
2591 } // end while()
2592#endif //UNIATA_CORE
2593 } // end if (!CompleteType != RESET_COMPLETE_NONE)
2594
2595 // Clear expecting interrupt flag.
2597 chan->RDP = FALSE;
2598 chan->ChannelCtrlFlags = ChannelCtrlFlags & CTRFLAGS_PERMANENT;
2601
2602 for (i = 0; i < MaxLuns; i++) {
2603 chan->lun[i]->PowerState = 0;
2604 }
2605 // Reset controller
2606 if(ChipFlags & UNIATA_AHCI) {
2607 KdPrint2((PRINT_PREFIX " AHCI path\n"));
2608 if(UniataAhciChanImplemented(deviceExtension, j)) {
2609#ifdef _DEBUG
2610 UniataDumpAhciPortRegs(chan);
2611#endif
2612 AtapiDisableInterrupts(deviceExtension, j);
2613 UniataAhciReset(HwDeviceExtension, j);
2614 } else {
2615 KdPrint2((PRINT_PREFIX " skip not implemented\n"));
2616 continue;
2617 }
2618 } else {
2619 KdPrint2((PRINT_PREFIX " ATA path, chan %#x\n", chan));
2620 KdPrint2((PRINT_PREFIX " disable intr (0)\n"));
2621 AtapiDisableInterrupts(deviceExtension, j);
2622 KdPrint2((PRINT_PREFIX " done\n"));
2623 switch(VendorID) {
2624 case ATA_INTEL_ID: {
2625 ULONG mask;
2626 ULONG pshift;
2627 ULONG timeout;
2628 if(!(ChipFlags & UNIATA_SATA)) {
2629 goto default_reset;
2630 }
2631 if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
2632 goto default_reset;
2633 }
2634
2635#if 0
2636 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2637 if(ChipFlags & UNIATA_AHCI) {
2638 mask = 0x0005 << j;
2639 } else {
2640 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2641 GetPciConfig1(0x90, tmp8);
2642 if(tmp8 & 0x04) {
2643 mask = 0x0003;
2644 } else {
2645 mask = 0x0001 << j;
2646 }
2647 }
2648#else
2649 mask = 1 << chan->lun[0]->SATA_lun_map;
2650 if (MaxLuns > 1) {
2651 mask |= (1 << chan->lun[1]->SATA_lun_map);
2652 }
2653#endif
2654 ChangePciConfig2(0x92, a & ~mask);
2656 ChangePciConfig2(0x92, a | mask);
2657 timeout = 100;
2658
2659 /* Wait up to 1 sec for "connect well". */
2660 if (ChipFlags & (I6CH | I6CH2)) {
2661 pshift = 8;
2662 } else {
2663 pshift = 4;
2664 }
2665 while (timeout--) {
2666 GetPciConfig2(0x92, tmp16);
2667 if (((tmp16 >> pshift) & mask) == mask) {
2668 GetBaseStatus(chan, statusByte);
2669 if(statusByte != IDE_STATUS_WRONG) {
2670 break;
2671 }
2672 }
2673 AtapiStallExecution(10000);
2674 }
2675 break; }
2676 case ATA_SIS_ID: {
2677 KdPrint2((PRINT_PREFIX " SIS\n"));
2678 if(!(ChipFlags & UNIATA_SATA))
2679 goto default_reset;
2680 break; }
2681#if 0
2682 case ATA_NVIDIA_ID: {
2683 KdPrint2((PRINT_PREFIX " nVidia\n"));
2684 if(!(ChipFlags & UNIATA_SATA))
2685 goto default_reset;
2686 break; }
2687#else
2688 case ATA_NVIDIA_ID: {
2689 ULONG offs;
2690 ULONG Channel = deviceExtension->Channel + j;
2691 KdPrint2((PRINT_PREFIX " nVidia\n"));
2692 if(!(ChipFlags & UNIATA_SATA)) {
2693 goto default_reset;
2694 }
2695 offs = (ChipFlags & NV4OFF) ? 0x0440 : 0x0010;
2696
2697 KdPrint2((PRINT_PREFIX " disable Phy intr, offs %#x, c %u\n", offs, Channel));
2698 /* disable device and PHY state change interrupts */
2699 if(ChipFlags & NVQ) {
2700 KdPrint2((PRINT_PREFIX " NVQ, 32bits reg\n"));
2701 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4,
2702 AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4) & ((~(ULONG)0x0000000d) << (!Channel*16)) );
2703 } else {
2704 AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1,
2705 AtapiReadPortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1) & ((~(UCHAR)0x0d) << (!Channel*4)) );
2706 }
2707 tmp16 = UniataSataPhyEnable(HwDeviceExtension, j, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE);
2708
2709 KdPrint2((PRINT_PREFIX " enable Phy intr, offs %#x\n", offs));
2710 /* enable device and PHY state change interrupts */
2711 if(ChipFlags & NVQ) {
2712 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4,
2713 AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4) | (((ULONG)0x0000000d) << (!Channel*16)) );
2714 } else {
2715 AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1,
2716 AtapiReadPortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1) | (((UCHAR)0x0d) << (!Channel*4)) );
2717 }
2718
2719 KdPrint2((PRINT_PREFIX " dev status %#x\n", tmp16));
2720 if(tmp16 != IDE_STATUS_WRONG) {
2721 goto default_reset;
2722 }
2723 break; }
2724#endif //0
2725 case ATA_SILICON_IMAGE_ID: {
2726 ULONG offset;
2727 ULONG Channel = deviceExtension->Channel + j;
2728 if(!(ChipFlags & UNIATA_SATA))
2729 goto default_reset;
2730 offset = ((Channel & 1) << 7) + ((Channel & 2) << 8);
2731 /* disable PHY state change interrupt */
2732 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + offset, 0);
2733
2734 UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0);
2735
2736 /* reset controller part for this channel */
2737 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
2738 AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) | (0xc0 >> Channel));
2739 AtapiStallExecution(1000);
2740 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
2741 AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) & ~(0xc0 >> Channel));
2742
2743
2744 break; }
2745 case ATA_PROMISE_ID: {
2746 break; }
2747 default:
2748 if(ChipFlags & UNIATA_SATA) {
2749 KdPrint2((PRINT_PREFIX " SATA generic reset\n"));
2750 UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0);
2751 }
2752default_reset:
2753/*
2754 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS |
2755 IDE_DC_RESET_CONTROLLER );
2756 chan->last_devsel = -1;
2757 KdPrint2((PRINT_PREFIX " wait a little\n"));
2758 AtapiStallExecution(10000);
2759 // Disable interrupts
2760 KdPrint2((PRINT_PREFIX " disable intr\n"));
2761 AtapiDisableInterrupts(deviceExtension, j);
2762 AtapiStallExecution(100);
2763 KdPrint2((PRINT_PREFIX " re-enable intr\n"));
2764 AtapiEnableInterrupts(deviceExtension, j);
2765 KdPrint2((PRINT_PREFIX " wait a little (2)\n"));
2766 AtapiStallExecution(100000);
2767*/
2768 AtapiHardReset(chan, TRUE, 100000);
2769 KdPrint2((PRINT_PREFIX " disable intr\n"));
2770 AtapiDisableInterrupts(deviceExtension, j);
2772 KdPrint2((PRINT_PREFIX " re-enable intr\n"));
2773 AtapiEnableInterrupts(deviceExtension, j);
2774 KdPrint2((PRINT_PREFIX " done\n"));
2775
2776 break;
2777 } // end switch()
2778
2779 //if(!(ChipFlags & UNIATA_SATA)) {}
2780 if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
2781 // Reset DMA engine if active
2782 KdPrint2((PRINT_PREFIX " check DMA engine\n"));
2783 dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
2784 KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
2785 if((ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
2786 (dma_status & BM_STATUS_INTR)) {
2787 AtapiDmaDone(HwDeviceExtension, 0, j, NULL);
2788 }
2789 }
2790 } // ATA vs AHCI
2791
2792 // all these shall be performed inside AtapiHwInitialize__() ?
2793#if 1
2794 KdPrint2((PRINT_PREFIX " process connected devices 0 - %d\n", MaxLuns-1));
2795 // Do special processing for ATAPI and IDE disk devices.
2796 for (i = 0; i < MaxLuns; i++) {
2797
2798 // Check if device present.
2799 KdPrint2((PRINT_PREFIX " Chan %#x\n", chan));
2800 KdPrint2((PRINT_PREFIX " Lun %#x\n", i));
2801 KdPrint2((PRINT_PREFIX " Lun ptr %#x\n", chan->lun[i]));
2802 if (!(chan->lun[i]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
2803 if(ChipFlags & UNIATA_AHCI) {
2804 // everything is done in UniataAhciReset()
2805 KdPrint2((PRINT_PREFIX " device have gone\n"));
2806 continue;
2807 }
2808#ifdef NAVO_TEST
2809 continue;
2810#else //NAVO_TEST
2811 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2812 if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
2813 continue;
2814 }
2815 if(!CheckDevice(HwDeviceExtension, j, i, TRUE)) {
2816 continue;
2817 }
2818 } else {
2819 if(ChipFlags & UNIATA_AHCI) {
2820 // everything is done in UniataAhciReset()
2821 KdPrint2((PRINT_PREFIX " found some device\n"));
2822
2823 if(!IssueIdentify(HwDeviceExtension,
2824 i, j,
2825 ATAPI_DEVICE(chan, i) ?
2827 FALSE)) {
2828 KdPrint2((PRINT_PREFIX " identify failed !\n"));
2829 UniataForgetDevice(chan->lun[i]);
2830 }
2831 continue;
2832 }
2833 if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
2834 KdPrint2((PRINT_PREFIX " device have gone\n"));
2835 UniataForgetDevice(chan->lun[i]);
2836 }
2837#endif //NAVO_TEST
2838 }
2839
2840 SelectDrive(chan, i);
2842 statusByte = WaitOnBusyLong(chan);
2843 statusByte = UniataIsIdle(deviceExtension, statusByte);
2844 if(statusByte == IDE_STATUS_WRONG) {
2846 "no drive, status %#x\n",
2847 statusByte));
2848 UniataForgetDevice(chan->lun[i]);
2849 } else
2850 // Check for ATAPI disk.
2851 if (ATAPI_DEVICE(chan, i)) {
2852 // Issue soft reset and issue identify.
2853 GetStatus(chan, statusByte);
2854 KdPrint2((PRINT_PREFIX "AtapiResetController: Status before Atapi reset (%#x).\n",
2855 statusByte));
2856
2857 AtapiDisableInterrupts(deviceExtension, j);
2858 AtapiSoftReset(chan, i);
2859 AtapiEnableInterrupts(deviceExtension, j);
2860
2861 GetStatus(chan, statusByte);
2862
2863 if(statusByte != IDE_STATUS_SUCCESS) {
2864 ULONG k;
2865 k = UniataAnybodyHome(deviceExtension, j, i);
2866 if(k == ATA_AT_HOME_HDD) {
2867 // device reset in progress, perform additional wait
2868 KdPrint2((PRINT_PREFIX " long reset, wait up to 4.5 s\n"));
2869 k = 30 * 1000;
2871 k--)
2872 {
2874 }
2875 KdPrint2((PRINT_PREFIX " exit after %u loops\n", k));
2876 GetStatus(chan, statusByte);
2877 }
2878 }
2879 if(statusByte == IDE_STATUS_SUCCESS) {
2880
2881 IssueIdentify(HwDeviceExtension,
2882 i, j,
2884 } else {
2885
2887 "AtapiResetController: Status after soft reset %#x\n",
2888 statusByte));
2889 }
2890 GetBaseStatus(chan, statusByte);
2891
2892 } else {
2893 // Issue identify and reinit after channel reset.
2894
2895 if (statusByte != IDE_STATUS_IDLE &&
2896 statusByte != IDE_STATUS_SUCCESS &&
2897 statusByte != IDE_STATUS_DRDY) {
2898// result2 = FALSE;
2899 KdPrint2((PRINT_PREFIX "AtapiResetController: IdeHardReset failed\n"));
2900 } else
2901 if(!IssueIdentify(HwDeviceExtension,
2902 i, j,
2904// result2 = FALSE;
2905 KdPrint2((PRINT_PREFIX "AtapiResetController: IDE IssueIdentify failed\n"));
2906 } else
2907 // Set disk geometry parameters.
2908 if (!SetDriveParameters(HwDeviceExtension, i, j)) {
2909 KdPrint2((PRINT_PREFIX "AtapiResetController: SetDriveParameters failed\n"));
2910 }
2911 GetBaseStatus(chan, statusByte);
2912 }
2913 // force DMA mode reinit
2914 KdPrint2((PRINT_PREFIX " set DFLAGS_REINIT_DMA\n"));
2915 chan->lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
2916 }
2917#endif //0
2918
2919 // Enable interrupts, note, we can have here recursive disable
2921 KdPrint2((PRINT_PREFIX "AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2922 j,
2923 chan->DisableIntr));
2924 AtapiEnableInterrupts(deviceExtension, j);
2925
2926 // Call the HwInitialize routine to setup multi-block.
2927 AtapiHwInitialize__(deviceExtension, j);
2928 } // for(channel)
2929 ScsiPortNotification(NextRequest, deviceExtension, NULL);
2930
2931 return TRUE;
2932
2933} // end AtapiResetController__()
2934
2935
2936/*++
2937
2938Routine Description:
2939 This routine maps ATAPI and IDE errors to specific SRB statuses.
2940
2941Arguments:
2942 HwDeviceExtension - HBA miniport driver's adapter data storage
2943 Srb - IO request packet
2944
2945Return Value:
2946 SRB status
2947
2948--*/
2949ULONG
2950NTAPI
2952 IN PVOID HwDeviceExtension,
2954 )
2955{
2956 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2957 ULONG lChannel = GET_CHANNEL(Srb);
2958 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
2959// ULONG i;
2960 UCHAR errorByte = 0;
2961 UCHAR srbStatus = SRB_STATUS_SUCCESS;
2962 UCHAR scsiStatus;
2964 PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
2965
2966 // Read the error register.
2967
2968 if(deviceExtension->HwFlags & UNIATA_AHCI) {
2969 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
2970 if(AtaReq) {
2971 errorByte = AtaReq->ahci.in_error;
2972 } else {
2973 }
2974 } else {
2975 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
2976 }
2978 "MapError: Error register is %#x\n",
2979 errorByte));
2980
2981 if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2982
2983 switch (errorByte >> 4) {
2985
2987 "ATAPI: No sense information\n"));
2988 scsiStatus = SCSISTAT_CHECK_CONDITION;
2989 srbStatus = SRB_STATUS_ERROR;
2990 break;
2991
2993
2995 "ATAPI: Recovered error\n"));
2996 scsiStatus = 0;
2997 srbStatus = SRB_STATUS_SUCCESS;
2998 break;
2999
3001
3003 "ATAPI: Device not ready\n"));
3004 scsiStatus = SCSISTAT_CHECK_CONDITION;
3005 srbStatus = SRB_STATUS_ERROR;
3006 break;
3007
3009
3011 "ATAPI: Media error\n"));
3012 scsiStatus = SCSISTAT_CHECK_CONDITION;
3013 srbStatus = SRB_STATUS_ERROR;
3014 break;
3015
3017
3019 "ATAPI: Hardware error\n"));
3020 scsiStatus = SCSISTAT_CHECK_CONDITION;
3021 srbStatus = SRB_STATUS_ERROR;
3022 break;
3023
3025
3027 "ATAPI: Illegal request\n"));
3028 scsiStatus = SCSISTAT_CHECK_CONDITION;
3029 srbStatus = SRB_STATUS_ERROR;
3030 break;
3031
3033
3035 "ATAPI: Unit attention\n"));
3036 scsiStatus = SCSISTAT_CHECK_CONDITION;
3037 srbStatus = SRB_STATUS_ERROR;
3038 break;
3039
3041
3043 "ATAPI: Data protect\n"));
3044 scsiStatus = SCSISTAT_CHECK_CONDITION;
3045 srbStatus = SRB_STATUS_ERROR;
3046 break;
3047
3049
3051 "ATAPI: Blank check\n"));
3052 scsiStatus = SCSISTAT_CHECK_CONDITION;
3053 srbStatus = SRB_STATUS_ERROR;
3054 break;
3055
3058 "Atapi: Command Aborted\n"));
3059 scsiStatus = SCSISTAT_CHECK_CONDITION;
3060 srbStatus = SRB_STATUS_ERROR;
3061 break;
3062
3063 default:
3064
3066 "ATAPI: Invalid sense information\n"));
3067 scsiStatus = 0;
3068 srbStatus = SRB_STATUS_ERROR;
3069 break;
3070 }
3071
3072 } else {
3073
3074 scsiStatus = 0;
3075
3076 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
3077 chan->ReturningMediaStatus = errorByte;
3078
3079 if (errorByte & IDE_ERROR_MEDIA_CHANGE_REQ) {
3081 "IDE: Media change\n"));
3082 scsiStatus = SCSISTAT_CHECK_CONDITION;
3083 srbStatus = SRB_STATUS_ERROR;
3084
3085 if (Srb->SenseInfoBuffer) {
3086
3088
3089 senseBuffer->ErrorCode = 0x70;
3090 senseBuffer->Valid = 1;
3091 senseBuffer->AdditionalSenseLength = 0xb;
3092 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
3094 senseBuffer->AdditionalSenseCodeQualifier = 0;
3095
3096 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3097 }
3098
3099 } else if (errorByte & IDE_ERROR_COMMAND_ABORTED) {
3101 "IDE: Command abort\n"));
3102 srbStatus = SRB_STATUS_ABORTED;
3103 scsiStatus = SCSISTAT_CHECK_CONDITION;
3104
3105 if (Srb->SenseInfoBuffer) {
3106
3108
3109 senseBuffer->ErrorCode = 0x70;
3110 senseBuffer->Valid = 1;
3111 senseBuffer->AdditionalSenseLength = 0xb;
3112 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
3113 senseBuffer->AdditionalSenseCode = 0;
3114 senseBuffer->AdditionalSenseCodeQualifier = 0;
3115
3116 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3117 }
3118
3119 LunExt->ErrorCount++;
3120
3121 } else if (errorByte & IDE_ERROR_END_OF_MEDIA) {
3122
3124 "IDE: End of media\n"));
3125 scsiStatus = SCSISTAT_CHECK_CONDITION;
3126 srbStatus = SRB_STATUS_ERROR;
3127
3128 if (Srb->SenseInfoBuffer) {
3129
3131
3132 senseBuffer->ErrorCode = 0x70;
3133 senseBuffer->Valid = 1;
3134 senseBuffer->AdditionalSenseLength = 0xb;
3135 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
3138 senseBuffer->EndOfMedia = 1;
3139
3140 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3141 }
3142
3143 if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
3144 LunExt->ErrorCount++;
3145 }
3146
3147 } else if (errorByte & IDE_ERROR_ILLEGAL_LENGTH) {
3148
3150 "IDE: Illegal length\n"));
3151 srbStatus = SRB_STATUS_INVALID_REQUEST;
3152
3153 if (Srb->SenseInfoBuffer) {
3154
3156
3157 senseBuffer->ErrorCode = 0x70;
3158 senseBuffer->Valid = 1;
3159 senseBuffer->AdditionalSenseLength = 0xb;
3160 senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST;
3163 senseBuffer->IncorrectLength = 1;
3164
3165 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3166 }
3167
3168 } else if (errorByte & IDE_ERROR_BAD_BLOCK) {
3169
3171 "IDE: Bad block\n"));
3172 srbStatus = SRB_STATUS_ERROR;
3173 scsiStatus = SCSISTAT_CHECK_CONDITION;
3174 if (Srb->SenseInfoBuffer) {
3175
3177
3178 senseBuffer->ErrorCode = 0x70;
3179 senseBuffer->Valid = 1;
3180 senseBuffer->AdditionalSenseLength = 0xb;
3181 senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
3182 senseBuffer->AdditionalSenseCode = 0;
3183 senseBuffer->AdditionalSenseCodeQualifier = 0;
3184
3185 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3186 }
3187
3188 } else if (errorByte & IDE_ERROR_ID_NOT_FOUND) {
3189
3191 "IDE: Id not found\n"));
3192 srbStatus = SRB_STATUS_ERROR;
3193 scsiStatus = SCSISTAT_CHECK_CONDITION;
3194
3195 if (Srb->SenseInfoBuffer) {
3196
3198
3199 senseBuffer->ErrorCode = 0x70;
3200 senseBuffer->Valid = 1;
3201 senseBuffer->AdditionalSenseLength = 0xb;
3202 senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
3203 senseBuffer->AdditionalSenseCode = 0;
3204 senseBuffer->AdditionalSenseCodeQualifier = 0;
3205
3206 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3207 }
3208
3209 LunExt->ErrorCount++;
3210
3211 } else if (errorByte & IDE_ERROR_MEDIA_CHANGE) {
3212
3214 "IDE: Media change\n"));
3215 scsiStatus = SCSISTAT_CHECK_CONDITION;
3216 srbStatus = SRB_STATUS_ERROR;
3217
3218 if (Srb->SenseInfoBuffer) {
3219
3221
3222 senseBuffer->ErrorCode = 0x70;
3223 senseBuffer->Valid = 1;
3224 senseBuffer->AdditionalSenseLength = 0xb;
3225 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
3227 senseBuffer->AdditionalSenseCodeQualifier = 0;
3228
3229 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3230 }
3231
3232 } else if (errorByte & IDE_ERROR_DATA_ERROR) {
3233
3235 "IDE: Data error\n"));
3236 scsiStatus = SCSISTAT_CHECK_CONDITION;
3237 srbStatus = SRB_STATUS_ERROR;
3238
3239 if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
3240 LunExt->ErrorCount++;
3241 }
3242
3243 // Build sense buffer
3244 if (Srb->SenseInfoBuffer) {
3245
3247
3248 senseBuffer->ErrorCode = 0x70;
3249 senseBuffer->Valid = 1;
3250 senseBuffer->AdditionalSenseLength = 0xb;
3251 senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
3252 senseBuffer->AdditionalSenseCode = 0;
3253 senseBuffer->AdditionalSenseCodeQualifier = 0;
3254
3255 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3256 }
3257 }
3258
3259 if (LunExt->ErrorCount >= MAX_ERRORS) {
3260// deviceExtension->DWordIO = FALSE;
3261
3263 "MapError: ErrorCount >= MAX_ERRORS\n"));
3264
3265 LunExt->DeviceFlags &= ~DFLAGS_DWORDIO_ENABLED;
3266 LunExt->MaximumBlockXfer = 0;
3267 BrutePoint();
3268
3270 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
3271
3272 // Log the error.
3274 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
3275 HwDeviceExtension,
3276 Srb,
3277 Srb->PathId,
3278 Srb->TargetId,
3279 Srb->Lun,
3281 4
3282 ));
3283 ScsiPortLogError( HwDeviceExtension,
3284 Srb,
3285 Srb->PathId,
3286 Srb->TargetId,
3287 Srb->Lun,
3289 4);
3290
3291 // Reprogram to not use Multi-sector.
3292 UCHAR statusByte;
3293
3294 if (LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT &&
3296
3297 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY);
3298
3299 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
3300 // command was aborted.
3301 if (statusByte & IDE_STATUS_ERROR) {
3302
3303 // Read the error register.
3304 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
3305
3306 KdPrint2((PRINT_PREFIX "MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
3307 statusByte,
3308 errorByte));
3309
3310 // Adjust the devExt. value, if necessary.
3311 LunExt->MaximumBlockXfer = 0;
3312 BrutePoint();
3313
3314 }
3315 }
3316 }
3317 }
3318
3319 // Set SCSI status to indicate a check condition.
3320 Srb->ScsiStatus = scsiStatus;
3321
3322 return srbStatus;
3323
3324} // end MapError()
3325
3326
3327/*++
3328
3329Routine Description:
3330
3331Arguments:
3332 HwDeviceExtension - HBA miniport driver's adapter data storage
3333 ->HwInitialize
3334
3335Return Value:
3336 TRUE - if initialization successful.
3337 FALSE - if initialization unsuccessful.
3338
3339--*/
3340BOOLEAN
3341NTAPI
3343 IN PVOID HwDeviceExtension
3344 )
3345{
3346 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3347 ULONG numberChannels = deviceExtension->NumberChannels;
3348 ULONG c;
3349
3350 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base)\n"));
3351
3352 if(WinVer_WDM_Model) {
3354 }
3355 if(deviceExtension->MasterDev) {
3356 KdPrint2((PRINT_PREFIX " mark chan %d of master controller [%x] as inited\n",
3357 deviceExtension->Channel, deviceExtension->DevIndex));
3358 BMList[deviceExtension->DevIndex].ChanInitOk |= 0x01 << deviceExtension->Channel;
3359 }
3360
3361 /* do extra chipset specific setups */
3363/*
3364 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
3365 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
3366 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
3367 }
3368*/
3369 for (c = 0; c < numberChannels; c++) {
3370 AtapiHwInitialize__(deviceExtension, c);
3371 }
3372 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base) done\n"));
3373 return TRUE;
3374} // end AtapiHwInitialize()
3375
3376VOID
3377NTAPI
3379 IN PHW_DEVICE_EXTENSION deviceExtension,
3380 IN ULONG lChannel
3381 )
3382{
3383 ULONG i;
3384 UCHAR statusByte, errorByte;
3385 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
3386 PHW_LU_EXTENSION LunExt;
3387// ULONG tmp32;
3388 ULONG PreferedMode = 0xffffffff;
3389
3390 if((deviceExtension->HwFlags & UNIATA_AHCI) &&
3391 !UniataAhciChanImplemented(deviceExtension, lChannel)) {
3392 return;
3393 }
3394
3395 AtapiChipInit(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel);
3396 FindDevices(deviceExtension, 0, lChannel);
3397
3398 for (i = 0; i < chan->NumberLuns; i++) {
3399
3400 KdPrint3((PRINT_PREFIX "AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel, i));
3401
3402 LunExt = chan->lun[i];
3403 // skip empty slots
3404 if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
3405 continue;
3406 }
3407
3408 AtapiDisableInterrupts(deviceExtension, lChannel);
3410
3411 if (!(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_MANUAL_CHS))) {
3412
3413 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: IDE branch\n"));
3414 // Enable media status notification
3415 IdeMediaStatus(TRUE,deviceExtension,lChannel,(UCHAR)i);
3416
3417 // If supported, setup Multi-block transfers.
3418 statusByte = AtaCommand(deviceExtension, i, lChannel,
3419 IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
3421
3422 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
3423 // command was aborted.
3424 if (statusByte & IDE_STATUS_ERROR) {
3425
3426 // Read the error register.
3427 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
3428
3429 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
3430 statusByte,
3431 errorByte));
3432
3433 statusByte = AtaCommand(deviceExtension, i, lChannel,
3434 IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
3435 0, 0, ATA_WAIT_BASE_READY);
3436
3437 if (statusByte & IDE_STATUS_ERROR) {
3438 // Read the error register.
3439 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
3440
3441 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
3442 statusByte,
3443 errorByte));
3444 }
3445 // Adjust the devExt. value, if necessary.
3446 LunExt->MaximumBlockXfer = 0;
3447
3448 } else {
3450 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
3451 i,
3452 LunExt->MaximumBlockXfer));
3453 }
3454
3455 if(LunExt->IdentifyData.MajorRevision) {
3456
3457 if(LunExt->opt_ReadCacheEnable) {
3458 KdPrint2((PRINT_PREFIX " Try Enable Read Cache\n"));
3459 // If supported, setup read/write cacheing
3460 statusByte = AtaCommand(deviceExtension, i, lChannel,
3461 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3463
3464 // Check for errors.
3465 if (statusByte & IDE_STATUS_ERROR) {
3467 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
3468 i));
3469 LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
3470 } else {
3472 }
3473 } else {
3474 KdPrint2((PRINT_PREFIX " Disable Read Cache\n"));
3475 statusByte = AtaCommand(deviceExtension, i, lChannel,
3476 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3478 LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
3479 }
3480 if(LunExt->IdentifyData.FeaturesSupport.WriteCache) {
3481 if(LunExt->opt_WriteCacheEnable) {
3482 KdPrint2((PRINT_PREFIX " Try Enable Write Cache\n"));
3483 // If supported & allowed, setup write cacheing
3484 statusByte = AtaCommand(deviceExtension, i, lChannel,
3485 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3487 // Check for errors.
3488 if (statusByte & IDE_STATUS_ERROR) {
3490 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
3491 i));
3492 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
3493 } else {
3495 }
3496 } else {
3497 KdPrint2((PRINT_PREFIX " Disable Write Cache\n"));
3498 statusByte = AtaCommand(deviceExtension, i, lChannel,
3499 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3501 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
3502 }
3503 }
3504
3505 if(/*LunExt->IdentifyData.FeaturesSupport.PowerMngt ||*/
3506 LunExt->IdentifyData.FeaturesSupport.APM) {
3507
3508 if(LunExt->opt_AdvPowerMode) {
3509 KdPrint2((PRINT_PREFIX " Try Enable Adv. Power Mgmt\n"));
3510 // setup APM
3511 statusByte = AtaCommand(deviceExtension, i, lChannel,
3512 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3514 // Check for errors.
3515 if (statusByte & IDE_STATUS_ERROR) {
3517 "AtapiHwInitialize: Enable APM on Device %d failed\n",
3518 i));
3519 }
3520 } else {
3521 KdPrint2((PRINT_PREFIX " Disable Adv. Power Mgmt\n"));
3522 statusByte = AtaCommand(deviceExtension, i, lChannel,
3523 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3525 }
3526 }
3527 if(LunExt->IdentifyData.FeaturesSupport.AutoAcoustic) {
3528 if(LunExt->opt_AcousticMode) {
3529 KdPrint2((PRINT_PREFIX " Try Enable Acoustic Mgmt\n"));
3530 // setup acoustic mgmt
3531 statusByte = AtaCommand(deviceExtension, i, lChannel,
3532 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3534 // Check for errors.
3535 if (statusByte & IDE_STATUS_ERROR) {
3537 "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n",
3538 i));
3539 }
3540 } else {
3541 KdPrint2((PRINT_PREFIX " Disable Acoustic Mgmt\n"));
3542 statusByte = AtaCommand(deviceExtension, i, lChannel,
3543 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3545 }
3546 }
3547 if(LunExt->IdentifyData.FeaturesSupport.Standby) {
3548 KdPrint2((PRINT_PREFIX " Try init standby timer: %d\n"));
3549 // setup standby timer
3550 statusByte = AtaCommand(deviceExtension, i, lChannel,
3551 IDE_COMMAND_IDLE, 0, 0, 0,
3553 // Check for errors.
3554 if (statusByte & IDE_STATUS_ERROR) {
3556 "AtapiHwInitialize: standby timer on Device %d failed\n",
3557 i));
3558 }
3559 }
3560 }
3561
3562 } else if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)){
3563
3564 ULONG j;
3565 //BOOLEAN isSanyo = FALSE;
3566 CCHAR vendorId[26];
3567
3568 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: ATAPI/Changer branch\n"));
3569
3570 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
3571 for (j = 0; j < 26; j += 2) {
3572
3573 // Build a buffer based on the identify data.
3574 MOV_DW_SWP(vendorId[j], ((PUCHAR)LunExt->IdentifyData.ModelNumber)[j]);
3575 }
3576
3577 if (!AtapiStringCmp (vendorId, "CD-ROM CDR", 11)) {
3578
3579 // Inquiry string for older model had a '-', newer is '_'
3580 if (vendorId[12] == 'C') {
3581
3582 // Torisan changer. Set the bit. This will be used in several places
3583 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
3585 LunExt->DiscsPresent = 3;
3586 //isSanyo = TRUE;
3587 }
3588 }
3589 }
3590
3591 PreferedMode = LunExt->opt_MaxTransferMode;
3592 if((PreferedMode == 0xffffffff) || (PreferedMode > chan->MaxTransferMode)) {
3593 KdPrint2((PRINT_PREFIX "MaxTransferMode (overriden): %#x\n", chan->MaxTransferMode));
3594 PreferedMode = chan->MaxTransferMode;
3595 }
3596
3597 if(LunExt->opt_PreferedTransferMode != 0xffffffff) {
3598 KdPrint2((PRINT_PREFIX "PreferedTransferMode: %#x\n", PreferedMode));
3599 PreferedMode = min(LunExt->opt_PreferedTransferMode, PreferedMode);
3600 }
3601
3602 KdPrint2((PRINT_PREFIX " try mode %#x\n", PreferedMode));
3603 LunExt->LimitedTransferMode =
3604 LunExt->TransferMode =
3605 (CHAR)PreferedMode;
3606
3607 AtapiDmaInit__(deviceExtension, LunExt);
3608
3609 LunExt->LimitedTransferMode =
3610 LunExt->TransferMode;
3611 KdPrint2((PRINT_PREFIX "Using %#x mode\n", LunExt->TransferMode));
3612
3613 // We need to get our device ready for action before
3614 // returning from this function
3615
3616 // According to the atapi spec 2.5 or 2.6, an atapi device
3617 // clears its status BSY bit when it is ready for atapi commands.
3618 // However, some devices (Panasonic SQ-TC500N) are still
3619 // not ready even when the status BSY is clear. They don't react
3620 // to atapi commands.
3621 //
3622 // Since there is really no other indication that tells us
3623 // the drive is really ready for action. We are going to check BSY
3624 // is clear and then just wait for an arbitrary amount of time!
3625 //
3626 if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
3627 ULONG waitCount;
3628
3629 // have to get out of the loop sometime!
3630 // 10000 * 100us = 1000,000us = 1000ms = 1s
3631 waitCount = 10000;
3632 GetStatus(chan, statusByte);
3633 if(statusByte == IDE_STATUS_WRONG) {
3634 waitCount = 0;
3635 }
3636 while ((statusByte & IDE_STATUS_BUSY) && waitCount) {
3637
3638 KdPrint2((PRINT_PREFIX "Wait for ATAPI (status %x)\n", statusByte));
3639 // Wait for Busy to drop.
3641 GetStatus(chan, statusByte);
3642 waitCount--;
3643 }
3644
3645 // 5000 * 100us = 500,000us = 500ms = 0.5s
3646 if(statusByte != IDE_STATUS_WRONG) {
3647 waitCount = 5000;
3648 do {
3650 } while (waitCount--);
3651 }
3652 }
3653 GetBaseStatus(chan, statusByte);
3654 AtapiEnableInterrupts(deviceExtension, lChannel);
3656 }
3657
3658 return;
3659
3660} // end AtapiHwInitialize__()
3661
3662
3663#ifndef UNIATA_CORE
3664
3665VOID
3666NTAPI
3668 IN PVOID HwDeviceExtension,
3671{
3672 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3673 ULONG lChannel = GET_CHANNEL(Srb);
3674 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
3676 PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
3677
3678 if (MechanismStatus) {
3679 LunExt->DiscsPresent = MechanismStatus->NumberAvailableSlots;
3680 if (LunExt->DiscsPresent > 1) {
3682 }
3683 }
3684 return;
3685} // end AtapiHwInitializeChanger()
3686
3687
3688/*++
3689
3690Routine Description:
3691 This routine will parse the string for a match on the keyword, then
3692 calculate the value for the keyword and return it to the caller.
3693
3694Arguments:
3695 String - The ASCII string to parse.
3696 KeyWord - The keyword for the value desired.
3697
3698Return Values:
3699 Zero if value not found
3700 Value converted from ASCII to binary.
3701
3702--*/
3703ULONG
3704NTAPI
3706 IN PCCH String,
3707 IN PCCH KeyWord
3708 )
3709{
3710 PCCH cptr;
3711 PCCH kptr;
3712 ULONG value;
3713 ULONG stringLength = 0;
3714 ULONG keyWordLength = 0;
3715 ULONG index;
3716
3717 if (!String) {
3718 return 0;
3719 }
3720 if (!KeyWord) {
3721 return 0;
3722 }
3723
3724 // Calculate the string length and lower case all characters.
3725 cptr = String;
3726 while (*cptr++) {
3727 stringLength++;
3728 }
3729
3730 // Calculate the keyword length.
3731 kptr = KeyWord;
3732 while (*kptr++) {
3733 keyWordLength++;
3734 }
3735
3736 if (keyWordLength > stringLength) {
3737
3738 // Can't possibly have a match.
3739 return 0;
3740 }
3741
3742 // Now setup and start the compare.
3743 cptr = String;
3744
3745ContinueSearch:
3746
3747 // The input string may start with white space. Skip it.
3748 while (*cptr == ' ' || *cptr == '\t') {
3749 cptr++;
3750 }
3751
3752 if (*cptr == '\0') {
3753 // end of string.
3754 return 0;
3755 }
3756
3757 kptr = KeyWord;
3758 while ((*cptr == *kptr) ||
3759 (*cptr >= 'A' && *cptr <= 'Z' && *cptr + ('a' - 'A') == *kptr) ||
3760 (*cptr >= 'a' && *cptr <= 'z' && *cptr - ('a' - 'A') == *kptr)) {
3761 cptr++;
3762 kptr++;
3763
3764 if (*cptr == '\0') {
3765 // end of string
3766 return 0;
3767 }
3768 }
3769
3770 if (*kptr == '\0') {
3771
3772 // May have a match backup and check for blank or equals.
3773 while (*cptr == ' ' || *cptr == '\t') {
3774 cptr++;
3775 }
3776
3777 // Found a match. Make sure there is an equals.
3778 if (*cptr != '=') {
3779
3780 // Not a match so move to the next semicolon.
3781 while (*cptr) {
3782 if (*cptr++ == ';') {
3783 goto ContinueSearch;
3784 }
3785 }
3786 return 0;
3787 }
3788 // Skip the equals sign.
3789 cptr++;
3790
3791 // Skip white space.
3792 while ((*cptr == ' ') || (*cptr == '\t')) {
3793 cptr++;
3794 }
3795
3796 if (*cptr == '\0') {
3797 // Early end of string, return not found
3798 return 0;
3799 }
3800
3801 if (*cptr == ';') {
3802 // This isn't it either.
3803 cptr++;
3804 goto ContinueSearch;
3805 }
3806
3807 value = 0;
3808 if ((*cptr == '0') && ((*(cptr + 1) == 'x') || (*(cptr + 1) == 'X'))) {
3809 // Value is in Hex. Skip the "0x"
3810 cptr += 2;
3811 for (index = 0; *(cptr + index); index++) {
3812
3813 if (*(cptr + index) == ' ' ||
3814 *(cptr + index) == '\t' ||
3815 *(cptr + index) == ';') {
3816 break;
3817 }
3818
3819 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
3820 value = (16 * value) + (*(cptr + index) - '0');
3821 } else {
3822 if ((*(cptr + index) >= 'a') && (*(cptr + index) <= 'f')) {
3823 value = (16 * value) + (*(cptr + index) - 'a' + 10);
3824 } else if ((*(cptr + index) >= 'A') && (*(cptr + index) <= 'F')) {
3825 value = (16 * value) + (*(cptr + index) - 'A' + 10);
3826 } else {
3827 // Syntax error, return not found.
3828 return 0;
3829 }
3830 }
3831 }
3832 } else {
3833
3834 // Value is in Decimal.
3835 for (index = 0; *(cptr + index); index++) {
3836
3837 if (*(cptr + index) == ' ' ||
3838 *(cptr + index) == '\t' ||
3839 *(cptr + index) == ';') {
3840 break;
3841 }
3842
3843 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
3844 value = (10 * value) + (*(cptr + index) - '0');
3845 } else {
3846
3847 // Syntax error return not found.
3848 return 0;
3849 }
3850 }
3851 }
3852
3853 return value;
3854 } else {
3855
3856 // Not a match check for ';' to continue search.
3857 while (*cptr) {
3858 if (*cptr++ == ';') {
3859 goto ContinueSearch;
3860 }
3861 }
3862
3863 return 0;
3864 }
3865} // end AtapiParseArgumentString()_
3866
3867/*
3868 Timer callback
3869*/
3870VOID
3871NTAPI
3873 IN PVOID HwDeviceExtension,
3874 IN UCHAR lChannel
3875 )
3876{
3877
3878 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3879 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
3880 ULONG c, _c;
3881
3883 UCHAR statusByte;
3884
3885 KdPrint2((PRINT_PREFIX "AtapiCallBack:\n"));
3886 // If the last command was DSC restrictive, see if it's set. If so, the device is
3887 // ready for a new request. Otherwise, reset the timer and come back to here later.
3888
3889 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3890 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3891 // we shall have no problem with interrupt handler.
3892 if (!srb || chan->ExpectingInterrupt) {
3893 KdPrint2((PRINT_PREFIX "AtapiCallBack: Calling ISR directly due to BUSY\n"));
3894 chan->DpcState = DPC_STATE_TIMER;
3895 if(!AtapiInterrupt__(HwDeviceExtension, lChannel)) {
3897 KdPrint2((PRINT_PREFIX "AtapiCallBack: What's fucking this ???\n"));
3898 }
3899 goto ReturnCallback;
3900 }
3901
3902#ifdef _DEBUG
3903 if (!IS_RDP((srb->Cdb[0]))) {
3904 KdPrint2((PRINT_PREFIX "AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb->Cdb[0]));
3905 }
3906#endif
3907 if(!(chan->RDP)) {
3908 goto ReturnEnableIntr;
3909 }
3910 GetStatus(chan, statusByte);
3911 if (statusByte & IDE_STATUS_DSC) {
3912
3913 UCHAR PathId = srb->PathId;
3914 UCHAR TargetId = srb->TargetId;
3915 UCHAR Lun = srb->Lun;
3916
3917 KdPrint2((PRINT_PREFIX "AtapiCallBack: Found DSC for RDP - %#x\n", srb->Cdb[0]));
3918 AtapiDmaDBSync(chan, srb);
3919 UniataRemoveRequest(chan, srb);
3920 ScsiPortNotification(RequestComplete, deviceExtension, srb);
3921 // Clear current SRB.
3922 if(!deviceExtension->simplexOnly) {
3923 srb = UniataGetCurRequest(chan);
3924 } else {
3925 srb = NULL;
3926 }
3927 chan->RDP = FALSE;
3928
3929 // Ask for next request.
3931 deviceExtension,
3932 PathId,
3933 TargetId,
3934 Lun);
3935 ScsiPortNotification(NextRequest, deviceExtension, NULL);
3936
3937 if(srb) {
3938 AtapiStartIo__(HwDeviceExtension, srb, FALSE);
3939 }
3940
3941 } else {
3942 KdPrint2((PRINT_PREFIX "AtapiCallBack: Requesting another timer for Op %#x\n",
3943 srb->Cdb[0]));
3944
3945 AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
3947 1000);
3948
3949 goto ReturnCallback;
3950 }
3951
3952ReturnEnableIntr:
3953
3954 if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) {
3955 KdPrint2((PRINT_PREFIX "AtapiCallBack: CallDisableInterrupts\n"));
3956 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3957#ifdef UNIATA_USE_XXableInterrupts
3959 // must be called on DISPATCH_LEVEL
3962#else
3963 AtapiEnableInterrupts(HwDeviceExtension, lChannel);
3966 // Will raise IRQL to DIRQL
3967 AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
3969 1);
3970 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
3971#endif // UNIATA_USE_XXableInterrupts
3972 } else {
3973 //ASSERT(!deviceExtension->simplexOnly);
3974 }
3975
3976ReturnCallback:
3977
3978 // Check other channel
3979 // In simplex mode no interrupts must appear on other channels
3980 for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
3981 c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
3982
3983 if(c == lChannel) {
3984 continue;
3985 }
3986
3987 chan = &(deviceExtension->chan[c]);
3988
3989 if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr),
3992 {
3993 //ASSERT(!deviceExtension->simplexOnly);
3994 chan->DpcState = DPC_STATE_ISR;
3995 if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
3997 }
3998 }
3999 }
4000 KdPrint2((PRINT_PREFIX "AtapiCallBack: return\n"));
4001 return;
4002
4003} // end AtapiCallBack__()
4004
4005VOID
4006NTAPI
4008 IN PVOID HwDeviceExtension
4009 )
4010{
4011 AtapiCallBack__(HwDeviceExtension, (UCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->ActiveDpcChan);
4012} // end AtapiCallBack_X()
4013
4014#endif //UNIATA_CORE
4015
4016/*++
4017
4018Routine Description:
4019
4020 This is the interrupt service routine for ATAPI IDE miniport driver.
4021
4022Arguments:
4023
4024 HwDeviceExtension - HBA miniport driver's adapter data storage
4025
4026Return Value:
4027
4028 TRUE if expecting an interrupt.
4029
4030--*/
4031BOOLEAN
4032NTAPI
4034 IN PVOID HwDeviceExtension
4035 )
4036{
4037 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4038 ULONG c, _c;
4040 ULONG c_state;
4041 ULONG i_res = 0;
4042 ULONG pass;
4043 //BOOLEAN checked[AHCI_MAX_PORT];
4044 ULONG hIS;
4045 ULONG checked;
4046
4047 KdPrint2((PRINT_PREFIX "Intr: DeviceID+VendorID/Rev %#x/%#x (ex %d)\n",
4048 deviceExtension->DevID, deviceExtension->RevID, deviceExtension->ExpectingInterrupt ));
4049
4050 if(deviceExtension->HwFlags & UNIATA_AHCI) {
4051 // AHCI may generate state change notification, never skip this check
4052 hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
4053 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
4054 if(!hIS) {
4055 return FALSE;
4056 }
4057 // assume all non-interrupted ports to be already checked
4058 checked = ~hIS;
4059 // assume all not implemented ports to be already checked
4060 checked |= ~deviceExtension->AHCI_PI;
4061 } else {
4062 checked = 0; // assume all ports are not checked
4063 }
4064
4065 if(!deviceExtension->ExpectingInterrupt) {
4066 // if we do not expect interrupt, exit now,
4067 // but keep in mind that it can be unexpected one
4068 // Note: this is just a hint, not exact counter
4069 KdPrint2((PRINT_PREFIX "unexpected, 1st chance\n"));
4070 //deviceExtension->ExpectingInterrupt++;
4071 //return FALSE;
4072 }
4073 // clear this flag now, it can be set again in sub-calls
4074 deviceExtension->ExpectingInterrupt=0;
4075
4076
4077// for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
4078// checked[_c] = (UCHAR)((hIS >> _c) & 0x01);
4079// }
4080
4081// fc =
4082 for(pass=0; pass<2; pass++) {
4083 //KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): pass %d\n", pass));
4084 if(status && pass) {
4085 // we catched some expected interrupts now.
4086 // do not touch unexpected until next ISR call
4087 break;
4088 }
4089 for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
4090
4091 c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
4092
4093 if((checked>>c) & 0x01)
4094 continue;
4095
4096 // check non-empty and expecting interrupt channels first
4097 if(!pass && !deviceExtension->chan[c].ExpectingInterrupt)
4098 continue;
4099
4100 checked |= (ULONG)1 << c;
4101
4102 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
4103
4104 if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
4105 // we get here on idle channels or when ISR is posted to DPC
4106 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): disabled INTR on ch %d\n", c));
4107 continue;
4108 }
4109 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
4110 do {
4111 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): try lock\n"));
4112 // c_state = deviceExtension->chan[c].CheckIntr;
4113 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
4114 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
4115 // }
4116 c_state =
4117 (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
4120 if(c_state == CHECK_INTR_IDLE) {
4121 // c_state = deviceExtension->chan[c].CheckIntr;
4122 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
4123 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
4124 // }
4125 c_state =
4126 (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
4129 }
4130 } while(c_state == CHECK_INTR_CHECK);
4131 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): locked\n"));
4132 // check if already serviced
4133 if(c_state == CHECK_INTR_ACTIVE) {
4134 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
4135 continue;
4136 }
4137
4138 if((c_state == CHECK_INTR_DETECTED) ||
4139 (i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
4140
4141 if(i_res == INTERRUPT_REASON_UNEXPECTED) {
4142 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): Catch unexpected\n"));
4143 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4144 //return TRUE;
4145 status = TRUE;
4146 continue;
4147 }
4148 // disable interrupts on other channel of legacy mode
4149 // ISA-bridged onboard controller
4150 if(deviceExtension->simplexOnly /*||
4151 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
4152 AtapiDisableInterrupts(deviceExtension, !c);
4153 }
4154
4155 deviceExtension->chan[c].DpcState = DPC_STATE_ISR;
4156 if(AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
4157 deviceExtension->LastInterruptedChannel = (UCHAR)c;
4158 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): return status TRUE\n"));
4159 status = TRUE;
4160 } else {
4161 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
4162 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4163 }
4164
4165 // re-enable interrupts on other channel
4166 if(deviceExtension->simplexOnly /*||
4167 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
4168 AtapiEnableInterrupts(deviceExtension, !c);
4169 }
4170
4171 } else {
4172 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
4173 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4174 }
4175
4176 }
4177 }
4178 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): exit with status %#x\n", status));
4179 if(status) {
4180 deviceExtension->FirstChannelToCheck++;
4181 if(deviceExtension->FirstChannelToCheck >= deviceExtension->NumberChannels)
4182 deviceExtension->FirstChannelToCheck = 0;
4183 }
4184 return status;
4185} // end AtapiInterrupt()
4186
4187//ULONG i2c = 0;
4188#ifndef UNIATA_CORE
4189
4190BOOLEAN
4191NTAPI
4194 IN PVOID Isr2HwDeviceExtension
4195 )
4196{
4197 // This ISR is intended to catch interrupts when we are already in other ISR instance
4198 // for the same device. This may happen when we have multiple channels,
4199 // especially on SMP machines
4200
4201 PISR2_DEVICE_EXTENSION Isr2DeviceExtension = (PISR2_DEVICE_EXTENSION)Isr2HwDeviceExtension;
4202 PHW_DEVICE_EXTENSION deviceExtension = Isr2DeviceExtension->HwDeviceExtension;
4203 ULONG c;
4205 ULONG c_count = 0;
4206 ULONG i_res;
4207 ULONG hIS;
4208 ULONG checked;
4209
4210 // we should never get here for ISA/MCA
4211 if(!BMList[deviceExtension->DevIndex].Isr2Enable) {
4212 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension->DevIndex, deviceExtension->Channel));
4213 return FALSE;
4214 }
4215
4216 if(deviceExtension->HwFlags & UNIATA_AHCI) {
4217 // AHCI may generate state change notification, never skip this check
4218 hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
4219 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
4220 if(!hIS) {
4221 return FALSE;
4222 }
4223 // assume all non-interrupted ports to be already checked
4224 checked = ~hIS;
4225 // assume all not implemented ports to be already checked
4226 checked |= ~deviceExtension->AHCI_PI;
4227
4228 } else {
4229 checked = 0; // assume all ports are not checked
4230 }
4231 if(!deviceExtension->ExpectingInterrupt) {
4232 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !deviceExtension->ExpectingInterrupt\n"));
4233 deviceExtension->ExpectingInterrupt++;
4234 return FALSE;
4235 }
4236 //deviceExtension->ExpectingInterrupt = 0;
4237
4238 for(c=0; c<deviceExtension->NumberChannels; c++) {
4239 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
4240
4241 if((checked>>c) & 0x01)
4242 continue;
4243
4244 checked |= (ULONG)1 << c;
4245
4246 if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
4247 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: disabled INTR\n"));
4248 continue;
4249 }
4250
4251 if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
4254 {
4255 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
4256 // hunt on unexpected intr (Some devices generate double interrupts,
4257 // some controllers (at least CMD649) interrupt twice with small delay.
4258 // If interrupts are disabled, they queue interrupt and re-issue it later,
4259 // when we do not expect it.
4260 continue;
4261 }
4262
4263 c_count++;
4264 if((i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
4265
4266 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: intr\n"));
4267 if(i_res == INTERRUPT_REASON_UNEXPECTED) {
4268 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: Catch unexpected\n"));
4269 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4270 return TRUE;
4271 }
4272
4273 status = TRUE;
4275 } else {
4276 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4277 }
4278 }
4279 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: status %d, c_count %d\n", status, c_count));
4280 if(status && (c_count != deviceExtension->NumberChannels)) {
4281 // there is an active ISR/DPC for one channel, but
4282 // we have an interrupt from another one
4283 // Lets inform current ISR/DPC about new interrupt
4285 } else {
4286 status = FALSE;
4287 }
4288 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: return %d\n", status));
4289 return status;
4290
4291} // end AtapiInterrupt2()
4292
4294NTAPI
4296 IN PVOID HwDeviceExtension
4297 )
4298{
4299 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4300 ULONG c;
4301
4302 for(c=0; c<deviceExtension->NumberChannels; c++) {
4303 KdPrint2((PRINT_PREFIX "AtapiInterruptDpc: %#x\n",c));
4304
4305 if(!(deviceExtension->chan[c].ChannelCtrlFlags & CTRFLAGS_DPC_REQ)) {
4306
4307 if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
4310 {
4311 continue;
4312 }
4313
4314 } else {
4315 deviceExtension->chan[c].ChannelCtrlFlags &= ~CTRFLAGS_DPC_REQ;
4316 }
4317/*
4318 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
4319 AtapiDisableInterrupts(deviceExtension, lChannel);
4320 }
4321*/
4322 deviceExtension->chan[c].DpcState = DPC_STATE_DPC;
4323 if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
4324 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
4325 }
4326 }
4328} // end AtapiInterruptDpc()
4329
4330
4332NTAPI
4334 IN PVOID HwDeviceExtension
4335 )
4336{
4337 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4338 KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__():\n"));
4339 ULONG c;
4340 PHW_CHANNEL chan = NULL;
4341
4342 for(c=0; c<deviceExtension->NumberChannels; c++) {
4343 KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__(2): %#x\n",c));
4344 chan = &(deviceExtension->chan[c]);
4345
4347 // enable intrs on requested channel
4348 chan->ChannelCtrlFlags &= ~CTRFLAGS_ENABLE_INTR_REQ;
4349 AtapiEnableInterrupts(HwDeviceExtension, c);
4352
4353 // check if current or other channel(s) interrupted
4354 //AtapiInterrupt(HwDeviceExtension);
4355
4356 if(deviceExtension->simplexOnly) {
4357 break;
4358 }
4359 } else {
4360 // check if other channel(s) interrupted
4361 // must do nothing in simplex mode
4362 if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr),
4365 continue;
4366 }
4367 //ASSERT(!deviceExtension->simplexOnly);
4368 chan->DpcState = DPC_STATE_ISR;
4369 if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)