3 Copyright (c) 2002-2007 Alexandr A. Telyatnikov (Alter)
9 This is the miniport driver for ATA/ATAPI IDE controllers
10 with Busmaster DMA and Serial ATA support
13 Alexander A. Telyatnikov (Alter)
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.
33 The skeleton was taken from standard ATAPI.SYS from NT4 DDK by
37 Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by
38 Søren Schmidt, Copyright (c) 1998-2007
40 All parts of code are greatly changed/updated by
41 Alter, Copyright (c) 2002-2007:
43 1. Internal command queueing/reordering
44 2. Drive identification
45 3. Support for 2 _independent_ channels in a single PCI device
46 4. Smart host<->drive transfer rate slowdown (for bad cable)
47 5. W2k support (binary compatibility)
48 6. HDD hot swap under NT4
49 7. XP support (binary compatibility)
50 8. Serial ATA (SATA/SATA2) support
51 9. NT 3.51 support (binary compatibility)
62 static const CHAR ver_string
[] = "\n\nATAPI IDE MiniPort Driver (UniATA) v 0." UNIATA_VER_STR
"\n";
64 UNICODE_STRING SavedRegPath
;
65 WCHAR SavedRegPathBuffer
[256];
69 UCHAR AtaCommands48
[256];
70 UCHAR AtaCommandFlags
[256];
73 ULONG ForceSimplex
= 0;
79 ULONG g_LogToDisplay
= 0;
82 ULONG g_WaitBusyInISR
= 1;
84 BOOLEAN InDriverEntry
= TRUE
;
86 BOOLEAN g_opt_Verbose
= 0;
88 //UCHAR EnableDma = FALSE;
89 //UCHAR EnableReorder = FALSE;
95 AtapiResetController__(
96 IN PVOID HwDeviceExtension
,
103 IN PHW_DEVICE_EXTENSION deviceExtension
,
107 #define RESET_COMPLETE_CURRENT 0x00
108 #define RESET_COMPLETE_ALL 0x01
109 #define RESET_COMPLETE_NONE 0x02
116 IN PVOID HwDeviceExtension
119 #ifdef UNIATA_USE_XXableInterrupts
120 #define RETTYPE_XXableInterrupts BOOLEAN
121 #define RETVAL_XXableInterrupts TRUE
123 #define RETTYPE_XXableInterrupts VOID
124 #define RETVAL_XXableInterrupts
127 RETTYPE_XXableInterrupts
130 IN PVOID HwDeviceExtension
133 RETTYPE_XXableInterrupts
135 AtapiEnableInterrupts__(
136 IN PVOID HwDeviceExtension
141 IN PVOID HwDeviceExtension
,
143 IN PHW_TIMER HwScsiTimer
,
144 IN ULONG MiniportTimerValue
147 SCSI_ADAPTER_CONTROL_STATUS
150 IN PVOID HwDeviceExtension
,
151 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
158 AtapiCheckInterrupt__(
159 IN PVOID HwDeviceExtension
,
167 AtapiRegGetStringParameterValue(
168 IN PWSTR RegistryPath
,
174 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
176 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
181 ustr
.MaximumLength
= (USHORT
)MaxLen
;
182 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
184 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
185 parameters
[0].Name
= Name
;
186 parameters
[0].EntryContext
= &ustr
;
187 parameters
[0].DefaultType
= REG_SZ
;
188 parameters
[0].DefaultData
= Str
;
189 parameters
[0].DefaultLength
= MaxLen
;
191 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
192 RegistryPath
, parameters
, NULL
, NULL
);
194 if(!NT_SUCCESS(status
))
199 #undef ITEMS_TO_QUERY
200 } // end AtapiRegGetStringParameterValue()
214 if(!nano
|| !g_Perf
|| !g_PerfDt
)
216 t
= (g_Perf
* nano
) / g_PerfDt
/ 1000;
221 KeQuerySystemTime(&t0
);
224 } // end UniataNanoSleep()
227 #define AtapiWritePortN_template(_type, _Type, sz) \
230 AtapiWritePort##sz( \
231 IN PHW_CHANNEL chan, \
237 if(_port >= IDX_MAX_REG) { \
238 res = (PIORES)(_port); \
241 res = &chan->RegTranslation[_port]; \
243 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
247 ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
249 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
250 ScsiPortWriteRegister##_Type((_type*)(res->Addr), data); \
255 AtapiWritePortN_template(ULONG
, Ulong
, 4);
256 AtapiWritePortN_template(USHORT
, Ushort
, 2);
257 AtapiWritePortN_template(UCHAR
, Uchar
, 1);
259 #define AtapiWritePortExN_template(_type, _Type, sz) \
262 AtapiWritePortEx##sz( \
263 IN PHW_CHANNEL chan, \
270 if(_port >= IDX_MAX_REG) { \
271 res = (PIORES)(_port); \
274 res = &chan->RegTranslation[_port]; \
276 KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
280 ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
282 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
283 ScsiPortWriteRegister##_Type((_type*)(res->Addr+offs), data); \
288 AtapiWritePortExN_template(ULONG
, Ulong
, 4);
289 //AtapiWritePortExN_template(USHORT, Ushort, 2);
290 AtapiWritePortExN_template(UCHAR
, Uchar
, 1);
292 #define AtapiReadPortN_template(_type, _Type, sz) \
296 IN PHW_CHANNEL chan, \
301 if(_port >= IDX_MAX_REG) { \
302 res = (PIORES)(_port); \
305 res = &chan->RegTranslation[_port]; \
307 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
308 return (_type)(-1); \
311 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
312 return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
314 /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
315 return ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
319 AtapiReadPortN_template(ULONG
, Ulong
, 4);
320 AtapiReadPortN_template(USHORT
, Ushort
, 2);
321 AtapiReadPortN_template(UCHAR
, Uchar
, 1);
323 #define AtapiReadPortExN_template(_type, _Type, sz) \
326 AtapiReadPortEx##sz( \
327 IN PHW_CHANNEL chan, \
333 if(_port >= IDX_MAX_REG) { \
334 res = (PIORES)(_port); \
337 res = &chan->RegTranslation[_port]; \
339 KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
340 return (_type)(-1); \
343 return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
345 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
346 return ScsiPortReadRegister##_Type((_type*)(res->Addr+offs)); \
350 AtapiReadPortExN_template(ULONG
, Ulong
, 4);
351 //AtapiReadPortExN_template(USHORT, Ushort, 2);
352 AtapiReadPortExN_template(UCHAR
, Uchar
, 1);
354 #define AtapiReadPortBufferN_template(type, Type, sz) \
357 AtapiReadBuffer##sz( \
358 IN PHW_CHANNEL chan, \
367 ((type*)Buffer)[i] = AtapiReadPort##sz(chan, _port); \
370 UniataNanoSleep(Timing); \
375 #define AtapiWritePortBufferN_template(type, Type, sz) \
378 AtapiWriteBuffer##sz( \
379 IN PHW_CHANNEL chan, \
388 AtapiWritePort##sz(chan, _port, ((type*)Buffer)[i]); \
391 UniataNanoSleep(Timing); \
396 AtapiWritePortBufferN_template(ULONG
, Ulong
, 4);
397 AtapiWritePortBufferN_template(USHORT
, Ushort
, 2);
399 AtapiReadPortBufferN_template(ULONG
, Ulong
, 4);
400 AtapiReadPortBufferN_template(USHORT
, Ushort
, 2);
412 WaitOnBusyLong(chan
);
413 for (i
= 0; i
< 0x10000; i
++) {
415 GetStatus(chan
, statusByte
);
416 if (statusByte
& IDE_STATUS_DRQ
) {
417 // Suck out any remaining bytes and throw away.
418 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
424 KdPrint2((PRINT_PREFIX
"AtapiSuckPort2: overrun detected (%#x words)\n", i
));
427 } // AtapiSuckPort2()
437 for (i
=0; i
<200; i
++) {
438 GetStatus(chan
, Status
);
439 if (Status
& IDE_STATUS_BUSY
) {
440 AtapiStallExecution(10);
447 } // end WaitOnBusy()
458 Status
= WaitOnBusy(chan
);
459 if(!(Status
& IDE_STATUS_BUSY
))
461 for (i
=0; i
<2000; i
++) {
462 GetStatus(chan
, Status
);
463 if (Status
& IDE_STATUS_BUSY
) {
464 AtapiStallExecution(250);
471 } // end WaitOnBusyLong()
481 for (i
=0; i
<200; i
++) {
482 GetBaseStatus(chan
, Status
);
483 if (Status
& IDE_STATUS_BUSY
) {
484 AtapiStallExecution(10);
491 } // end WaitOnBaseBusy()
502 Status
= WaitOnBaseBusy(chan
);
503 if(!(Status
& IDE_STATUS_BUSY
))
505 for (i
=0; i
<2000; i
++) {
506 GetBaseStatus(chan
, Status
);
507 if (Status
& IDE_STATUS_BUSY
) {
508 AtapiStallExecution(250);
515 } // end WaitOnBaseBusyLong()
520 IN
struct _HW_DEVICE_EXTENSION
* deviceExtension
,
529 if(Status
& IDE_STATUS_BUSY
) {
532 // if(deviceExtension->HwFlags & UNIATA_SATA) {
533 if(deviceExtension
->BaseIoAddressSATA_0
.Addr
) {
534 if(Status
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
538 Status2
= Status
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
);
539 if ((Status
& IDE_STATUS_BUSY
) ||
540 (Status2
!= IDE_STATUS_IDLE
&& Status2
!= IDE_STATUS_DRDY
)) {
544 return IDE_STATUS_IDLE
;
545 } // end UniataIsIdle()
556 for (i
=0; i
<20000; i
++) {
557 GetStatus(chan
, Status
);
558 Status2
= UniataIsIdle(chan
->DeviceExtension
, Status
);
559 if(Status2
== 0xff) {
563 if(Status2
& IDE_STATUS_BUSY
) {
564 AtapiStallExecution(10);
571 } // end WaitForIdleLong()
581 for (i
=0; i
<1000; i
++) {
582 GetStatus(chan
, Status
);
583 if (Status
& IDE_STATUS_BUSY
) {
584 AtapiStallExecution(10);
585 } else if (Status
& IDE_STATUS_DRQ
) {
588 AtapiStallExecution(10);
592 } // end WaitForDrq()
602 for (i
=0; i
<2; i
++) {
603 GetStatus(chan
, Status
);
604 if (Status
& IDE_STATUS_BUSY
) {
605 AtapiStallExecution(10);
606 } else if (Status
& IDE_STATUS_DRQ
) {
609 AtapiStallExecution(10);
613 } // end WaitShortForDrq()
622 //ULONG c = chan->lChannel;
624 UCHAR dma_status
= 0;
625 KdPrint2((PRINT_PREFIX
"AtapiSoftReset:\n"));
628 GetBaseStatus(chan
, statusByte2
);
629 KdPrint2((PRINT_PREFIX
" statusByte2 %x:\n", statusByte2
));
630 SelectDrive(chan
, DeviceNumber
);
631 AtapiStallExecution(10000);
632 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_RESET
);
633 for (i
= 0; i
< 1000; i
++) {
634 AtapiStallExecution(999);
636 SelectDrive(chan
, DeviceNumber
);
638 GetBaseStatus(chan
, statusByte2
);
639 AtapiStallExecution(500);
641 GetBaseStatus(chan
, statusByte2
);
642 if(chan
&& chan
->DeviceExtension
) {
643 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
644 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
646 KdPrint2((PRINT_PREFIX
" can't get DMA status\n"));
648 if(dma_status
& BM_STATUS_INTR
) {
649 // bullshit, we have DMA interrupt, but had never initiate DMA operation
650 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr on ATAPI reset\n"));
651 AtapiDmaDone(chan
->DeviceExtension
, DeviceNumber
, chan
->lChannel
, NULL
);
652 GetBaseStatus(chan
, statusByte2
);
654 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
655 UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
);
659 } // end AtapiSoftReset()
662 Send command to device.
663 Translate to 48-Lba form if required
667 IN PHW_DEVICE_EXTENSION deviceExtension
,
668 IN ULONG DeviceNumber
,
677 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
679 ULONG ldev
= lChannel
*2 + DeviceNumber
;
683 KdPrint2((PRINT_PREFIX
"AtaCommand48: cntrlr %#x:%#x ldev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
684 deviceExtension
->DevIndex
, deviceExtension
->Channel
, ldev
, command
, lba
, count
, feature
));
686 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
687 SelectDrive(chan
, DeviceNumber
);
689 statusByte
= WaitOnBusy(chan
);
691 /* ready to issue command ? */
692 if (statusByte
& IDE_STATUS_BUSY
) {
693 KdPrint2((PRINT_PREFIX
" Returning BUSY status\n"));
697 // !!! We should not check ERROR condition here
698 // ERROR bit may be asserted durring previous operation
699 // and not cleared after SELECT
701 //>>>>>> NV: 2006/08/03
702 if((AtaCommandFlags
[command
] & ATA_CMD_FLAG_LBAIOsupp
) &&
703 CheckIfBadBlock(&(deviceExtension
->lun
[ldev
]), lba
, count
)) {
704 KdPrint2((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
705 return IDE_STATUS_ERROR
;
706 //return SRB_STATUS_ERROR;
708 //<<<<<< NV: 2006/08/03
710 /* only use 48bit addressing if needed because of the overhead */
711 if ((lba
>= ATA_MAX_LBA28
|| count
> 256) &&
712 deviceExtension
->lun
[ldev
].IdentifyData
.FeaturesSupport
.Address48
) {
714 KdPrint2((PRINT_PREFIX
" ldev %#x USE_LBA_48\n", ldev
));
715 /* translate command into 48bit version */
716 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
717 command
= AtaCommands48
[command
];
719 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
723 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
726 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)(feature
>>8) & 0xff);
727 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
728 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)(count
>>8) & 0xff);
729 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
& 0xff);
730 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[3]));
731 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[0]));
732 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[4]));
733 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[1]));
734 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[5]));
735 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[2]));
737 //KdPrint2((PRINT_PREFIX "AtaCommand48: ldev %#x USE_LBA48 (2)\n", ldev ));
738 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
) );
741 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
744 // (deviceExtension->lun[ldev].DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
745 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
747 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
748 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)lba
& 0xff);
749 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(lba
>>8) & 0xff);
750 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(lba
>>16) & 0xff);
751 if(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_LBA_ENABLED
) {
752 //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_LBA\n", ldev ));
753 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)((lba
>>24) & 0xf) | IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
755 //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_CHS\n", ldev ));
756 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)((lba
>>24) & 0xf) | (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
760 // write command code to device
761 AtapiWritePort1(chan
, IDX_IO1_o_Command
, command
);
766 // caller requested wait for interrupt
769 statusByte
= WaitForDrq(chan
);
770 if (statusByte
& IDE_STATUS_DRQ
)
772 AtapiStallExecution(500);
773 KdPrint2((PRINT_PREFIX
" retry waiting DRQ, status %#x\n", statusByte
));
780 // caller requested wait for entering Wait state
781 for (i
=0; i
<30 * 1000; i
++) {
783 GetStatus(chan
, statusByte
);
784 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
785 if(statusByte
== 0xff) {
789 if(statusByte
& IDE_STATUS_ERROR
) {
792 if(statusByte
& IDE_STATUS_BUSY
) {
793 AtapiStallExecution(100);
796 if(statusByte
== IDE_STATUS_IDLE
) {
799 //if(deviceExtension->HwFlags & UNIATA_SATA) {
800 if(deviceExtension
->BaseIoAddressSATA_0
.Addr
) {
803 AtapiStallExecution(100);
806 //statusByte |= IDE_STATUS_BUSY;
810 statusByte
= WaitOnBusyLong(chan
);
812 case ATA_WAIT_BASE_READY
:
813 statusByte
= WaitOnBaseBusyLong(chan
);
816 GetStatus(chan
, statusByte
);
817 if (statusByte
& IDE_STATUS_ERROR
) {
818 KdPrint2((PRINT_PREFIX
" Warning: Immed Status %#x :(\n", statusByte
));
819 if(statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_ERROR
)) {
822 KdPrint2((PRINT_PREFIX
" try to continue\n"));
823 statusByte
&= ~IDE_STATUS_ERROR
;
825 chan
->ExpectingInterrupt
= TRUE
;
827 InterlockedExchange(&(chan
->CheckIntr
),
833 KdPrint2((PRINT_PREFIX
" Status %#x\n", statusByte
));
836 } // end AtaCommand48()
839 Send command to device.
840 This is simply wrapper for AtaCommand48()
844 IN PHW_DEVICE_EXTENSION deviceExtension
,
845 IN ULONG DeviceNumber
,
856 return AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
858 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
859 count
, feature
, flags
);
860 } // end AtaCommand()
863 AtaPio2Mode(LONG pio
)
866 default: return ATA_PIO
;
867 case 0: return ATA_PIO0
;
868 case 1: return ATA_PIO1
;
869 case 2: return ATA_PIO2
;
870 case 3: return ATA_PIO3
;
871 case 4: return ATA_PIO4
;
872 case 5: return ATA_PIO5
;
874 } // end AtaPio2Mode()
877 AtaPioMode(PIDENTIFY_DATA2 ident
)
879 if (ident
->PioTimingsValid
) {
880 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_5
)
882 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_4
)
884 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_3
)
887 if (ident
->PioCycleTimingMode
== 2)
889 if (ident
->PioCycleTimingMode
== 1)
891 if (ident
->PioCycleTimingMode
== 0)
894 } // end AtaPioMode()
897 AtaWmode(PIDENTIFY_DATA2 ident
)
899 if (ident
->MultiWordDMASupport
& 0x04)
901 if (ident
->MultiWordDMASupport
& 0x02)
903 if (ident
->MultiWordDMASupport
& 0x01)
909 AtaUmode(PIDENTIFY_DATA2 ident
)
911 if (!ident
->UdmaModesValid
)
913 if (ident
->UltraDMASupport
& 0x40)
915 if (ident
->UltraDMASupport
& 0x20)
917 if (ident
->UltraDMASupport
& 0x10)
919 if (ident
->UltraDMASupport
& 0x08)
921 if (ident
->UltraDMASupport
& 0x04)
923 if (ident
->UltraDMASupport
& 0x02)
925 if (ident
->UltraDMASupport
& 0x01)
936 IN PVOID HwDeviceExtension
939 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
940 PHW_TIMER HwScsiTimer
;
942 ULONG MiniportTimerValue
;
943 BOOLEAN recall
= FALSE
;
947 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc:\n"));
949 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
950 if(lChannel
== (ULONG
)-1) {
951 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no items\n"));
954 chan
= &deviceExtension
->chan
[lChannel
];
958 HwScsiTimer
= chan
->HwScsiTimer
;
959 chan
->HwScsiTimer
= NULL
;
961 deviceExtension
->FirstDpcChan
= chan
->NextDpcChan
;
962 if(deviceExtension
->FirstDpcChan
!= (ULONG
)-1) {
966 HwScsiTimer(HwDeviceExtension
);
968 chan
->NextDpcChan
= -1;
970 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
971 if(lChannel
== (ULONG
)-1) {
972 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no more items\n"));
973 deviceExtension
->FirstDpcChan
=
974 deviceExtension
->ActiveDpcChan
= -1;
978 KeQuerySystemTime(&time
);
979 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
981 chan
= &deviceExtension
->chan
[lChannel
];
982 if(time
.QuadPart
>= chan
->DpcTime
- 10) {
984 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
985 (ULONG
)(chan
->DpcTime
>> 32), (ULONG
)(chan
->DpcTime
)));
992 deviceExtension
->ActiveDpcChan
= -1;
993 MiniportTimerValue
= (ULONG
)(time
.QuadPart
- chan
->DpcTime
)/10;
994 if(!MiniportTimerValue
)
995 MiniportTimerValue
= 1;
997 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: recall AtapiTimerDpc\n"));
998 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1005 } // end AtapiTimerDpc()
1008 Wrapper for ScsiPort, that implements smart Dpc
1009 queueing. We need it to allow parallel functioning
1010 of IDE channles with shared interrupt. Standard Dpc mechanism
1011 cancels previous Dpc request (if any), but we need Dpc queue.
1015 IN PVOID HwDeviceExtension
,
1017 IN PHW_TIMER HwScsiTimer
,
1018 IN ULONG MiniportTimerValue
1021 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1023 LARGE_INTEGER time2
;
1025 PHW_CHANNEL prev_chan
;
1027 // BOOLEAN UseRequestTimerCall = TRUE;
1029 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1030 KeQuerySystemTime(&time
);
1032 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1033 time
.QuadPart
+= MiniportTimerValue
*10;
1034 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1036 KdPrint2((PRINT_PREFIX
" ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension
->ActiveDpcChan
, deviceExtension
->FirstDpcChan
));
1038 i
= deviceExtension
->FirstDpcChan
;
1039 chan
= prev_chan
= NULL
;
1040 while(i
!= (ULONG
)-1) {
1042 chan
= &deviceExtension
->chan
[i
];
1043 if(chan
->DpcTime
> time
.QuadPart
) {
1046 i
= chan
->NextDpcChan
;
1048 chan
= &deviceExtension
->chan
[lChannel
];
1050 deviceExtension
->FirstDpcChan
= lChannel
;
1052 prev_chan
->NextDpcChan
= lChannel
;
1054 chan
->NextDpcChan
= i
;
1055 chan
->HwScsiTimer
= HwScsiTimer
;
1056 chan
->DpcTime
= time
.QuadPart
;
1058 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2
.HighPart
, time2
.LowPart
));
1059 if(time
.QuadPart
<= time2
.QuadPart
) {
1060 MiniportTimerValue
= 1;
1062 MiniportTimerValue
= (ULONG
)((time
.QuadPart
- time2
.QuadPart
) / 10);
1065 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1066 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1068 MiniportTimerValue
);
1070 } // end AtapiQueueTimerDpc()
1072 #endif //UNIATA_CORE
1080 UCHAR statusByteAlt
;
1082 GetStatus(chan
, statusByteAlt
);
1083 KdPrint2((PRINT_PREFIX
" AltStatus (%#x)\n", statusByteAlt
));
1085 for(j
=1; j
<IDX_IO1_SZ
; j
++) {
1086 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1087 KdPrint2((PRINT_PREFIX
1088 " Reg_%#x (%#x) = %#x\n",
1090 chan
->RegTranslation
[IDX_IO1
+j
].Addr
,
1093 for(j
=0; j
<IDX_BM_IO_SZ
-1; j
++) {
1094 statusByteAlt
= AtapiReadPort1(chan
, IDX_BM_IO
+j
);
1095 KdPrint2((PRINT_PREFIX
1096 " BM_%#x (%#x) = %#x\n",
1098 chan
->RegTranslation
[IDX_BM_IO
+j
].Addr
,
1102 } // end UniataDumpATARegs()
1106 Routine Description:
1108 Issue IDENTIFY command to a device.
1112 HwDeviceExtension - HBA miniport driver's adapter data storage
1113 DeviceNumber - Indicates which device.
1114 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1118 TRUE if all goes well.
1123 IN PVOID HwDeviceExtension
,
1124 IN ULONG DeviceNumber
,
1130 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1131 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1132 ULONG waitCount
= 50000;
1138 BOOLEAN atapiDev
= FALSE
;
1139 ULONG ldev
= (lChannel
* 2) + DeviceNumber
;
1140 PHW_LU_EXTENSION LunExt
= &(deviceExtension
->lun
[ldev
]);
1142 if(DeviceNumber
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
1143 KdPrint2((PRINT_PREFIX
"IssueIdentify: NO SLAVE\n"));
1147 SelectDrive(chan
, DeviceNumber
);
1148 AtapiStallExecution(10);
1149 statusByte
= WaitOnBusyLong(chan
);
1150 // Check that the status register makes sense.
1151 GetBaseStatus(chan
, statusByte2
);
1153 UniataDumpATARegs(chan
);
1155 if (Command
== IDE_COMMAND_IDENTIFY
) {
1156 // Mask status byte ERROR bits.
1157 statusByte
= UniataIsIdle(deviceExtension
, statusByte
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
));
1158 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte
));
1159 // Check if register value is reasonable.
1161 if(statusByte
!= IDE_STATUS_IDLE
) {
1163 // No reset here !!!
1164 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1166 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1167 if(!deviceExtension
->BaseIoAddressSATA_0
.Addr
) {
1168 SelectDrive(chan
, DeviceNumber
);
1169 WaitOnBusyLong(chan
);
1171 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1172 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1174 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1175 signatureHigh
== ATAPI_MAGIC_MSB
) {
1177 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (ldev %d)\n", ldev
));
1181 // We really should wait up to 31 seconds
1182 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1183 // (30 seconds for device 1)
1185 // Wait for Busy to drop.
1186 AtapiStallExecution(100);
1187 GetStatus(chan
, statusByte
);
1189 } while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
--);
1190 GetBaseStatus(chan
, statusByte2
);
1192 SelectDrive(chan
, DeviceNumber
);
1194 GetBaseStatus(chan
, statusByte2
);
1196 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1198 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1199 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1201 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1202 signatureHigh
== ATAPI_MAGIC_MSB
) {
1203 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (2) (ldev %d)\n", ldev
));
1208 statusByte
= UniataIsIdle(deviceExtension
, statusByte
) & ~IDE_STATUS_INDEX
;
1209 if (statusByte
!= IDE_STATUS_IDLE
) {
1211 KdPrint2((PRINT_PREFIX
"IssueIdentify: no dev (ldev %d)\n", ldev
));
1216 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte
));
1217 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1218 if(!deviceExtension
->BaseIoAddressSATA_0
.Addr
) {
1219 statusByte
= WaitForIdleLong(chan
);
1220 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte
));
1225 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1226 if(deviceExtension
->BaseIoAddressSATA_0
.Addr
) {
1231 for (; j
< 4*2; j
++) {
1232 // Send IDENTIFY command.
1233 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, Command
, 0, 0, 0, (j
>= 4) ? 0x200 : 0, 0, ATA_WAIT_INTR
);
1236 if (statusByte
& IDE_STATUS_DRQ
) {
1237 // Read status to acknowledge any interrupts generated.
1238 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte
));
1239 GetBaseStatus(chan
, statusByte
);
1240 // One last check for Atapi.
1241 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1242 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1244 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1245 signatureHigh
== ATAPI_MAGIC_MSB
) {
1246 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (3) (ldev %d)\n", ldev
));
1252 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte
));
1253 if (Command
== IDE_COMMAND_IDENTIFY
) {
1254 // Check the signature. If DRQ didn't come up it's likely Atapi.
1255 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1256 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1258 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1259 signatureHigh
== ATAPI_MAGIC_MSB
) {
1261 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (4) (ldev %d)\n", ldev
));
1265 // Device didn't respond correctly. It will be given one more chances.
1266 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1267 statusByte
, AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
1268 GetBaseStatus(chan
, statusByte
);
1269 AtapiSoftReset(chan
,DeviceNumber
);
1271 AtapiDisableInterrupts(deviceExtension
, lChannel
);
1272 AtapiEnableInterrupts(deviceExtension
, lChannel
);
1274 GetBaseStatus(chan
, statusByte
);
1275 //GetStatus(chan, statusByte);
1276 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after soft reset (%#x)\n", statusByte
));
1279 // Check for error on really stupid master devices that assert random
1280 // patterns of bits in the status register at the slave address.
1281 if ((Command
== IDE_COMMAND_IDENTIFY
) && (statusByte
& IDE_STATUS_ERROR
)) {
1282 KdPrint2((PRINT_PREFIX
"IssueIdentify: Exit on error (%#x)\n", statusByte
));
1286 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status before read words %#x\n", statusByte
));
1287 // Suck out 256 words. After waiting for one model that asserts busy
1288 // after receiving the Packet Identify command.
1289 statusByte
= WaitForDrq(chan
);
1290 statusByte
= WaitOnBusyLong(chan
);
1291 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1293 if (!(statusByte
& IDE_STATUS_DRQ
)) {
1294 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte
));
1295 GetBaseStatus(chan
, statusByte
);
1298 GetBaseStatus(chan
, statusByte
);
1299 KdPrint2((PRINT_PREFIX
"IssueIdentify: BASE statusByte %#x\n", statusByte
));
1301 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
1303 KdPrint2((PRINT_PREFIX
" use 16bit IO\n"));
1307 // ATI/SII chipsets with memory-mapped IO hangs when
1308 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1309 // Unfortunately, I don't know yet how to workaround it except the way you see below.
1310 KdPrint2((PRINT_PREFIX
1311 " IO_%#x (%#x), %s:\n",
1313 chan
->RegTranslation
[IDX_IO1_i_Data
].Addr
,
1314 chan
->RegTranslation
[IDX_IO1_i_Data
].MemIo
? "Mem" : "IO"));
1315 for(i
=0; i
<256; i
++) {
1317 KdPrint2((PRINT_PREFIX
1320 chan->RegTranslation[IDX_IO1_i_Data].Addr));
1322 w
= AtapiReadPort2(chan
, IDX_IO1_i_Data
);
1323 KdPrint2((PRINT_PREFIX
1325 AtapiStallExecution(1);
1326 ((PUSHORT
)&deviceExtension
->FullIdentifyData
)[i
] = w
;
1329 ReadBuffer(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256, PIO0_TIMING
);
1331 // Work around for some IDE and one model Atapi that will present more than
1332 // 256 bytes for the Identify data.
1333 KdPrint2((PRINT_PREFIX
"IssueIdentify: suck data port\n", statusByte
));
1334 statusByte
= AtapiSuckPort2(chan
);
1336 KdPrint2((PRINT_PREFIX
" use 32bit IO\n"));
1337 ReadBuffer2(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256/2, PIO0_TIMING
);
1340 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1341 statusByte
= WaitForDrq(chan
);
1342 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1343 GetBaseStatus(chan
, statusByte
);
1345 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after read words %#x\n", statusByte
));
1348 KdPrint2((PRINT_PREFIX
"IssueIdentify: no setup, exiting\n"));
1352 KdPrint2((PRINT_PREFIX
"Model: %20.20s\n", deviceExtension
->FullIdentifyData
.ModelNumber
));
1353 KdPrint2((PRINT_PREFIX
"FW: %4.4s\n", deviceExtension
->FullIdentifyData
.FirmwareRevision
));
1354 KdPrint2((PRINT_PREFIX
"S/N: %20.20s\n", deviceExtension
->FullIdentifyData
.SerialNumber
));
1355 KdPrint2((PRINT_PREFIX
"Pio: %x\n", deviceExtension
->FullIdentifyData
.PioCycleTimingMode
));
1356 if(deviceExtension
->FullIdentifyData
.PioTimingsValid
) {
1357 KdPrint2((PRINT_PREFIX
"APio: %x\n", deviceExtension
->FullIdentifyData
.AdvancedPIOModes
));
1359 KdPrint2((PRINT_PREFIX
"SWDMA: %x\n", deviceExtension
->FullIdentifyData
.SingleWordDMAActive
));
1360 KdPrint2((PRINT_PREFIX
"MWDMA: %x\n", deviceExtension
->FullIdentifyData
.MultiWordDMAActive
));
1361 if(deviceExtension
->FullIdentifyData
.UdmaModesValid
) {
1362 KdPrint2((PRINT_PREFIX
"UDMA: %x\n", deviceExtension
->FullIdentifyData
.UltraDMAActive
));
1364 KdPrint2((PRINT_PREFIX
"SATA: %x\n", deviceExtension
->FullIdentifyData
.SataEnable
));
1366 // Check out a few capabilities / limitations of the device.
1367 if (deviceExtension
->FullIdentifyData
.RemovableStatus
& 1) {
1368 // Determine if this drive supports the MSN functions.
1369 KdPrint2((PRINT_PREFIX
"IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1371 deviceExtension
->FullIdentifyData
.RemovableStatus
));
1372 LunExt
->DeviceFlags
|= DFLAGS_REMOVABLE_DRIVE
;
1374 if (deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
) {
1375 // Determine max. block transfer for this device.
1376 LunExt
->MaximumBlockXfer
=
1377 (UCHAR
)(deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
& 0xFF);
1379 LunExt
->NumOfSectors
= 0;
1380 if (Command
== IDE_COMMAND_IDENTIFY
) {
1381 ULONGLONG NumOfSectors
=0;
1382 ULONGLONG NativeNumOfSectors
=0;
1383 ULONGLONG cylinders
=0;
1384 ULONGLONG tmp_cylinders
=0;
1385 // Read very-old-style drive geometry
1386 KdPrint2((PRINT_PREFIX
"CHS %#x:%#x:%#x\n",
1387 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1388 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1389 deviceExtension
->FullIdentifyData
.SectorsPerTrack
1391 NumOfSectors
= deviceExtension
->FullIdentifyData
.NumberOfCylinders
*
1392 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1393 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1394 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1395 // Check for HDDs > 8Gb
1396 if ((deviceExtension
->FullIdentifyData
.NumberOfCylinders
== 0x3fff) &&
1397 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1398 (NumOfSectors
< deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1399 KdPrint2((PRINT_PREFIX
"NumberOfCylinders == 0x3fff\n"));
1401 (deviceExtension
->FullIdentifyData
.UserAddressableSectors
/
1402 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1403 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1405 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1407 NumOfSectors
= cylinders
*
1408 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1409 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1411 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1415 // Check for LBA mode
1416 KdPrint2((PRINT_PREFIX
"SupportLba flag %#x\n", deviceExtension
->FullIdentifyData
.SupportLba
));
1417 KdPrint2((PRINT_PREFIX
"MajorRevision %#x\n", deviceExtension
->FullIdentifyData
.MajorRevision
));
1418 KdPrint2((PRINT_PREFIX
"UserAddressableSectors %#x\n", deviceExtension
->FullIdentifyData
.UserAddressableSectors
));
1419 if ( deviceExtension
->FullIdentifyData
.SupportLba
1421 (deviceExtension
->FullIdentifyData
.MajorRevision
&&
1422 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1423 deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1424 KdPrint2((PRINT_PREFIX
"LBA mode\n"));
1425 LunExt
->DeviceFlags
|= DFLAGS_LBA_ENABLED
;
1427 KdPrint2((PRINT_PREFIX
"Keep orig geometry\n"));
1428 LunExt
->DeviceFlags
|= DFLAGS_ORIG_GEOMETRY
;
1429 goto skip_lba_staff
;
1431 // Check for LBA48 support
1432 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1433 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
&&
1434 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Address48
&&
1435 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
> NumOfSectors
)
1437 KdPrint2((PRINT_PREFIX
"LBA48\n"));
1439 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
/
1440 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1441 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1443 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1445 NativeNumOfSectors
= cylinders
*
1446 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1447 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1449 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1451 if(NativeNumOfSectors
> NumOfSectors
) {
1452 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1453 NumOfSectors
= NativeNumOfSectors
;
1457 // Check drive capacity report for LBA48-capable drives.
1458 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
) {
1459 ULONG hNativeNumOfSectors
;
1460 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1462 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1463 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1465 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1466 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1467 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1468 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) ;
1470 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
1473 KdPrint2((PRINT_PREFIX
"Read high order bytes\n"));
1474 NativeNumOfSectors
|=
1475 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24 );
1476 hNativeNumOfSectors
=
1477 (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) |
1478 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 8) ;
1479 ((PULONG
)&NativeNumOfSectors
)[1] = hNativeNumOfSectors
;
1481 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1483 // Some drives report LBA48 capability while has capacity below 128Gb
1484 // Probably they support large block-counters.
1485 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
1486 // Here we check this
1487 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1488 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!!\n"));
1490 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1491 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1493 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1494 NativeNumOfSectors
= (ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1495 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24) |
1496 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8 ) |
1497 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 32) |
1498 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1499 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 40)
1503 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1504 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!! (2)\n"));
1505 NativeNumOfSectors
= 0;
1509 if(NumOfSectors
<= ATA_MAX_LBA28
&&
1510 NativeNumOfSectors
> NumOfSectors
) {
1512 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
1513 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1515 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1516 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1517 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1518 NumOfSectors
= NativeNumOfSectors
;
1524 if(NumOfSectors
< 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
1525 // check for native LBA size
1526 // some drives report ~32Gb in Identify Block
1527 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
1529 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_READ_NATIVE_SIZE
,
1530 0, IDE_USE_LBA
, 0, 0, 0, ATA_WAIT_READY
);
1532 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1533 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1534 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1535 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1536 (((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
) & 0xf) << 24);
1538 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1540 if(NativeNumOfSectors
> NumOfSectors
) {
1542 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
1543 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1545 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1546 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1547 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1548 NumOfSectors
= NativeNumOfSectors
;
1554 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
1556 // fill IdentifyData with bogus geometry
1557 KdPrint2((PRINT_PREFIX
"requested LunExt->GeomType=%x\n", LunExt
->opt_GeomType
));
1558 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*
1559 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
);
1560 KdPrint2((PRINT_PREFIX
"tmp_cylinders = %#I64x\n", tmp_cylinders
));
1561 if((tmp_cylinders
< 0xffff) || (LunExt
->opt_GeomType
== GEOM_ORIG
)) {
1562 // ok, we can keep original values
1563 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1564 LunExt
->opt_GeomType
= GEOM_ORIG
;
1567 tmp_cylinders
= NumOfSectors
/ (255*63);
1568 if(tmp_cylinders
< 0xffff) {
1569 // we can use generic values for H/S for generic geometry approach
1570 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1571 LunExt
->opt_GeomType
= GEOM_STD
;
1574 // we should use UNIATA geometry approach
1575 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1576 LunExt
->opt_GeomType
= GEOM_UNIATA
;
1580 KdPrint2((PRINT_PREFIX
"final LunExt->opt_GeomType=%x\n", LunExt
->opt_GeomType
));
1582 if(LunExt
->opt_GeomType
== GEOM_STD
) {
1583 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
=
1584 deviceExtension
->FullIdentifyData
.SectorsPerTrack
= 63;
1586 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
=
1587 deviceExtension
->FullIdentifyData
.NumberOfHeads
= 255;
1589 cylinders
= NumOfSectors
/ (255*63);
1590 KdPrint2((PRINT_PREFIX
"Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders
, 255, 63));
1592 if(LunExt
->opt_GeomType
== GEOM_UNIATA
) {
1593 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x80)) {
1595 KdPrint2((PRINT_PREFIX
"cylinders /= 2\n"));
1596 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1597 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1599 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x80)) {
1601 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (2)\n"));
1602 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1603 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1605 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x8000)) {
1607 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (3)\n"));
1608 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1609 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1611 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x8000)) {
1613 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (4)\n"));
1614 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1615 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1617 KdPrint2((PRINT_PREFIX
"Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders
,
1618 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
,
1619 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
));
1622 KdPrint2((PRINT_PREFIX
"cylinders = tmp_cylinders (%x = %x)\n", cylinders
, tmp_cylinders
));
1623 cylinders
= tmp_cylinders
;
1625 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
=
1626 deviceExtension
->FullIdentifyData
.NumberOfCylinders
= (USHORT
)cylinders
;
1630 KdPrint2((PRINT_PREFIX
"Geometry: C %#x (%#x)\n",
1631 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1632 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
1634 KdPrint2((PRINT_PREFIX
"Geometry: H %#x (%#x)\n",
1635 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1636 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
1638 KdPrint2((PRINT_PREFIX
"Geometry: S %#x (%#x)\n",
1639 deviceExtension
->FullIdentifyData
.SectorsPerTrack
,
1640 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
1644 LunExt
->NumOfSectors
= NumOfSectors
;
1645 /* if(deviceExtension->FullIdentifyData.MajorRevision &&
1646 deviceExtension->FullIdentifyData.DoubleWordIo) {
1647 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
1651 ScsiPortMoveMemory(&LunExt
->IdentifyData
,
1652 &deviceExtension
->FullIdentifyData
,sizeof(IDENTIFY_DATA2
));
1654 InitBadBlocks(LunExt
);
1656 if ((LunExt
->IdentifyData
.DrqType
& ATAPI_DRQT_INTR
) &&
1657 (Command
!= IDE_COMMAND_IDENTIFY
)) {
1659 // This device interrupts with the assertion of DRQ after receiving
1660 // Atapi Packet Command
1661 LunExt
->DeviceFlags
|= DFLAGS_INT_DRQ
;
1662 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
1665 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
1668 if(Command
!= IDE_COMMAND_IDENTIFY
) {
1670 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_TAPE
) {
1672 LunExt
->DeviceFlags
|= DFLAGS_TAPE_DEVICE
;
1673 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is a tape drive.\n"));
1675 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
||
1676 LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_OPTICAL
) {
1677 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is CD/Optical drive.\n"));
1678 // set CD default costs
1679 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_CD
;
1680 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_CD
;
1681 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_CD
;
1682 statusByte
= WaitForDrq(chan
);
1684 KdPrint2((PRINT_PREFIX
"IssueIdentify: ATAPI drive type %#x.\n",
1685 LunExt
->IdentifyData
.DeviceType
));
1688 KdPrint2((PRINT_PREFIX
"IssueIdentify: hard drive.\n"));
1691 GetBaseStatus(chan
, statusByte
);
1692 KdPrint2((PRINT_PREFIX
"IssueIdentify: final Status on exit (%#x)\n", statusByte
));
1695 } // end IssueIdentify()
1700 Routine Description:
1701 Set drive parameters using the IDENTIFY data.
1704 HwDeviceExtension - HBA miniport driver's adapter data storage
1705 DeviceNumber - Indicates which device.
1708 TRUE if all goes well.
1713 IN PVOID HwDeviceExtension
,
1714 IN ULONG DeviceNumber
,
1718 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1719 PIDENTIFY_DATA2 identifyData
= &deviceExtension
->lun
[(lChannel
* 2) + DeviceNumber
].IdentifyData
;
1724 if(deviceExtension
->lun
[(lChannel
* 2) + DeviceNumber
].DeviceFlags
&
1725 (DFLAGS_LBA_ENABLED
| DFLAGS_ORIG_GEOMETRY
))
1728 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Number of heads %#x\n", identifyData
->NumberOfHeads
));
1729 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Sectors per track %#x\n", identifyData
->SectorsPerTrack
));
1731 // Send SET PARAMETER command.
1732 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
1733 IDE_COMMAND_SET_DRIVE_PARAMETERS
, 0,
1734 (identifyData
->NumberOfHeads
- 1), 0,
1735 (UCHAR
)identifyData
->SectorsPerTrack
, 0, ATA_WAIT_IDLE
);
1737 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
1738 if(statusByte
& IDE_STATUS_ERROR
) {
1739 errorByte
= AtapiReadPort1(&deviceExtension
->chan
[lChannel
], IDX_IO1_i_Error
);
1740 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Error bit set. Status %#x, error %#x\n",
1741 errorByte
, statusByte
));
1745 if(statusByte
== IDE_STATUS_IDLE
) {
1751 } // end SetDriveParameters()
1756 Routine Description:
1757 Reset IDE controller and/or Atapi device.
1760 HwDeviceExtension - HBA miniport driver's adapter data storage
1769 AtapiResetController(
1770 IN PVOID HwDeviceExtension
,
1774 KdPrint2((PRINT_PREFIX
"AtapiResetController()\n"));
1775 return AtapiResetController__(HwDeviceExtension
, PathId
, RESET_COMPLETE_ALL
);
1776 } // end AtapiResetController()
1780 AtapiResetController__(
1781 IN PVOID HwDeviceExtension
,
1783 IN BOOLEAN CompleteType
1786 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1787 ULONG numberChannels
= deviceExtension
->NumberChannels
;
1788 PHW_CHANNEL chan
= NULL
;
1792 PSCSI_REQUEST_BLOCK CurSrb
;
1793 ULONG ChannelCtrlFlags
;
1794 UCHAR dma_status
= 0;
1796 ULONG slotNumber
= deviceExtension
->slotNumber
;
1797 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
1798 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
1799 ULONG DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
1800 //ULONG RevID = deviceExtension->RevID;
1801 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
1805 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID
, DeviceID
, slotNumber
));
1807 if(!deviceExtension
->simplexOnly
) {
1808 // we shall reset both channels on SimplexOnly devices,
1809 // It's not worth doing so on normal controllers
1811 numberChannels
= j
+1;
1814 numberChannels
= deviceExtension
->NumberChannels
;
1817 for (; j
< numberChannels
; j
++) {
1819 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset channel %d\n", j
));
1820 chan
= &deviceExtension
->chan
[j
];
1821 KdPrint2((PRINT_PREFIX
" CompleteType %#x\n", CompleteType
));
1822 max_ldev
= (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
) ? 1 : 2;
1823 if(CompleteType
!= RESET_COMPLETE_NONE
) {
1825 while((CurSrb
= UniataGetCurRequest(chan
))) {
1827 PATA_REQ AtaReq
= (PATA_REQ
)(CurSrb
->SrbExtension
);
1829 KdPrint2((PRINT_PREFIX
"AtapiResetController: pending SRB %#x\n", CurSrb
));
1830 // Check and see if we are processing an internal srb
1831 if (AtaReq
->OriginalSrb
) {
1832 KdPrint2((PRINT_PREFIX
" restore original SRB %#x\n", AtaReq
->OriginalSrb
));
1833 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
1834 AtaReq
->OriginalSrb
= NULL
;
1835 // NOTE: internal SRB doesn't get to SRB queue !!!
1836 CurSrb
= AtaReq
->Srb
;
1839 // Remove current request from queue
1840 UniataRemoveRequest(chan
, CurSrb
);
1842 // Check if request is in progress.
1843 ASSERT(AtaReq
->Srb
== CurSrb
);
1845 // Complete outstanding request with SRB_STATUS_BUS_RESET.
1846 UCHAR PathId
= CurSrb
->PathId
;
1847 UCHAR TargetId
= CurSrb
->TargetId
;
1848 UCHAR Lun
= CurSrb
->Lun
;
1850 CurSrb
->SrbStatus
= ((CompleteType
== RESET_COMPLETE_ALL
) ? SRB_STATUS_BUS_RESET
: SRB_STATUS_ABORTED
) | SRB_STATUS_AUTOSENSE_VALID
;
1851 CurSrb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
1853 if (CurSrb
->SenseInfoBuffer
) {
1855 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)CurSrb
->SenseInfoBuffer
;
1857 senseBuffer
->ErrorCode
= 0x70;
1858 senseBuffer
->Valid
= 1;
1859 senseBuffer
->AdditionalSenseLength
= 0xb;
1860 if(CompleteType
== RESET_COMPLETE_ALL
) {
1861 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
1862 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
1863 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_BUS_RESET
;
1864 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_SCSI_BUS
;
1866 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
1867 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
1868 senseBuffer
->AdditionalSenseCode
= 0;
1869 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
1873 // Clear request tracking fields.
1874 AtaReq
->WordsLeft
= 0;
1875 AtaReq
->DataBuffer
= NULL
;
1877 ScsiPortNotification(RequestComplete
,
1881 // Indicate ready for next request.
1882 ScsiPortNotification(NextLuRequest
,
1888 if(CompleteType
!= RESET_COMPLETE_ALL
)
1891 #endif //UNIATA_CORE
1892 } // end if (!CompleteType != RESET_COMPLETE_NONE)
1894 // Save control flags
1895 ChannelCtrlFlags
= chan
->ChannelCtrlFlags
;
1896 // Clear expecting interrupt flag.
1897 chan
->ExpectingInterrupt
= FALSE
;
1899 chan
->ChannelCtrlFlags
= 0;
1900 InterlockedExchange(&(chan
->CheckIntr
),
1904 KdPrint2((PRINT_PREFIX
" disable intr (0)\n"));
1905 AtapiDisableInterrupts(deviceExtension
, j
);
1906 KdPrint2((PRINT_PREFIX
" done\n"));
1908 case ATA_INTEL_ID
: {
1911 if(!(ChipFlags
& UNIATA_SATA
))
1913 if(!deviceExtension
->BaseIoAddressSATA_0
.Addr
) {
1917 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
1918 if(ChipFlags
& UNIATA_AHCI
) {
1921 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
1922 GetPciConfig1(0x90, tmp8
);
1929 ChangePciConfig2(0x92, a
& ~mask
);
1930 AtapiStallExecution(10);
1931 ChangePciConfig2(0x92, a
| mask
);
1934 AtapiStallExecution(10000);
1935 GetPciConfig2(0x92, tmp16
);
1936 if ((tmp16
& (mask
<< 4)) == (mask
<< 4)) {
1937 AtapiStallExecution(10000);
1943 case ATA_NVIDIA_ID
: {
1944 KdPrint2((PRINT_PREFIX
" SIS/nVidia\n"));
1945 if(!(ChipFlags
& UNIATA_SATA
))
1948 case ATA_SILICON_IMAGE_ID
: {
1950 ULONG Channel
= deviceExtension
->Channel
+ j
;
1951 if(!(ChipFlags
& UNIATA_SATA
))
1953 offset
= ((Channel
& 1) << 7) + ((Channel
& 2) << 8);
1954 /* disable PHY state change interrupt */
1955 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x148 + offset
, 0);
1957 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
);
1959 /* reset controller part for this channel */
1960 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
1961 AtapiReadPortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) | (0xc0 >> Channel
));
1962 AtapiStallExecution(1000);
1963 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
1964 AtapiReadPortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) & ~(0xc0 >> Channel
));
1968 case ATA_PROMISE_ID
: {
1971 if(ChipFlags
& UNIATA_SATA
) {
1972 KdPrint2((PRINT_PREFIX
" SATA generic reset\n"));
1973 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
);
1976 KdPrint2((PRINT_PREFIX
" send reset\n"));
1977 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
|
1978 IDE_DC_RESET_CONTROLLER
);
1979 KdPrint2((PRINT_PREFIX
" wait a little\n"));
1980 AtapiStallExecution(10000);
1981 // Disable interrupts
1982 KdPrint2((PRINT_PREFIX
" disable intr\n"));
1983 AtapiDisableInterrupts(deviceExtension
, j
);
1984 KdPrint2((PRINT_PREFIX
" re-enable intr\n"));
1985 AtapiEnableInterrupts(deviceExtension
, j
);
1986 KdPrint2((PRINT_PREFIX
" wait a little (2)\n"));
1987 AtapiStallExecution(100000);
1988 KdPrint2((PRINT_PREFIX
" done\n"));
1993 //if(!(ChipFlags & UNIATA_SATA)) {
1994 if(!deviceExtension
->BaseIoAddressSATA_0
.Addr
) {
1995 // Reset DMA engine if active
1996 KdPrint2((PRINT_PREFIX
" check DMA engine\n"));
1997 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
1998 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
1999 if((ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
2000 (dma_status
& BM_STATUS_INTR
)) {
2001 AtapiDmaDone(HwDeviceExtension
, 0, j
, NULL
);
2005 // all these shall be performed inside AtapiHwInitialize__() ?
2007 KdPrint2((PRINT_PREFIX
" process connected devices\n"));
2008 // Do special processing for ATAPI and IDE disk devices.
2009 for (i
= 0; i
< max_ldev
; i
++) {
2011 // Check if device present.
2012 if (!(deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2013 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2014 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2017 if(!CheckDevice(HwDeviceExtension
, j
, i
, TRUE
)) {
2021 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2022 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2023 deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
&= ~DFLAGS_DEVICE_PRESENT
;
2027 SelectDrive(chan
, i
);
2028 AtapiStallExecution(10);
2029 statusByte
= WaitOnBusyLong(chan
);
2030 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2031 if(statusByte
== 0xff) {
2032 KdPrint2((PRINT_PREFIX
2033 "no drive, status %#x\n",
2035 deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
= 0;
2037 // Check for ATAPI disk.
2038 if (deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2039 // Issue soft reset and issue identify.
2040 GetStatus(chan
, statusByte
);
2041 KdPrint2((PRINT_PREFIX
"AtapiResetController: Status before Atapi reset (%#x).\n",
2044 AtapiDisableInterrupts(deviceExtension
, j
);
2045 AtapiSoftReset(chan
, i
);
2046 AtapiEnableInterrupts(deviceExtension
, j
);
2048 GetStatus(chan
, statusByte
);
2050 if(statusByte
== IDE_STATUS_SUCCESS
) {
2052 IssueIdentify(HwDeviceExtension
,
2054 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
2057 KdPrint2((PRINT_PREFIX
2058 "AtapiResetController: Status after soft reset %#x\n",
2061 GetBaseStatus(chan
, statusByte
);
2064 // Issue identify and reinit after channel reset.
2066 if (statusByte
!= IDE_STATUS_IDLE
&&
2067 statusByte
!= IDE_STATUS_SUCCESS
&&
2068 statusByte
!= IDE_STATUS_DRDY
) {
2070 KdPrint2((PRINT_PREFIX
"AtapiResetController: IdeHardReset failed\n"));
2072 if(!IssueIdentify(HwDeviceExtension
,
2074 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2076 KdPrint2((PRINT_PREFIX
"AtapiResetController: IDE IssueIdentify failed\n"));
2078 // Set disk geometry parameters.
2079 if (!SetDriveParameters(HwDeviceExtension
, i
, j
)) {
2080 KdPrint2((PRINT_PREFIX
"AtapiResetController: SetDriveParameters failed\n"));
2082 GetBaseStatus(chan
, statusByte
);
2084 // force DMA mode reinit
2085 deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
|= DFLAGS_REINIT_DMA
;
2089 // Enable interrupts, note, the we can have here recursive disable
2090 AtapiStallExecution(10);
2091 KdPrint2((PRINT_PREFIX
"AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2093 chan
->DisableIntr
));
2094 AtapiEnableInterrupts(deviceExtension
, j
);
2096 // Call the HwInitialize routine to setup multi-block.
2097 AtapiHwInitialize__(deviceExtension
, j
);
2099 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
2103 } // end AtapiResetController__()
2108 Routine Description:
2109 This routine maps ATAPI and IDE errors to specific SRB statuses.
2112 HwDeviceExtension - HBA miniport driver's adapter data storage
2113 Srb - IO request packet
2121 IN PVOID HwDeviceExtension
,
2122 IN PSCSI_REQUEST_BLOCK Srb
2125 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2126 ULONG lChannel
= GET_CHANNEL(Srb
);
2127 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2130 UCHAR srbStatus
= SRB_STATUS_SUCCESS
;
2132 ULONG ldev
= GET_LDEV(Srb
);
2134 // Read the error register.
2136 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2137 KdPrint2((PRINT_PREFIX
2138 "MapError: Error register is %#x\n",
2141 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2143 switch (errorByte
>> 4) {
2144 case SCSI_SENSE_NO_SENSE
:
2146 KdPrint2((PRINT_PREFIX
2147 "ATAPI: No sense information\n"));
2148 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2149 srbStatus
= SRB_STATUS_ERROR
;
2152 case SCSI_SENSE_RECOVERED_ERROR
:
2154 KdPrint2((PRINT_PREFIX
2155 "ATAPI: Recovered error\n"));
2157 srbStatus
= SRB_STATUS_SUCCESS
;
2160 case SCSI_SENSE_NOT_READY
:
2162 KdPrint2((PRINT_PREFIX
2163 "ATAPI: Device not ready\n"));
2164 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2165 srbStatus
= SRB_STATUS_ERROR
;
2168 case SCSI_SENSE_MEDIUM_ERROR
:
2170 KdPrint2((PRINT_PREFIX
2171 "ATAPI: Media error\n"));
2172 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2173 srbStatus
= SRB_STATUS_ERROR
;
2176 case SCSI_SENSE_HARDWARE_ERROR
:
2178 KdPrint2((PRINT_PREFIX
2179 "ATAPI: Hardware error\n"));
2180 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2181 srbStatus
= SRB_STATUS_ERROR
;
2184 case SCSI_SENSE_ILLEGAL_REQUEST
:
2186 KdPrint2((PRINT_PREFIX
2187 "ATAPI: Illegal request\n"));
2188 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2189 srbStatus
= SRB_STATUS_ERROR
;
2192 case SCSI_SENSE_UNIT_ATTENTION
:
2194 KdPrint2((PRINT_PREFIX
2195 "ATAPI: Unit attention\n"));
2196 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2197 srbStatus
= SRB_STATUS_ERROR
;
2200 case SCSI_SENSE_DATA_PROTECT
:
2202 KdPrint2((PRINT_PREFIX
2203 "ATAPI: Data protect\n"));
2204 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2205 srbStatus
= SRB_STATUS_ERROR
;
2208 case SCSI_SENSE_BLANK_CHECK
:
2210 KdPrint2((PRINT_PREFIX
2211 "ATAPI: Blank check\n"));
2212 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2213 srbStatus
= SRB_STATUS_ERROR
;
2216 case SCSI_SENSE_ABORTED_COMMAND
:
2217 KdPrint2((PRINT_PREFIX
2218 "Atapi: Command Aborted\n"));
2219 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2220 srbStatus
= SRB_STATUS_ERROR
;
2225 KdPrint2((PRINT_PREFIX
2226 "ATAPI: Invalid sense information\n"));
2228 srbStatus
= SRB_STATUS_ERROR
;
2236 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
2237 chan
->ReturningMediaStatus
= errorByte
;
2239 if (errorByte
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
2240 KdPrint2((PRINT_PREFIX
2241 "IDE: Media change\n"));
2242 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2243 srbStatus
= SRB_STATUS_ERROR
;
2245 if (Srb
->SenseInfoBuffer
) {
2247 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2249 senseBuffer
->ErrorCode
= 0x70;
2250 senseBuffer
->Valid
= 1;
2251 senseBuffer
->AdditionalSenseLength
= 0xb;
2252 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2253 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2254 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2256 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2259 } else if (errorByte
& IDE_ERROR_COMMAND_ABORTED
) {
2260 KdPrint2((PRINT_PREFIX
2261 "IDE: Command abort\n"));
2262 srbStatus
= SRB_STATUS_ABORTED
;
2263 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2265 if (Srb
->SenseInfoBuffer
) {
2267 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2269 senseBuffer
->ErrorCode
= 0x70;
2270 senseBuffer
->Valid
= 1;
2271 senseBuffer
->AdditionalSenseLength
= 0xb;
2272 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2273 senseBuffer
->AdditionalSenseCode
= 0;
2274 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2276 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2279 deviceExtension
->lun
[ldev
].ErrorCount
++;
2281 } else if (errorByte
& IDE_ERROR_END_OF_MEDIA
) {
2283 KdPrint2((PRINT_PREFIX
2284 "IDE: End of media\n"));
2285 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2286 srbStatus
= SRB_STATUS_ERROR
;
2288 if (Srb
->SenseInfoBuffer
) {
2290 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2292 senseBuffer
->ErrorCode
= 0x70;
2293 senseBuffer
->Valid
= 1;
2294 senseBuffer
->AdditionalSenseLength
= 0xb;
2295 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2296 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIA_STATE
;
2297 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_END_OF_MEDIUM
;
2298 senseBuffer
->EndOfMedia
= 1;
2300 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2303 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2304 deviceExtension
->lun
[ldev
].ErrorCount
++;
2307 } else if (errorByte
& IDE_ERROR_ILLEGAL_LENGTH
) {
2309 KdPrint2((PRINT_PREFIX
2310 "IDE: Illegal length\n"));
2311 srbStatus
= SRB_STATUS_INVALID_REQUEST
;
2313 if (Srb
->SenseInfoBuffer
) {
2315 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2317 senseBuffer
->ErrorCode
= 0x70;
2318 senseBuffer
->Valid
= 1;
2319 senseBuffer
->AdditionalSenseLength
= 0xb;
2320 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
2321 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_VALUE
;
2322 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_PARAM_INVALID_VALUE
;
2323 senseBuffer
->IncorrectLength
= 1;
2325 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2328 } else if (errorByte
& IDE_ERROR_BAD_BLOCK
) {
2330 KdPrint2((PRINT_PREFIX
2331 "IDE: Bad block\n"));
2332 srbStatus
= SRB_STATUS_ERROR
;
2333 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2334 if (Srb
->SenseInfoBuffer
) {
2336 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2338 senseBuffer
->ErrorCode
= 0x70;
2339 senseBuffer
->Valid
= 1;
2340 senseBuffer
->AdditionalSenseLength
= 0xb;
2341 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2342 senseBuffer
->AdditionalSenseCode
= 0;
2343 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2345 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2348 } else if (errorByte
& IDE_ERROR_ID_NOT_FOUND
) {
2350 KdPrint2((PRINT_PREFIX
2351 "IDE: Id not found\n"));
2352 srbStatus
= SRB_STATUS_ERROR
;
2353 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2355 if (Srb
->SenseInfoBuffer
) {
2357 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2359 senseBuffer
->ErrorCode
= 0x70;
2360 senseBuffer
->Valid
= 1;
2361 senseBuffer
->AdditionalSenseLength
= 0xb;
2362 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2363 senseBuffer
->AdditionalSenseCode
= 0;
2364 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2366 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2369 deviceExtension
->lun
[ldev
].ErrorCount
++;
2371 } else if (errorByte
& IDE_ERROR_MEDIA_CHANGE
) {
2373 KdPrint2((PRINT_PREFIX
2374 "IDE: Media change\n"));
2375 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2376 srbStatus
= SRB_STATUS_ERROR
;
2378 if (Srb
->SenseInfoBuffer
) {
2380 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2382 senseBuffer
->ErrorCode
= 0x70;
2383 senseBuffer
->Valid
= 1;
2384 senseBuffer
->AdditionalSenseLength
= 0xb;
2385 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2386 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2387 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2389 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2392 } else if (errorByte
& IDE_ERROR_DATA_ERROR
) {
2394 KdPrint2((PRINT_PREFIX
2395 "IDE: Data error\n"));
2396 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2397 srbStatus
= SRB_STATUS_ERROR
;
2399 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2400 deviceExtension
->lun
[ldev
].ErrorCount
++;
2403 // Build sense buffer
2404 if (Srb
->SenseInfoBuffer
) {
2406 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2408 senseBuffer
->ErrorCode
= 0x70;
2409 senseBuffer
->Valid
= 1;
2410 senseBuffer
->AdditionalSenseLength
= 0xb;
2411 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2412 senseBuffer
->AdditionalSenseCode
= 0;
2413 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2415 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2419 if (deviceExtension
->lun
[ldev
].ErrorCount
>= MAX_ERRORS
) {
2420 // deviceExtension->DWordIO = FALSE;
2422 KdPrint2((PRINT_PREFIX
2423 "MapError: ErrorCount >= MAX_ERRORS\n"));
2425 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_DWORDIO_ENABLED
;
2426 deviceExtension
->lun
[ldev
].MaximumBlockXfer
= 0;
2429 KdPrint2((PRINT_PREFIX
2430 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
2433 KdPrint2((PRINT_PREFIX
2434 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
2443 ScsiPortLogError( HwDeviceExtension
,
2451 // Reprogram to not use Multi-sector.
2454 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
&&
2455 !(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
2457 statusByte
= AtaCommand(deviceExtension
, ldev
& 0x1, lChannel
, IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY
);
2459 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2460 // command was aborted.
2461 if (statusByte
& IDE_STATUS_ERROR
) {
2463 // Read the error register.
2464 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2466 KdPrint2((PRINT_PREFIX
"MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
2470 // Adjust the devExt. value, if necessary.
2471 deviceExtension
->lun
[ldev
].MaximumBlockXfer
= 0;
2479 // Set SCSI status to indicate a check condition.
2480 Srb
->ScsiStatus
= scsiStatus
;
2489 Routine Description:
2492 HwDeviceExtension - HBA miniport driver's adapter data storage
2495 TRUE - if initialization successful.
2496 FALSE - if initialization unsuccessful.
2502 IN PVOID HwDeviceExtension
2505 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2506 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2509 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base)\n"));
2511 /* do extra chipset specific setups */
2512 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
2514 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
2515 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
2516 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
2519 for (c
= 0; c
< numberChannels
; c
++) {
2520 AtapiHwInitialize__(deviceExtension
, c
);
2522 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base) done\n"));
2524 } // end AtapiHwInitialize()
2527 AtapiHwInitialize__(
2528 IN PHW_DEVICE_EXTENSION deviceExtension
,
2533 UCHAR statusByte
, errorByte
;
2534 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2535 PHW_LU_EXTENSION LunExt
;
2537 ULONG PreferedMode
= 0xffffffff;
2539 AtapiChipInit(deviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
);
2540 FindDevices(deviceExtension
, FALSE
, lChannel
);
2542 for (i
= lChannel
*2; i
< (lChannel
+1)*2; i
++) {
2544 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: lChannel %#x\n", lChannel
));
2546 LunExt
= &(deviceExtension
->lun
[i
]);
2548 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2552 AtapiDisableInterrupts(deviceExtension
, lChannel
);
2553 AtapiStallExecution(1);
2555 if (!(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
2557 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: IDE branch\n"));
2558 // Enable media status notification
2559 IdeMediaStatus(TRUE
,deviceExtension
,(UCHAR
)i
);
2561 // If supported, setup Multi-block transfers.
2562 if (LunExt
->MaximumBlockXfer
) {
2564 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2565 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2566 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2568 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2569 // command was aborted.
2570 if (statusByte
& IDE_STATUS_ERROR
) {
2572 // Read the error register.
2573 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2575 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
2579 // Adjust the devExt. value, if necessary.
2580 LunExt
->MaximumBlockXfer
= 0;
2583 KdPrint2((PRINT_PREFIX
2584 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
2586 LunExt
->MaximumBlockXfer
));
2590 if(LunExt
->IdentifyData
.MajorRevision
) {
2592 if(LunExt
->opt_ReadCacheEnable
) {
2593 KdPrint2((PRINT_PREFIX
" Try Enable Read Cache\n"));
2594 // If supported, setup read/write cacheing
2595 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2596 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2597 0, ATA_C_F_ENAB_RCACHE
, ATA_WAIT_BASE_READY
);
2599 // Check for errors.
2600 if (statusByte
& IDE_STATUS_ERROR
) {
2601 KdPrint2((PRINT_PREFIX
2602 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
2604 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
2606 LunExt
->DeviceFlags
|= DFLAGS_RCACHE_ENABLED
;
2609 KdPrint2((PRINT_PREFIX
" Disable Read Cache\n"));
2610 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2611 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2612 0, ATA_C_F_DIS_RCACHE
, ATA_WAIT_BASE_READY
);
2613 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
2615 if(LunExt
->opt_WriteCacheEnable
) {
2616 KdPrint2((PRINT_PREFIX
" Try Enable Write Cache\n"));
2617 // If supported & allowed, setup write cacheing
2618 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2619 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2620 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
2621 // Check for errors.
2622 if (statusByte
& IDE_STATUS_ERROR
) {
2623 KdPrint2((PRINT_PREFIX
2624 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
2626 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
2628 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
2631 KdPrint2((PRINT_PREFIX
" Disable Write Cache\n"));
2632 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2633 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2634 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
2635 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
2639 } else if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)){
2642 BOOLEAN isSanyo
= FALSE
;
2645 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: ATAPI/Changer branch\n"));
2647 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
2648 for (j
= 0; j
< 26; j
+= 2) {
2650 // Build a buffer based on the identify data.
2651 MOV_DW_SWP(vendorId
[j
], ((PUCHAR
)LunExt
->IdentifyData
.ModelNumber
)[j
]);
2654 if (!AtapiStringCmp (vendorId
, "CD-ROM CDR", 11)) {
2656 // Inquiry string for older model had a '-', newer is '_'
2657 if (vendorId
[12] == 'C') {
2659 // Torisan changer. Set the bit. This will be used in several places
2660 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
2661 LunExt
->DeviceFlags
|= (DFLAGS_CHANGER_INITED
| DFLAGS_SANYO_ATAPI_CHANGER
);
2662 LunExt
->DiscsPresent
= 3;
2668 PreferedMode
= LunExt
->opt_MaxTransferMode
;
2669 if(PreferedMode
== 0xffffffff) {
2670 KdPrint2((PRINT_PREFIX
"MaxTransferMode (overriden): %#x\n", chan
->MaxTransferMode
));
2671 PreferedMode
= chan
->MaxTransferMode
;
2674 if(LunExt
->opt_PreferedTransferMode
!= 0xffffffff) {
2675 KdPrint2((PRINT_PREFIX
"PreferedTransferMode: %#x\n", PreferedMode
));
2676 PreferedMode
= min(LunExt
->opt_PreferedTransferMode
, PreferedMode
);
2679 KdPrint2((PRINT_PREFIX
" try mode %#x\n", PreferedMode
));
2680 LunExt
->OrigTransferMode
=
2681 LunExt
->LimitedTransferMode
=
2682 LunExt
->TransferMode
=
2685 AtapiDmaInit__(deviceExtension
, i
);
2687 LunExt
->OrigTransferMode
=
2688 LunExt
->LimitedTransferMode
=
2689 LunExt
->TransferMode
;
2690 KdPrint2((PRINT_PREFIX
"Using %#x mode\n", LunExt
->TransferMode
));
2692 // We need to get our device ready for action before
2693 // returning from this function
2695 // According to the atapi spec 2.5 or 2.6, an atapi device
2696 // clears its status BSY bit when it is ready for atapi commands.
2697 // However, some devices (Panasonic SQ-TC500N) are still
2698 // not ready even when the status BSY is clear. They don't react
2699 // to atapi commands.
2701 // Since there is really no other indication that tells us
2702 // the drive is really ready for action. We are going to check BSY
2703 // is clear and then just wait for an arbitrary amount of time!
2705 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2708 // have to get out of the loop sometime!
2709 // 10000 * 100us = 1000,000us = 1000ms = 1s
2711 GetStatus(chan
, statusByte
);
2712 while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
) {
2714 KdPrint2((PRINT_PREFIX
"Wait for ATAPI (status %x\n)", statusByte
));
2715 // Wait for Busy to drop.
2716 AtapiStallExecution(100);
2717 GetStatus(chan
, statusByte
);
2721 // 5000 * 100us = 500,000us = 500ms = 0.5s
2724 AtapiStallExecution(100);
2725 } while (waitCount
--);
2727 GetBaseStatus(chan
, statusByte
);
2728 AtapiEnableInterrupts(deviceExtension
, lChannel
);
2729 AtapiStallExecution(10);
2734 } // end AtapiHwInitialize()
2740 AtapiHwInitializeChanger(
2741 IN PVOID HwDeviceExtension
,
2742 IN PSCSI_REQUEST_BLOCK Srb
,
2743 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus
)
2745 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2746 ULONG ldev
= GET_LDEV(Srb
);
2748 if (MechanismStatus
) {
2749 deviceExtension
->lun
[ldev
].DiscsPresent
= MechanismStatus
->NumberAvailableSlots
;
2750 if (deviceExtension
->lun
[ldev
].DiscsPresent
> 1) {
2751 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_ATAPI_CHANGER
;
2755 } // end AtapiHwInitializeChanger()
2760 Routine Description:
2761 This routine will parse the string for a match on the keyword, then
2762 calculate the value for the keyword and return it to the caller.
2765 String - The ASCII string to parse.
2766 KeyWord - The keyword for the value desired.
2769 Zero if value not found
2770 Value converted from ASCII to binary.
2774 AtapiParseArgumentString(
2782 ULONG stringLength
= 0;
2783 ULONG keyWordLength
= 0;
2793 // Calculate the string length and lower case all characters.
2796 if (*cptr
>= 'A' && *cptr
<= 'Z') {
2797 *cptr
= *cptr
+ ('a' - 'A');
2803 // Calculate the keyword length and lower case all characters.
2807 if (*cptr
>= 'A' && *cptr
<= 'Z') {
2808 *cptr
= *cptr
+ ('a' - 'A');
2814 if (keyWordLength
> stringLength
) {
2816 // Can't possibly have a match.
2820 // Now setup and start the compare.
2825 // The input string may start with white space. Skip it.
2826 while (*cptr
== ' ' || *cptr
== '\t') {
2830 if (*cptr
== '\0') {
2836 while (*cptr
++ == *kptr
++) {
2838 if (*(cptr
- 1) == '\0') {
2844 if (*(kptr
- 1) == '\0') {
2846 // May have a match backup and check for blank or equals.
2848 while (*cptr
== ' ' || *cptr
== '\t') {
2852 // Found a match. Make sure there is an equals.
2855 // Not a match so move to the next semicolon.
2857 if (*cptr
++ == ';') {
2858 goto ContinueSearch
;
2863 // Skip the equals sign.
2866 // Skip white space.
2867 while ((*cptr
== ' ') || (*cptr
== '\t')) {
2871 if (*cptr
== '\0') {
2872 // Early end of string, return not found
2877 // This isn't it either.
2879 goto ContinueSearch
;
2883 if ((*cptr
== '0') && (*(cptr
+ 1) == 'x')) {
2884 // Value is in Hex. Skip the "0x"
2886 for (index
= 0; *(cptr
+ index
); index
++) {
2888 if (*(cptr
+ index
) == ' ' ||
2889 *(cptr
+ index
) == '\t' ||
2890 *(cptr
+ index
) == ';') {
2894 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
2895 value
= (16 * value
) + (*(cptr
+ index
) - '0');
2897 if ((*(cptr
+ index
) >= 'a') && (*(cptr
+ index
) <= 'f')) {
2898 value
= (16 * value
) + (*(cptr
+ index
) - 'a' + 10);
2900 // Syntax error, return not found.
2907 // Value is in Decimal.
2908 for (index
= 0; *(cptr
+ index
); index
++) {
2910 if (*(cptr
+ index
) == ' ' ||
2911 *(cptr
+ index
) == '\t' ||
2912 *(cptr
+ index
) == ';') {
2916 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
2917 value
= (10 * value
) + (*(cptr
+ index
) - '0');
2920 // Syntax error return not found.
2929 // Not a match check for ';' to continue search.
2931 if (*cptr
++ == ';') {
2932 goto ContinueSearch
;
2938 } // end AtapiParseArgumentString()_
2945 IN PVOID HwDeviceExtension
,
2950 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2951 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2954 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
2957 KdPrint2((PRINT_PREFIX
"AtapiCallBack:\n"));
2958 // If the last command was DSC restrictive, see if it's set. If so, the device is
2959 // ready for a new request. Otherwise, reset the timer and come back to here later.
2961 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
2962 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
2963 // we shall have no problem with interrupt handler.
2964 if (!srb
|| chan
->ExpectingInterrupt
) {
2965 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Calling ISR directly due to BUSY\n"));
2966 chan
->DpcState
= DPC_STATE_TIMER
;
2967 if(!AtapiInterrupt__(HwDeviceExtension
, lChannel
)) {
2968 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
2969 KdPrint2((PRINT_PREFIX
"AtapiCallBack: What's fucking this ???\n"));
2971 goto ReturnCallback
;
2975 if (!IS_RDP((srb
->Cdb
[0]))) {
2976 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb
->Cdb
[0]));
2980 goto ReturnEnableIntr
;
2982 GetStatus(chan
, statusByte
);
2983 if (statusByte
& IDE_STATUS_DSC
) {
2985 UCHAR PathId
= srb
->PathId
;
2986 UCHAR TargetId
= srb
->TargetId
;
2987 UCHAR Lun
= srb
->Lun
;
2989 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Found DSC for RDP - %#x\n", srb
->Cdb
[0]));
2990 AtapiDmaDBSync(chan
, srb
);
2991 UniataRemoveRequest(chan
, srb
);
2992 ScsiPortNotification(RequestComplete
, deviceExtension
, srb
);
2993 // Clear current SRB.
2994 if(!deviceExtension
->simplexOnly
) {
2995 srb
= UniataGetCurRequest(chan
);
3001 // Ask for next request.
3002 ScsiPortNotification(NextLuRequest
,
3007 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
3010 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3014 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Requesting another timer for Op %#x\n",
3017 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3021 goto ReturnCallback
;
3026 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
3027 KdPrint2((PRINT_PREFIX
"AtapiCallBack: CallDisableInterrupts\n"));
3028 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3029 #ifdef UNIATA_USE_XXableInterrupts
3030 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
3031 // must be called on DISPATCH_LEVEL
3032 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
3033 AtapiEnableInterrupts__
);
3035 AtapiEnableInterrupts(HwDeviceExtension
, lChannel
);
3036 InterlockedExchange(&(chan
->CheckIntr
),
3038 // Will raise IRQL to DIRQL
3039 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3040 AtapiEnableInterrupts__
,
3042 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
3043 #endif // UNIATA_USE_XXableInterrupts
3045 //ASSERT(!deviceExtension->simplexOnly);
3050 // Check other channel
3051 // In simplex mode no interrupts must appear on other channels
3052 for(_c
=0; _c
<deviceExtension
->NumberChannels
-1; _c
++) {
3053 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3055 chan
= &(deviceExtension
->chan
[c
]);
3057 if((ULONG
)InterlockedCompareExchange(&chan
->CheckIntr
,
3059 CHECK_INTR_DETECTED
) == CHECK_INTR_DETECTED
) {
3060 //ASSERT(!deviceExtension->simplexOnly);
3061 chan
->DpcState
= DPC_STATE_ISR
;
3062 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3063 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3067 KdPrint2((PRINT_PREFIX
"AtapiCallBack: return\n"));
3070 } // end AtapiCallBack__()
3074 IN PVOID HwDeviceExtension
3077 AtapiCallBack__(HwDeviceExtension
, (UCHAR
)((PHW_DEVICE_EXTENSION
)HwDeviceExtension
)->ActiveDpcChan
);
3080 #endif //UNIATA_CORE
3084 Routine Description:
3086 This is the interrupt service routine for ATAPI IDE miniport driver.
3090 HwDeviceExtension - HBA miniport driver's adapter data storage
3094 TRUE if expecting an interrupt.
3100 IN PVOID HwDeviceExtension
3103 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3105 BOOLEAN status
= FALSE
;
3109 BOOLEAN checked
[AHCI_MAX_PORT
];
3111 KdPrint2((PRINT_PREFIX
"Intr: VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
3113 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3114 checked
[_c
] = FALSE
;
3117 // atapiDev = (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
3118 for(pass
=0; pass
<2; pass
++) {
3119 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3121 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3122 //non_empty_chan = (deviceExtension->lun[c*2].DeviceFlags | deviceExtension->lun[c*2+1].DeviceFlags)
3123 // & DFLAGS_DEVICE_PRESENT;
3128 // check non-empty and execting interrupt channels first
3129 if(!pass
&& !deviceExtension
->chan
[c
].ExpectingInterrupt
)
3134 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3136 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3137 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): disabled INTR on ch %d\n", c
));
3140 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
3142 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): try lock\n"));
3143 // c_state = deviceExtension->chan[c].CheckIntr;
3144 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
3145 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
3147 c_state
= (ULONG
)InterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3149 CHECK_INTR_DETECTED
);
3150 if(c_state
== CHECK_INTR_IDLE
) {
3151 // c_state = deviceExtension->chan[c].CheckIntr;
3152 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
3153 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
3155 c_state
= (ULONG
)InterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3159 } while(c_state
== CHECK_INTR_CHECK
);
3160 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): locked\n"));
3161 // check if already serviced
3162 if(c_state
== CHECK_INTR_ACTIVE
) {
3163 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
3167 if((c_state
== CHECK_INTR_DETECTED
) ||
3168 (i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3171 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): Catch unexpected\n"));
3172 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3175 // disable interrupts on other channel of legacy mode
3176 // ISA-bridged onboard controller
3177 if(deviceExtension
->simplexOnly
/*||
3178 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3179 AtapiDisableInterrupts(deviceExtension
, !c
);
3182 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_ISR
;
3183 if(AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3184 deviceExtension
->LastInterruptedChannel
= (UCHAR
)c
;
3185 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): return status TRUE\n"));
3188 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
3189 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3192 // re-enable interrupts on other channel
3193 if(deviceExtension
->simplexOnly
/*||
3194 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3195 AtapiEnableInterrupts(deviceExtension
, !c
);
3199 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
3200 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3205 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): exit with status %#x\n", status
));
3207 deviceExtension
->FirstChannelToCheck
++;
3208 if(deviceExtension
->FirstChannelToCheck
>= deviceExtension
->NumberChannels
)
3209 deviceExtension
->FirstChannelToCheck
= 0;
3212 } // end AtapiInterrupt()
3219 IN PKINTERRUPT Interrupt
,
3220 IN PVOID Isr2HwDeviceExtension
3224 PISR2_DEVICE_EXTENSION Isr2DeviceExtension
= (PISR2_DEVICE_EXTENSION
)Isr2HwDeviceExtension
;
3225 PHW_DEVICE_EXTENSION deviceExtension
= Isr2DeviceExtension
->HwDeviceExtension
;
3227 BOOLEAN status
= FALSE
;
3231 if(!BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
3232 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3236 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3237 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3239 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3240 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: disabled INTR\n"));
3244 if((ULONG
)CrNtInterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3246 CHECK_INTR_IDLE
) != CHECK_INTR_IDLE
) {
3247 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
3248 // hunt on unexpected intr (Some devices generate double interrupts,
3249 // some controllers (at least CMD649) interrupt twice with small delay.
3250 // If interrupts are disabled, they queue interrupt and re-issue it later,
3251 // when we do not expect it.
3256 if((i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3258 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: intr\n"));
3260 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: Catch unexpected\n"));
3261 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3266 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_DETECTED
);
3268 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3271 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: status %d, c_count %d\n", status
, c_count
));
3272 if(status
&& (c_count
!= deviceExtension
->NumberChannels
)) {
3273 // there is an active ISR/DPC for one channel, but
3274 // we have an interrupt from another one
3275 // Lets inform current ISR/DPC about new interrupt
3276 InterlockedExchange(&(deviceExtension
->ReCheckIntr
), CHECK_INTR_DETECTED
);
3280 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: return %d\n", status
));
3283 } // end AtapiInterrupt2()
3285 RETTYPE_XXableInterrupts
3288 IN PVOID HwDeviceExtension
3291 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3294 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3295 KdPrint2((PRINT_PREFIX
"AtapiInterruptDpc: %#x\n",c
));
3297 if(!(deviceExtension
->chan
[c
].ChannelCtrlFlags
& CTRFLAGS_DPC_REQ
)) {
3299 if((ULONG
)InterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3301 CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
3306 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_DPC_REQ
;
3309 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
3310 AtapiDisableInterrupts(deviceExtension, lChannel);
3313 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_DPC
;
3314 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3315 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3318 return RETVAL_XXableInterrupts
;
3319 } // end AtapiInterruptDpc()
3322 RETTYPE_XXableInterrupts
3324 AtapiEnableInterrupts__(
3325 IN PVOID HwDeviceExtension
3328 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3329 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__():\n"));
3331 PHW_CHANNEL chan
= NULL
;
3333 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3334 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__(2): %#x\n",c
));
3335 chan
= &(deviceExtension
->chan
[c
]);
3337 if(chan
->ChannelCtrlFlags
& CTRFLAGS_ENABLE_INTR_REQ
) {
3338 // enable intrs on requested channel
3339 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_ENABLE_INTR_REQ
;
3340 AtapiEnableInterrupts(HwDeviceExtension
, c
);
3341 InterlockedExchange(&(chan
->CheckIntr
),
3344 // check if current or other channel(s) interrupted
3345 //AtapiInterrupt(HwDeviceExtension);
3347 if(deviceExtension
->simplexOnly
) {
3351 // check if other channel(s) interrupted
3352 // must do nothing in simplex mode
3353 if((ULONG
)CrNtInterlockedCompareExchange(&(chan
->CheckIntr
),
3355 CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
3358 //ASSERT(!deviceExtension->simplexOnly);
3359 chan
->DpcState
= DPC_STATE_ISR
;
3360 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3361 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3365 // In simplex mode next command must be sent to device here
3366 if(deviceExtension
->simplexOnly
&& chan
) {
3367 PSCSI_REQUEST_BLOCK srb
;
3368 chan
= UniataGetNextChannel(chan
);
3370 srb
= UniataGetCurRequest(chan
);
3375 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3379 return RETVAL_XXableInterrupts
;
3381 } // end AtapiEnableInterrupts__()
3383 #endif //UNIATA_CORE
3387 AtapiEnableInterrupts(
3388 IN PVOID HwDeviceExtension
,
3392 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3393 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: %d\n",c
, deviceExtension
->chan
[c
].DisableIntr
));
3394 if(c
>= deviceExtension
->NumberChannels
) {
3397 if(!InterlockedDecrement(&deviceExtension
->chan
[c
].DisableIntr
)) {
3398 AtapiWritePort1(&deviceExtension
->chan
[c
], IDX_IO2_o_Control
,
3400 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_INTR_DISABLED
;
3402 AtapiWritePort1(&deviceExtension
->chan
[c
], IDX_IO2_o_Control
,
3403 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
3406 } // end AtapiEnableInterrupts()
3409 AtapiDisableInterrupts(
3410 IN PVOID HwDeviceExtension
,
3414 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3415 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: %d\n",c
, deviceExtension
->chan
[c
].DisableIntr
));
3416 // mark channel as busy
3417 if(c
>= deviceExtension
->NumberChannels
) {
3420 if(InterlockedIncrement(&deviceExtension
->chan
[c
].DisableIntr
)) {
3421 AtapiWritePort1(&deviceExtension
->chan
[c
], IDX_IO2_o_Control
,
3422 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
3423 deviceExtension
->chan
[c
].ChannelCtrlFlags
|= CTRFLAGS_INTR_DISABLED
;
3427 } // end AtapiDisableInterrupts()
3431 Check hardware for interrupt state
3434 AtapiCheckInterrupt__(
3435 IN PVOID HwDeviceExtension
,
3436 IN UCHAR c
// logical channel
3439 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3440 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
3442 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
3443 ULONG ChipType
= deviceExtension
->HwFlags
& CHIPTYPE_MASK
;
3446 ULONG pr_status
= 0;
3447 UCHAR dma_status
= 0;
3451 ULONG slotNumber
= deviceExtension
->slotNumber
;
3452 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
3453 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
3456 BOOLEAN DmaTransfer
= FALSE
;
3457 BOOLEAN OurInterrupt
= FALSE
;
3459 UCHAR interruptReason
;
3460 BOOLEAN EarlyIntr
= FALSE
;
3462 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__:\n"));
3465 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
3467 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
3469 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension
->DevIndex
,
3470 deviceExtension
->Channel
+ c
, c
));
3472 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension
->DevIndex
,
3473 deviceExtension
->Channel
+ c
, c
));
3474 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
3475 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
3478 // do controller-specific interrupt servicing staff
3479 if(deviceExtension
->UnknownDev
) {
3480 KdPrint2((PRINT_PREFIX
" UnknownDev\n"));
3485 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
3486 // Such behavior was observed with Intel ICH-xxx chips
3487 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
3491 case ATA_PROMISE_ID
: {
3495 status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x1c);
3499 ((Channel
) ? 0x00004000 : 0x00000400))) {
3500 KdPrint2((PRINT_PREFIX
" Promise old/new unexpected\n"));
3505 AtapiWritePort1(chan
, IDX_BM_DeviceSpecific0
, 0x0b);
3506 status
= AtapiReadPort1(chan
, IDX_BM_DeviceSpecific1
);
3509 if(!(status
& 0x20)) {
3510 KdPrint2((PRINT_PREFIX
" Promise tx unexpected\n"));
3515 status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x0040);
3516 if(ChipFlags
& PRSATA
) {
3517 pr_status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c);
3518 AtapiWritePortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c, pr_status
& 0x000000ff);
3520 if(pr_status
& (0x11 << Channel
)) {
3521 // TODO: reset channel
3522 KdPrint2((PRINT_PREFIX
" Promise mio unexpected + reset req\n"));
3525 if(!(status
& (0x01 << Channel
))) {
3526 KdPrint2((PRINT_PREFIX
" Promise mio unexpected\n"));
3529 AtapiWritePort4(chan
, IDX_BM_DeviceSpecific0
, 0x00000001);
3533 case ATA_NVIDIA_ID
: {
3534 if(!(ChipFlags
& UNIATA_SATA
))
3537 KdPrint2((PRINT_PREFIX
"NVIDIA\n"));
3539 ULONG offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
3540 ULONG shift
= Channel
<< ((ChipFlags
& NVQ
) ? 4 : 2);
3542 /* get and clear interrupt status */
3543 if(ChipFlags
& NVQ
) {
3544 pr_status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
3545 AtapiWritePortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0fUL
<< shift
) | 0x00f000f0);
3547 pr_status
= AtapiReadPortEx1(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
3548 AtapiWritePortEx1(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0f << shift
));
3550 KdPrint2((PRINT_PREFIX
" pr_status %x\n", pr_status
));
3552 /* check for and handle connect events */
3553 if(((pr_status
& (0x0cUL
<< shift
)) == (0x04UL
<< shift
)) ) {
3554 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
3556 /* check for and handle disconnect events */
3557 if((pr_status
& (0x08UL
<< shift
)) &&
3558 !((pr_status
& (0x04UL
<< shift
) &&
3559 AtapiReadPort4(chan
, IDX_SATA_SStatus
))) ) {
3560 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
3562 /* do we have any device action ? */
3563 if(!(pr_status
& (0x01UL
<< shift
))) {
3564 KdPrint2((PRINT_PREFIX
" nVidia unexpected\n"));
3565 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
)) {
3574 KdPrint2((PRINT_PREFIX
"ATI\n"));
3575 if(ChipType
== SIIMIO
) {
3580 case ATA_SILICON_IMAGE_ID
:
3582 if(ChipType
== SIIMIO
) {
3584 reg32
= AtapiReadPort1(chan
, IDX_BM_DeviceSpecific0
);
3585 KdPrint2((PRINT_PREFIX
" Sii DS0 %x\n", reg32
));
3586 if(reg32
== (UCHAR
)-1) {
3587 KdPrint2((PRINT_PREFIX
" Sii mio unexpected\n"));
3590 if(!(reg32
& (BM_DS0_SII_DMA_SATA_IRQ
| BM_DS0_SII_DMA_COMPLETE
| BM_DS0_SII_IRQ
| BM_DS0_SII_DMA_ENABLE
| BM_DS0_SII_DMA_ERROR
))) {
3591 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (2)\n"));
3595 if(ChipFlags
& UNIATA_SATA
) {
3596 if(reg32
& (BM_DS0_SII_DMA_SATA_IRQ
| BM_DS0_SII_IRQ
)) {
3598 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
3599 * controllers continue to assert IRQ as long as
3600 * SError bits are pending. Clear SError immediately.
3602 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
)) {
3610 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3611 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (3)\n"));
3612 return OurInterrupt
;
3614 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
& ~BM_STATUS_ERR
);
3615 goto skip_dma_stat_check
;
3618 if(!(deviceExtension
->HwFlags
& SIIINTR
))
3620 GetPciConfig1(0x71, reg8
);
3621 KdPrint2((PRINT_PREFIX
" 0x71 = %#x\n", reg8
));
3623 (Channel
? 0x08 : 0x04))) {
3627 KdPrint2((PRINT_PREFIX
" cmd our\n"));
3630 SetPciConfig1(0x71, (Channel
? 0x08 : 0x04));
3637 //dma_status = GetDmaStatus(deviceExtension, lChannel);
3638 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3639 KdPrint2((PRINT_PREFIX
" Acard unexpected\n"));
3642 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
| BM_STATUS_INTR
);
3643 AtapiStallExecution(1);
3644 AtapiWritePort1(chan
, IDX_BM_Command
,
3645 AtapiReadPort1(chan
, IDX_BM_Command
) & ~BM_COMMAND_START_STOP
);
3646 goto skip_dma_stat_check
;
3648 if(deviceExtension
->BaseIoAddressSATA_0
.Addr
&&
3649 (ChipFlags
& UNIATA_SATA
)) {
3650 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
)) {
3656 KdPrint2((PRINT_PREFIX
" perform generic check\n"));
3658 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3659 KdPrint2((PRINT_PREFIX
" DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status
));
3660 if(dma_status
& BM_STATUS_ERR
) {
3661 KdPrint2((PRINT_PREFIX
" DmaTransfer + BM_STATUS_ERR -> our\n"));
3664 KdPrint2((PRINT_PREFIX
" getting status...\n"));
3665 GetStatus(chan
, statusByte
);
3666 KdPrint2((PRINT_PREFIX
" status %#x\n", statusByte
));
3667 if(statusByte
& IDE_STATUS_ERROR
) {
3668 KdPrint2((PRINT_PREFIX
" IDE_STATUS_ERROR -> our\n", statusByte
));
3676 if(dma_status
& BM_STATUS_INTR
) {
3677 // bullshit, we have DMA interrupt, but had never initiate DMA operation
3678 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr\n"));
3679 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
3684 skip_dma_stat_check
:
3685 if(!(ChipFlags
& UNIATA_SATA
)) {
3686 AtapiStallExecution(1);
3689 /* if drive is busy it didn't interrupt */
3690 /* the exception is DCS + BSY state of ATAPI dvices */
3691 KdPrint2((PRINT_PREFIX
" getting status...\n"));
3692 GetStatus(chan
, statusByte
);
3693 KdPrint2((PRINT_PREFIX
" status %#x\n", statusByte
));
3694 if (statusByte
== 0xff) {
3695 // interrupt from empty controller ?
3697 if (statusByte
& IDE_STATUS_BUSY
) {
3698 if(!chan
->ExpectingInterrupt
) {
3699 KdPrint2((PRINT_PREFIX
" unexpected intr + BUSY\n"));
3700 return OurInterrupt
;
3703 if(deviceExtension
->lun
[c
*2 + chan
->cur_cdev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3704 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
3706 KdPrint2((PRINT_PREFIX
" expecting intr + BUSY (3), non ATAPI\n"));
3709 if(statusByte
!= (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
| IDE_STATUS_DSC
)) {
3710 KdPrint2((PRINT_PREFIX
" unexpected status, seems it is not our\n"));
3716 if(dma_status
& BM_STATUS_INTR
) {
3717 KdPrint2((PRINT_PREFIX
" our interrupt with BSY set, try wait in ISR or post to DPC\n"));
3718 /* clear interrupt and get status */
3719 GetBaseStatus(chan
, statusByte
);
3720 KdPrint2((PRINT_PREFIX
" base status %#x\n", statusByte
));
3724 if(g_WaitBusyInISR
) {
3726 GetStatus(chan
, statusByte
);
3727 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
3728 KdPrint2((PRINT_PREFIX
" Error reg (%#x)\n",
3729 AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
3730 if (!(statusByte
& IDE_STATUS_BUSY
)) {
3731 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
3735 //AtapiStallExecution(25);
3737 if (statusByte
& IDE_STATUS_BUSY
) {
3738 KdPrint2((PRINT_PREFIX
" still BUSY, seems it is not our\n"));
3745 /* clear interrupt and get status */
3746 GetBaseStatus(chan
, statusByte
);
3747 KdPrint2((PRINT_PREFIX
" base status %#x\n", statusByte
));
3748 if (statusByte
== 0xff) {
3749 // interrupt from empty controller ?
3751 if(!(statusByte
& (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
))) {
3752 KdPrint2((PRINT_PREFIX
" no DRQ/DRDY set\n"));
3753 return OurInterrupt
;
3756 #ifndef UNIATA_PIO_ONLY
3758 if(!EarlyIntr
|| g_WaitBusyInISR
) {
3759 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
3761 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3762 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
3766 KdPrint2((PRINT_PREFIX
" set REQ_STATE_EARLY_INTR.\n"));
3768 AtaReq
->ReqState
= REQ_STATE_EARLY_INTR
;
3774 if (!(chan
->ExpectingInterrupt
)) {
3776 KdPrint2((PRINT_PREFIX
" Unexpected interrupt.\n"));
3778 if(deviceExtension
->lun
[c
*2 + chan
->cur_cdev
* 2].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3779 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
3781 KdPrint2((PRINT_PREFIX
" OurInterrupt = %d\n", OurInterrupt
));
3782 return OurInterrupt
;
3784 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
3785 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason
));
3786 return OurInterrupt
;
3788 //ASSERT(!chan->queue_depth || chan->cur_req);
3790 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__: exit with TRUE\n"));
3793 } // end AtapiCheckInterrupt__()
3798 IN PVOID HwDeviceExtension
,
3802 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3803 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
3805 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3806 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
3808 ULONG wordCount
= 0, wordsThisInterrupt
= DEV_BSIZE
/2;
3809 ULONG status
= SRB_STATUS_SUCCESS
;
3810 UCHAR dma_status
= 0;
3813 UCHAR statusByte
= 0,interruptReason
;
3815 BOOLEAN atapiDev
= FALSE
;
3820 BOOLEAN DmaTransfer
= FALSE
;
3822 ULONG TimerValue
= 1000;
3823 #ifdef UNIATA_USE_XXableInterrupts
3824 BOOLEAN InDpc
= (KeGetCurrentIrql() == DISPATCH_LEVEL
);
3826 BOOLEAN InDpc
= (chan
->DpcState
!= DPC_STATE_ISR
);
3827 #endif // UNIATA_USE_XXableInterrupts
3828 BOOLEAN UseDpc
= deviceExtension
->UseDpc
;
3829 // BOOLEAN RestoreUseDpc = FALSE;
3830 BOOLEAN DataOverrun
= FALSE
;
3831 BOOLEAN NoStartIo
= TRUE
;
3833 KdPrint2((PRINT_PREFIX
"AtapiInterrupt:\n"));
3835 KdPrint2((PRINT_PREFIX
" InDpc = TRUE\n"));
3836 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
3842 UCHAR OldReqState
= REQ_STATE_NONE
;
3844 PHW_LU_EXTENSION LunExt
;
3847 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
3849 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension
->DevIndex
, Channel
, KeGetCurrentIrql(), c
));
3851 if((chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
3852 (AtaReq
&& (AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
)) ) {
3854 KdPrint2((PRINT_PREFIX
" DmaTransfer = TRUE\n"));
3858 PathId
= srb
->PathId
;
3859 TargetId
= srb
->TargetId
;
3865 goto enqueue_next_req
;
3868 ldev
= GET_LDEV2(PathId
, TargetId
, Lun
);
3869 DeviceNumber
= (UCHAR
)(ldev
& 1);
3870 LunExt
= &(deviceExtension
->lun
[ldev
]);
3871 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
3872 KdPrint2((PRINT_PREFIX
" dev_type %s\n", atapiDev
? "ATAPI" : "IDE"));
3874 // check if we are in ISR DPC
3876 KdPrint2((PRINT_PREFIX
" InDpc -> CTRFLAGS_INTR_DISABLED\n"));
3877 goto ServiceInterrupt
;
3881 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
3884 if (!(chan
->ExpectingInterrupt
)) {
3886 KdPrint2((PRINT_PREFIX
" Unexpected interrupt for this channel.\n"));
3890 // change request state
3892 OldReqState
= AtaReq
->ReqState
;
3893 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
3894 KdPrint2((PRINT_PREFIX
" OldReqState = %x\n", OldReqState
));
3897 // We don't want using DPC for fast operations, like
3898 // DMA completion, sending CDB, short ATAPI transfers, etc.
3900 // We MUST use DPC, because of interprocessor synchronization
3901 // on multiprocessor platforms
3904 goto ServiceInterrupt
;
3906 switch(OldReqState
) {
3907 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR
:
3908 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR
:
3909 case REQ_STATE_DPC_WAIT_BUSY0
:
3910 case REQ_STATE_DPC_WAIT_BUSY1
:
3911 KdPrint2((PRINT_PREFIX
" continue service interrupt\n"));
3912 goto ServiceInterrupt
;
3913 case REQ_STATE_ATAPI_DO_NOTHING_INTR
:
3914 KdPrint2((PRINT_PREFIX
" do nothing on interrupt\n"));
3918 if(!DmaTransfer
&& !atapiDev
) {
3919 KdPrint2((PRINT_PREFIX
" service PIO HDD\n"));
3926 goto ServiceInterrupt
;
3928 #ifdef UNIATA_USE_XXableInterrupts
3930 KdPrint2((PRINT_PREFIX
" Unexpected InDpc\n"));
3932 // shall never get here
3937 KdPrint2((PRINT_PREFIX
" this is direct DPC call on DRQL\n"));
3939 AtaReq
->ReqState
= REQ_STATE_DPC_INTR_REQ
;
3940 KdPrint2((PRINT_PREFIX
" ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
3942 KdPrint2((PRINT_PREFIX
" DPC without AtaReq!!!\n"));
3945 KdPrint2((PRINT_PREFIX
"call service interrupt\n"));
3946 goto ServiceInterrupt
;
3947 #endif // UNIATA_USE_XXableInterrupts
3952 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
3953 // We always get here when are called from timer callback, which is invoked on DRQL.
3954 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
3956 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: start DPC init...\n"));
3957 // disable interrupts for this channel,
3958 // but avoid recursion and double-disable
3959 if(OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
3960 AtapiDisableInterrupts(deviceExtension
, lChannel
);
3963 chan
->ChannelCtrlFlags
|= CTRFLAGS_DPC_REQ
;
3965 #ifdef UNIATA_USE_XXableInterrupts
3966 // Will lower IRQL to DISPATCH_LEVEL
3967 ScsiPortNotification(CallEnableInterrupts
, HwDeviceExtension
,
3968 /*c ?*/ AtapiInterruptDpc
/*_1 : AtapiInterruptDpc_0*/);
3969 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DPC inited\n"));
3971 // Will raise IRQL to DIRQL
3972 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
3975 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
3976 #endif // UNIATA_USE_XXableInterrupts
3981 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
3983 // Will raise IRQL to DIRQL
3984 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
3988 #endif //UNIATA_CORE
3992 if(AtaReq
&& InDpc
) {
3993 switch(AtaReq
->ReqState
) {
3994 case REQ_STATE_DPC_WAIT_DRQ0
:
3996 case REQ_STATE_DPC_WAIT_BUSY
:
3998 case REQ_STATE_DPC_WAIT_DRQ
:
4000 case REQ_STATE_DPC_WAIT_DRQ_ERR
:
4002 case REQ_STATE_DPC_WAIT_BUSY0
:
4003 case REQ_STATE_DPC_WAIT_BUSY1
:
4004 // continue normal execution
4010 #endif //UNIATA_CORE
4012 // make additional delay for old devices (if we are not in DPC)
4013 if((!LunExt
->IdentifyData
.MajorRevision
|| (deviceExtension
->lun
[DeviceNumber
].TransferMode
< ATA_PIO4
))
4017 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
4019 KdPrint2((PRINT_PREFIX
" additional delay 10us for old devices\n"));
4020 AtapiStallExecution(10);
4023 /* clear interrupt and get status */
4024 GetBaseStatus(chan
, statusByte
);
4025 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Entered with status (%#x)\n", statusByte
));
4028 KdPrint2((PRINT_PREFIX
" operate like in DPC\n"));
4034 if (statusByte
& IDE_STATUS_BUSY
) {
4035 if (deviceExtension
->DriverMustPoll
) {
4036 // Crashdump is polling and we got caught with busy asserted.
4037 // Just go away, and we will be polled again shortly.
4038 KdPrint2((PRINT_PREFIX
" Hit BUSY while polling during crashdump.\n"));
4039 goto ReturnEnableIntr
;
4042 // Ensure BUSY is non-asserted.
4043 // make a very small idle before falling to DPC
4044 k
= (InDpc
&& UseDpc
) ? 1000 : 2;
4046 for (i
= 0; i
< k
; i
++) {
4048 GetBaseStatus(chan
, statusByte
);
4049 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4052 AtapiStallExecution(10);
4055 if (!InDpc
&& UseDpc
&& i
== 2) {
4057 KdPrint2((PRINT_PREFIX
" BUSY on entry. Status %#x, Base IO %#x\n", statusByte
));
4060 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4065 AtapiStallExecution(TimerValue
);
4066 goto ServiceInterrupt
;
4067 #endif //UNIATA_CORE
4069 if (InDpc
&& i
== k
) {
4070 // reset the controller.
4071 KdPrint2((PRINT_PREFIX
4072 " Resetting due to BUSY on entry - %#x.\n",
4074 goto IntrPrepareResetController
;
4079 if(!LunExt
->IdentifyData
.MajorRevision
&&
4082 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
4084 KdPrint2((PRINT_PREFIX
" additional delay 10us for old devices (2)\n"));
4085 AtapiStallExecution(10);
4087 if (statusByte
& IDE_STATUS_BUSY
) {
4088 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {
4089 KdPrint2((PRINT_PREFIX
" BUSY on ATAPI device, waiting\n"));
4091 GetStatus(chan
, statusByte
);
4092 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4093 KdPrint2((PRINT_PREFIX
" Error reg (%#x)\n",
4094 AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
4095 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4096 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4100 KdPrint2((PRINT_PREFIX
" too long wait -> DPC\n"));
4102 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC\n"));
4104 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4106 KdPrint2((PRINT_PREFIX
" too long wait: DPC -> DPC\n"));
4108 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY1
;
4113 AtapiStallExecution(TimerValue
);
4114 #endif //UNIATA_CORE
4117 AtapiStallExecution(10);
4119 if (statusByte
& IDE_STATUS_BUSY
) {
4120 KdPrint2((PRINT_PREFIX
" expecting intr + BUSY (2), try DPC wait\n"));
4126 if(AtaReq
&& DmaTransfer
) {
4127 switch(OldReqState
) {
4128 case REQ_STATE_EARLY_INTR
:
4129 case REQ_STATE_DPC_WAIT_BUSY0
:
4131 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4132 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DMA still active\n"));
4133 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4140 // Check for error conditions.
4141 if ((statusByte
& IDE_STATUS_ERROR
) ||
4142 (dma_status
& BM_STATUS_ERR
)) {
4144 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4145 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error %#x\n", error
));
4147 if(error & IDE_STATUS_CORRECTED_ERROR) {
4148 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
4149 statusByte &= ~IDE_STATUS_ERROR;
4154 KdPrint2((PRINT_PREFIX
" Bad Lba %#I64x\n", AtaReq
->lba
));
4156 KdPrint2((PRINT_PREFIX
" Bad Lba unknown\n"));
4159 KdPrint2((PRINT_PREFIX
" wait ready after error\n"));
4162 AtapiStallExecution(100);
4164 AtapiStallExecution(10);
4168 KdPrint2((PRINT_PREFIX
" Intr on DRQ %x\n",
4169 LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
));
4171 for (k
= atapiDev
? 0 : 200; k
; k
--) {
4172 GetStatus(chan
, statusByte
);
4173 if (!(statusByte
& IDE_STATUS_DRQ
)) {
4174 AtapiStallExecution(50);
4181 /* if this is a UDMA CRC error, reinject request */
4184 if(AtaReq
->retry
< MAX_RETRIES
) {
4185 #ifdef IO_STATISTICS
4186 chan
->lun
[DeviceNumber
]->ModeErrorCount
[AtaReq
->retry
]++;
4187 #endif //IO_STATISTICS
4189 (error & IDE_ERROR_ICRC)*/) {
4190 if(AtaReq
->retry
< MAX_RETRIES
) {
4192 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
4193 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
4194 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
4195 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
4199 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
4202 KdPrint2((PRINT_PREFIX
"Errors in PIO mode\n"));
4206 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
4207 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason
));
4210 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error\n"));
4211 if (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
4212 // Fail this request.
4213 status
= SRB_STATUS_ERROR
;
4214 goto CompleteRequest
;
4216 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n"));
4218 #ifdef IO_STATISTICS
4220 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE_LBA48
) {
4221 KdPrint2((PRINT_PREFIX
"DMA doesn't work right with LBA48\n"));
4222 deviceExtension
->HbaCtrlFlags
|= HBAFLAGS_DMA_DISABLED_LBA48
;
4224 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
) {
4225 KdPrint2((PRINT_PREFIX
"Some higher mode doesn't work right :((\n"));
4226 chan
->lun
[DeviceNumber
]->RecoverCount
[AtaReq
->retry
]++;
4227 if(chan
->lun
[DeviceNumber
]->RecoverCount
[AtaReq
->retry
] >= chan
->lun
[DeviceNumber
]->IoCount
/3) {
4228 deviceExtension
->lun
[DeviceNumber
].LimitedTransferMode
=
4229 deviceExtension
->lun
[DeviceNumber
].TransferMode
;
4231 #endif //IO_STATISTICS
4233 #ifdef IO_STATISTICS
4234 chan
->lun
[DeviceNumber
]->IoCount
++;
4235 #endif //IO_STATISTICS
4239 // check reason for this interrupt.
4242 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI branch\n"));
4245 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
4246 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
4248 wordsThisInterrupt
= DEV_BSIZE
/2*512;
4250 wordsThisInterrupt
= DEV_BSIZE
;
4258 // simulate DRQ for DMA transfers
4259 statusByte
|= IDE_STATUS_DRQ
;
4261 if (statusByte
& IDE_STATUS_DRQ
) {
4264 wordsThisInterrupt
= DEV_BSIZE
/2*512;
4266 if (LunExt
->MaximumBlockXfer
) {
4267 wordsThisInterrupt
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
4270 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4272 interruptReason
= 0x2;
4274 } else if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
4275 interruptReason
= 0x0;
4278 status
= SRB_STATUS_ERROR
;
4279 goto CompleteRequest
;
4282 } else if (statusByte
& IDE_STATUS_BUSY
) {
4284 //AtapiEnableInterrupts(deviceExtension, lChannel);
4285 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
4290 if (AtaReq
->WordsLeft
) {
4292 // Funky behaviour seen with PCI IDE (not all, just one).
4294 // The ISR hits with DRQ low, but comes up later.
4295 for (k
= 0; k
< 5000; k
++) {
4296 GetStatus(chan
, statusByte
);
4297 if (statusByte
& IDE_STATUS_DRQ
) {
4302 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ0
;
4304 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq0)\n"));
4308 AtapiStallExecution(TimerValue
);
4309 goto ServiceInterrupt
;
4310 #endif //UNIATA_CORE
4312 AtapiStallExecution(100);
4315 // reset the controller.
4316 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
4318 IntrPrepareResetController
:
4319 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
);
4320 goto ReturnEnableIntr
;
4323 interruptReason
= (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? 0x2 : 0x0;
4327 // Command complete - verify, write, or the SMART enable/disable.
4328 // Also get_media_status
4329 interruptReason
= 0x3;
4334 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason
, statusByte
));
4335 if (interruptReason
== 0x1 && (statusByte
& IDE_STATUS_DRQ
)) {
4336 // Write the packet.
4337 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Writing Atapi packet.\n"));
4338 // Send CDB to device.
4339 WriteBuffer(chan
, (PUSHORT
)srb
->Cdb
, 6, 0);
4340 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4342 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
4343 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: AtapiDmaStart().\n"));
4344 AtapiDmaStart(HwDeviceExtension
, ldev
& 1, lChannel
, srb
);
4347 goto ReturnEnableIntr
;
4349 } else if (interruptReason
== 0x0 && (statusByte
& IDE_STATUS_DRQ
)) {
4354 // Pick up bytes to transfer and convert to words.
4356 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
4359 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
4361 // Covert bytes to words.
4363 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get W wordCount %#x\n", wordCount
));
4365 if (wordCount
!= AtaReq
->WordsLeft
) {
4366 KdPrint2((PRINT_PREFIX
4367 "AtapiInterrupt: %d words requested; %d words xferred\n",
4372 // Verify this makes sense.
4373 if (wordCount
> AtaReq
->WordsLeft
) {
4374 wordCount
= AtaReq
->WordsLeft
;
4375 KdPrint2((PRINT_PREFIX
4376 "AtapiInterrupt: Write underrun\n"));
4382 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
4383 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
4385 // Transfer only words requested.
4386 wordCount
= AtaReq
->WordsLeft
;
4390 // Transfer next block.
4391 wordCount
= wordsThisInterrupt
;
4395 if (DmaTransfer
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
4396 //ASSERT(AtaReq->WordsLeft == wordCount);
4397 AtaReq
->WordsLeft
= 0;
4398 status
= SRB_STATUS_SUCCESS
;
4399 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
4400 goto CompleteRequest
;
4402 // Ensure that this is a write command.
4403 if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
4405 KdPrint2((PRINT_PREFIX
4406 "AtapiInterrupt: Write interrupt\n"));
4408 statusByte
= WaitOnBusy(chan
);
4410 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
4415 UniataGetPioTiming(LunExt
));
4419 (PULONG
)(AtaReq
->DataBuffer
),
4421 UniataGetPioTiming(LunExt
));
4425 KdPrint2((PRINT_PREFIX
4426 "AtapiInterrupt: Int reason %#x, but srb is for a write %#x.\n",
4430 // Fail this request.
4431 status
= SRB_STATUS_ERROR
;
4432 goto CompleteRequest
;
4435 // Advance data buffer pointer and bytes left.
4436 AtaReq
->DataBuffer
+= wordCount
;
4437 AtaReq
->WordsLeft
-= wordCount
;
4440 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4443 goto ReturnEnableIntr
;
4445 } else if (interruptReason
== 0x2 && (statusByte
& IDE_STATUS_DRQ
)) {
4450 // Pick up bytes to transfer and convert to words.
4452 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
) |
4453 (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8);
4455 // Covert bytes to words.
4457 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get R wordCount %#x\n", wordCount
));
4459 if (wordCount
!= AtaReq
->WordsLeft
) {
4460 KdPrint2((PRINT_PREFIX
4461 "AtapiInterrupt: %d words requested; %d words xferred\n",
4466 // Verify this makes sense.
4467 if (wordCount
> AtaReq
->WordsLeft
) {
4468 wordCount
= AtaReq
->WordsLeft
;
4474 // Check if words left is at least 256.
4475 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
4477 // Transfer only words requested.
4478 wordCount
= AtaReq
->WordsLeft
;
4482 // Transfer next block.
4483 wordCount
= wordsThisInterrupt
;
4487 if (DmaTransfer
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
4488 //ASSERT(AtaReq->WordsLeft == wordCount);
4489 AtaReq
->WordsLeft
= 0;
4490 status
= SRB_STATUS_SUCCESS
;
4491 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
4492 goto CompleteRequest
;
4494 // Ensure that this is a read command.
4495 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4498 "AtapiInterrupt: Read interrupt\n"));*/
4500 statusByte
= WaitOnBusy(chan
);
4502 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
4503 KdPrint2((PRINT_PREFIX
4504 "IdeIntr: Read %#x words\n", wordCount
));
4509 UniataGetPioTiming(LunExt
));
4510 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)-1) ));
4511 //KdDump(AtaReq->DataBuffer, wordCount*2);
4513 GetStatus(chan
, statusByte
);
4514 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4517 KdPrint2((PRINT_PREFIX
" DataOverrun\n"));
4518 AtapiSuckPort2(chan
);
4522 KdPrint2((PRINT_PREFIX
4523 "IdeIntr: Read %#x Dwords\n", wordCount
/2));
4526 (PULONG
)(AtaReq
->DataBuffer
),
4528 UniataGetPioTiming(LunExt
));
4532 KdPrint2((PRINT_PREFIX
4533 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
4537 // Fail this request.
4538 status
= SRB_STATUS_ERROR
;
4539 goto CompleteRequest
;
4542 // Advance data buffer pointer and bytes left.
4543 AtaReq
->DataBuffer
+= wordCount
;
4544 AtaReq
->WordsLeft
-= wordCount
;
4546 // Check for read command complete.
4547 if (AtaReq
->WordsLeft
== 0) {
4549 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
4552 // Work around to make many atapi devices return correct sector size
4553 // of 2048. Also certain devices will have sector count == 0x00, check
4555 if ((srb
->Cdb
[0] == SCSIOP_READ_CAPACITY
) &&
4556 (LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
)) {
4558 AtaReq
->DataBuffer
-= wordCount
;
4559 if (AtaReq
->DataBuffer
[0] == 0x00) {
4561 *((ULONG
*) &(AtaReq
->DataBuffer
[0])) = 0xFFFFFF7F;
4565 *((ULONG
*) &(AtaReq
->DataBuffer
[2])) = 0x00080000;
4566 AtaReq
->DataBuffer
+= wordCount
;
4571 // Completion for IDE drives.
4572 if (AtaReq->WordsLeft) {
4573 status = SRB_STATUS_DATA_OVERRUN;
4575 status = SRB_STATUS_SUCCESS;
4578 goto CompleteRequest;
4580 status
= SRB_STATUS_SUCCESS
;
4581 goto CompleteRequest
;
4586 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4590 goto ReturnEnableIntr
;
4592 } else if (interruptReason
== 0x3 && !(statusByte
& IDE_STATUS_DRQ
)) {
4594 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: interruptReason = CompleteRequest\n"));
4595 // Command complete.
4597 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
4598 AtaReq
->WordsLeft
= 0;
4600 if (AtaReq
->WordsLeft
) {
4601 status
= SRB_STATUS_DATA_OVERRUN
;
4603 status
= SRB_STATUS_SUCCESS
;
4606 #ifdef UNIATA_DUMP_ATAPI
4608 srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4612 PCHAR ModeSelectData
;
4614 PSCSI_REQUEST_BLOCK Srb
= srb
;
4616 Cdb
= (PCDB
)(Srb
->Cdb
);
4617 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
4618 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
4619 CdbDataLen
= Srb
->DataTransferLength
;
4621 if(CdbDataLen
> 0x1000) {
4622 CdbDataLen
= 0x1000;
4626 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
4627 KdPrint2(("P:T:D=%d:%d:%d\n",
4631 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand
));
4634 if(ScsiCommand
== SCSIOP_MODE_SENSE
) {
4635 KdPrint(("ModeSense 6\n"));
4636 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
4637 ModeSelectData
= CdbData
+4;
4638 KdDump(CdbData
, CdbDataLen
);
4640 if(ScsiCommand
== SCSIOP_MODE_SENSE10
) {
4641 KdPrint(("ModeSense 10\n"));
4642 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
4643 ModeSelectData
= CdbData
+8;
4644 KdDump(CdbData
, CdbDataLen
);
4646 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4647 KdPrint(("Read buffer from device:\n"));
4648 KdDump(CdbData
, CdbDataLen
);
4653 #endif //UNIATA_DUMP_ATAPI
4657 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest\n"));
4658 // Check and see if we are processing our secret (mechanism status/request sense) srb
4659 if (AtaReq
->OriginalSrb
) {
4663 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: OriginalSrb != NULL\n"));
4664 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
4666 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
4667 if (status
== SRB_STATUS_SUCCESS
) {
4669 AtapiHwInitializeChanger (HwDeviceExtension
,
4671 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
4673 // Get ready to issue the original srb
4674 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
4675 AtaReq
->OriginalSrb
= NULL
;
4678 // failed! Get the sense key and maybe try again
4679 srb
= AtaReq
->Srb
= BuildRequestSenseSrb (
4681 AtaReq
->OriginalSrb
);
4684 // do not enable interrupts in DPC, do not waste time, do it now!
4685 if(UseDpc && chan->DisableIntr) {
4686 AtapiEnableInterrupts(HwDeviceExtension, c);
4688 RestoreUseDpc = TRUE;
4691 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
4693 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
4695 if (srbStatus
== SRB_STATUS_PENDING
) {
4696 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
4697 goto ReturnEnableIntr
;
4701 // restore state on error
4703 AtapiDisableInterrupts(HwDeviceExtension, c);
4707 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
4709 PSENSE_DATA senseData
= (PSENSE_DATA
) srb
->DataBuffer
;
4711 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI command status %#x\n", status
));
4712 if (status
== SRB_STATUS_DATA_OVERRUN
) {
4713 // Check to see if we at least get mininum number of bytes
4714 if ((srb
->DataTransferLength
- AtaReq
->WordsLeft
) >
4715 (offsetof (SENSE_DATA
, AdditionalSenseLength
) + sizeof(senseData
->AdditionalSenseLength
))) {
4716 status
= SRB_STATUS_SUCCESS
;
4720 if (status
== SRB_STATUS_SUCCESS
) {
4722 if ((senseData
->SenseKey
!= SCSI_SENSE_ILLEGAL_REQUEST
) &&
4723 chan
->MechStatusRetryCount
) {
4725 // The sense key doesn't say the last request is illegal, so try again
4726 chan
->MechStatusRetryCount
--;
4727 srb
= AtaReq
->Srb
= BuildMechanismStatusSrb (
4729 AtaReq
->OriginalSrb
);
4732 // last request was illegal. No point trying again
4733 AtapiHwInitializeChanger (HwDeviceExtension
,
4735 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
4737 // Get ready to issue the original srb
4738 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
4739 AtaReq
->OriginalSrb
= NULL
;
4741 #endif //UNIATA_CORE
4743 // do not enable interrupts in DPC, do not waste time, do it now!
4744 if(UseDpc && chan->DisableIntr) {
4745 AtapiEnableInterrupts(HwDeviceExtension, c);
4747 RestoreUseDpc = TRUE;
4750 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
4752 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan
->ExpectingInterrupt
));
4754 if (srbStatus
== SRB_STATUS_PENDING
) {
4755 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
4756 goto ReturnEnableIntr
;
4760 // restore state on error
4762 AtapiDisableInterrupts(HwDeviceExtension, c);
4768 // If we get here, it means AtapiSendCommand() has failed
4769 // Can't recover. Pretend the original srb has failed and complete it.
4771 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error. complete OriginalSrb\n"));
4773 if (AtaReq
->OriginalSrb
) {
4774 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
4775 AtapiHwInitializeChanger (HwDeviceExtension
,
4777 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
4778 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
4779 AtaReq
->OriginalSrb
= NULL
;
4782 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan
->ExpectingInterrupt
));
4784 // fake an error and read no data
4785 status
= SRB_STATUS_ERROR
;
4786 srb
->ScsiStatus
= 0;
4787 AtaReq
->DataBuffer
= (PUSHORT
)(srb
->DataBuffer
);
4788 AtaReq
->WordsLeft
= srb
->DataTransferLength
;
4791 } else if (status
== SRB_STATUS_ERROR
) {
4793 // Map error to specific SRB status and handle request sense.
4794 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error. Begin mapping...\n"));
4795 status
= MapError(deviceExtension
,
4800 } else if(!DmaTransfer
) {
4802 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion\n"));
4804 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion, wait BUSY\n"));
4805 // Wait for busy to drop.
4806 for (i
= 0; i
< 5*30; i
++) {
4807 GetStatus(chan
, statusByte
);
4808 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4813 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY
;
4815 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (busy)\n"));
4819 AtapiStallExecution(TimerValue
);
4820 goto ServiceInterrupt
;
4821 #endif //UNIATA_CORE
4823 AtapiStallExecution(100);
4828 // reset the controller.
4829 KdPrint2((PRINT_PREFIX
4830 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
4832 goto IntrPrepareResetController
;
4834 // Check to see if DRQ is still up.
4835 if(statusByte
& IDE_STATUS_DRQ
) {
4836 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DRQ...\n"));
4838 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4839 KdPrint2((PRINT_PREFIX
"srb %x data in\n", srb
));
4841 KdPrint2((PRINT_PREFIX
"srb %x data out\n", srb
));
4844 KdPrint2((PRINT_PREFIX
"srb NULL\n"));
4847 KdPrint2((PRINT_PREFIX
"AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq
, AtaReq
->WordsLeft
));
4849 KdPrint2((PRINT_PREFIX
"AtaReq NULL\n"));
4851 if(AtaReq
&& AtaReq
->WordsLeft
/*&&
4852 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
4853 KdPrint2((PRINT_PREFIX
"DRQ+AtaReq->WordsLeft -> next portion\n"));
4857 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
4858 //if ((statusByte & IDE_STATUS_DRQ)) {}
4859 if((statusByte
& IDE_STATUS_DRQ
) &&
4860 (LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_TAPE_DEVICE
| DFLAGS_LBA_ENABLED
)) ) {
4863 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO_wait_DRQ\n"));
4864 for (i
= 0; i
< 200; i
++) {
4865 GetStatus(chan
, statusByte
);
4866 if (!(statusByte
& IDE_STATUS_DRQ
)) {
4871 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq)\n"));
4872 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ
;
4877 AtapiStallExecution(TimerValue
);
4878 goto ServiceInterrupt
;
4879 #endif //UNIATA_CORE
4881 AtapiStallExecution(100);
4885 // reset the controller.
4886 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
4888 goto IntrPrepareResetController
;
4892 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
4893 AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)(-1)), srb
->DataTransferLength
));
4894 //KdDump(srb->DataBuffer, srb->DataTransferLength);
4896 if(!AtapiDmaPioSync(HwDeviceExtension
, srb
, (PUCHAR
)(srb
->DataBuffer
), srb
->DataTransferLength
)) {
4897 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
4901 // Clear interrupt expecting flag.
4902 chan
->ExpectingInterrupt
= FALSE
;
4903 InterlockedExchange(&(chan
->CheckIntr
),
4906 // Sanity check that there is a current request.
4908 // Set status in SRB.
4909 srb
->SrbStatus
= (UCHAR
)status
;
4911 // Check for underflow.
4912 if (AtaReq
->WordsLeft
) {
4914 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq
->WordsLeft
));
4915 // Subtract out residual words and update if filemark hit,
4916 // setmark hit , end of data, end of media...
4917 if (!(LunExt
->DeviceFlags
& DFLAGS_TAPE_DEVICE
)) {
4918 if (status
== SRB_STATUS_DATA_OVERRUN
) {
4919 srb
->DataTransferLength
-= AtaReq
->WordsLeft
;
4921 srb
->DataTransferLength
= 0;
4924 srb
->DataTransferLength
-= AtaReq
->WordsLeft
;
4928 if (srb
->Function
!= SRB_FUNCTION_IO_CONTROL
) {
4931 // Indicate command complete.
4933 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete\n"));
4936 if (status
== SRB_STATUS_SUCCESS
&&
4937 srb
->SenseInfoBuffer
&&
4938 srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
4940 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)srb
->SenseInfoBuffer
;
4942 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: set AutoSense\n"));
4943 senseBuffer
->ErrorCode
= 0;
4944 senseBuffer
->Valid
= 1;
4945 senseBuffer
->AdditionalSenseLength
= 0xb;
4946 senseBuffer
->SenseKey
= 0;
4947 senseBuffer
->AdditionalSenseCode
= 0;
4948 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
4950 srb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
4952 AtapiDmaDBSync(chan
, srb
);
4953 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove srb %#x, status %x\n", srb
, status
));
4954 UniataRemoveRequest(chan
, srb
);
4955 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete, srb %#x\n", srb
));
4956 ScsiPortNotification(RequestComplete
,
4962 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: IOCTL completion\n"));
4963 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
4965 if (status
!= SRB_STATUS_SUCCESS
) {
4966 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4967 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: error %#x\n", error
));
4970 // Build the SMART status block depending upon the completion status.
4971 cmdOutParameters
->cBufferSize
= wordCount
;
4972 cmdOutParameters
->DriverStatus
.bDriverError
= (error
) ? SMART_IDE_ERROR
: 0;
4973 cmdOutParameters
->DriverStatus
.bIDEError
= error
;
4975 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
4977 if (chan
->SmartCommand
== RETURN_SMART_STATUS
) {
4978 cmdOutParameters
->bBuffer
[0] = RETURN_SMART_STATUS
;
4979 cmdOutParameters
->bBuffer
[1] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
);
4980 cmdOutParameters
->bBuffer
[2] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Unused1
);
4981 cmdOutParameters
->bBuffer
[3] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
4982 cmdOutParameters
->bBuffer
[4] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
);
4983 cmdOutParameters
->bBuffer
[5] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_DriveSelect
);
4984 cmdOutParameters
->bBuffer
[6] = SMART_CMD
;
4985 cmdOutParameters
->cBufferSize
= 8;
4988 // Indicate command complete.
4989 goto IntrCompleteReq
;
4994 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: No SRB!\n"));
4999 for (i
= 0; i
< 5; i
++) {
5000 GetStatus(chan
, statusByte
);
5001 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5002 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RDP + cleared BUSY\n"));
5006 if (statusByte
& IDE_STATUS_DSC
) {
5007 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Clear RDP\n"));
5011 AtapiStallExecution(50);
5014 // RDP can be cleared since previous check
5016 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestTimerCall 2000\n"));
5022 AtapiStallExecution(TimerValue
);
5023 goto ServiceInterrupt
;
5024 #endif //UNIATA_CORE
5027 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
5030 srb
= UniataGetCurRequest(chan
);
5035 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: NextRequest, srb=%#x\n",srb
));
5037 ScsiPortNotification(NextRequest
,
5041 ScsiPortNotification(NextLuRequest
,
5046 // in simplex mode next command must NOT be sent here
5047 if(!deviceExtension
->simplexOnly
) {
5048 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
5051 // Try to get SRB fron any non-empty queue (later)
5052 if(deviceExtension
->simplexOnly
) {
5055 #endif //UNIATA_CORE
5057 goto ReturnEnableIntr
;
5061 // Unexpected int. Catch it
5062 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
5070 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ReturnEnableIntr\n",srb
));
5072 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
5073 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
5074 #ifdef UNIATA_USE_XXableInterrupts
5075 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
5076 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
5077 // must be called on DISPATCH_LEVEL
5078 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
5079 AtapiEnableInterrupts__
);
5081 AtapiEnableInterrupts(HwDeviceExtension
, c
);
5082 InterlockedExchange(&(chan
->CheckIntr
),
5084 // Will raise IRQL to DIRQL
5086 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
5087 AtapiEnableInterrupts__
,
5089 #endif // UNIATA_CORE
5090 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
5091 #endif // UNIATA_USE_XXableInterrupts
5095 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
5096 // in simplex mode next command must be sent here if
5098 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc
, NoStartIo
));
5101 if(!UseDpc
&& /*deviceExtension->simplexOnly &&*/ !NoStartIo
) {
5102 chan
= UniataGetNextChannel(chan
);
5104 srb
= UniataGetCurRequest(chan
);
5108 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: run srb %x\n", srb
));
5110 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
5113 #endif //UNIATA_CORE
5116 } // end AtapiInterrupt__()
5122 Routine Description:
5124 This routine handles SMART enable, disable, read attributes and threshold commands.
5128 HwDeviceExtension - HBA miniport driver's adapter data storage
5129 Srb - IO request packet
5137 IdeSendSmartCommand(
5138 IN PVOID HwDeviceExtension
,
5139 IN PSCSI_REQUEST_BLOCK Srb
5142 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5143 ULONG c
= GET_CHANNEL(Srb
);
5144 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
5145 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5146 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5147 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5148 PIDEREGS regs
= &cmdInParameters
.irDriveRegs
;
5150 UCHAR statusByte
,targetId
;
5153 if (regs
->bCommandReg
!= SMART_CMD
) {
5154 KdPrint2((PRINT_PREFIX
5155 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
5156 return SRB_STATUS_INVALID_REQUEST
;
5159 targetId
= cmdInParameters
.bDriveNumber
;
5161 //TODO optimize this check
5162 if ((!(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) ||
5163 (deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
5165 return SRB_STATUS_SELECTION_TIMEOUT
;
5168 chan
->SmartCommand
= regs
->bFeaturesReg
;
5170 // Determine which of the commands to carry out.
5171 switch(regs
->bFeaturesReg
) {
5172 case READ_ATTRIBUTES
:
5173 case READ_THRESHOLDS
:
5175 statusByte
= WaitOnBusy(chan
);
5177 if (statusByte
& IDE_STATUS_BUSY
) {
5178 KdPrint2((PRINT_PREFIX
5179 "IdeSendSmartCommand: Returning BUSY status\n"));
5180 return SRB_STATUS_BUSY
;
5183 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
5184 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1);
5186 // Set data buffer pointer and words left.
5187 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
5188 AtaReq
->WordsLeft
= READ_ATTRIBUTE_BUFFER_SIZE
/ 2;
5190 statusByte
= AtaCommand(deviceExtension
, targetId
& 0x1, c
,
5192 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
5194 regs
->bSectorNumberReg
,
5195 regs
->bSectorCountReg
,
5199 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5200 // Wait for interrupt.
5201 return SRB_STATUS_PENDING
;
5203 return SRB_STATUS_ERROR
;
5207 case RETURN_SMART_STATUS
:
5208 case ENABLE_DISABLE_AUTOSAVE
:
5209 case EXECUTE_OFFLINE_DIAGS
:
5210 case SAVE_ATTRIBUTE_VALUES
:
5212 statusByte
= WaitOnBusy(chan
);
5214 if (statusByte
& IDE_STATUS_BUSY
) {
5215 KdPrint2((PRINT_PREFIX
5216 "IdeSendSmartCommand: Returning BUSY status\n"));
5217 return SRB_STATUS_BUSY
;
5220 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
5221 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) - 1);
5223 // Set data buffer pointer and indicate no data transfer.
5224 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
5225 AtaReq
->WordsLeft
= 0;
5227 statusByte
= AtaCommand(deviceExtension
, targetId
& 0x1, c
,
5229 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
5231 regs
->bSectorNumberReg
,
5232 regs
->bSectorCountReg
,
5236 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5237 // Wait for interrupt.
5238 return SRB_STATUS_PENDING
;
5240 return SRB_STATUS_ERROR
;
5241 } // end switch(regs->bFeaturesReg)
5243 return SRB_STATUS_INVALID_REQUEST
;
5245 } // end IdeSendSmartCommand()
5247 #endif //UNIATA_CORE
5250 UniAtaCalculateLBARegs(
5251 PHW_LU_EXTENSION LunExt
,
5252 ULONG startingSector
5255 UCHAR drvSelect
,sectorNumber
;
5259 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
5260 return startingSector
;
5262 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
5263 LunExt
->IdentifyData
.NumberOfHeads
;
5265 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
5270 cylinder
= (USHORT
)(startingSector
/ tmp
);
5271 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
5272 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
5275 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
5276 } // end UniAtaCalculateLBARegs()
5279 UniAtaCalculateLBARegsBack(
5280 PHW_LU_EXTENSION LunExt
,
5284 ULONG drvSelect
,sectorNumber
;
5288 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
5291 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
5292 LunExt
->IdentifyData
.NumberOfHeads
;
5294 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
5295 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
5296 sectorNumber
= (UCHAR
)(lba
& 0xff);
5298 lba
= sectorNumber
-1 +
5299 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
5303 } // end UniAtaCalculateLBARegsBack()
5308 Routine Description:
5310 This routine handles IDE read and writes.
5314 HwDeviceExtension - HBA miniport driver's adapter data storage
5315 Srb - IO request packet
5324 IN PVOID HwDeviceExtension
,
5325 IN PSCSI_REQUEST_BLOCK Srb
,
5329 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5330 UCHAR lChannel
= GET_CHANNEL(Srb
);
5331 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5332 PHW_LU_EXTENSION LunExt
;
5333 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5334 ULONG ldev
= GET_LDEV(Srb
);
5335 UCHAR DeviceNumber
= (UCHAR
)(ldev
& 1);
5336 ULONG startingSector
;
5337 ULONG wordCount
= 0;
5338 UCHAR statusByte
,statusByte2
;
5341 BOOLEAN use_dma
= FALSE
;
5343 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
5344 LunExt
= &deviceExtension
->lun
[ldev
];
5346 if((CmdAction
& CMD_ACTION_PREPARE
) &&
5347 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
5349 // Set data buffer pointer and words left.
5350 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
5352 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
5353 //ASSERT(Srb->DataTransferLength == AtaReq->bcount * DEV_BSIZE);
5354 AtaReq
->WordsLeft
= min(Srb
->DataTransferLength
,
5355 AtaReq
->bcount
* DEV_BSIZE
) / 2;
5357 // Set up 1st block.
5358 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
5360 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %#x, Number of WORDS %#x, DevSize %#x\n",
5365 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
);
5368 // assume best case here
5369 // we cannot reinit Dma until previous request is completed
5370 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
5372 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
5373 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
5374 (PUCHAR
)(AtaReq
->DataBuffer
),
5375 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
5379 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
5380 } else { // exec_only
5381 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
5384 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
5388 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
5389 return SRB_STATUS_PENDING
;
5392 // if this is queued request, reinit DMA and check
5393 // if DMA mode is still available
5394 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
5395 if (/*EnableDma &&*/
5396 (LunExt
->TransferMode
>= ATA_DMA
)) {
5399 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5403 // Check if write request.
5404 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5406 // Prepare read command.
5408 cmd
= IDE_COMMAND_READ_DMA
;
5410 if(LunExt
->MaximumBlockXfer
) {
5411 cmd
= IDE_COMMAND_READ_MULTIPLE
;
5413 cmd
= IDE_COMMAND_READ
;
5417 // Prepare write command.
5419 wordCount
= Srb
->DataTransferLength
/2;
5420 cmd
= IDE_COMMAND_WRITE_DMA
;
5422 if (LunExt
->MaximumBlockXfer
) {
5423 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5425 if (AtaReq
->WordsLeft
< wordCount
) {
5426 // Transfer only words requested.
5427 wordCount
= AtaReq
->WordsLeft
;
5429 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
5432 wordCount
= DEV_BSIZE
/2;
5433 cmd
= IDE_COMMAND_WRITE
;
5438 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
5440 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5444 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
5445 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
5447 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
5449 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
5451 (UCHAR
)((Srb
->DataTransferLength
+ DEV_BSIZE
-1) / DEV_BSIZE
),
5452 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
5454 GetStatus(chan
, statusByte2
);
5455 if(statusByte2
& IDE_STATUS_ERROR
) {
5456 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5457 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
5458 return SRB_STATUS_ERROR
;
5461 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
5463 return SRB_STATUS_PENDING
;
5466 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
5468 (UCHAR
)((Srb
->DataTransferLength
+ DEV_BSIZE
-1) / DEV_BSIZE
),
5469 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
5472 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5474 KdPrint2((PRINT_PREFIX
5475 "IdeReadWrite: DRQ never asserted (%#x)\n",
5478 AtaReq
->WordsLeft
= 0;
5480 // Clear interrupt expecting flag.
5481 chan
->ExpectingInterrupt
= FALSE
;
5482 InterlockedExchange(&(chan
->CheckIntr
),
5485 // Clear current SRB.
5486 UniataRemoveRequest(chan
, Srb
);
5488 return SRB_STATUS_TIMEOUT
;
5491 chan
->ExpectingInterrupt
= TRUE
;
5492 InterlockedExchange(&(chan
->CheckIntr
),
5495 // Write next DEV_BSIZE/2*N words.
5496 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
)) {
5497 KdPrint2((PRINT_PREFIX
5498 "IdeReadWrite: Write %#x words\n", wordCount
));
5503 UniataGetPioTiming(LunExt
));
5507 KdPrint2((PRINT_PREFIX
5508 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
5511 (PULONG
)(AtaReq
->DataBuffer
),
5513 UniataGetPioTiming(LunExt
));
5516 // Adjust buffer address and words left count.
5517 AtaReq
->WordsLeft
-= wordCount
;
5518 AtaReq
->DataBuffer
+= wordCount
;
5520 // Wait for interrupt.
5521 return SRB_STATUS_PENDING
;
5523 } // end IdeReadWrite()
5529 Routine Description:
5530 This routine handles IDE Verify.
5533 HwDeviceExtension - HBA miniport driver's adapter data storage
5534 Srb - IO request packet
5542 IN PVOID HwDeviceExtension
,
5543 IN PSCSI_REQUEST_BLOCK Srb
5546 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5547 UCHAR lChannel
= GET_CHANNEL(Srb
);
5548 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5549 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5550 PHW_LU_EXTENSION LunExt
;
5551 ULONG ldev
= GET_LDEV(Srb
);
5553 ULONG startingSector
;
5559 LunExt
= &deviceExtension
->lun
[ldev
];
5560 // Drive has these number sectors.
5561 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
5562 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
5563 LunExt
->IdentifyData
.NumberOfHeads
*
5564 LunExt
->IdentifyData
.NumberOfCylinders
;
5567 KdPrint2((PRINT_PREFIX
5568 "IdeVerify: Total sectors %#x\n",
5571 // Get starting sector number from CDB.
5572 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
5573 MOV_DW_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
5575 KdPrint2((PRINT_PREFIX
5576 "IdeVerify: Starting sector %#x. Number of blocks %#x\n",
5580 endSector
= startingSector
+ sectorCount
;
5582 KdPrint2((PRINT_PREFIX
5583 "IdeVerify: Ending sector %#x\n",
5586 if (endSector
> sectors
) {
5588 // Too big, round down.
5589 KdPrint2((PRINT_PREFIX
5590 "IdeVerify: Truncating request to %#x blocks\n",
5591 sectors
- startingSector
- 1));
5593 sectorCount
= (USHORT
)(sectors
- startingSector
- 1);
5597 // Set up sector count register. Round up to next block.
5598 if (sectorCount
> 0xFF) {
5599 sectorCount
= (USHORT
)0xFF;
5603 // Set data buffer pointer and words left.
5604 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
5605 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
5607 // Indicate expecting an interrupt.
5608 InterlockedExchange(&(chan
->CheckIntr
),
5611 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
);
5613 statusByte
= AtaCommand48(deviceExtension
, ldev
& 0x01, GET_CHANNEL(Srb
),
5614 IDE_COMMAND_VERIFY
, lba
,
5618 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5619 // Wait for interrupt.
5620 return SRB_STATUS_PENDING
;
5622 return SRB_STATUS_ERROR
;
5624 } // end IdeVerify()
5626 #endif //UNIATA_CORE
5630 Routine Description:
5631 Send ATAPI packet command to device.
5634 HwDeviceExtension - HBA miniport driver's adapter data storage
5635 Srb - IO request packet
5642 IN PVOID HwDeviceExtension
,
5643 IN PSCSI_REQUEST_BLOCK Srb
,
5647 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5648 UCHAR lChannel
= GET_CHANNEL(Srb
);
5649 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5650 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5651 ULONG ldev
= GET_LDEV(Srb
);
5654 UCHAR statusByte
,byteCountLow
,byteCountHigh
;
5655 BOOLEAN use_dma
= FALSE
;
5656 BOOLEAN dma_reinited
= FALSE
;
5658 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: req state %#x\n", AtaReq
->ReqState
));
5659 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
5660 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
5662 #ifdef UNIATA_DUMP_ATAPI
5663 if(CmdAction
& CMD_ACTION_PREPARE
) {
5667 PCHAR ModeSelectData
;
5670 Cdb
= (PCDB
)(Srb
->Cdb
);
5671 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
5672 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
5673 CdbDataLen
= Srb
->DataTransferLength
;
5675 if(CdbDataLen
> 0x1000) {
5676 CdbDataLen
= 0x1000;
5680 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
5681 KdPrint2(("P:T:D=%d:%d:%d\n",
5685 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
5688 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
5689 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
5690 Cdb
->WRITE_CD
.LBA
[0],
5691 Cdb
->WRITE_CD
.LBA
[1],
5692 Cdb
->WRITE_CD
.LBA
[2],
5693 Cdb
->WRITE_CD
.LBA
[3]
5696 if(ScsiCommand
== SCSIOP_WRITE12
) {
5697 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
5698 Cdb
->CDB12READWRITE
.LBA
[0],
5699 Cdb
->CDB12READWRITE
.LBA
[1],
5700 Cdb
->CDB12READWRITE
.LBA
[2],
5701 Cdb
->CDB12READWRITE
.LBA
[3]
5704 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
5705 KdPrint(("ModeSelect 6\n"));
5706 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5707 ModeSelectData
= CdbData
+4;
5708 KdDump(CdbData
, CdbDataLen
);
5710 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
5711 KdPrint(("ModeSelect 10\n"));
5712 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5713 ModeSelectData
= CdbData
+8;
5714 KdDump(CdbData
, CdbDataLen
);
5716 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5717 KdPrint(("Send buffer to device:\n"));
5718 KdDump(CdbData
, CdbDataLen
);
5723 #endif //UNIATA_DUMP_ATAPI
5726 if(CmdAction
== CMD_ACTION_PREPARE
) {
5727 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE\n"));
5728 switch (Srb
->Cdb
[0]) {
5732 case SCSIOP_WRITE12
:
5736 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
5737 return SRB_STATUS_BUSY
;
5740 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
5741 !AtaReq
->OriginalSrb
) {
5742 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
5743 return SRB_STATUS_BUSY
;
5747 if((CmdAction
& CMD_ACTION_PREPARE
) &&
5748 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
5750 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x\n", Srb
->Cdb
[0]));
5751 // Set data buffer pointer and words left.
5752 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
5753 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
5754 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
5755 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5757 // check if reorderable
5758 switch(Srb
->Cdb
[0]) {
5760 case SCSIOP_WRITE12
:
5762 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
5768 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
5770 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
5772 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
5773 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
5774 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
|| Srb
->Cdb
[0] == SCSIOP_WRITE12
) ?
5775 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
5779 // check if DMA read/write
5780 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
5781 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
5783 if(AtaReq
->TransferLength
) {
5785 switch(Srb
->Cdb
[0]) {
5787 case SCSIOP_WRITE12
:
5788 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
5794 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
5796 if(AtapiDmaSetup(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
,
5797 (PUCHAR
)(AtaReq
->DataBuffer
),
5798 Srb
->DataTransferLength
5799 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
5801 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
5806 case SCSIOP_READ_CD
:
5807 if(deviceExtension
->opt_AtapiDmaRawRead
)
5808 goto call_dma_setup
;
5812 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
5813 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5818 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
5819 KdPrint2((PRINT_PREFIX
"dma RO\n"));
5830 if(!AtapiDmaSetup(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
,
5831 (PUCHAR
)(AtaReq
->DataBuffer
),
5832 Srb
->DataTransferLength
)) {
5833 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
5836 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
5840 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer, no DMA setup\n"));
5844 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
5845 // if this is queued request, reinit DMA and check
5846 // if DMA mode is still available
5847 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
5848 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
5849 if (/*EnableDma &&*/
5850 (deviceExtension
->lun
[ldev
].TransferMode
>= ATA_DMA
)) {
5851 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
5854 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5855 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
5858 dma_reinited
= TRUE
;
5862 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
5863 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
5864 return SRB_STATUS_PENDING
;
5866 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
5867 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
5868 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
5871 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
5872 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
5874 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5875 //AtapiDmaReinit(deviceExtension, ldev, AtaReq);
5876 } if(AtaReq
->TransferLength
) {
5878 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
5879 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
5880 if (/*EnableDma &&*/
5881 (deviceExtension
->lun
[ldev
].TransferMode
>= ATA_DMA
)) {
5884 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5889 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
5891 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5892 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
) {
5893 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
5894 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
5897 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
5898 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
5899 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
5902 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
5905 // We need to know how many platters our atapi cd-rom device might have.
5906 // Before anyone tries to send a srb to our target for the first time,
5907 // we must "secretly" send down a separate mechanism status srb in order to
5908 // initialize our device extension changer data. That's how we know how
5909 // many platters our target has.
5911 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
5912 !AtaReq
->OriginalSrb
) {
5916 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
5917 // Set this flag now. If the device hangs on the mech. status
5918 // command, we will not have the chance to set it.
5919 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_CHANGER_INITED
;
5921 chan
->MechStatusRetryCount
= 3;
5922 AtaReq
->OriginalSrb
= Srb
;
5923 AtaReq
->Srb
= BuildMechanismStatusSrb (
5927 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
5928 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
5929 if (srbStatus
== SRB_STATUS_PENDING
) {
5930 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
5933 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5934 AtaReq
->OriginalSrb
= NULL
;
5935 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiHwInitializeChanger()\n"));
5936 AtapiHwInitializeChanger (HwDeviceExtension
, Srb
,
5937 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
5941 #endif //UNIATA_CORE
5943 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Command %#x to TargetId %d lun %d\n",
5944 Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
5946 // Make sure command is to ATAPI device.
5947 flags
= deviceExtension
->lun
[ldev
].DeviceFlags
;
5948 if (flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
5949 if ((Srb
->Lun
) > (deviceExtension
->lun
[ldev
].DiscsPresent
- 1)) {
5951 // Indicate no device found at this address.
5952 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
5953 return SRB_STATUS_SELECTION_TIMEOUT
;
5955 } else if (Srb
->Lun
> 0) {
5956 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
5957 return SRB_STATUS_SELECTION_TIMEOUT
;
5960 if (!(flags
& DFLAGS_ATAPI_DEVICE
)) {
5961 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
5962 return SRB_STATUS_SELECTION_TIMEOUT
;
5965 // Select device 0 or 1.
5966 SelectDrive(chan
, ldev
& 0x1);
5968 // Verify that controller is ready for next command.
5969 GetStatus(chan
, statusByte
);
5970 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
5972 if (statusByte
== 0xff) {
5973 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
5976 if (statusByte
& IDE_STATUS_BUSY
) {
5977 if(statusByte
& IDE_STATUS_DSC
) {
5978 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
5980 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x)\n", statusByte
));
5981 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
5982 return SRB_STATUS_BUSY
;
5984 if (statusByte
& IDE_STATUS_ERROR
) {
5985 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
5987 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
5988 // Read the error reg. to clear it and fail this request.
5989 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
5990 return MapError(deviceExtension
, Srb
);
5992 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
5995 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
5996 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
5997 if ((!(statusByte
& IDE_STATUS_DSC
)) &&
5998 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
6000 AtapiStallExecution(200);
6001 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
6002 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
6003 return SRB_STATUS_PENDING
;
6006 if (IS_RDP(Srb
->Cdb
[0])) {
6008 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
6012 if (statusByte
& IDE_STATUS_DRQ
) {
6014 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
6016 // Try to drain the data that one preliminary device thinks that it has
6017 // to transfer. Hopefully this random assertion of DRQ will not be present
6018 // in production devices.
6019 for (i
= 0; i
< 0x10000; i
++) {
6020 GetStatus(chan
, statusByte
);
6021 if (statusByte
& IDE_STATUS_DRQ
) {
6022 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
6030 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte
));
6032 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6034 AtapiSoftReset(chan
, ldev
& 1);
6036 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
6037 // Re-initialize Atapi device.
6038 IssueIdentify(HwDeviceExtension
, ldev
& 1, GET_CHANNEL(Srb
),
6039 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
6040 // Inform the port driver that the bus has been reset.
6041 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
6042 // Clean up device extension fields that AtapiStartIo won't.
6043 chan
->ExpectingInterrupt
= FALSE
;
6045 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
6048 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6050 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6051 return SRB_STATUS_BUS_RESET
;
6056 if (flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
6057 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
6058 Srb
->Cdb
[1] &= ~0xE0;
6059 if ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
6060 // Torisan changer. TUR's are overloaded to be platter switches.
6061 Srb
->Cdb
[7] = Srb
->Lun
;
6068 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
6070 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6073 statusByte
= WaitOnBusy(chan
);
6074 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
6077 AtapiWritePort1(chan
, IDX_IO1_o_Feature
,
6078 use_dma
? ATA_F_DMA
: 0);
6080 // Write transfer byte count to registers.
6081 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
6082 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
6084 if (Srb
->DataTransferLength
>= 0x10000) {
6085 byteCountLow
= byteCountHigh
= 0xFF;
6088 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
6089 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
6091 if (flags
& DFLAGS_INT_DRQ
) {
6093 // This device interrupts when ready to receive the packet.
6095 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
6098 chan
->ExpectingInterrupt
= TRUE
;
6099 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
6100 InterlockedExchange(&(chan
->CheckIntr
),
6103 // Write ATAPI packet command.
6104 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
6106 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING\n"));
6107 return SRB_STATUS_PENDING
;
6111 // This device quickly sets DRQ when ready to receive the packet.
6113 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
6116 chan
->ExpectingInterrupt
= TRUE
;
6117 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
6118 InterlockedExchange(&(chan
->CheckIntr
),
6121 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6123 // Write ATAPI packet command.
6124 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
6128 statusByte
= WaitForDrq(chan
);
6130 // Need to read status register and clear interrupt (if any)
6131 GetBaseStatus(chan
, statusByte
);
6133 if (!(statusByte
& IDE_STATUS_DRQ
)) {
6135 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6136 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte
));
6137 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6138 return SRB_STATUS_ERROR
;
6142 GetStatus(chan
, statusByte
);
6143 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
6145 // Send CDB to device.
6146 statusByte
= WaitOnBaseBusy(chan
);
6148 // Indicate expecting an interrupt and wait for it.
6149 chan
->ExpectingInterrupt
= TRUE
;
6150 InterlockedExchange(&(chan
->CheckIntr
),
6152 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
6154 GetBaseStatus(chan
, statusByte
);
6156 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6163 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
6164 AtapiDmaStart(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
);
6167 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
6169 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
6170 return SRB_STATUS_PENDING
;
6172 } // end AtapiSendCommand()
6179 Routine Description:
6180 Program ATA registers for IDE disk transfer.
6183 HwDeviceExtension - ATAPI driver storage.
6184 Srb - System request block.
6187 SRB status (pending if all goes well).
6192 ULONG check_point
= 0;
6193 #define SetCheckPoint(cp) { check_point = (cp) ; }
6195 #define SetCheckPoint(cp)
6200 IN PVOID HwDeviceExtension
,
6201 IN PSCSI_REQUEST_BLOCK Srb
,
6206 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
6209 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6217 UCHAR statusByte
,errorByte
;
6220 PMODE_PARAMETER_HEADER modeData
;
6224 //ULONG __ebp__ = 0;
6226 SetCheckPoint(0x20);
6227 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
6232 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
6233 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
6234 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
6235 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
6236 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
6238 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
6239 Srb->SrbExtension));
6240 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
6243 SetCheckPoint(0x30);
6244 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6246 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
6248 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
6250 KdPrint2((PRINT_PREFIX
"** --- **\n"));
6252 lChannel
= GET_CHANNEL(Srb
);
6253 chan
= &(deviceExtension
->chan
[lChannel
]);
6254 ldev
= GET_LDEV(Srb
);
6256 SetCheckPoint(0x40);
6257 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
6258 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
6260 if(CmdAction
== CMD_ACTION_PREPARE
) {
6261 switch (Srb
->Cdb
[0]) {
6262 //case SCSIOP_INQUIRY: // now it requires device access
6263 case SCSIOP_READ_CAPACITY
:
6266 case SCSIOP_REQUEST_SENSE
:
6268 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
6273 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
6274 return SRB_STATUS_BUSY
;
6278 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
6279 switch (Srb
->Cdb
[0]) {
6280 case SCSIOP_INQUIRY
:
6282 KdPrint2((PRINT_PREFIX
6283 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
6284 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6285 // Filter out all TIDs but 0 and 1 since this is an IDE interface
6286 // which support up to two devices.
6287 if ((Srb
->Lun
!= 0) ||
6288 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
6289 (Srb
->TargetId
> 2) /*||
6290 (!deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT)*/) {
6292 KdPrint2((PRINT_PREFIX
6293 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
6294 // Indicate no device found at this address.
6295 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6300 KdPrint2((PRINT_PREFIX
6301 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
6302 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
6303 PIDENTIFY_DATA2 identifyData
= &(deviceExtension
->lun
[ldev
].IdentifyData
);
6305 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
6307 if(!CheckDevice(HwDeviceExtension
, lChannel
, ldev
& 1, FALSE
)) {
6308 KdPrint2((PRINT_PREFIX
6309 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
6310 // Indicate no device found at this address.
6311 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6315 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, ldev
& 1)) {
6316 KdPrint2((PRINT_PREFIX
6317 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
6318 // Indicate no device found at this address.
6319 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_DEVICE_PRESENT
;
6320 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6325 // Zero INQUIRY data structure.
6326 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
6328 // Standard IDE interface only supports disks.
6329 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
6331 // Set the removable bit, if applicable.
6332 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
6333 KdPrint2((PRINT_PREFIX
6334 "RemovableMedia\n"));
6335 inquiryData
->RemovableMedia
= 1;
6337 // Set the Relative Addressing (LBA) bit, if applicable.
6338 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6339 inquiryData
->RelativeAddressing
= 1;
6340 KdPrint2((PRINT_PREFIX
6341 "RelativeAddressing\n"));
6343 // Set the CommandQueue bit
6344 inquiryData
->CommandQueue
= 1;
6346 // Fill in vendor identification fields.
6347 for (i
= 0; i
< 24; i
+= 2) {
6348 MOV_DW_SWP(inquiryData
->VendorId
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
6351 // Initialize unused portion of product id.
6352 for (i = 0; i < 4; i++) {
6353 inquiryData->ProductId[12+i] = ' ';
6356 // Move firmware revision from IDENTIFY data to
6357 // product revision in INQUIRY data.
6358 for (i
= 0; i
< 4; i
+= 2) {
6359 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
6362 status
= SRB_STATUS_SUCCESS
;
6367 case SCSIOP_MODE_SENSE
:
6369 KdPrint2((PRINT_PREFIX
6370 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
6371 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6372 // This is used to determine if the media is write-protected.
6373 // Since IDE does not support mode sense then we will modify just the portion we need
6374 // so the higher level driver can determine if media is protected.
6375 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6377 SelectDrive(chan
, ldev
& 0x1);
6378 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_GET_MEDIA_STATUS
);
6379 statusByte
= WaitOnBusy(chan
);
6381 if (!(statusByte
& IDE_STATUS_ERROR
)){
6383 // no error occured return success, media is not protected
6384 chan
->ExpectingInterrupt
= FALSE
;
6385 InterlockedExchange(&(chan
->CheckIntr
),
6387 status
= SRB_STATUS_SUCCESS
;
6391 // error occured, handle it locally, clear interrupt
6392 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6394 GetBaseStatus(chan
, statusByte
);
6395 chan
->ExpectingInterrupt
= FALSE
;
6396 InterlockedExchange(&(chan
->CheckIntr
),
6398 status
= SRB_STATUS_SUCCESS
;
6400 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
6402 //media is write-protected, set bit in mode sense buffer
6403 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
6405 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
6406 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
6409 status
= SRB_STATUS_SUCCESS
;
6411 status
= SRB_STATUS_INVALID_REQUEST
;
6415 case SCSIOP_TEST_UNIT_READY
:
6417 KdPrint2((PRINT_PREFIX
6418 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
6419 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6420 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6422 // Select device 0 or 1.
6423 SelectDrive(chan
, ldev
& 0x1);
6424 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_GET_MEDIA_STATUS
);
6426 // Wait for busy. If media has not changed, return success
6427 statusByte
= WaitOnBusy(chan
);
6429 if (!(statusByte
& IDE_STATUS_ERROR
)){
6430 chan
->ExpectingInterrupt
= FALSE
;
6431 InterlockedExchange(&(chan
->CheckIntr
),
6433 status
= SRB_STATUS_SUCCESS
;
6435 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6436 if (errorByte
== IDE_ERROR_DATA_ERROR
){
6438 // Special case: If current media is write-protected,
6439 // the 0xDA command will always fail since the write-protect bit
6440 // is sticky,so we can ignore this error
6441 GetBaseStatus(chan
, statusByte
);
6442 chan
->ExpectingInterrupt
= FALSE
;
6443 InterlockedExchange(&(chan
->CheckIntr
),
6445 status
= SRB_STATUS_SUCCESS
;
6449 // Request sense buffer to be build
6450 chan
->ExpectingInterrupt
= TRUE
;
6451 InterlockedExchange(&(chan
->CheckIntr
),
6453 status
= SRB_STATUS_PENDING
;
6457 status
= SRB_STATUS_SUCCESS
;
6462 case SCSIOP_READ_CAPACITY
:
6464 KdPrint2((PRINT_PREFIX
6465 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
6466 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6467 // Claim 512 byte blocks (big-endian).
6468 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
6470 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
6472 // Calculate last sector.
6473 if(!(i
= (ULONG
)deviceExtension
->lun
[ldev
].NumOfSectors
)) {
6474 i
= deviceExtension
->lun
[ldev
].IdentifyData
.SectorsPerTrack
*
6475 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfHeads
*
6476 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfCylinders
;
6480 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
6481 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
6482 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
6484 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
6486 KdPrint2((PRINT_PREFIX
6487 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
6489 deviceExtension
->lun
[ldev
].IdentifyData
.SectorsPerTrack
,
6490 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfHeads
,
6491 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfCylinders
));
6494 status
= SRB_STATUS_SUCCESS
;
6499 KdPrint2((PRINT_PREFIX
6500 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
6501 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6502 status
= IdeVerify(HwDeviceExtension
,Srb
);
6509 KdPrint2((PRINT_PREFIX
6510 "IdeSendCommand: SCSIOP_READ/SCSIOP_WRITE PATH:LUN:TID = %#x:%#x:%#x\n",
6511 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6512 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6513 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
6514 status
= IdeReadWrite(HwDeviceExtension
,
6518 case SCSIOP_START_STOP_UNIT
:
6520 KdPrint2((PRINT_PREFIX
6521 "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
6522 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6523 //Determine what type of operation we should perform
6524 cdb
= (PCDB
)Srb
->Cdb
;
6526 if (cdb
->START_STOP
.LoadEject
== 1){
6528 statusByte
= WaitOnBaseBusy(chan
);
6530 // first select device 0 or 1.
6531 SelectDrive(chan
, ldev
& 0x1);
6532 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_MEDIA_EJECT
);
6534 status
= SRB_STATUS_SUCCESS
;
6537 case SCSIOP_MEDIUM_REMOVAL
:
6539 cdb
= (PCDB
)Srb
->Cdb
;
6541 statusByte
= WaitOnBaseBusy(chan
);
6543 SelectDrive(chan
, ldev
& 0x1);
6544 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
6545 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_DOOR_LOCK
);
6547 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_DOOR_UNLOCK
);
6549 status
= SRB_STATUS_SUCCESS
;
6552 // Note: I don't implement this, because NTFS driver too often issues this command
6553 // It causes awful performance degrade. However, if somebody wants, I will implement
6554 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
6557 case SCSIOP_FLUSH_BUFFER
:
6558 case SCSIOP_SYNCHRONIZE_CACHE
:
6560 SelectDrive(chan
, ldev
& 0x1);
6561 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
6562 status
= SRB_STATUS_SUCCESS
;
6563 // status = SRB_STATUS_PENDING;
6564 statusByte
= WaitOnBusy(chan
);
6568 case SCSIOP_REQUEST_SENSE
:
6569 // this function makes sense buffers to report the results
6570 // of the original GET_MEDIA_STATUS command
6572 KdPrint2((PRINT_PREFIX
6573 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
6574 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6575 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6576 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
6579 status
= SRB_STATUS_INVALID_REQUEST
;
6583 case SCSIOP_ATA_PASSTHROUGH
:
6586 BOOLEAN use_dma
= FALSE
;
6589 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
6591 lChannel
= Srb
->TargetId
>> 1;
6593 regs
->bDriveHeadReg
&= 0x0f;
6594 regs
->bDriveHeadReg
|= (UCHAR
) (((Srb
->TargetId
& 0x1) << 4) | 0xA0);
6596 if((regs
->bReserved
& 1) == 0) { // execute ATA command
6598 KdPrint2((PRINT_PREFIX
6599 "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
6600 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6603 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6605 if(AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) {
6606 if((chan
->lun
[Srb
->TargetId
& 0x1]->LimitedTransferMode
>= ATA_DMA
)) {
6608 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6609 if(!AtapiDmaSetup(HwDeviceExtension
, Srb
->TargetId
& 0x1, lChannel
, Srb
,
6610 (PUCHAR
)(Srb
->DataBuffer
),
6611 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
6617 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
6618 AtapiStallExecution(10);
6620 if((regs
->bReserved
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
6621 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
6622 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
6623 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
6624 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
6625 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
6627 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
6628 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
6629 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
6630 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
6631 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
6632 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
6633 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
6634 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
6635 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
6636 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
6638 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
6641 GetBaseStatus(chan
, statusByte
);
6642 if(statusByte
& IDE_STATUS_ERROR
) {
6643 goto passthrough_err
;
6645 AtapiDmaStart(HwDeviceExtension
, (Srb
->TargetId
& 0x1), lChannel
, Srb
);
6648 ScsiPortStallExecution(1); // wait for busy to be set
6650 if(regs
->bReserved
& UNIATA_SPTI_EX_SPEC_TO
) {
6651 to_lim
= Srb
->TimeOutValue
;
6653 if(Srb
->TimeOutValue
<= 2) {
6654 to_lim
= Srb
->TimeOutValue
*900;
6656 to_lim
= (Srb
->TimeOutValue
*999) - 500;
6659 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
6660 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
6661 GetBaseStatus(chan
, statusByte
);
6662 if(statusByte
& IDE_STATUS_ERROR
) {
6665 if(!(statusByte
& IDE_STATUS_BUSY
)) {
6670 //if(regs->bReserved & UNIATA_SPTI_EX_FREEZE_TO) {
6672 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
6673 goto passthrough_err
;
6677 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
6679 AtapiDmaDone(deviceExtension
, (Srb
->TargetId
& 0x1), lChannel
, NULL
);
6680 GetBaseStatus(chan
, statusByte
);
6682 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
6683 AtapiSuckPort2(chan
);
6685 if (Srb
->SenseInfoBuffer
) {
6687 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
6689 senseBuffer
->ErrorCode
= 0x70;
6690 senseBuffer
->Valid
= 1;
6691 senseBuffer
->AdditionalSenseLength
= 0xb;
6692 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
6693 senseBuffer
->AdditionalSenseCode
= 0;
6694 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
6696 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
6697 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
6699 status
= SRB_STATUS_ERROR
;
6703 if (statusByte
& IDE_STATUS_DRQ
) {
6704 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6706 (PUSHORT
) Srb
->DataBuffer
,
6707 Srb
->DataTransferLength
/ 2,
6709 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
6711 (PUSHORT
) Srb
->DataBuffer
,
6712 Srb
->DataTransferLength
/ 2,
6717 status
= SRB_STATUS_SUCCESS
;
6720 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6722 } else { // read task register
6724 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
6726 regs
->bDriveHeadReg
= AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
);
6728 if((regs
->bReserved
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
6729 regs
->bFeaturesReg
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6730 regs
->bSectorCountReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6731 regs
->bSectorNumberReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6732 regs
->bCylLowReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6733 regs
->bCylHighReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
6735 regs
->bFeaturesReg
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6736 regs
->bFeaturesRegH
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6737 regs
->bSectorCountReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6738 regs
->bSectorCountRegH
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6739 regs
->bSectorNumberReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6740 regs
->bSectorNumberRegH
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6741 regs
->bCylLowReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6742 regs
->bCylLowRegH
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6743 regs
->bCylHighReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
6744 regs
->bCylHighRegH
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
6746 regs
->bCommandReg
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
6747 status
= SRB_STATUS_SUCCESS
;
6754 KdPrint2((PRINT_PREFIX
6755 "IdeSendCommand: Unsupported command %#x\n",
6758 status
= SRB_STATUS_INVALID_REQUEST
;
6762 if(status
== SRB_STATUS_PENDING
) {
6763 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
6764 if(CmdAction
& CMD_ACTION_EXEC
) {
6765 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
6766 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
6769 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
6770 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6775 } // end IdeSendCommand()
6780 Routine Description:
6781 Enables disables media status notification
6784 HwDeviceExtension - ATAPI driver storage.
6790 IN PVOID HwDeviceExtension
,
6794 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6796 UCHAR lChannel
= ldev
>> 1;
6797 UCHAR statusByte
,errorByte
;
6799 chan
= &(deviceExtension
->chan
[lChannel
]);
6801 if (EnableMSN
== TRUE
){
6803 // If supported enable Media Status Notification support
6804 if ((deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
6807 statusByte
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
6808 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
6809 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
6811 if (statusByte
& IDE_STATUS_ERROR
) {
6812 // Read the error register.
6813 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6815 KdPrint2((PRINT_PREFIX
6816 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
6820 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
6821 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
6822 chan
->ReturningMediaStatus
= 0;
6827 } else { // end if EnableMSN == TRUE
6829 // disable if previously enabled
6830 if ((deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
6832 statusByte
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
6833 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
6834 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
6835 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
6842 } // end IdeMediaStatus()
6847 Routine Description:
6849 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
6850 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
6853 HwDeviceExtension - ATAPI driver storage.
6854 Srb - System request block.
6858 SRB status (ALWAYS SUCCESS).
6862 IdeBuildSenseBuffer(
6863 IN PVOID HwDeviceExtension
,
6864 IN PSCSI_REQUEST_BLOCK Srb
6867 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6869 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
6870 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
6874 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
6876 senseBuffer
->ErrorCode
= 0x70;
6877 senseBuffer
->Valid
= 1;
6878 senseBuffer
->AdditionalSenseLength
= 0xb;
6879 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
6880 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
6881 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
6882 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
6884 senseBuffer
->ErrorCode
= 0x70;
6885 senseBuffer
->Valid
= 1;
6886 senseBuffer
->AdditionalSenseLength
= 0xb;
6887 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
6888 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
6889 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
6890 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
6892 senseBuffer
->ErrorCode
= 0x70;
6893 senseBuffer
->Valid
= 1;
6894 senseBuffer
->AdditionalSenseLength
= 0xb;
6895 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
6896 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
6897 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
6898 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
6900 senseBuffer
->ErrorCode
= 0x70;
6901 senseBuffer
->Valid
= 1;
6902 senseBuffer
->AdditionalSenseLength
= 0xb;
6903 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
6904 senseBuffer
->AdditionalSenseCode
= 0;
6905 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
6907 return SRB_STATUS_SUCCESS
;
6909 return SRB_STATUS_ERROR
;
6911 }// End of IdeBuildSenseBuffer
6914 UniataUserDeviceReset(
6915 PHW_DEVICE_EXTENSION deviceExtension
,
6916 PHW_LU_EXTENSION LunExt
,
6921 AtapiDisableInterrupts(deviceExtension
, PathId
);
6922 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
6923 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
6924 AtapiSoftReset(&(deviceExtension
->chan
[PathId
]), ldev
& 1);
6926 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
6927 AtapiResetController__(deviceExtension
, PathId
, RESET_COMPLETE_NONE
);
6929 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
6930 AtapiEnableInterrupts(deviceExtension
, PathId
);
6932 } // end UniataUserDeviceReset()
6936 PHW_DEVICE_EXTENSION deviceExtension
,
6941 BOOLEAN PostReq
= FALSE
;
6943 if(chan
->queue_depth
> 0) {
6946 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
6947 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
6948 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
6950 status
= SRB_STATUS_BUSY
;
6959 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
6964 } // end UniataNeedQueueing()
6968 Routine Description:
6970 This routine is called from the SCSI port driver synchronized
6971 with the kernel to start an IO request.
6975 HwDeviceExtension - HBA miniport driver's adapter data storage
6976 Srb - IO request packet
6986 IN PVOID HwDeviceExtension
,
6987 IN PSCSI_REQUEST_BLOCK Srb
6990 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
6991 } // end AtapiStartIo()
6995 IN PVOID HwDeviceExtension
,
6996 IN PSCSI_REQUEST_BLOCK Srb
,
7000 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7009 PSCSI_REQUEST_BLOCK tmpSrb
;
7010 BOOLEAN PostReq
= FALSE
;
7013 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
7014 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
7015 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
7017 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
7019 /* KeBugCheckEx(0xc000000e,
7020 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7022 TopLevel, 0x80000001);
7024 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
7025 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
7026 RtlZeroMemory(Srb
->SrbExtension
, sizeof(ATA_REQ
));
7031 lChannel
= GET_CHANNEL(Srb
);
7032 chan
= &(deviceExtension
->chan
[lChannel
]);
7033 ldev
= GET_LDEV(Srb
);
7035 //ASSERT(deviceExtension);
7038 KdPrint2((PRINT_PREFIX
7039 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
7040 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7041 KdPrint2((PRINT_PREFIX
" VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
7043 if(GET_CDEV(Srb
) >= 2 ||
7044 ldev
>= deviceExtension
->NumberChannels
*2 ||
7045 lChannel
>= deviceExtension
->NumberChannels
||
7048 if(lChannel
>= deviceExtension
->NumberChannels
) {
7053 //if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) {
7054 KdPrint2((PRINT_PREFIX
7055 "AtapiStartIo: SRB rejected\n"));
7056 // Indicate no device found at this address.
7057 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7058 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7063 atapiDev
= (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
7066 if(!(chan
->lun
[ldev
& 1])) {
7067 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
7070 deviceExtension
->NumberChannels
);
7071 PrintNtConsole("lchan = %#x, ldev %#x, cdev %#x, lun0 %#x\n",
7072 lChannel
, ldev
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
7073 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
7074 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
7077 for(i=0; i<1000; i++) {
7078 AtapiStallExecution(3*1000);
7084 //ASSERT(chan->lun[ldev & 1]);
7086 // Determine which function.
7087 switch (Srb
->Function
) {
7089 case SRB_FUNCTION_EXECUTE_SCSI
:
7091 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7092 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
7093 // let passthrough go
7095 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
7099 //if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) {
7100 KdPrint2((PRINT_PREFIX
7101 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
7102 // Indicate no device found at this address.
7103 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7104 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7111 if(Srb->DataTransferLength) {
7113 a = ((PUCHAR)(Srb->DataBuffer))[0];
7116 } __except(EXCEPTION_EXECUTE_HANDLER) {
7117 KdPrint2((PRINT_PREFIX
7118 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
7119 // Indicate no device found at this address.
7120 KdPrint2((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
7121 status = SRB_STATUS_ERROR;
7122 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
7127 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7131 KdPrint2((PRINT_PREFIX
"Non-empty queue\n"));
7133 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
7134 KdPrint2((PRINT_PREFIX
"Try ATAPI prepare\n"));
7136 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
7138 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
7139 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
7141 /*KeBugCheckEx(0xc000000e,
7142 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7144 status, 0x80000001);*/
7145 if(status
== SRB_STATUS_BUSY
)
7146 status
= SRB_STATUS_PENDING
;
7147 // Insert requests AFTER they have been initialized on
7148 // CMD_ACTION_PREPARE stage
7149 // we should not check TopLevel here (it is always TRUE)
7150 //ASSERT(chan->lun[GET_LDEV(Srb) & 1]);
7151 UniataQueueRequest(chan
, Srb
);
7153 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7156 // Send command to device.
7157 KdPrint2((PRINT_PREFIX
"Send to device\n"));
7159 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
7160 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7161 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
7162 //ASSERT(!AtaReq->Flags);
7163 //ASSERT(chan->lun[GET_LDEV(Srb) & 1]);
7164 UniataQueueRequest(chan
, Srb
);
7165 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
7166 //ASSERT(!AtaReq->Flags);
7167 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7168 //ASSERT(!AtaReq->Flags);
7171 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7172 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
7173 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, ldev
& 1)) {
7174 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, ldev
& 1, TRUE
)) {
7178 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7182 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
7190 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
7191 KdPrint2((PRINT_PREFIX
"Try ATAPI send\n"));
7192 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
7194 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
7199 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
7206 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
7208 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
7210 /* KeBugCheckEx(0xc000000e,
7211 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7213 status, 0x80000002);*/
7221 case SRB_FUNCTION_ABORT_COMMAND
:
7223 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
7225 // Verify that SRB to abort is still outstanding.
7226 if((tmpSrb
!= Srb
->NextSrb
) ||
7227 !chan
->queue_depth
) {
7229 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
7231 // Complete abort SRB.
7232 status
= SRB_STATUS_ABORT_FAILED
;
7236 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
7237 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
7238 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
7239 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
7240 // Log reset failure.
7241 KdPrint2((PRINT_PREFIX
7242 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
7243 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
7245 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
7246 status
= SRB_STATUS_ERROR
;
7249 status
= SRB_STATUS_SUCCESS
;
7252 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
7253 if (tmpSrb
->SenseInfoBuffer
&&
7254 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
7256 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
7258 senseBuffer
->ErrorCode
= 0;
7259 senseBuffer
->Valid
= 1;
7260 senseBuffer
->AdditionalSenseLength
= 0xb;
7261 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
7262 senseBuffer
->AdditionalSenseCode
= 0;
7263 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7265 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
7267 AtapiDmaDBSync(chan
, tmpSrb
);
7268 UniataRemoveRequest(chan
, tmpSrb
);
7269 // Indicate command complete.
7270 ScsiPortNotification(RequestComplete
,
7273 status
= SRB_STATUS_SUCCESS
;
7277 // Abort function indicates that a request timed out.
7278 // Call reset routine. Card will only be reset if
7279 // status indicates something is wrong.
7280 // Fall through to reset code.
7282 case SRB_FUNCTION_RESET_DEVICE
:
7283 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
7285 // Reset single device.
7286 // For now we support only Lun=0
7288 // Note: reset is immediate command, it cannot be queued since it is usually used to
7289 // revert not- responding device to operational state
7290 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
7291 UniataUserDeviceReset(deviceExtension
, &(deviceExtension
->lun
[ldev
]), lChannel
, ldev
);
7292 status
= SRB_STATUS_SUCCESS
;
7295 case SRB_FUNCTION_RESET_BUS
:
7297 // Reset Atapi and SCSI bus.
7299 // Note: reset is immediate command, it cannot be queued since it is usually used to
7300 // revert not- responding device to operational state
7301 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
7302 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
7303 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
7304 // Log reset failure.
7305 KdPrint2((PRINT_PREFIX
7306 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
7307 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
7309 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
7310 status
= SRB_STATUS_ERROR
;
7313 status
= SRB_STATUS_SUCCESS
;
7318 case SRB_FUNCTION_SHUTDOWN
:
7320 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
7321 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7322 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
7325 // FLUSH ATAPI device - do nothing
7326 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
7328 // FLUSH IDE/ATA device
7329 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
7330 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7331 status
= AtaCommand(deviceExtension
, ldev
& 1, GET_CHANNEL(Srb
),
7332 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
7333 // If supported & allowed, reset write cacheing
7334 if(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
7336 // Disable write cache
7337 status
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7338 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7339 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
7340 // Check for errors.
7341 if (status
& IDE_STATUS_ERROR
) {
7342 KdPrint2((PRINT_PREFIX
7343 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
7346 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
7348 // Re-enable write cache
7349 status
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7350 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7351 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
7352 // Check for errors.
7353 if (status
& IDE_STATUS_ERROR
) {
7354 KdPrint2((PRINT_PREFIX
7355 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
7357 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
7359 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
7363 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7365 status
= SRB_STATUS_SUCCESS
;
7369 case SRB_FUNCTION_FLUSH
:
7371 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
7372 status
= SRB_STATUS_SUCCESS
;
7375 /* case SRB_FUNCTION_SHUTDOWN:
7376 case SRB_FUNCTION_FLUSH:
7378 // Flush device's cache.
7379 KdPrint2((PRINT_PREFIX "AtapiStartIo: Device flush received\n"));
7381 if (chan->CurrentSrb) {
7383 KdPrint2((PRINT_PREFIX "AtapiStartIo (SRB_FUNCTION_FLUSH): Already have a request!\n"));
7384 Srb->SrbStatus = SRB_STATUS_BUSY;
7385 ScsiPortNotification(RequestComplete,
7391 if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) {
7392 status = SRB_STATUS_SUCCESS;
7394 status = AtaCommand(deviceExtension, ldev & 1, GET_CHANNEL(Srb),
7395 IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_INTR);
7396 if (status & IDE_STATUS_DRQ) {
7397 status = SRB_STATUS_SUCCESS;
7399 status = SRB_STATUS_SELECTION_TIMEOUT;
7404 case SRB_FUNCTION_IO_CONTROL
: {
7408 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
7410 len
= Srb
->DataTransferLength
;
7412 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
7414 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
7415 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
7417 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7420 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
7422 // Version and revision per SMART 1.03
7424 versionParameters
->bVersion
= 1;
7425 versionParameters
->bRevision
= 1;
7426 versionParameters
->bReserved
= 0;
7428 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
7429 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
7431 // This is done because of how the IOCTL_SCSI_MINIPORT
7432 // determines 'targetid's'. Disk.sys places the real target id value
7433 // in the DeviceMap field. Once we do some parameter checking, the value passed
7434 // back to the application will be determined.
7436 deviceNumber
= versionParameters
->bIDEDeviceMap
;
7438 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
) ||
7441 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7445 // NOTE: This will only set the bit
7446 // corresponding to this drive's target id.
7447 // The bit mask is as follows:
7453 if (deviceExtension
->NumberChannels
== 1) {
7454 if (chan
->PrimaryAddress
) {
7455 deviceNumber
= 1 << ldev
;
7457 deviceNumber
= 4 << ldev
;
7460 deviceNumber
= 1 << ldev
;
7463 versionParameters
->bIDEDeviceMap
= deviceNumber
;
7465 status
= SRB_STATUS_SUCCESS
;
7469 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
7471 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7472 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7475 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
7476 // Extract the target.
7477 targetId
= cmdInParameters
.bDriveNumber
;
7478 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
7479 if((targetId
>= deviceExtension
->NumberChannels
*2) ||
7480 !(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7481 KdPrint2((PRINT_PREFIX
"Error: xxx_ID_CMD for non-existant device\n"));
7482 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7486 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
7488 if((deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
7489 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
7490 status
= SRB_STATUS_INVALID_REQUEST
;
7496 if(!(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
7497 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
7498 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
7499 status
= SRB_STATUS_INVALID_REQUEST
;
7503 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
7504 // Zero the output buffer
7505 RtlZeroMemory(cmdOutParameters
, len
);
7506 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
7507 ((PUCHAR)cmdOutParameters)[i] = 0;
7510 // Build status block.
7511 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
7512 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
7513 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
7515 // Extract the identify data from the device extension.
7516 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &deviceExtension
->lun
[targetId
].IdentifyData
,
7517 cmdOutParameters
->cBufferSize
);
7519 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
7521 status
= SRB_STATUS_SUCCESS
;
7525 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
7526 cmdInParameters
.irDriveRegs
.bCommandReg
));
7527 status
= SRB_STATUS_INVALID_REQUEST
;
7533 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
7534 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
7535 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
7536 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
7537 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
7538 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
7539 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
7540 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
7542 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7544 if(PostReq
|| TopLevel
) {
7545 UniataQueueRequest(chan
, Srb
);
7546 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7547 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7552 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
7553 status
= SRB_STATUS_PENDING
;
7555 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7558 status
= IdeSendSmartCommand(HwDeviceExtension
,Srb
);
7563 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
7564 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
7565 status
= SRB_STATUS_INVALID_REQUEST
;
7570 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
7572 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
7573 ULONG ldev
= GET_LDEV2(AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
, 0);
7574 PHW_LU_EXTENSION LunExt
= &(deviceExtension
->lun
[ldev
]);
7577 //chan = &(deviceExtension->chan[lChannel]);
7579 if(AtaCtl
->addr
.Lun
||
7580 ldev
>= deviceExtension
->NumberChannels
*2 ||
7581 AtaCtl
->addr
.PathId
> deviceExtension
->NumberChannels
) {
7588 LunExt
= &(deviceExtension
->lun
[ldev
]);
7591 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, ldev %#x\n", AtaCtl
->hdr
.ControlCode
, ldev
));
7593 /* check for valid LUN */
7594 switch (AtaCtl
->hdr
.ControlCode
) {
7595 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7596 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
7597 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
7598 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
7599 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
7600 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
7602 KdPrint2((PRINT_PREFIX
7603 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
7604 // Indicate no device found at this address.
7609 /* check if queueing is necessary */
7610 switch (AtaCtl
->hdr
.ControlCode
) {
7611 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
7612 if(!LunExt
->nBadBlocks
) {
7615 goto uata_ctl_queue
;
7616 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
7617 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
7620 goto uata_ctl_queue
;
7621 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7622 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
7624 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
7625 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7627 if(PostReq
|| TopLevel
) {
7628 UniataQueueRequest(chan
, Srb
);
7629 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7630 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7633 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
7634 status
= SRB_STATUS_PENDING
;
7636 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7641 /* process request */
7642 switch (AtaCtl
->hdr
.ControlCode
) {
7643 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7645 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
7647 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
7648 AtapiStallExecution(1000 * 1000);
7651 FindDevices(HwDeviceExtension
, FALSE
, AtaCtl
->addr
.PathId
);
7652 status
= SRB_STATUS_SUCCESS
;
7656 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
7658 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
7660 deviceExtension
->lun
[ldev
].DeviceFlags
= 0;
7662 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
7663 AtapiStallExecution(1000 * 1000);
7666 status
= SRB_STATUS_SUCCESS
;
7669 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
7671 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
7673 if(AtaCtl
->SetMode
.OrigMode
!= (ULONG
)-1) {
7674 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
7676 if(AtaCtl
->SetMode
.MaxMode
!= (ULONG
)-1) {
7677 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
7678 if(LunExt
->LimitedTransferMode
>
7679 LunExt
->OrigTransferMode
) {
7680 // check for incorrect value
7681 LunExt
->LimitedTransferMode
=
7682 LunExt
->OrigTransferMode
;
7685 LunExt
->TransferMode
= LunExt
->OrigTransferMode
;
7687 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
7688 if(AtaCtl
->SetMode
.ApplyImmediately
) {
7689 AtapiDmaInit__(deviceExtension
, ldev
);
7691 /* deviceExtension->lun[ldev].TransferMode =
7692 deviceExtension->lun[ldev].LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
7693 status
= SRB_STATUS_SUCCESS
;
7696 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
7698 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
7700 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
7701 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
7702 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
7704 status
= SRB_STATUS_SUCCESS
;
7707 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
7709 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
7711 AtaCtl
->AdapterInfo
.HeaderLength
= offsetof(ADAPTERINFO
, Chan
);
7713 if(len
< AtaCtl
->AdapterInfo
.HeaderLength
+ sizeof(AtaCtl
->AdapterInfo
.Chan
)) {
7714 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", len
,
7715 AtaCtl
->AdapterInfo
.HeaderLength
+ sizeof(AtaCtl
->AdapterInfo
.Chan
)));
7716 status
= SRB_STATUS_DATA_OVERRUN
;
7720 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
7721 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
7722 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
7723 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
7724 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
7725 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
7726 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
7727 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
7728 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
7729 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
7730 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
7731 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
7732 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
7733 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
7734 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
7735 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
7736 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
7737 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
7739 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
7741 RtlZeroMemory(&AtaCtl
->AdapterInfo
.Chan
, sizeof(AtaCtl
->AdapterInfo
.Chan
));
7743 status
= SRB_STATUS_SUCCESS
;
7746 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
7748 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
7750 ForgetBadBlocks(LunExt
);
7752 status
= SRB_STATUS_SUCCESS
;
7755 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
7757 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
7759 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
, ldev
);
7761 status
= SRB_STATUS_SUCCESS
;
7765 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
7766 AtaCtl
->hdr
.ControlCode
));
7767 status
= SRB_STATUS_INVALID_REQUEST
;
7772 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
7773 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
7774 "SCSIDISK", "-UNIATA-"));
7776 status
= SRB_STATUS_INVALID_REQUEST
;
7781 } // end SRB_FUNCTION_IO_CONTROL
7784 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
7785 // Indicate unsupported command.
7786 status
= SRB_STATUS_INVALID_REQUEST
;
7794 PathId
= Srb
->PathId
;
7795 TargetId
= Srb
->TargetId
;
7798 if (status
!= SRB_STATUS_PENDING
) {
7800 KdPrint2((PRINT_PREFIX
7801 "AtapiStartIo: Srb %#x complete with status %#x\n",
7805 // Set status in SRB.
7806 Srb
->SrbStatus
= (UCHAR
)status
;
7808 AtapiDmaDBSync(chan
, Srb
);
7809 UniataRemoveRequest(chan
, Srb
);
7810 // Indicate command complete.
7811 ScsiPortNotification(RequestComplete
,
7815 // Remove current Srb & get next one
7816 if((Srb
= UniataGetCurRequest(chan
))) {
7817 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7818 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
7819 // current request is under precessing, thus
7820 // we should do nothing here
7828 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
7830 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
7832 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
7833 // Indicate ready for next request.
7834 ScsiPortNotification(NextRequest
,
7838 ScsiPortNotification(NextLuRequest
,
7846 } // end AtapiStartIo__()
7850 UniataInitAtaCommands()
7856 for(i
=0, command
=0; i
<256; i
++, command
++) {
7859 case IDE_COMMAND_READ_DMA48
:
7860 case IDE_COMMAND_READ_DMA_Q48
:
7861 case IDE_COMMAND_READ_STREAM_DMA48
:
7862 case IDE_COMMAND_READ_STREAM48
:
7863 case IDE_COMMAND_WRITE_DMA48
:
7864 case IDE_COMMAND_WRITE_DMA_Q48
:
7865 case IDE_COMMAND_READ_DMA_Q
:
7866 case IDE_COMMAND_READ_DMA
:
7867 case IDE_COMMAND_WRITE_DMA
:
7868 case IDE_COMMAND_WRITE_DMA_Q
:
7869 case IDE_COMMAND_WRITE_STREAM_DMA48
:
7870 case IDE_COMMAND_WRITE_STREAM48
:
7871 case IDE_COMMAND_WRITE_FUA_DMA48
:
7872 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
7873 case IDE_COMMAND_READ_LOG_DMA48
:
7874 case IDE_COMMAND_WRITE_LOG_DMA48
:
7875 case IDE_COMMAND_TRUSTED_RCV_DMA
:
7876 case IDE_COMMAND_TRUSTED_SEND_DMA
:
7877 flags
|= ATA_CMD_FLAG_DMA
;
7881 case IDE_COMMAND_READ48
:
7882 case IDE_COMMAND_READ_DMA48
:
7883 case IDE_COMMAND_READ_DMA_Q48
:
7884 case IDE_COMMAND_READ_MUL48
:
7885 case IDE_COMMAND_READ_STREAM_DMA48
:
7886 case IDE_COMMAND_READ_STREAM48
:
7887 case IDE_COMMAND_WRITE48
:
7888 case IDE_COMMAND_WRITE_DMA48
:
7889 case IDE_COMMAND_WRITE_DMA_Q48
:
7890 case IDE_COMMAND_WRITE_MUL48
:
7891 case IDE_COMMAND_WRITE_STREAM_DMA48
:
7892 case IDE_COMMAND_WRITE_STREAM48
:
7893 case IDE_COMMAND_WRITE_FUA_DMA48
:
7894 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
7895 case IDE_COMMAND_WRITE_MUL_FUA48
:
7896 case IDE_COMMAND_FLUSH_CACHE48
:
7897 case IDE_COMMAND_VERIFY48
:
7899 flags
|= ATA_CMD_FLAG_48
;
7902 case IDE_COMMAND_READ
:
7903 case IDE_COMMAND_READ_MULTIPLE
:
7904 case IDE_COMMAND_READ_DMA
:
7905 case IDE_COMMAND_READ_DMA_Q
:
7906 case IDE_COMMAND_WRITE
:
7907 case IDE_COMMAND_WRITE_MULTIPLE
:
7908 case IDE_COMMAND_WRITE_DMA
:
7909 case IDE_COMMAND_WRITE_DMA_Q
:
7910 case IDE_COMMAND_FLUSH_CACHE
:
7911 case IDE_COMMAND_VERIFY
:
7913 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
7916 flags
|= ATA_CMD_FLAG_48supp
;
7919 case IDE_COMMAND_READ
:
7920 command
= IDE_COMMAND_READ48
; break;
7921 case IDE_COMMAND_READ_MULTIPLE
:
7922 command
= IDE_COMMAND_READ_MUL48
; break;
7923 case IDE_COMMAND_READ_DMA
:
7924 command
= IDE_COMMAND_READ_DMA48
; break;
7925 case IDE_COMMAND_READ_DMA_Q
:
7926 command
= IDE_COMMAND_READ_DMA_Q48
; break;
7927 case IDE_COMMAND_WRITE
:
7928 command
= IDE_COMMAND_WRITE48
; break;
7929 case IDE_COMMAND_WRITE_MULTIPLE
:
7930 command
= IDE_COMMAND_WRITE_MUL48
; break;
7931 case IDE_COMMAND_WRITE_DMA
:
7932 command
= IDE_COMMAND_WRITE_DMA48
; break;
7933 case IDE_COMMAND_WRITE_DMA_Q
:
7934 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
7935 case IDE_COMMAND_FLUSH_CACHE
:
7936 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
7937 case IDE_COMMAND_READ_NATIVE_SIZE
:
7938 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
7939 case IDE_COMMAND_SET_NATIVE_SIZE
:
7940 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
7941 case IDE_COMMAND_VERIFY
:
7942 command
= IDE_COMMAND_VERIFY48
; break;
7944 flags
&= ~ATA_CMD_FLAG_48supp
;
7947 AtaCommands48
[i
] = command
;
7948 AtaCommandFlags
[i
] = flags
;
7950 } // end UniataInitAtaCommands()
7954 Routine Description:
7956 Installable driver initialization entry point for system.
7964 Status from ScsiPortInitialize()
7971 IN PVOID DriverObject
,
7975 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
7978 ULONG statusToReturn
, newStatus
;
7979 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
7980 BOOLEAN ReEnter
= FALSE
;
7983 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
7984 BOOLEAN PrimaryClaimed
= FALSE
;
7985 BOOLEAN SecondaryClaimed
= FALSE
;
7987 LARGE_INTEGER t0
, t1
;
7990 KdPrint2((PRINT_PREFIX (PCCHAR
)ver_string
));
7991 a
= (WCHAR
)strlen(ver_string
);
7993 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
7995 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
7998 if(!SavedDriverObject
) {
7999 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
8000 KdPrint(("UniATA Init: OS should be ReactOS\n"));
8002 KeQuerySystemTime(&t0
);
8004 KeQuerySystemTime(&t1
);
8005 } while(t0
.QuadPart
== t1
.QuadPart
);
8009 KeQuerySystemTime(&t1
);
8011 } while(t0
.QuadPart
== t1
.QuadPart
);
8012 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
8013 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
8019 // (re)read bad block list
8020 InitBadBlocks(NULL
);
8023 // init ATA command translation table
8024 UniataInitAtaCommands();
8025 // get registry path to settings
8026 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
8027 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
8028 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
8029 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
8030 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
8031 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
8034 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
8035 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
8037 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
8040 statusToReturn
= 0xffffffff;
8042 // Zero out structure.
8043 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
8045 // Set size of hwInitializationData.
8046 hwInitializationData
.comm
.HwInitializationDataSize
=
8047 sizeof(hwInitializationData
.comm
) +
8048 // sizeof(hwInitializationData.nt4) +
8049 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
8051 // Set entry points.
8052 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
8053 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
8054 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
8055 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
8057 // Specify size of extensions.
8058 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
8059 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
8060 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
8062 // Indicate PIO device.
8063 hwInitializationData
.comm
.MapBuffers
= TRUE
;
8064 // Set PnP-specific API
8065 if(WinVer_Id() > WinVer_NT
) {
8066 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
8067 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
8070 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE enum supported BusMaster Devices\n"));
8073 UniataEnumBusMasterController(DriverObject
, Argument2
);
8076 // Look for legacy ISA-bridged PCI IDE controller (onboard)
8077 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
8078 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
8079 for (i
=0; i
<BMListLen
; i
++) {
8081 if(!BMList
[i
].MasterDev
) {
8082 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
8085 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
8089 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
8090 if(BMList
[i
].ChanInitOk
& 0x03) {
8091 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
8093 newStatus
= STATUS_SUCCESS
;
8097 BMList
[i
].AltInitMasterDev
= (UCHAR
)0xff;
8099 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
8100 PrimaryClaimed
= TRUE
;
8101 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
8102 SecondaryClaimed
= TRUE
;
8105 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
8107 for(alt
= 0; alt
< 2; alt
++) {
8109 for(c
=0; c
<2; c
++) {
8111 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
8115 if(PrimaryClaimed
) {
8116 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
8121 if(SecondaryClaimed
) {
8122 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
8127 if((WinVer_Id() <= WinVer_NT
)) {
8128 // do not even try if already claimed
8130 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
8133 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
8136 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
8137 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
8138 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
8140 BMList
[i
].channel
= (UCHAR
)c
;
8142 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
8143 newStatus
= ScsiPortInitialize(DriverObject
,
8145 &hwInitializationData
.comm
,
8146 (PVOID
)(i
| (alt
? 0x80000000 : 0)));
8147 KdPrint2((PRINT_PREFIX
"Status %#x\n", newStatus
));
8148 if (newStatus
< statusToReturn
) {
8149 statusToReturn
= newStatus
;
8151 if (newStatus
== STATUS_SUCCESS
) {
8152 BMList
[i
].ChanInitOk
|= 0x01 << c
;
8154 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
8155 c = 1; // this will break our for()
8156 BMList[i].ChanInitOk |= 0x01 << c;
8161 if(WinVer_Id() > WinVer_NT
) {
8162 // the following doesn't work under higher OSes
8163 KdPrint2((PRINT_PREFIX
"make still one attempt\n"));
8166 if(BMList
[i
].ChanInitOk
& 0x03) {
8167 // under NT we receive status immediately, so
8168 // we can omit alternative init method id STATUS_SUCCESS returned
8169 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
8172 // if (WinVer_Id() == WinVer_NT) and some error occured
8173 // try alternative init method
8176 if(BMList
[i
].ChanInitOk
& 0x03) {
8177 _PrintNtConsole(" OK\n");
8179 _PrintNtConsole(" failed\n");
8185 /* KeBugCheckEx(0xc000000e,
8186 (i << 16) | BMList[0].ChanInitOk,
8188 newStatus, statusToReturn);*/
8190 // Look for PCI IDE controller
8191 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
8192 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
8193 for (; i
<BMListLen
; i
++) {
8195 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", 0)) {
8198 /* if(BMList[i].MasterDev)
8201 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
8202 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
8203 BMList
[i
].busNumber
,
8204 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
8205 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
8208 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
8209 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
8210 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
8212 hwInitializationData
.comm
.VendorId
= BMList
[i
].VendorId
;
8213 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
8214 hwInitializationData
.comm
.DeviceId
= BMList
[i
].DeviceId
;
8215 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
8217 BMList
[i
].channel
= 0/*(UCHAR)c*/;
8219 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
8220 hwInitializationData
.comm
.VendorId
,
8221 hwInitializationData
.comm
.DeviceId
));
8222 newStatus
= ScsiPortInitialize(DriverObject
,
8224 &hwInitializationData
.comm
,
8226 if (newStatus
< statusToReturn
)
8227 statusToReturn
= newStatus
;
8230 if(newStatus
== STATUS_SUCCESS
) {
8231 _PrintNtConsole(" OK\n");
8233 _PrintNtConsole(" failed\n");
8239 /* KeBugCheckEx(0xc000000e,
8242 newStatus, statusToReturn);*/
8246 hwInitializationData
.comm
.VendorId
= 0;
8247 hwInitializationData
.comm
.VendorIdLength
= 0;
8248 hwInitializationData
.comm
.DeviceId
= 0;
8249 hwInitializationData
.comm
.DeviceIdLength
= 0;
8251 // The adapter count is used by the find adapter routine to track how
8252 // which adapter addresses have been tested.
8254 // Indicate 2 access ranges and reset FindAdapter.
8255 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
8256 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindController
;
8258 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
8259 // Indicate ISA bustype.
8260 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
8263 // Call initialization for ISA bustype.
8264 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
8265 newStatus
= ScsiPortInitialize(DriverObject
,
8267 &hwInitializationData
.comm
,
8269 if (newStatus
< statusToReturn
)
8270 statusToReturn
= newStatus
;
8272 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
8274 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
8275 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
8278 newStatus
= ScsiPortInitialize(DriverObject
,
8280 &hwInitializationData
.comm
,
8282 if (newStatus
< statusToReturn
)
8283 statusToReturn
= newStatus
;
8285 InDriverEntry
= FALSE
;
8287 KdPrint2((PRINT_PREFIX
"\n\nLeave ATAPI IDE MiniPort DriverEntry with status %#x\n", statusToReturn
));
8289 return statusToReturn
;
8291 } // end DriverEntry()
8295 BuildMechanismStatusSrb(
8296 IN PVOID HwDeviceExtension
,
8297 IN PSCSI_REQUEST_BLOCK Srb
8300 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8301 PSCSI_REQUEST_BLOCK srb
;
8303 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8305 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
8307 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
8309 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
8310 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
8311 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
8312 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
8314 // Set flags to disable synchronous negociation.
8315 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
8317 // Set timeout to 4 seconds.
8318 srb
->TimeOutValue
= 4;
8321 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
8322 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
8323 srb
->SrbExtension
= AtaReq
;
8325 // Set CDB operation code.
8326 cdb
= (PCDB
)srb
->Cdb
;
8327 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
8328 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
8331 } // end BuildMechanismStatusSrb()
8333 #endif //UNIATA_CORE
8336 BuildRequestSenseSrb (
8337 IN PVOID HwDeviceExtension
,
8338 IN PSCSI_REQUEST_BLOCK Srb
8341 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8342 PSCSI_REQUEST_BLOCK srb
;
8344 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8346 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
8348 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
8350 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
8351 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
8352 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
8353 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
8355 // Set flags to disable synchronous negociation.
8356 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
8358 // Set timeout to 2 seconds.
8359 srb
->TimeOutValue
= 4;
8362 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
8363 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
8364 srb
->SrbExtension
= AtaReq
;
8366 // Set CDB operation code.
8367 cdb
= (PCDB
)srb
->Cdb
;
8368 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
8369 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
8372 } // end BuildRequestSenseSrb()
8377 AtapiRegCheckDevLunValue(
8378 IN PVOID HwDeviceExtension
,
8379 IN PWCHAR NamePrefix
,
8387 ULONG val
= Default
;
8389 val
= AtapiRegCheckParameterValue(
8390 HwDeviceExtension
, NamePrefix
, Name
, val
);
8392 if(chan
!= CHAN_NOT_SPECIFIED
) {
8393 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
8394 val
= AtapiRegCheckParameterValue(
8395 HwDeviceExtension
, namex
, Name
, val
);
8396 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
8397 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
8398 val
= AtapiRegCheckParameterValue(
8399 HwDeviceExtension
, namex
, Name
, val
);
8403 } // end AtapiRegCheckDevLunValue()
8415 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
8434 swprintf(Buffer
+j
, L
"%2.2x", a
);
8442 } // end EncodeVendorStr()
8445 AtapiRegCheckDevValue(
8446 IN PVOID HwDeviceExtension
,
8453 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8455 // WCHAR name1[11+4+5];
8456 // WCHAR name2[11+4+4+10];
8457 // WCHAR name3[11+4+4+5+20];
8458 // WCHAR name3[11+4+4+5+20+1];
8467 IN ULONG SlotNumber
;
8469 ULONG val
= Default
;
8471 KdPrint(( " Parameter %ws\n", Name
));
8473 if(deviceExtension
) {
8474 VendorID
= deviceExtension
->DevID
& 0xffff;
8475 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
8476 SlotNumber
= deviceExtension
->slotNumber
;
8480 SlotNumber
= 0xffffffff;
8483 val
= AtapiRegCheckDevLunValue(
8484 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
8486 if(deviceExtension
) {
8487 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
8488 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
8489 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
8491 swprintf(namex
, L
"Parameters%s", namev
);
8492 val
= AtapiRegCheckDevLunValue(
8493 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8495 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
8496 val
= AtapiRegCheckDevLunValue(
8497 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8499 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
8500 val
= AtapiRegCheckDevLunValue(
8501 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8504 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
8507 } // end AtapiRegCheckDevValue()
8510 The user must specify that Xxx is to run on the platform
8511 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
8512 Services\UniATA\Xxx:REG_DWORD:Zzz.
8514 The user can override the global setting to enable or disable Xxx on a
8515 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
8516 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
8518 If this registry value does not exist or contains the value zero then
8519 the timer to check for media change does not run.
8523 RegistryPath - pointer to the unicode string inside
8524 ...\CurrentControlSet\Services\UniATA
8525 DeviceNumber - The number of the HBA device object
8527 Returns: Registry Key value
8530 AtapiRegCheckParameterValue(
8531 IN PVOID HwDeviceExtension
,
8532 IN PWSTR PathSuffix
,
8537 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
8539 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
8541 LONG zero
= Default
;
8543 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
8546 LONG doRun
= Default
;
8548 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
8550 UNICODE_STRING paramPath
;
8552 // <SavedRegPath>\<PathSuffix> -> <Name>
8553 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
8554 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
8556 paramPath
.Length
= 0;
8557 paramPath
.MaximumLength
= RegistryPath
->Length
+
8558 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
8559 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
8560 if(!paramPath
.Buffer
) {
8561 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
8565 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
8566 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
8567 RtlAppendUnicodeToString(¶mPath
, L
"\\");
8568 RtlAppendUnicodeToString(¶mPath
, PathSuffix
);
8570 // Check for the Xxx value.
8571 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
8573 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
8574 parameters
[0].Name
= Name
;
8575 parameters
[0].EntryContext
= &doRun
;
8576 parameters
[0].DefaultType
= REG_DWORD
;
8577 parameters
[0].DefaultData
= &zero
;
8578 parameters
[0].DefaultLength
= sizeof(ULONG
);
8580 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
8581 paramPath
.Buffer
, parameters
, NULL
, NULL
);
8582 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix
, Name
, doRun
));
8584 ExFreePool(paramPath
.Buffer
);
8586 if(!NT_SUCCESS(status
)) {
8592 #undef ITEMS_TO_QUERY
8594 } // end AtapiRegCheckParameterValue()
8597 SCSI_ADAPTER_CONTROL_STATUS
8599 AtapiAdapterControl(
8600 IN PVOID HwDeviceExtension
,
8601 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
8605 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8606 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
8607 ULONG numberChannels
= deviceExtension
->NumberChannels
;
8611 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
8613 switch(ControlType
) {
8614 case ScsiQuerySupportedControlTypes
: {
8615 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
8616 TRUE
, // ScsiQuerySupportedControlTypes
8617 TRUE
, // ScsiStopAdapter
8618 TRUE
, // ScsiRestartAdapter
8619 FALSE
, // ScsiSetBootConfig
8620 FALSE
// ScsiSetRunningConfig
8623 ULONG lim
= ScsiAdapterControlMax
;
8626 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
8628 if(pControlTypeList
->MaxControlType
< lim
) {
8629 lim
= pControlTypeList
->MaxControlType
;
8632 for(i
= 0; i
< lim
; i
++) {
8633 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
8639 case ScsiStopAdapter
: {
8641 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
8642 // Shut down all interrupts on the adapter. They'll get re-enabled
8643 // by the initialization routines.
8644 for (c
= 0; c
< numberChannels
; c
++) {
8645 AtapiResetController(deviceExtension
, c
);
8646 AtapiDisableInterrupts(deviceExtension
, c
);
8648 status
= UniataDisconnectIntr2(HwDeviceExtension
);
8649 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
8652 case ScsiRestartAdapter
: {
8654 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
8655 // Enable all the interrupts on the adapter while port driver call
8656 // for power up an HBA that was shut down for power management
8658 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
8659 status
= UniataConnectIntr2(HwDeviceExtension
);
8660 for (c
= 0; c
< numberChannels
; c
++) {
8661 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
8662 FindDevices(HwDeviceExtension
, FALSE
, c
);
8663 AtapiEnableInterrupts(deviceExtension
, c
);
8664 AtapiHwInitialize__(deviceExtension
, c
);
8666 if(deviceExtension
->Isr2DevObj
) {
8667 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
8674 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
8675 return ScsiAdapterControlUnsuccessful
;
8679 return ScsiAdapterControlSuccess
;
8680 } // end AtapiAdapterControl()
8682 #endif //UNIATA_CORE
8701 UCHAR dbg_print_tmp_buff
[512];
8702 // UNICODE_STRING msgBuff;
8704 va_start(ap
, DebugMessage
);
8706 len
= _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], 511, DebugMessage
, ap
);
8708 dbg_print_tmp_buff
[511] = 0;
8710 HalDisplayString(dbg_print_tmp_buff
);
8714 } // end PrintNtConsole()