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 static const CHAR uniata_comm_name
[] = UNIATA_COMM_PORT_VENDOR_STR
" \n";
66 UNICODE_STRING SavedRegPath
;
67 WCHAR SavedRegPathBuffer
[256];
71 UCHAR AtaCommands48
[256];
72 UCHAR AtaCommandFlags
[256];
75 ULONG ForceSimplex
= 0;
81 ULONG g_LogToDisplay
= 0;
84 ULONG g_WaitBusyInISR
= 1;
86 BOOLEAN InDriverEntry
= TRUE
;
88 BOOLEAN g_opt_Verbose
= 0;
90 BOOLEAN WinVer_WDM_Model
= FALSE
;
91 //UCHAR EnableDma = FALSE;
92 //UCHAR EnableReorder = FALSE;
98 AtapiResetController__(
99 IN PVOID HwDeviceExtension
,
101 IN UCHAR CompleteType
106 IN PHW_DEVICE_EXTENSION deviceExtension
,
110 #define RESET_COMPLETE_CURRENT 0x00
111 #define RESET_COMPLETE_ALL 0x01
112 #define RESET_COMPLETE_NONE 0x02
119 IN PVOID HwDeviceExtension
122 #ifdef UNIATA_USE_XXableInterrupts
123 #define RETTYPE_XXableInterrupts BOOLEAN
124 #define RETVAL_XXableInterrupts TRUE
126 #define RETTYPE_XXableInterrupts VOID
127 #define RETVAL_XXableInterrupts
130 RETTYPE_XXableInterrupts
133 IN PVOID HwDeviceExtension
136 RETTYPE_XXableInterrupts
138 AtapiEnableInterrupts__(
139 IN PVOID HwDeviceExtension
144 IN PVOID HwDeviceExtension
,
146 IN PHW_TIMER HwScsiTimer
,
147 IN ULONG MiniportTimerValue
150 SCSI_ADAPTER_CONTROL_STATUS
153 IN PVOID HwDeviceExtension
,
154 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
161 AtapiCheckInterrupt__(
162 IN PVOID HwDeviceExtension
,
170 AtapiRegGetStringParameterValue(
171 IN PWSTR RegistryPath
,
177 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
179 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
184 ustr
.MaximumLength
= (USHORT
)MaxLen
;
185 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
187 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
188 parameters
[0].Name
= Name
;
189 parameters
[0].EntryContext
= &ustr
;
190 parameters
[0].DefaultType
= REG_SZ
;
191 parameters
[0].DefaultData
= Str
;
192 parameters
[0].DefaultLength
= MaxLen
;
194 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
195 RegistryPath
, parameters
, NULL
, NULL
);
197 if(!NT_SUCCESS(status
))
202 #undef ITEMS_TO_QUERY
203 } // end AtapiRegGetStringParameterValue()
221 if(!nano
|| !g_Perf
|| !g_PerfDt
)
223 t
= (g_Perf
* nano
) / g_PerfDt
/ 1000;
228 KeQuerySystemTime(&t0
);
231 } // end UniataNanoSleep()
234 #define AtapiWritePortN_template(_type, _Type, sz) \
237 AtapiWritePort##sz( \
238 IN PHW_CHANNEL chan, \
244 if(_port >= IDX_MAX_REG) { \
245 res = (PIORES)(_port); \
248 res = &chan->RegTranslation[_port]; \
250 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
254 ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
256 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
257 ScsiPortWriteRegister##_Type((_type*)(res->Addr), data); \
262 AtapiWritePortN_template(ULONG
, Ulong
, 4);
263 AtapiWritePortN_template(USHORT
, Ushort
, 2);
264 AtapiWritePortN_template(UCHAR
, Uchar
, 1);
266 #define AtapiWritePortExN_template(_type, _Type, sz) \
269 AtapiWritePortEx##sz( \
270 IN PHW_CHANNEL chan, \
277 if(_port >= IDX_MAX_REG) { \
278 res = (PIORES)(_port); \
281 res = &chan->RegTranslation[_port]; \
283 KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
287 ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
289 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
290 ScsiPortWriteRegister##_Type((_type*)(res->Addr+offs), data); \
295 AtapiWritePortExN_template(ULONG
, Ulong
, 4);
296 //AtapiWritePortExN_template(USHORT, Ushort, 2);
297 AtapiWritePortExN_template(UCHAR
, Uchar
, 1);
299 #define AtapiReadPortN_template(_type, _Type, sz) \
303 IN PHW_CHANNEL chan, \
308 if(_port >= IDX_MAX_REG) { \
309 res = (PIORES)(_port); \
312 res = &chan->RegTranslation[_port]; \
314 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
315 return (_type)(-1); \
318 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
319 return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
321 /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
322 return ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
326 AtapiReadPortN_template(ULONG
, Ulong
, 4);
327 AtapiReadPortN_template(USHORT
, Ushort
, 2);
328 AtapiReadPortN_template(UCHAR
, Uchar
, 1);
330 #define AtapiReadPortExN_template(_type, _Type, sz) \
333 AtapiReadPortEx##sz( \
334 IN PHW_CHANNEL chan, \
340 if(_port >= IDX_MAX_REG) { \
341 res = (PIORES)(_port); \
344 res = &chan->RegTranslation[_port]; \
346 KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
347 return (_type)(-1); \
350 return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
352 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
353 return ScsiPortReadRegister##_Type((_type*)(res->Addr+offs)); \
357 AtapiReadPortExN_template(ULONG
, Ulong
, 4);
358 //AtapiReadPortExN_template(USHORT, Ushort, 2);
359 AtapiReadPortExN_template(UCHAR
, Uchar
, 1);
361 #define AtapiReadPortBufferN_template(_type, _Type, sz) \
364 AtapiReadBuffer##sz( \
365 IN PHW_CHANNEL chan, \
376 (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
378 Buffer = ((_type*)Buffer)+1; \
379 UniataNanoSleep(Timing); \
384 if(_port >= IDX_MAX_REG) { \
385 res = (PIORES)(_port); \
388 res = &chan->RegTranslation[_port]; \
390 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
394 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
395 ScsiPortReadPortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
399 (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
401 Buffer = ((_type*)Buffer)+1; \
406 #define AtapiWritePortBufferN_template(_type, _Type, sz) \
409 AtapiWriteBuffer##sz( \
410 IN PHW_CHANNEL chan, \
421 AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
422 Buffer = ((_type*)Buffer)+1; \
424 UniataNanoSleep(Timing); \
429 if(_port >= IDX_MAX_REG) { \
430 res = (PIORES)(_port); \
433 res = &chan->RegTranslation[_port]; \
435 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
439 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
440 ScsiPortWritePortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
444 ScsiPortWriteRegister##_Type((_type*)(res->Addr), *((_type*)Buffer)); \
446 Buffer = ((_type*)Buffer)+1; \
451 AtapiWritePortBufferN_template(ULONG
, Ulong
, 4);
452 AtapiWritePortBufferN_template(USHORT
, Ushort
, 2);
454 AtapiReadPortBufferN_template(ULONG
, Ulong
, 4);
455 AtapiReadPortBufferN_template(USHORT
, Ushort
, 2);
467 WaitOnBusyLong(chan
);
468 for (i
= 0; i
< 0x10000; i
++) {
470 GetStatus(chan
, statusByte
);
471 if (statusByte
& IDE_STATUS_DRQ
) {
472 // Suck out any remaining bytes and throw away.
473 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
479 KdPrint2((PRINT_PREFIX
"AtapiSuckPort2: overrun detected (%#x words)\n", i
));
482 } // AtapiSuckPort2()
492 for (i
=0; i
<200; i
++) {
493 GetStatus(chan
, Status
);
494 if (Status
& IDE_STATUS_BUSY
) {
495 AtapiStallExecution(10);
502 } // end WaitOnBusy()
513 Status
= WaitOnBusy(chan
);
514 if(!(Status
& IDE_STATUS_BUSY
))
516 for (i
=0; i
<2000; i
++) {
517 GetStatus(chan
, Status
);
518 if (Status
& IDE_STATUS_BUSY
) {
519 AtapiStallExecution(250);
526 } // end WaitOnBusyLong()
536 for (i
=0; i
<200; i
++) {
537 GetBaseStatus(chan
, Status
);
538 if (Status
& IDE_STATUS_BUSY
) {
539 AtapiStallExecution(10);
546 } // end WaitOnBaseBusy()
557 Status
= WaitOnBaseBusy(chan
);
558 if(!(Status
& IDE_STATUS_BUSY
))
560 for (i
=0; i
<2000; i
++) {
561 GetBaseStatus(chan
, Status
);
562 if (Status
& IDE_STATUS_BUSY
) {
563 AtapiStallExecution(250);
570 } // end WaitOnBaseBusyLong()
575 IN
struct _HW_DEVICE_EXTENSION
* deviceExtension
,
584 if(Status
& IDE_STATUS_BUSY
) {
587 // if(deviceExtension->HwFlags & UNIATA_SATA) {
588 if(UniataIsSATARangeAvailable(deviceExtension
, 0)) {
589 if(Status
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
593 Status2
= Status
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
);
594 if ((Status
& IDE_STATUS_BUSY
) ||
595 (Status2
!= IDE_STATUS_IDLE
&& Status2
!= IDE_STATUS_DRDY
)) {
599 return IDE_STATUS_IDLE
;
600 } // end UniataIsIdle()
611 for (i
=0; i
<20000; i
++) {
612 GetStatus(chan
, Status
);
613 Status2
= UniataIsIdle(chan
->DeviceExtension
, Status
);
614 if(Status2
== 0xff) {
618 if(Status2
& IDE_STATUS_BUSY
) {
619 AtapiStallExecution(10);
626 } // end WaitForIdleLong()
636 for (i
=0; i
<1000; i
++) {
637 GetStatus(chan
, Status
);
638 if (Status
& IDE_STATUS_BUSY
) {
639 AtapiStallExecution(10);
640 } else if (Status
& IDE_STATUS_DRQ
) {
643 AtapiStallExecution(10);
647 } // end WaitForDrq()
657 for (i
=0; i
<2; i
++) {
658 GetStatus(chan
, Status
);
659 if (Status
& IDE_STATUS_BUSY
) {
660 AtapiStallExecution(10);
661 } else if (Status
& IDE_STATUS_DRQ
) {
664 AtapiStallExecution(10);
668 } // end WaitShortForDrq()
677 //ULONG c = chan->lChannel;
679 UCHAR dma_status
= 0;
680 KdPrint2((PRINT_PREFIX
"AtapiSoftReset:\n"));
683 GetBaseStatus(chan
, statusByte2
);
684 KdPrint2((PRINT_PREFIX
" statusByte2 %x:\n", statusByte2
));
685 SelectDrive(chan
, DeviceNumber
);
686 AtapiStallExecution(10000);
687 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_RESET
);
688 for (i
= 0; i
< 1000; i
++) {
689 AtapiStallExecution(999);
691 SelectDrive(chan
, DeviceNumber
);
693 GetBaseStatus(chan
, statusByte2
);
694 AtapiStallExecution(500);
696 GetBaseStatus(chan
, statusByte2
);
697 if(chan
&& chan
->DeviceExtension
) {
698 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
699 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
701 KdPrint2((PRINT_PREFIX
" can't get DMA status\n"));
703 if(dma_status
& BM_STATUS_INTR
) {
704 // bullshit, we have DMA interrupt, but had never initiate DMA operation
705 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr on ATAPI reset\n"));
706 AtapiDmaDone(chan
->DeviceExtension
, DeviceNumber
, chan
->lChannel
, NULL
);
707 GetBaseStatus(chan
, statusByte2
);
709 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
710 UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
);
714 } // end AtapiSoftReset()
717 Send command to device.
718 Translate to 48-Lba form if required
722 IN PHW_DEVICE_EXTENSION deviceExtension
,
723 IN ULONG DeviceNumber
,
732 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
734 ULONG ldev
= lChannel
*2 + DeviceNumber
;
738 KdPrint2((PRINT_PREFIX
"AtaCommand48: cntrlr %#x:%#x ldev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
739 deviceExtension
->DevIndex
, deviceExtension
->Channel
, ldev
, command
, lba
, count
, feature
));
741 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
742 SelectDrive(chan
, DeviceNumber
);
744 statusByte
= WaitOnBusy(chan
);
746 /* ready to issue command ? */
747 if (statusByte
& IDE_STATUS_BUSY
) {
748 KdPrint2((PRINT_PREFIX
" Returning BUSY status\n"));
752 // !!! We should not check ERROR condition here
753 // ERROR bit may be asserted durring previous operation
754 // and not cleared after SELECT
756 //>>>>>> NV: 2006/08/03
757 if((AtaCommandFlags
[command
] & ATA_CMD_FLAG_LBAIOsupp
) &&
758 CheckIfBadBlock(&(deviceExtension
->lun
[ldev
]), lba
, count
)) {
759 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
760 return IDE_STATUS_ERROR
;
761 //return SRB_STATUS_ERROR;
763 //<<<<<< NV: 2006/08/03
765 /* only use 48bit addressing if needed because of the overhead */
766 if ((lba
>= ATA_MAX_LBA28
|| count
> 256) &&
767 deviceExtension
->lun
[ldev
].IdentifyData
.FeaturesSupport
.Address48
) {
769 KdPrint2((PRINT_PREFIX
" ldev %#x USE_LBA_48\n", ldev
));
770 /* translate command into 48bit version */
771 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
772 command
= AtaCommands48
[command
];
774 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
778 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
781 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)(feature
>>8));
782 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
783 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)(count
>>8));
784 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
785 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[3]));
786 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[0]));
787 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[4]));
788 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[1]));
789 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[5]));
790 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[2]));
792 //KdPrint2((PRINT_PREFIX "AtaCommand48: ldev %#x USE_LBA48 (2)\n", ldev ));
793 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
) );
796 plba
= (PUCHAR
)&lba
; //ktp
797 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
800 // (deviceExtension->lun[ldev].DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
801 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
803 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
804 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)plba
[0]);
805 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)plba
[1]);
806 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)plba
[2]);
807 if(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_LBA_ENABLED
) {
808 //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_LBA\n", ldev ));
809 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
811 //KdPrint2((PRINT_PREFIX "AtaCommand28: ldev %#x USE_CHS\n", ldev ));
812 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
816 // write command code to device
817 AtapiWritePort1(chan
, IDX_IO1_o_Command
, command
);
822 // caller requested wait for interrupt
825 statusByte
= WaitForDrq(chan
);
826 if (statusByte
& IDE_STATUS_DRQ
)
828 AtapiStallExecution(500);
829 KdPrint2((PRINT_PREFIX
" retry waiting DRQ, status %#x\n", statusByte
));
836 // caller requested wait for entering Wait state
837 for (i
=0; i
<30 * 1000; i
++) {
839 GetStatus(chan
, statusByte
);
840 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
841 if(statusByte
== 0xff) {
845 if(statusByte
& IDE_STATUS_ERROR
) {
848 if(statusByte
& IDE_STATUS_BUSY
) {
849 AtapiStallExecution(100);
852 if(statusByte
== IDE_STATUS_IDLE
) {
855 //if(deviceExtension->HwFlags & UNIATA_SATA) {
856 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
859 AtapiStallExecution(100);
862 //statusByte |= IDE_STATUS_BUSY;
866 statusByte
= WaitOnBusyLong(chan
);
868 case ATA_WAIT_BASE_READY
:
869 statusByte
= WaitOnBaseBusyLong(chan
);
872 GetStatus(chan
, statusByte
);
873 if (statusByte
& IDE_STATUS_ERROR
) {
874 KdPrint2((PRINT_PREFIX
" Warning: Immed Status %#x :(\n", statusByte
));
875 if(statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_ERROR
)) {
878 KdPrint2((PRINT_PREFIX
" try to continue\n"));
879 statusByte
&= ~IDE_STATUS_ERROR
;
881 chan
->ExpectingInterrupt
= TRUE
;
883 InterlockedExchange(&(chan
->CheckIntr
),
889 KdPrint2((PRINT_PREFIX
" Status %#x\n", statusByte
));
892 } // end AtaCommand48()
895 Send command to device.
896 This is simply wrapper for AtaCommand48()
900 IN PHW_DEVICE_EXTENSION deviceExtension
,
901 IN ULONG DeviceNumber
,
912 return AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
914 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
915 count
, feature
, flags
);
916 } // end AtaCommand()
919 AtaPio2Mode(LONG pio
)
922 default: return ATA_PIO
;
923 case 0: return ATA_PIO0
;
924 case 1: return ATA_PIO1
;
925 case 2: return ATA_PIO2
;
926 case 3: return ATA_PIO3
;
927 case 4: return ATA_PIO4
;
928 case 5: return ATA_PIO5
;
930 } // end AtaPio2Mode()
933 AtaPioMode(PIDENTIFY_DATA2 ident
)
935 if (ident
->PioTimingsValid
) {
936 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_5
)
938 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_4
)
940 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_3
)
943 if (ident
->PioCycleTimingMode
== 2)
945 if (ident
->PioCycleTimingMode
== 1)
947 if (ident
->PioCycleTimingMode
== 0)
950 } // end AtaPioMode()
953 AtaWmode(PIDENTIFY_DATA2 ident
)
955 if (ident
->MultiWordDMASupport
& 0x04)
957 if (ident
->MultiWordDMASupport
& 0x02)
959 if (ident
->MultiWordDMASupport
& 0x01)
965 AtaUmode(PIDENTIFY_DATA2 ident
)
967 if (!ident
->UdmaModesValid
)
969 if (ident
->UltraDMASupport
& 0x40)
971 if (ident
->UltraDMASupport
& 0x20)
973 if (ident
->UltraDMASupport
& 0x10)
975 if (ident
->UltraDMASupport
& 0x08)
977 if (ident
->UltraDMASupport
& 0x04)
979 if (ident
->UltraDMASupport
& 0x02)
981 if (ident
->UltraDMASupport
& 0x01)
992 IN PVOID HwDeviceExtension
995 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
996 PHW_TIMER HwScsiTimer
;
998 ULONG MiniportTimerValue
;
999 BOOLEAN recall
= FALSE
;
1003 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc:\n"));
1005 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1006 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1007 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no items\n"));
1010 chan
= &deviceExtension
->chan
[lChannel
];
1014 HwScsiTimer
= chan
->HwScsiTimer
;
1015 chan
->HwScsiTimer
= NULL
;
1017 deviceExtension
->FirstDpcChan
= chan
->NextDpcChan
;
1018 if(deviceExtension
->FirstDpcChan
!= CHAN_NOT_SPECIFIED
) {
1022 HwScsiTimer(HwDeviceExtension
);
1024 chan
->NextDpcChan
= CHAN_NOT_SPECIFIED
;
1026 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1027 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1028 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no more items\n"));
1029 deviceExtension
->FirstDpcChan
=
1030 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1034 KeQuerySystemTime(&time
);
1035 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1037 chan
= &deviceExtension
->chan
[lChannel
];
1038 if(time
.QuadPart
>= chan
->DpcTime
- 10) {
1040 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1041 (ULONG
)(chan
->DpcTime
>> 32), (ULONG
)(chan
->DpcTime
)));
1048 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1049 MiniportTimerValue
= (ULONG
)(time
.QuadPart
- chan
->DpcTime
)/10;
1050 if(!MiniportTimerValue
)
1051 MiniportTimerValue
= 1;
1053 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: recall AtapiTimerDpc\n"));
1054 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1061 } // end AtapiTimerDpc()
1064 Wrapper for ScsiPort, that implements smart Dpc
1065 queueing. We need it to allow parallel functioning
1066 of IDE channles with shared interrupt. Standard Dpc mechanism
1067 cancels previous Dpc request (if any), but we need Dpc queue.
1071 IN PVOID HwDeviceExtension
,
1073 IN PHW_TIMER HwScsiTimer
,
1074 IN ULONG MiniportTimerValue
1077 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1079 LARGE_INTEGER time2
;
1081 PHW_CHANNEL prev_chan
;
1083 // BOOLEAN UseRequestTimerCall = TRUE;
1085 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1086 KeQuerySystemTime(&time
);
1088 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1089 time
.QuadPart
+= MiniportTimerValue
*10;
1090 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1092 KdPrint2((PRINT_PREFIX
" ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension
->ActiveDpcChan
, deviceExtension
->FirstDpcChan
));
1094 i
= deviceExtension
->FirstDpcChan
;
1095 chan
= prev_chan
= NULL
;
1096 while(i
!= CHAN_NOT_SPECIFIED
) {
1098 chan
= &deviceExtension
->chan
[i
];
1099 if(chan
->DpcTime
> time
.QuadPart
) {
1102 i
= chan
->NextDpcChan
;
1104 chan
= &deviceExtension
->chan
[lChannel
];
1106 deviceExtension
->FirstDpcChan
= lChannel
;
1108 prev_chan
->NextDpcChan
= lChannel
;
1110 chan
->NextDpcChan
= i
;
1111 chan
->HwScsiTimer
= HwScsiTimer
;
1112 chan
->DpcTime
= time
.QuadPart
;
1114 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2
.HighPart
, time2
.LowPart
));
1115 if(time
.QuadPart
<= time2
.QuadPart
) {
1116 MiniportTimerValue
= 1;
1118 MiniportTimerValue
= (ULONG
)((time
.QuadPart
- time2
.QuadPart
) / 10);
1121 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1122 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1124 MiniportTimerValue
);
1126 } // end AtapiQueueTimerDpc()
1128 #endif //UNIATA_CORE
1136 UCHAR statusByteAlt
;
1138 GetStatus(chan
, statusByteAlt
);
1139 KdPrint2((PRINT_PREFIX
" AltStatus (%#x)\n", statusByteAlt
));
1141 for(j
=1; j
<IDX_IO1_SZ
; j
++) {
1142 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1143 KdPrint2((PRINT_PREFIX
1144 " Reg_%#x (%#x) = %#x\n",
1146 chan
->RegTranslation
[IDX_IO1
+j
].Addr
,
1149 for(j
=0; j
<IDX_BM_IO_SZ
-1; j
++) {
1150 statusByteAlt
= AtapiReadPort1(chan
, IDX_BM_IO
+j
);
1151 KdPrint2((PRINT_PREFIX
1152 " BM_%#x (%#x) = %#x\n",
1154 chan
->RegTranslation
[IDX_BM_IO
+j
].Addr
,
1158 } // end UniataDumpATARegs()
1162 Routine Description:
1164 Issue IDENTIFY command to a device.
1168 HwDeviceExtension - HBA miniport driver's adapter data storage
1169 DeviceNumber - Indicates which device.
1170 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1174 TRUE if all goes well.
1179 IN PVOID HwDeviceExtension
,
1180 IN ULONG DeviceNumber
,
1186 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1187 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
1188 ULONG waitCount
= 50000;
1194 BOOLEAN atapiDev
= FALSE
;
1195 ULONG ldev
= (lChannel
* 2) + DeviceNumber
;
1196 PHW_LU_EXTENSION LunExt
= &(deviceExtension
->lun
[ldev
]);
1198 if(DeviceNumber
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
1199 KdPrint2((PRINT_PREFIX
"IssueIdentify: NO SLAVE\n"));
1202 if(LunExt
->DeviceFlags
& DFLAGS_HIDDEN
) {
1203 KdPrint2((PRINT_PREFIX
"IssueIdentify: HIDDEN\n"));
1207 SelectDrive(chan
, DeviceNumber
);
1208 AtapiStallExecution(10);
1209 statusByte
= WaitOnBusyLong(chan
);
1210 // Check that the status register makes sense.
1211 GetBaseStatus(chan
, statusByte2
);
1213 UniataDumpATARegs(chan
);
1215 if (Command
== IDE_COMMAND_IDENTIFY
) {
1216 // Mask status byte ERROR bits.
1217 statusByte
= UniataIsIdle(deviceExtension
, statusByte
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
));
1218 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte
));
1219 // Check if register value is reasonable.
1221 if(statusByte
!= IDE_STATUS_IDLE
) {
1223 // No reset here !!!
1224 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1226 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1227 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1228 SelectDrive(chan
, DeviceNumber
);
1229 WaitOnBusyLong(chan
);
1231 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1232 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1234 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1235 signatureHigh
== ATAPI_MAGIC_MSB
) {
1237 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (ldev %d)\n", ldev
));
1241 // We really should wait up to 31 seconds
1242 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1243 // (30 seconds for device 1)
1245 // Wait for Busy to drop.
1246 AtapiStallExecution(100);
1247 GetStatus(chan
, statusByte
);
1249 } while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
--);
1250 GetBaseStatus(chan
, statusByte2
);
1252 SelectDrive(chan
, DeviceNumber
);
1254 GetBaseStatus(chan
, statusByte2
);
1256 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1258 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1259 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1261 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1262 signatureHigh
== ATAPI_MAGIC_MSB
) {
1263 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (2) (ldev %d)\n", ldev
));
1268 statusByte
= UniataIsIdle(deviceExtension
, statusByte
) & ~IDE_STATUS_INDEX
;
1269 if (statusByte
!= IDE_STATUS_IDLE
) {
1271 KdPrint2((PRINT_PREFIX
"IssueIdentify: no dev (ldev %d)\n", ldev
));
1276 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte
));
1277 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1278 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1279 statusByte
= WaitForIdleLong(chan
);
1280 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte
));
1285 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1286 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1291 for (; j
< 4*2; j
++) {
1292 // Send IDENTIFY command.
1293 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, Command
, 0, 0, 0, (j
>= 4) ? 0x200 : 0, 0, ATA_WAIT_INTR
);
1296 if (statusByte
& IDE_STATUS_DRQ
) {
1297 // Read status to acknowledge any interrupts generated.
1298 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte
));
1299 GetBaseStatus(chan
, statusByte
);
1300 // One last check for Atapi.
1301 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1302 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1304 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1305 signatureHigh
== ATAPI_MAGIC_MSB
) {
1306 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (3) (ldev %d)\n", ldev
));
1312 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte
));
1313 if (Command
== IDE_COMMAND_IDENTIFY
) {
1314 // Check the signature. If DRQ didn't come up it's likely Atapi.
1315 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1316 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1318 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1319 signatureHigh
== ATAPI_MAGIC_MSB
) {
1321 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (4) (ldev %d)\n", ldev
));
1325 // Device didn't respond correctly. It will be given one more chances.
1326 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1327 statusByte
, AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
1328 GetBaseStatus(chan
, statusByte
);
1329 AtapiSoftReset(chan
,DeviceNumber
);
1331 AtapiDisableInterrupts(deviceExtension
, lChannel
);
1332 AtapiEnableInterrupts(deviceExtension
, lChannel
);
1334 GetBaseStatus(chan
, statusByte
);
1335 //GetStatus(chan, statusByte);
1336 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after soft reset (%#x)\n", statusByte
));
1339 // Check for error on really stupid master devices that assert random
1340 // patterns of bits in the status register at the slave address.
1341 if ((Command
== IDE_COMMAND_IDENTIFY
) && (statusByte
& IDE_STATUS_ERROR
)) {
1342 KdPrint2((PRINT_PREFIX
"IssueIdentify: Exit on error (%#x)\n", statusByte
));
1346 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status before read words %#x\n", statusByte
));
1347 // Suck out 256 words. After waiting for one model that asserts busy
1348 // after receiving the Packet Identify command.
1349 statusByte
= WaitForDrq(chan
);
1350 statusByte
= WaitOnBusyLong(chan
);
1351 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1353 if (!(statusByte
& IDE_STATUS_DRQ
)) {
1354 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte
));
1355 GetBaseStatus(chan
, statusByte
);
1358 GetBaseStatus(chan
, statusByte
);
1359 KdPrint2((PRINT_PREFIX
"IssueIdentify: BASE statusByte %#x\n", statusByte
));
1361 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
1363 KdPrint2((PRINT_PREFIX
" use 16bit IO\n"));
1367 // ATI/SII chipsets with memory-mapped IO hangs when
1368 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1369 // Unfortunately, I don't know yet how to workaround it except the way you see below.
1370 KdPrint2((PRINT_PREFIX
1371 " IO_%#x (%#x), %s:\n",
1373 chan
->RegTranslation
[IDX_IO1_i_Data
].Addr
,
1374 chan
->RegTranslation
[IDX_IO1_i_Data
].MemIo
? "Mem" : "IO"));
1375 for(i
=0; i
<256; i
++) {
1377 KdPrint2((PRINT_PREFIX
1380 chan->RegTranslation[IDX_IO1_i_Data].Addr));
1382 w
= AtapiReadPort2(chan
, IDX_IO1_i_Data
);
1383 KdPrint2((PRINT_PREFIX
1385 AtapiStallExecution(1);
1386 ((PUSHORT
)&deviceExtension
->FullIdentifyData
)[i
] = w
;
1389 ReadBuffer(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256, PIO0_TIMING
);
1391 // Work around for some IDE and one model Atapi that will present more than
1392 // 256 bytes for the Identify data.
1393 KdPrint2((PRINT_PREFIX
"IssueIdentify: suck data port\n", statusByte
));
1394 statusByte
= AtapiSuckPort2(chan
);
1396 KdPrint2((PRINT_PREFIX
" use 32bit IO\n"));
1397 ReadBuffer2(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256/2, PIO0_TIMING
);
1400 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1401 statusByte
= WaitForDrq(chan
);
1402 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1403 GetBaseStatus(chan
, statusByte
);
1405 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after read words %#x\n", statusByte
));
1408 KdPrint2((PRINT_PREFIX
"IssueIdentify: no setup, exiting\n"));
1412 KdPrint2((PRINT_PREFIX
"Model: %20.20s\n", deviceExtension
->FullIdentifyData
.ModelNumber
));
1413 KdPrint2((PRINT_PREFIX
"FW: %4.4s\n", deviceExtension
->FullIdentifyData
.FirmwareRevision
));
1414 KdPrint2((PRINT_PREFIX
"S/N: %20.20s\n", deviceExtension
->FullIdentifyData
.SerialNumber
));
1415 KdPrint2((PRINT_PREFIX
"Pio: %x\n", deviceExtension
->FullIdentifyData
.PioCycleTimingMode
));
1416 if(deviceExtension
->FullIdentifyData
.PioTimingsValid
) {
1417 KdPrint2((PRINT_PREFIX
"APio: %x\n", deviceExtension
->FullIdentifyData
.AdvancedPIOModes
));
1419 KdPrint2((PRINT_PREFIX
"SWDMA: %x\n", deviceExtension
->FullIdentifyData
.SingleWordDMAActive
));
1420 KdPrint2((PRINT_PREFIX
"MWDMA: %x\n", deviceExtension
->FullIdentifyData
.MultiWordDMAActive
));
1421 if(deviceExtension
->FullIdentifyData
.UdmaModesValid
) {
1422 KdPrint2((PRINT_PREFIX
"UDMA: %x\n", deviceExtension
->FullIdentifyData
.UltraDMAActive
));
1424 KdPrint2((PRINT_PREFIX
"SATA: %x\n", deviceExtension
->FullIdentifyData
.SataEnable
));
1426 // Check out a few capabilities / limitations of the device.
1427 if (deviceExtension
->FullIdentifyData
.RemovableStatus
& 1) {
1428 // Determine if this drive supports the MSN functions.
1429 KdPrint2((PRINT_PREFIX
"IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1431 deviceExtension
->FullIdentifyData
.RemovableStatus
));
1432 LunExt
->DeviceFlags
|= DFLAGS_REMOVABLE_DRIVE
;
1434 if (deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
) {
1435 // Determine max. block transfer for this device.
1436 LunExt
->MaximumBlockXfer
=
1437 (UCHAR
)(deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
& 0xFF);
1439 LunExt
->NumOfSectors
= 0;
1440 if (Command
== IDE_COMMAND_IDENTIFY
) {
1441 ULONGLONG NumOfSectors
=0;
1442 ULONGLONG NativeNumOfSectors
=0;
1443 ULONGLONG cylinders
=0;
1444 ULONGLONG tmp_cylinders
=0;
1445 // Read very-old-style drive geometry
1446 KdPrint2((PRINT_PREFIX
"CHS %#x:%#x:%#x\n",
1447 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1448 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1449 deviceExtension
->FullIdentifyData
.SectorsPerTrack
1451 NumOfSectors
= deviceExtension
->FullIdentifyData
.NumberOfCylinders
*
1452 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1453 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1454 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1455 // Check for HDDs > 8Gb
1456 if ((deviceExtension
->FullIdentifyData
.NumberOfCylinders
== 0x3fff) &&
1457 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1458 (NumOfSectors
< deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1459 KdPrint2((PRINT_PREFIX
"NumberOfCylinders == 0x3fff\n"));
1461 (deviceExtension
->FullIdentifyData
.UserAddressableSectors
/
1462 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1463 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1465 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1467 NumOfSectors
= cylinders
*
1468 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1469 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1471 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1475 // Check for LBA mode
1476 KdPrint2((PRINT_PREFIX
"SupportLba flag %#x\n", deviceExtension
->FullIdentifyData
.SupportLba
));
1477 KdPrint2((PRINT_PREFIX
"MajorRevision %#x\n", deviceExtension
->FullIdentifyData
.MajorRevision
));
1478 KdPrint2((PRINT_PREFIX
"UserAddressableSectors %#x\n", deviceExtension
->FullIdentifyData
.UserAddressableSectors
));
1479 if ( deviceExtension
->FullIdentifyData
.SupportLba
1481 (deviceExtension
->FullIdentifyData
.MajorRevision
&&
1482 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1483 deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1484 KdPrint2((PRINT_PREFIX
"LBA mode\n"));
1485 LunExt
->DeviceFlags
|= DFLAGS_LBA_ENABLED
;
1487 KdPrint2((PRINT_PREFIX
"Keep orig geometry\n"));
1488 LunExt
->DeviceFlags
|= DFLAGS_ORIG_GEOMETRY
;
1489 goto skip_lba_staff
;
1491 // Check for LBA48 support
1492 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1493 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
&&
1494 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Address48
&&
1495 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
> NumOfSectors
)
1497 KdPrint2((PRINT_PREFIX
"LBA48\n"));
1499 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
/
1500 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1501 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1503 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1505 NativeNumOfSectors
= cylinders
*
1506 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1507 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1509 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1511 if(NativeNumOfSectors
> NumOfSectors
) {
1512 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1513 NumOfSectors
= NativeNumOfSectors
;
1517 // Check drive capacity report for LBA48-capable drives.
1518 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
) {
1519 ULONG hNativeNumOfSectors
;
1520 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1522 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1523 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1525 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1526 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1527 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1528 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) ;
1530 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
1533 KdPrint2((PRINT_PREFIX
"Read high order bytes\n"));
1534 NativeNumOfSectors
|=
1535 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24 );
1536 hNativeNumOfSectors
=
1537 (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) |
1538 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 8) ;
1539 ((PULONG
)&NativeNumOfSectors
)[1] = hNativeNumOfSectors
;
1541 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1543 // Some drives report LBA48 capability while has capacity below 128Gb
1544 // Probably they support large block-counters.
1545 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
1546 // Here we check this
1547 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1548 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!!\n"));
1550 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1551 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1553 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1554 NativeNumOfSectors
= (ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1555 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24) |
1556 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8 ) |
1557 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 32) |
1558 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1559 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 40)
1563 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1564 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!! (2)\n"));
1565 NativeNumOfSectors
= 0;
1569 if(NumOfSectors
<= ATA_MAX_LBA28
&&
1570 NativeNumOfSectors
> NumOfSectors
) {
1572 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
1573 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1575 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1576 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1577 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1578 NumOfSectors
= NativeNumOfSectors
;
1584 if(NumOfSectors
< 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
1585 // check for native LBA size
1586 // some drives report ~32Gb in Identify Block
1587 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
1589 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_READ_NATIVE_SIZE
,
1590 0, IDE_USE_LBA
, 0, 0, 0, ATA_WAIT_READY
);
1592 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1593 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1594 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1595 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1596 (((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
) & 0xf) << 24);
1598 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1600 if(NativeNumOfSectors
> NumOfSectors
) {
1602 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
1603 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1605 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1606 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1607 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1608 NumOfSectors
= NativeNumOfSectors
;
1614 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
1616 // fill IdentifyData with bogus geometry
1617 KdPrint2((PRINT_PREFIX
"requested LunExt->GeomType=%x\n", LunExt
->opt_GeomType
));
1618 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*
1619 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
);
1620 KdPrint2((PRINT_PREFIX
"tmp_cylinders = %#I64x\n", tmp_cylinders
));
1621 if((tmp_cylinders
< 0xffff) || (LunExt
->opt_GeomType
== GEOM_ORIG
)) {
1622 // ok, we can keep original values
1623 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1624 LunExt
->opt_GeomType
= GEOM_ORIG
;
1627 tmp_cylinders
= NumOfSectors
/ (255*63);
1628 if(tmp_cylinders
< 0xffff) {
1629 // we can use generic values for H/S for generic geometry approach
1630 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1631 LunExt
->opt_GeomType
= GEOM_STD
;
1634 // we should use UNIATA geometry approach
1635 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1636 LunExt
->opt_GeomType
= GEOM_UNIATA
;
1640 KdPrint2((PRINT_PREFIX
"final LunExt->opt_GeomType=%x\n", LunExt
->opt_GeomType
));
1642 if(LunExt
->opt_GeomType
== GEOM_STD
) {
1643 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
=
1644 deviceExtension
->FullIdentifyData
.SectorsPerTrack
= 63;
1646 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
=
1647 deviceExtension
->FullIdentifyData
.NumberOfHeads
= 255;
1649 cylinders
= NumOfSectors
/ (255*63);
1650 KdPrint2((PRINT_PREFIX
"Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders
, 255, 63));
1652 if(LunExt
->opt_GeomType
== GEOM_UNIATA
) {
1653 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x80)) {
1655 KdPrint2((PRINT_PREFIX
"cylinders /= 2\n"));
1656 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1657 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1659 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x80)) {
1661 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (2)\n"));
1662 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1663 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1665 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x8000)) {
1667 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (3)\n"));
1668 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1669 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1671 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x8000)) {
1673 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (4)\n"));
1674 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1675 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1677 KdPrint2((PRINT_PREFIX
"Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders
,
1678 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
,
1679 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
));
1682 KdPrint2((PRINT_PREFIX
"cylinders = tmp_cylinders (%x = %x)\n", cylinders
, tmp_cylinders
));
1683 cylinders
= tmp_cylinders
;
1685 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
=
1686 deviceExtension
->FullIdentifyData
.NumberOfCylinders
= (USHORT
)cylinders
;
1690 KdPrint2((PRINT_PREFIX
"Geometry: C %#x (%#x)\n",
1691 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1692 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
1694 KdPrint2((PRINT_PREFIX
"Geometry: H %#x (%#x)\n",
1695 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1696 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
1698 KdPrint2((PRINT_PREFIX
"Geometry: S %#x (%#x)\n",
1699 deviceExtension
->FullIdentifyData
.SectorsPerTrack
,
1700 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
1704 LunExt
->NumOfSectors
= NumOfSectors
;
1705 /* if(deviceExtension->FullIdentifyData.MajorRevision &&
1706 deviceExtension->FullIdentifyData.DoubleWordIo) {
1707 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
1711 ScsiPortMoveMemory(&LunExt
->IdentifyData
,
1712 &deviceExtension
->FullIdentifyData
,sizeof(IDENTIFY_DATA2
));
1714 InitBadBlocks(LunExt
);
1716 if ((LunExt
->IdentifyData
.DrqType
& ATAPI_DRQT_INTR
) &&
1717 (Command
!= IDE_COMMAND_IDENTIFY
)) {
1719 // This device interrupts with the assertion of DRQ after receiving
1720 // Atapi Packet Command
1721 LunExt
->DeviceFlags
|= DFLAGS_INT_DRQ
;
1722 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
1725 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
1728 if(Command
!= IDE_COMMAND_IDENTIFY
) {
1730 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_TAPE
) {
1732 LunExt
->DeviceFlags
|= DFLAGS_TAPE_DEVICE
;
1733 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is a tape drive.\n"));
1735 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
||
1736 LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_OPTICAL
) {
1737 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is CD/Optical drive.\n"));
1738 // set CD default costs
1739 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_CD
;
1740 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_CD
;
1741 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_CD
;
1742 statusByte
= WaitForDrq(chan
);
1744 KdPrint2((PRINT_PREFIX
"IssueIdentify: ATAPI drive type %#x.\n",
1745 LunExt
->IdentifyData
.DeviceType
));
1748 KdPrint2((PRINT_PREFIX
"IssueIdentify: hard drive.\n"));
1751 GetBaseStatus(chan
, statusByte
);
1752 KdPrint2((PRINT_PREFIX
"IssueIdentify: final Status on exit (%#x)\n", statusByte
));
1755 } // end IssueIdentify()
1760 Routine Description:
1761 Set drive parameters using the IDENTIFY data.
1764 HwDeviceExtension - HBA miniport driver's adapter data storage
1765 DeviceNumber - Indicates which device.
1768 TRUE if all goes well.
1773 IN PVOID HwDeviceExtension
,
1774 IN ULONG DeviceNumber
,
1778 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1779 PIDENTIFY_DATA2 identifyData
= &deviceExtension
->lun
[(lChannel
* 2) + DeviceNumber
].IdentifyData
;
1784 if(deviceExtension
->lun
[(lChannel
* 2) + DeviceNumber
].DeviceFlags
&
1785 (DFLAGS_LBA_ENABLED
| DFLAGS_ORIG_GEOMETRY
))
1788 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Number of heads %#x\n", identifyData
->NumberOfHeads
));
1789 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Sectors per track %#x\n", identifyData
->SectorsPerTrack
));
1791 // Send SET PARAMETER command.
1792 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
1793 IDE_COMMAND_SET_DRIVE_PARAMETERS
, 0,
1794 (identifyData
->NumberOfHeads
- 1), 0,
1795 (UCHAR
)identifyData
->SectorsPerTrack
, 0, ATA_WAIT_IDLE
);
1797 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
1798 if(statusByte
& IDE_STATUS_ERROR
) {
1799 errorByte
= AtapiReadPort1(&deviceExtension
->chan
[lChannel
], IDX_IO1_i_Error
);
1800 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Error bit set. Status %#x, error %#x\n",
1801 errorByte
, statusByte
));
1805 if(statusByte
== IDE_STATUS_IDLE
) {
1811 } // end SetDriveParameters()
1815 PHW_LU_EXTENSION LunExt
1818 LunExt
->DeviceFlags
&= DFLAGS_HIDDEN
;
1819 } // end UniataForgetDevice()
1824 Routine Description:
1825 Reset IDE controller and/or Atapi device.
1828 HwDeviceExtension - HBA miniport driver's adapter data storage
1837 AtapiResetController(
1838 IN PVOID HwDeviceExtension
,
1842 KdPrint2((PRINT_PREFIX
"AtapiResetController()\n"));
1843 return AtapiResetController__(HwDeviceExtension
, PathId
, RESET_COMPLETE_ALL
);
1844 } // end AtapiResetController()
1848 AtapiResetController__(
1849 IN PVOID HwDeviceExtension
,
1851 IN BOOLEAN CompleteType
1854 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1855 ULONG numberChannels
= deviceExtension
->NumberChannels
;
1856 PHW_CHANNEL chan
= NULL
;
1860 PSCSI_REQUEST_BLOCK CurSrb
;
1861 ULONG ChannelCtrlFlags
;
1862 UCHAR dma_status
= 0;
1864 ULONG slotNumber
= deviceExtension
->slotNumber
;
1865 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
1866 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
1867 ULONG DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
1868 //ULONG RevID = deviceExtension->RevID;
1869 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
1873 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID
, DeviceID
, slotNumber
));
1875 if(!deviceExtension
->simplexOnly
&& (PathId
!= CHAN_NOT_SPECIFIED
)) {
1876 // we shall reset both channels on SimplexOnly devices,
1877 // It's not worth doing so on normal controllers
1879 numberChannels
= min(j
+1, deviceExtension
->NumberChannels
);
1882 numberChannels
= deviceExtension
->NumberChannels
;
1885 for (; j
< numberChannels
; j
++) {
1887 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset channel %d\n", j
));
1888 chan
= &deviceExtension
->chan
[j
];
1889 KdPrint2((PRINT_PREFIX
" CompleteType %#x\n", CompleteType
));
1890 max_ldev
= (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
) ? 1 : 2;
1891 if(CompleteType
!= RESET_COMPLETE_NONE
) {
1893 while((CurSrb
= UniataGetCurRequest(chan
))) {
1895 PATA_REQ AtaReq
= (PATA_REQ
)(CurSrb
->SrbExtension
);
1897 KdPrint2((PRINT_PREFIX
"AtapiResetController: pending SRB %#x\n", CurSrb
));
1898 // Check and see if we are processing an internal srb
1899 if (AtaReq
->OriginalSrb
) {
1900 KdPrint2((PRINT_PREFIX
" restore original SRB %#x\n", AtaReq
->OriginalSrb
));
1901 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
1902 AtaReq
->OriginalSrb
= NULL
;
1903 // NOTE: internal SRB doesn't get to SRB queue !!!
1904 CurSrb
= AtaReq
->Srb
;
1907 // Remove current request from queue
1908 UniataRemoveRequest(chan
, CurSrb
);
1910 // Check if request is in progress.
1911 ASSERT(AtaReq
->Srb
== CurSrb
);
1913 // Complete outstanding request with SRB_STATUS_BUS_RESET.
1914 UCHAR PathId
= CurSrb
->PathId
;
1915 UCHAR TargetId
= CurSrb
->TargetId
;
1916 UCHAR Lun
= CurSrb
->Lun
;
1918 CurSrb
->SrbStatus
= ((CompleteType
== RESET_COMPLETE_ALL
) ? SRB_STATUS_BUS_RESET
: SRB_STATUS_ABORTED
) | SRB_STATUS_AUTOSENSE_VALID
;
1919 CurSrb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
1921 if (CurSrb
->SenseInfoBuffer
) {
1923 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)CurSrb
->SenseInfoBuffer
;
1925 senseBuffer
->ErrorCode
= 0x70;
1926 senseBuffer
->Valid
= 1;
1927 senseBuffer
->AdditionalSenseLength
= 0xb;
1928 if(CompleteType
== RESET_COMPLETE_ALL
) {
1929 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
1930 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
1931 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_BUS_RESET
;
1932 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_SCSI_BUS
;
1934 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
1935 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
1936 senseBuffer
->AdditionalSenseCode
= 0;
1937 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
1941 // Clear request tracking fields.
1942 AtaReq
->WordsLeft
= 0;
1943 AtaReq
->DataBuffer
= NULL
;
1944 AtaReq
->TransferLength
= 0;
1946 ScsiPortNotification(RequestComplete
,
1950 // Indicate ready for next request.
1951 ScsiPortNotification(NextLuRequest
,
1957 if(CompleteType
!= RESET_COMPLETE_ALL
)
1960 #endif //UNIATA_CORE
1961 } // end if (!CompleteType != RESET_COMPLETE_NONE)
1963 // Save control flags
1964 ChannelCtrlFlags
= chan
->ChannelCtrlFlags
;
1965 // Clear expecting interrupt flag.
1966 chan
->ExpectingInterrupt
= FALSE
;
1968 chan
->ChannelCtrlFlags
= 0;
1969 InterlockedExchange(&(chan
->CheckIntr
),
1973 KdPrint2((PRINT_PREFIX
" disable intr (0)\n"));
1974 AtapiDisableInterrupts(deviceExtension
, j
);
1975 KdPrint2((PRINT_PREFIX
" done\n"));
1977 case ATA_INTEL_ID
: {
1980 if(!(ChipFlags
& UNIATA_SATA
))
1982 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
1986 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
1987 if(ChipFlags
& UNIATA_AHCI
) {
1990 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
1991 GetPciConfig1(0x90, tmp8
);
1998 ChangePciConfig2(0x92, a
& ~mask
);
1999 AtapiStallExecution(10);
2000 ChangePciConfig2(0x92, a
| mask
);
2003 AtapiStallExecution(10000);
2004 GetPciConfig2(0x92, tmp16
);
2005 if ((tmp16
& (mask
<< 4)) == (mask
<< 4)) {
2006 AtapiStallExecution(10000);
2012 case ATA_NVIDIA_ID
: {
2013 KdPrint2((PRINT_PREFIX
" SIS/nVidia\n"));
2014 if(!(ChipFlags
& UNIATA_SATA
))
2017 case ATA_SILICON_IMAGE_ID
: {
2019 ULONG Channel
= deviceExtension
->Channel
+ j
;
2020 if(!(ChipFlags
& UNIATA_SATA
))
2022 offset
= ((Channel
& 1) << 7) + ((Channel
& 2) << 8);
2023 /* disable PHY state change interrupt */
2024 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x148 + offset
, 0);
2026 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
);
2028 /* reset controller part for this channel */
2029 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2030 AtapiReadPortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) | (0xc0 >> Channel
));
2031 AtapiStallExecution(1000);
2032 AtapiWritePortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2033 AtapiReadPortEx4(NULL
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) & ~(0xc0 >> Channel
));
2037 case ATA_PROMISE_ID
: {
2040 if(ChipFlags
& UNIATA_SATA
) {
2041 KdPrint2((PRINT_PREFIX
" SATA generic reset\n"));
2042 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
);
2045 KdPrint2((PRINT_PREFIX
" send reset\n"));
2046 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
|
2047 IDE_DC_RESET_CONTROLLER
);
2048 KdPrint2((PRINT_PREFIX
" wait a little\n"));
2049 AtapiStallExecution(10000);
2050 // Disable interrupts
2051 KdPrint2((PRINT_PREFIX
" disable intr\n"));
2052 AtapiDisableInterrupts(deviceExtension
, j
);
2053 AtapiStallExecution(100);
2054 KdPrint2((PRINT_PREFIX
" re-enable intr\n"));
2055 AtapiEnableInterrupts(deviceExtension
, j
);
2056 KdPrint2((PRINT_PREFIX
" wait a little (2)\n"));
2057 AtapiStallExecution(100000);
2058 KdPrint2((PRINT_PREFIX
" done\n"));
2063 //if(!(ChipFlags & UNIATA_SATA)) {
2064 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2065 // Reset DMA engine if active
2066 KdPrint2((PRINT_PREFIX
" check DMA engine\n"));
2067 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
2068 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
2069 if((ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
2070 (dma_status
& BM_STATUS_INTR
)) {
2071 AtapiDmaDone(HwDeviceExtension
, 0, j
, NULL
);
2075 // all these shall be performed inside AtapiHwInitialize__() ?
2077 KdPrint2((PRINT_PREFIX
" process connected devices\n"));
2078 // Do special processing for ATAPI and IDE disk devices.
2079 for (i
= 0; i
< max_ldev
; i
++) {
2081 // Check if device present.
2082 if (!(deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2086 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2087 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2090 if(!CheckDevice(HwDeviceExtension
, j
, i
, TRUE
)) {
2094 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2095 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2096 UniataForgetDevice(&(deviceExtension
->lun
[i
+ (j
* 2)]));
2101 SelectDrive(chan
, i
);
2102 AtapiStallExecution(10);
2103 statusByte
= WaitOnBusyLong(chan
);
2104 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2105 if(statusByte
== 0xff) {
2106 KdPrint2((PRINT_PREFIX
2107 "no drive, status %#x\n",
2109 UniataForgetDevice(&(deviceExtension
->lun
[i
+ (j
* 2)]));
2111 // Check for ATAPI disk.
2112 if (deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2113 // Issue soft reset and issue identify.
2114 GetStatus(chan
, statusByte
);
2115 KdPrint2((PRINT_PREFIX
"AtapiResetController: Status before Atapi reset (%#x).\n",
2118 AtapiDisableInterrupts(deviceExtension
, j
);
2119 AtapiSoftReset(chan
, i
);
2120 AtapiEnableInterrupts(deviceExtension
, j
);
2122 GetStatus(chan
, statusByte
);
2124 if(statusByte
== IDE_STATUS_SUCCESS
) {
2126 IssueIdentify(HwDeviceExtension
,
2128 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
2131 KdPrint2((PRINT_PREFIX
2132 "AtapiResetController: Status after soft reset %#x\n",
2135 GetBaseStatus(chan
, statusByte
);
2138 // Issue identify and reinit after channel reset.
2140 if (statusByte
!= IDE_STATUS_IDLE
&&
2141 statusByte
!= IDE_STATUS_SUCCESS
&&
2142 statusByte
!= IDE_STATUS_DRDY
) {
2144 KdPrint2((PRINT_PREFIX
"AtapiResetController: IdeHardReset failed\n"));
2146 if(!IssueIdentify(HwDeviceExtension
,
2148 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2150 KdPrint2((PRINT_PREFIX
"AtapiResetController: IDE IssueIdentify failed\n"));
2152 // Set disk geometry parameters.
2153 if (!SetDriveParameters(HwDeviceExtension
, i
, j
)) {
2154 KdPrint2((PRINT_PREFIX
"AtapiResetController: SetDriveParameters failed\n"));
2156 GetBaseStatus(chan
, statusByte
);
2158 // force DMA mode reinit
2159 deviceExtension
->lun
[i
+ (j
* 2)].DeviceFlags
|= DFLAGS_REINIT_DMA
;
2163 // Enable interrupts, note, the we can have here recursive disable
2164 AtapiStallExecution(10);
2165 KdPrint2((PRINT_PREFIX
"AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2167 chan
->DisableIntr
));
2168 AtapiEnableInterrupts(deviceExtension
, j
);
2170 // Call the HwInitialize routine to setup multi-block.
2171 AtapiHwInitialize__(deviceExtension
, j
);
2173 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
2177 } // end AtapiResetController__()
2182 Routine Description:
2183 This routine maps ATAPI and IDE errors to specific SRB statuses.
2186 HwDeviceExtension - HBA miniport driver's adapter data storage
2187 Srb - IO request packet
2195 IN PVOID HwDeviceExtension
,
2196 IN PSCSI_REQUEST_BLOCK Srb
2199 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2200 ULONG lChannel
= GET_CHANNEL(Srb
);
2201 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2204 UCHAR srbStatus
= SRB_STATUS_SUCCESS
;
2206 ULONG ldev
= GET_LDEV(Srb
);
2208 // Read the error register.
2210 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2211 KdPrint2((PRINT_PREFIX
2212 "MapError: Error register is %#x\n",
2215 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2217 switch (errorByte
>> 4) {
2218 case SCSI_SENSE_NO_SENSE
:
2220 KdPrint2((PRINT_PREFIX
2221 "ATAPI: No sense information\n"));
2222 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2223 srbStatus
= SRB_STATUS_ERROR
;
2226 case SCSI_SENSE_RECOVERED_ERROR
:
2228 KdPrint2((PRINT_PREFIX
2229 "ATAPI: Recovered error\n"));
2231 srbStatus
= SRB_STATUS_SUCCESS
;
2234 case SCSI_SENSE_NOT_READY
:
2236 KdPrint2((PRINT_PREFIX
2237 "ATAPI: Device not ready\n"));
2238 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2239 srbStatus
= SRB_STATUS_ERROR
;
2242 case SCSI_SENSE_MEDIUM_ERROR
:
2244 KdPrint2((PRINT_PREFIX
2245 "ATAPI: Media error\n"));
2246 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2247 srbStatus
= SRB_STATUS_ERROR
;
2250 case SCSI_SENSE_HARDWARE_ERROR
:
2252 KdPrint2((PRINT_PREFIX
2253 "ATAPI: Hardware error\n"));
2254 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2255 srbStatus
= SRB_STATUS_ERROR
;
2258 case SCSI_SENSE_ILLEGAL_REQUEST
:
2260 KdPrint2((PRINT_PREFIX
2261 "ATAPI: Illegal request\n"));
2262 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2263 srbStatus
= SRB_STATUS_ERROR
;
2266 case SCSI_SENSE_UNIT_ATTENTION
:
2268 KdPrint2((PRINT_PREFIX
2269 "ATAPI: Unit attention\n"));
2270 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2271 srbStatus
= SRB_STATUS_ERROR
;
2274 case SCSI_SENSE_DATA_PROTECT
:
2276 KdPrint2((PRINT_PREFIX
2277 "ATAPI: Data protect\n"));
2278 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2279 srbStatus
= SRB_STATUS_ERROR
;
2282 case SCSI_SENSE_BLANK_CHECK
:
2284 KdPrint2((PRINT_PREFIX
2285 "ATAPI: Blank check\n"));
2286 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2287 srbStatus
= SRB_STATUS_ERROR
;
2290 case SCSI_SENSE_ABORTED_COMMAND
:
2291 KdPrint2((PRINT_PREFIX
2292 "Atapi: Command Aborted\n"));
2293 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2294 srbStatus
= SRB_STATUS_ERROR
;
2299 KdPrint2((PRINT_PREFIX
2300 "ATAPI: Invalid sense information\n"));
2302 srbStatus
= SRB_STATUS_ERROR
;
2310 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
2311 chan
->ReturningMediaStatus
= errorByte
;
2313 if (errorByte
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
2314 KdPrint2((PRINT_PREFIX
2315 "IDE: Media change\n"));
2316 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2317 srbStatus
= SRB_STATUS_ERROR
;
2319 if (Srb
->SenseInfoBuffer
) {
2321 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2323 senseBuffer
->ErrorCode
= 0x70;
2324 senseBuffer
->Valid
= 1;
2325 senseBuffer
->AdditionalSenseLength
= 0xb;
2326 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2327 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2328 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2330 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2333 } else if (errorByte
& IDE_ERROR_COMMAND_ABORTED
) {
2334 KdPrint2((PRINT_PREFIX
2335 "IDE: Command abort\n"));
2336 srbStatus
= SRB_STATUS_ABORTED
;
2337 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2339 if (Srb
->SenseInfoBuffer
) {
2341 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2343 senseBuffer
->ErrorCode
= 0x70;
2344 senseBuffer
->Valid
= 1;
2345 senseBuffer
->AdditionalSenseLength
= 0xb;
2346 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2347 senseBuffer
->AdditionalSenseCode
= 0;
2348 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2350 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2353 deviceExtension
->lun
[ldev
].ErrorCount
++;
2355 } else if (errorByte
& IDE_ERROR_END_OF_MEDIA
) {
2357 KdPrint2((PRINT_PREFIX
2358 "IDE: End of media\n"));
2359 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2360 srbStatus
= SRB_STATUS_ERROR
;
2362 if (Srb
->SenseInfoBuffer
) {
2364 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2366 senseBuffer
->ErrorCode
= 0x70;
2367 senseBuffer
->Valid
= 1;
2368 senseBuffer
->AdditionalSenseLength
= 0xb;
2369 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2370 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIA_STATE
;
2371 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_END_OF_MEDIUM
;
2372 senseBuffer
->EndOfMedia
= 1;
2374 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2377 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2378 deviceExtension
->lun
[ldev
].ErrorCount
++;
2381 } else if (errorByte
& IDE_ERROR_ILLEGAL_LENGTH
) {
2383 KdPrint2((PRINT_PREFIX
2384 "IDE: Illegal length\n"));
2385 srbStatus
= SRB_STATUS_INVALID_REQUEST
;
2387 if (Srb
->SenseInfoBuffer
) {
2389 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2391 senseBuffer
->ErrorCode
= 0x70;
2392 senseBuffer
->Valid
= 1;
2393 senseBuffer
->AdditionalSenseLength
= 0xb;
2394 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
2395 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_VALUE
;
2396 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_PARAM_INVALID_VALUE
;
2397 senseBuffer
->IncorrectLength
= 1;
2399 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2402 } else if (errorByte
& IDE_ERROR_BAD_BLOCK
) {
2404 KdPrint2((PRINT_PREFIX
2405 "IDE: Bad block\n"));
2406 srbStatus
= SRB_STATUS_ERROR
;
2407 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2408 if (Srb
->SenseInfoBuffer
) {
2410 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2412 senseBuffer
->ErrorCode
= 0x70;
2413 senseBuffer
->Valid
= 1;
2414 senseBuffer
->AdditionalSenseLength
= 0xb;
2415 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2416 senseBuffer
->AdditionalSenseCode
= 0;
2417 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2419 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2422 } else if (errorByte
& IDE_ERROR_ID_NOT_FOUND
) {
2424 KdPrint2((PRINT_PREFIX
2425 "IDE: Id not found\n"));
2426 srbStatus
= SRB_STATUS_ERROR
;
2427 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2429 if (Srb
->SenseInfoBuffer
) {
2431 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2433 senseBuffer
->ErrorCode
= 0x70;
2434 senseBuffer
->Valid
= 1;
2435 senseBuffer
->AdditionalSenseLength
= 0xb;
2436 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2437 senseBuffer
->AdditionalSenseCode
= 0;
2438 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2440 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2443 deviceExtension
->lun
[ldev
].ErrorCount
++;
2445 } else if (errorByte
& IDE_ERROR_MEDIA_CHANGE
) {
2447 KdPrint2((PRINT_PREFIX
2448 "IDE: Media change\n"));
2449 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2450 srbStatus
= SRB_STATUS_ERROR
;
2452 if (Srb
->SenseInfoBuffer
) {
2454 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2456 senseBuffer
->ErrorCode
= 0x70;
2457 senseBuffer
->Valid
= 1;
2458 senseBuffer
->AdditionalSenseLength
= 0xb;
2459 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2460 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2461 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2463 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2466 } else if (errorByte
& IDE_ERROR_DATA_ERROR
) {
2468 KdPrint2((PRINT_PREFIX
2469 "IDE: Data error\n"));
2470 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2471 srbStatus
= SRB_STATUS_ERROR
;
2473 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2474 deviceExtension
->lun
[ldev
].ErrorCount
++;
2477 // Build sense buffer
2478 if (Srb
->SenseInfoBuffer
) {
2480 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2482 senseBuffer
->ErrorCode
= 0x70;
2483 senseBuffer
->Valid
= 1;
2484 senseBuffer
->AdditionalSenseLength
= 0xb;
2485 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2486 senseBuffer
->AdditionalSenseCode
= 0;
2487 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2489 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2493 if (deviceExtension
->lun
[ldev
].ErrorCount
>= MAX_ERRORS
) {
2494 // deviceExtension->DWordIO = FALSE;
2496 KdPrint2((PRINT_PREFIX
2497 "MapError: ErrorCount >= MAX_ERRORS\n"));
2499 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_DWORDIO_ENABLED
;
2500 deviceExtension
->lun
[ldev
].MaximumBlockXfer
= 0;
2503 KdPrint2((PRINT_PREFIX
2504 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
2507 KdPrint2((PRINT_PREFIX
2508 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
2517 ScsiPortLogError( HwDeviceExtension
,
2525 // Reprogram to not use Multi-sector.
2528 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
&&
2529 !(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
2531 statusByte
= AtaCommand(deviceExtension
, ldev
& 0x1, lChannel
, IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY
);
2533 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2534 // command was aborted.
2535 if (statusByte
& IDE_STATUS_ERROR
) {
2537 // Read the error register.
2538 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2540 KdPrint2((PRINT_PREFIX
"MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
2544 // Adjust the devExt. value, if necessary.
2545 deviceExtension
->lun
[ldev
].MaximumBlockXfer
= 0;
2553 // Set SCSI status to indicate a check condition.
2554 Srb
->ScsiStatus
= scsiStatus
;
2563 Routine Description:
2566 HwDeviceExtension - HBA miniport driver's adapter data storage
2569 TRUE - if initialization successful.
2570 FALSE - if initialization unsuccessful.
2576 IN PVOID HwDeviceExtension
2579 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2580 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2583 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base)\n"));
2585 if(WinVer_WDM_Model
) {
2586 AtapiResetController__(HwDeviceExtension
, CHAN_NOT_SPECIFIED
, RESET_COMPLETE_ALL
);
2589 /* do extra chipset specific setups */
2590 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
2592 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
2593 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
2594 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
2597 for (c
= 0; c
< numberChannels
; c
++) {
2598 AtapiHwInitialize__(deviceExtension
, c
);
2600 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base) done\n"));
2602 } // end AtapiHwInitialize()
2605 AtapiHwInitialize__(
2606 IN PHW_DEVICE_EXTENSION deviceExtension
,
2611 UCHAR statusByte
, errorByte
;
2612 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2613 PHW_LU_EXTENSION LunExt
;
2615 ULONG PreferedMode
= 0xffffffff;
2617 AtapiChipInit(deviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
);
2618 FindDevices(deviceExtension
, 0, lChannel
);
2620 for (i
= lChannel
*2; i
< (lChannel
+1)*2; i
++) {
2622 KdPrint3((PRINT_PREFIX
"AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel
, i
));
2624 LunExt
= &(deviceExtension
->lun
[i
]);
2626 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2630 AtapiDisableInterrupts(deviceExtension
, lChannel
);
2631 AtapiStallExecution(1);
2633 if (!(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
2635 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: IDE branch\n"));
2636 // Enable media status notification
2637 IdeMediaStatus(TRUE
,deviceExtension
,(UCHAR
)i
);
2639 // If supported, setup Multi-block transfers.
2640 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2641 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2642 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2644 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2645 // command was aborted.
2646 if (statusByte
& IDE_STATUS_ERROR
) {
2648 // Read the error register.
2649 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2651 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
2655 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2656 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2657 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2659 if (statusByte
& IDE_STATUS_ERROR
) {
2660 // Read the error register.
2661 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2663 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
2667 // Adjust the devExt. value, if necessary.
2668 LunExt
->MaximumBlockXfer
= 0;
2671 KdPrint2((PRINT_PREFIX
2672 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
2674 LunExt
->MaximumBlockXfer
));
2677 if(LunExt
->IdentifyData
.MajorRevision
) {
2679 if(LunExt
->opt_ReadCacheEnable
) {
2680 KdPrint2((PRINT_PREFIX
" Try Enable Read Cache\n"));
2681 // If supported, setup read/write cacheing
2682 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2683 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2684 0, ATA_C_F_ENAB_RCACHE
, ATA_WAIT_BASE_READY
);
2686 // Check for errors.
2687 if (statusByte
& IDE_STATUS_ERROR
) {
2688 KdPrint2((PRINT_PREFIX
2689 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
2691 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
2693 LunExt
->DeviceFlags
|= DFLAGS_RCACHE_ENABLED
;
2696 KdPrint2((PRINT_PREFIX
" Disable Read Cache\n"));
2697 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2698 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2699 0, ATA_C_F_DIS_RCACHE
, ATA_WAIT_BASE_READY
);
2700 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
2702 if(LunExt
->opt_WriteCacheEnable
) {
2703 KdPrint2((PRINT_PREFIX
" Try Enable Write Cache\n"));
2704 // If supported & allowed, setup write cacheing
2705 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2706 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2707 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
2708 // Check for errors.
2709 if (statusByte
& IDE_STATUS_ERROR
) {
2710 KdPrint2((PRINT_PREFIX
2711 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
2713 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
2715 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
2718 KdPrint2((PRINT_PREFIX
" Disable Write Cache\n"));
2719 statusByte
= AtaCommand(deviceExtension
, i
& 1, lChannel
,
2720 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
2721 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
2722 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
2726 } else if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)){
2729 BOOLEAN isSanyo
= FALSE
;
2732 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: ATAPI/Changer branch\n"));
2734 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
2735 for (j
= 0; j
< 26; j
+= 2) {
2737 // Build a buffer based on the identify data.
2738 MOV_DW_SWP(vendorId
[j
], ((PUCHAR
)LunExt
->IdentifyData
.ModelNumber
)[j
]);
2741 if (!AtapiStringCmp (vendorId
, "CD-ROM CDR", 11)) {
2743 // Inquiry string for older model had a '-', newer is '_'
2744 if (vendorId
[12] == 'C') {
2746 // Torisan changer. Set the bit. This will be used in several places
2747 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
2748 LunExt
->DeviceFlags
|= (DFLAGS_CHANGER_INITED
| DFLAGS_SANYO_ATAPI_CHANGER
);
2749 LunExt
->DiscsPresent
= 3;
2755 PreferedMode
= LunExt
->opt_MaxTransferMode
;
2756 if(PreferedMode
== 0xffffffff) {
2757 KdPrint2((PRINT_PREFIX
"MaxTransferMode (overriden): %#x\n", chan
->MaxTransferMode
));
2758 PreferedMode
= chan
->MaxTransferMode
;
2761 if(LunExt
->opt_PreferedTransferMode
!= 0xffffffff) {
2762 KdPrint2((PRINT_PREFIX
"PreferedTransferMode: %#x\n", PreferedMode
));
2763 PreferedMode
= min(LunExt
->opt_PreferedTransferMode
, PreferedMode
);
2766 KdPrint2((PRINT_PREFIX
" try mode %#x\n", PreferedMode
));
2767 LunExt
->OrigTransferMode
=
2768 LunExt
->LimitedTransferMode
=
2769 LunExt
->TransferMode
=
2772 AtapiDmaInit__(deviceExtension
, i
);
2774 LunExt
->OrigTransferMode
=
2775 LunExt
->LimitedTransferMode
=
2776 LunExt
->TransferMode
;
2777 KdPrint2((PRINT_PREFIX
"Using %#x mode\n", LunExt
->TransferMode
));
2779 // We need to get our device ready for action before
2780 // returning from this function
2782 // According to the atapi spec 2.5 or 2.6, an atapi device
2783 // clears its status BSY bit when it is ready for atapi commands.
2784 // However, some devices (Panasonic SQ-TC500N) are still
2785 // not ready even when the status BSY is clear. They don't react
2786 // to atapi commands.
2788 // Since there is really no other indication that tells us
2789 // the drive is really ready for action. We are going to check BSY
2790 // is clear and then just wait for an arbitrary amount of time!
2792 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2795 // have to get out of the loop sometime!
2796 // 10000 * 100us = 1000,000us = 1000ms = 1s
2798 GetStatus(chan
, statusByte
);
2799 while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
) {
2801 KdPrint2((PRINT_PREFIX
"Wait for ATAPI (status %x\n)", statusByte
));
2802 // Wait for Busy to drop.
2803 AtapiStallExecution(100);
2804 GetStatus(chan
, statusByte
);
2808 // 5000 * 100us = 500,000us = 500ms = 0.5s
2811 AtapiStallExecution(100);
2812 } while (waitCount
--);
2814 GetBaseStatus(chan
, statusByte
);
2815 AtapiEnableInterrupts(deviceExtension
, lChannel
);
2816 AtapiStallExecution(10);
2821 } // end AtapiHwInitialize()
2827 AtapiHwInitializeChanger(
2828 IN PVOID HwDeviceExtension
,
2829 IN PSCSI_REQUEST_BLOCK Srb
,
2830 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus
)
2832 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2833 ULONG ldev
= GET_LDEV(Srb
);
2835 if (MechanismStatus
) {
2836 deviceExtension
->lun
[ldev
].DiscsPresent
= MechanismStatus
->NumberAvailableSlots
;
2837 if (deviceExtension
->lun
[ldev
].DiscsPresent
> 1) {
2838 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_ATAPI_CHANGER
;
2842 } // end AtapiHwInitializeChanger()
2847 Routine Description:
2848 This routine will parse the string for a match on the keyword, then
2849 calculate the value for the keyword and return it to the caller.
2852 String - The ASCII string to parse.
2853 KeyWord - The keyword for the value desired.
2856 Zero if value not found
2857 Value converted from ASCII to binary.
2861 AtapiParseArgumentString(
2869 ULONG stringLength
= 0;
2870 ULONG keyWordLength
= 0;
2880 // Calculate the string length and lower case all characters.
2883 if (*cptr
>= 'A' && *cptr
<= 'Z') {
2884 *cptr
= *cptr
+ ('a' - 'A');
2890 // Calculate the keyword length and lower case all characters.
2894 if (*cptr
>= 'A' && *cptr
<= 'Z') {
2895 *cptr
= *cptr
+ ('a' - 'A');
2901 if (keyWordLength
> stringLength
) {
2903 // Can't possibly have a match.
2907 // Now setup and start the compare.
2912 // The input string may start with white space. Skip it.
2913 while (*cptr
== ' ' || *cptr
== '\t') {
2917 if (*cptr
== '\0') {
2923 while (*cptr
++ == *kptr
++) {
2925 if (*(cptr
- 1) == '\0') {
2931 if (*(kptr
- 1) == '\0') {
2933 // May have a match backup and check for blank or equals.
2935 while (*cptr
== ' ' || *cptr
== '\t') {
2939 // Found a match. Make sure there is an equals.
2942 // Not a match so move to the next semicolon.
2944 if (*cptr
++ == ';') {
2945 goto ContinueSearch
;
2950 // Skip the equals sign.
2953 // Skip white space.
2954 while ((*cptr
== ' ') || (*cptr
== '\t')) {
2958 if (*cptr
== '\0') {
2959 // Early end of string, return not found
2964 // This isn't it either.
2966 goto ContinueSearch
;
2970 if ((*cptr
== '0') && (*(cptr
+ 1) == 'x')) {
2971 // Value is in Hex. Skip the "0x"
2973 for (index
= 0; *(cptr
+ index
); index
++) {
2975 if (*(cptr
+ index
) == ' ' ||
2976 *(cptr
+ index
) == '\t' ||
2977 *(cptr
+ index
) == ';') {
2981 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
2982 value
= (16 * value
) + (*(cptr
+ index
) - '0');
2984 if ((*(cptr
+ index
) >= 'a') && (*(cptr
+ index
) <= 'f')) {
2985 value
= (16 * value
) + (*(cptr
+ index
) - 'a' + 10);
2987 // Syntax error, return not found.
2994 // Value is in Decimal.
2995 for (index
= 0; *(cptr
+ index
); index
++) {
2997 if (*(cptr
+ index
) == ' ' ||
2998 *(cptr
+ index
) == '\t' ||
2999 *(cptr
+ index
) == ';') {
3003 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3004 value
= (10 * value
) + (*(cptr
+ index
) - '0');
3007 // Syntax error return not found.
3016 // Not a match check for ';' to continue search.
3018 if (*cptr
++ == ';') {
3019 goto ContinueSearch
;
3025 } // end AtapiParseArgumentString()_
3032 IN PVOID HwDeviceExtension
,
3037 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3038 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3041 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3044 KdPrint2((PRINT_PREFIX
"AtapiCallBack:\n"));
3045 // If the last command was DSC restrictive, see if it's set. If so, the device is
3046 // ready for a new request. Otherwise, reset the timer and come back to here later.
3048 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3049 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3050 // we shall have no problem with interrupt handler.
3051 if (!srb
|| chan
->ExpectingInterrupt
) {
3052 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Calling ISR directly due to BUSY\n"));
3053 chan
->DpcState
= DPC_STATE_TIMER
;
3054 if(!AtapiInterrupt__(HwDeviceExtension
, lChannel
)) {
3055 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3056 KdPrint2((PRINT_PREFIX
"AtapiCallBack: What's fucking this ???\n"));
3058 goto ReturnCallback
;
3062 if (!IS_RDP((srb
->Cdb
[0]))) {
3063 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb
->Cdb
[0]));
3067 goto ReturnEnableIntr
;
3069 GetStatus(chan
, statusByte
);
3070 if (statusByte
& IDE_STATUS_DSC
) {
3072 UCHAR PathId
= srb
->PathId
;
3073 UCHAR TargetId
= srb
->TargetId
;
3074 UCHAR Lun
= srb
->Lun
;
3076 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Found DSC for RDP - %#x\n", srb
->Cdb
[0]));
3077 AtapiDmaDBSync(chan
, srb
);
3078 UniataRemoveRequest(chan
, srb
);
3079 ScsiPortNotification(RequestComplete
, deviceExtension
, srb
);
3080 // Clear current SRB.
3081 if(!deviceExtension
->simplexOnly
) {
3082 srb
= UniataGetCurRequest(chan
);
3088 // Ask for next request.
3089 ScsiPortNotification(NextLuRequest
,
3094 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
3097 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3101 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Requesting another timer for Op %#x\n",
3104 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3108 goto ReturnCallback
;
3113 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
3114 KdPrint2((PRINT_PREFIX
"AtapiCallBack: CallDisableInterrupts\n"));
3115 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3116 #ifdef UNIATA_USE_XXableInterrupts
3117 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
3118 // must be called on DISPATCH_LEVEL
3119 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
3120 AtapiEnableInterrupts__
);
3122 AtapiEnableInterrupts(HwDeviceExtension
, lChannel
);
3123 InterlockedExchange(&(chan
->CheckIntr
),
3125 // Will raise IRQL to DIRQL
3126 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3127 AtapiEnableInterrupts__
,
3129 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
3130 #endif // UNIATA_USE_XXableInterrupts
3132 //ASSERT(!deviceExtension->simplexOnly);
3137 // Check other channel
3138 // In simplex mode no interrupts must appear on other channels
3139 for(_c
=0; _c
<deviceExtension
->NumberChannels
-1; _c
++) {
3140 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3142 chan
= &(deviceExtension
->chan
[c
]);
3144 if((ULONG
)InterlockedCompareExchange(&chan
->CheckIntr
,
3146 CHECK_INTR_DETECTED
) == CHECK_INTR_DETECTED
) {
3147 //ASSERT(!deviceExtension->simplexOnly);
3148 chan
->DpcState
= DPC_STATE_ISR
;
3149 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3150 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3154 KdPrint2((PRINT_PREFIX
"AtapiCallBack: return\n"));
3157 } // end AtapiCallBack__()
3161 IN PVOID HwDeviceExtension
3164 AtapiCallBack__(HwDeviceExtension
, (UCHAR
)((PHW_DEVICE_EXTENSION
)HwDeviceExtension
)->ActiveDpcChan
);
3167 #endif //UNIATA_CORE
3171 Routine Description:
3173 This is the interrupt service routine for ATAPI IDE miniport driver.
3177 HwDeviceExtension - HBA miniport driver's adapter data storage
3181 TRUE if expecting an interrupt.
3187 IN PVOID HwDeviceExtension
3190 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3192 BOOLEAN status
= FALSE
;
3196 BOOLEAN checked
[AHCI_MAX_PORT
];
3198 KdPrint2((PRINT_PREFIX
"Intr: VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
3200 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3201 checked
[_c
] = FALSE
;
3204 // atapiDev = (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
3205 for(pass
=0; pass
<2; pass
++) {
3206 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3208 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3209 //non_empty_chan = (deviceExtension->lun[c*2].DeviceFlags | deviceExtension->lun[c*2+1].DeviceFlags)
3210 // & DFLAGS_DEVICE_PRESENT;
3215 // check non-empty and expecting interrupt channels first
3216 if(!pass
&& !deviceExtension
->chan
[c
].ExpectingInterrupt
)
3221 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3223 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3224 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): disabled INTR on ch %d\n", c
));
3227 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
3229 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): try lock\n"));
3230 // c_state = deviceExtension->chan[c].CheckIntr;
3231 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
3232 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
3234 c_state
= (ULONG
)InterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3236 CHECK_INTR_DETECTED
);
3237 if(c_state
== CHECK_INTR_IDLE
) {
3238 // c_state = deviceExtension->chan[c].CheckIntr;
3239 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
3240 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
3242 c_state
= (ULONG
)InterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3246 } while(c_state
== CHECK_INTR_CHECK
);
3247 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): locked\n"));
3248 // check if already serviced
3249 if(c_state
== CHECK_INTR_ACTIVE
) {
3250 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
3254 if((c_state
== CHECK_INTR_DETECTED
) ||
3255 (i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3258 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): Catch unexpected\n"));
3259 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3262 // disable interrupts on other channel of legacy mode
3263 // ISA-bridged onboard controller
3264 if(deviceExtension
->simplexOnly
/*||
3265 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3266 AtapiDisableInterrupts(deviceExtension
, !c
);
3269 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_ISR
;
3270 if(AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3271 deviceExtension
->LastInterruptedChannel
= (UCHAR
)c
;
3272 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): return status TRUE\n"));
3275 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
3276 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3279 // re-enable interrupts on other channel
3280 if(deviceExtension
->simplexOnly
/*||
3281 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3282 AtapiEnableInterrupts(deviceExtension
, !c
);
3286 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
3287 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3292 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): exit with status %#x\n", status
));
3294 deviceExtension
->FirstChannelToCheck
++;
3295 if(deviceExtension
->FirstChannelToCheck
>= deviceExtension
->NumberChannels
)
3296 deviceExtension
->FirstChannelToCheck
= 0;
3299 } // end AtapiInterrupt()
3306 IN PKINTERRUPT Interrupt
,
3307 IN PVOID Isr2HwDeviceExtension
3311 PISR2_DEVICE_EXTENSION Isr2DeviceExtension
= (PISR2_DEVICE_EXTENSION
)Isr2HwDeviceExtension
;
3312 PHW_DEVICE_EXTENSION deviceExtension
= Isr2DeviceExtension
->HwDeviceExtension
;
3314 BOOLEAN status
= FALSE
;
3318 // we should never get here for ISA/MCA
3319 if(!BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
3320 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3324 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3325 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3327 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3328 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: disabled INTR\n"));
3332 if((ULONG
)CrNtInterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3334 CHECK_INTR_IDLE
) != CHECK_INTR_IDLE
) {
3335 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
3336 // hunt on unexpected intr (Some devices generate double interrupts,
3337 // some controllers (at least CMD649) interrupt twice with small delay.
3338 // If interrupts are disabled, they queue interrupt and re-issue it later,
3339 // when we do not expect it.
3344 if((i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3346 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: intr\n"));
3348 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: Catch unexpected\n"));
3349 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3354 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_DETECTED
);
3356 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3359 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: status %d, c_count %d\n", status
, c_count
));
3360 if(status
&& (c_count
!= deviceExtension
->NumberChannels
)) {
3361 // there is an active ISR/DPC for one channel, but
3362 // we have an interrupt from another one
3363 // Lets inform current ISR/DPC about new interrupt
3364 InterlockedExchange(&(deviceExtension
->ReCheckIntr
), CHECK_INTR_DETECTED
);
3368 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: return %d\n", status
));
3371 } // end AtapiInterrupt2()
3373 RETTYPE_XXableInterrupts
3376 IN PVOID HwDeviceExtension
3379 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3382 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3383 KdPrint2((PRINT_PREFIX
"AtapiInterruptDpc: %#x\n",c
));
3385 if(!(deviceExtension
->chan
[c
].ChannelCtrlFlags
& CTRFLAGS_DPC_REQ
)) {
3387 if((ULONG
)InterlockedCompareExchange(&(deviceExtension
->chan
[c
].CheckIntr
),
3389 CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
3394 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_DPC_REQ
;
3397 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
3398 AtapiDisableInterrupts(deviceExtension, lChannel);
3401 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_DPC
;
3402 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3403 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3406 return RETVAL_XXableInterrupts
;
3407 } // end AtapiInterruptDpc()
3410 RETTYPE_XXableInterrupts
3412 AtapiEnableInterrupts__(
3413 IN PVOID HwDeviceExtension
3416 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3417 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__():\n"));
3419 PHW_CHANNEL chan
= NULL
;
3421 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3422 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__(2): %#x\n",c
));
3423 chan
= &(deviceExtension
->chan
[c
]);
3425 if(chan
->ChannelCtrlFlags
& CTRFLAGS_ENABLE_INTR_REQ
) {
3426 // enable intrs on requested channel
3427 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_ENABLE_INTR_REQ
;
3428 AtapiEnableInterrupts(HwDeviceExtension
, c
);
3429 InterlockedExchange(&(chan
->CheckIntr
),
3432 // check if current or other channel(s) interrupted
3433 //AtapiInterrupt(HwDeviceExtension);
3435 if(deviceExtension
->simplexOnly
) {
3439 // check if other channel(s) interrupted
3440 // must do nothing in simplex mode
3441 if((ULONG
)CrNtInterlockedCompareExchange(&(chan
->CheckIntr
),
3443 CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
3446 //ASSERT(!deviceExtension->simplexOnly);
3447 chan
->DpcState
= DPC_STATE_ISR
;
3448 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3449 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3453 // In simplex mode next command must be sent to device here
3454 if(deviceExtension
->simplexOnly
&& chan
) {
3455 PSCSI_REQUEST_BLOCK srb
;
3456 chan
= UniataGetNextChannel(chan
);
3458 srb
= UniataGetCurRequest(chan
);
3463 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3467 return RETVAL_XXableInterrupts
;
3469 } // end AtapiEnableInterrupts__()
3471 #endif //UNIATA_CORE
3475 AtapiEnableInterrupts(
3476 IN PVOID HwDeviceExtension
,
3480 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3481 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: %d\n",c
, deviceExtension
->chan
[c
].DisableIntr
));
3482 if(c
>= deviceExtension
->NumberChannels
) {
3485 if(!InterlockedDecrement(&deviceExtension
->chan
[c
].DisableIntr
)) {
3486 AtapiWritePort1(&deviceExtension
->chan
[c
], IDX_IO2_o_Control
,
3488 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_INTR_DISABLED
;
3490 AtapiWritePort1(&deviceExtension
->chan
[c
], IDX_IO2_o_Control
,
3491 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
3494 } // end AtapiEnableInterrupts()
3497 AtapiDisableInterrupts(
3498 IN PVOID HwDeviceExtension
,
3502 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3503 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: %d\n",c
, deviceExtension
->chan
[c
].DisableIntr
));
3504 // mark channel as busy
3505 if(c
>= deviceExtension
->NumberChannels
) {
3508 if(InterlockedIncrement(&deviceExtension
->chan
[c
].DisableIntr
)) {
3509 AtapiWritePort1(&deviceExtension
->chan
[c
], IDX_IO2_o_Control
,
3510 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
3511 deviceExtension
->chan
[c
].ChannelCtrlFlags
|= CTRFLAGS_INTR_DISABLED
;
3515 } // end AtapiDisableInterrupts()
3519 Check hardware for interrupt state
3522 AtapiCheckInterrupt__(
3523 IN PVOID HwDeviceExtension
,
3524 IN UCHAR c
// logical channel
3527 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3528 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
3529 PHW_LU_EXTENSION LunExt
;
3531 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
3532 ULONG ChipType
= deviceExtension
->HwFlags
& CHIPTYPE_MASK
;
3535 ULONG pr_status
= 0;
3536 UCHAR dma_status
= 0;
3540 ULONG slotNumber
= deviceExtension
->slotNumber
;
3541 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
3542 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
3545 BOOLEAN DmaTransfer
= FALSE
;
3546 BOOLEAN OurInterrupt
= FALSE
;
3548 UCHAR interruptReason
;
3549 BOOLEAN EarlyIntr
= FALSE
;
3551 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__:\n"));
3554 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
3556 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
3558 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension
->DevIndex
,
3559 deviceExtension
->Channel
+ c
, c
));
3561 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension
->DevIndex
,
3562 deviceExtension
->Channel
+ c
, c
));
3563 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
3564 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
3567 // do controller-specific interrupt servicing staff
3568 if(deviceExtension
->UnknownDev
) {
3569 KdPrint2((PRINT_PREFIX
" UnknownDev\n"));
3573 if((ChipFlags
& UNIATA_AHCI
) &&
3574 UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
3575 OurInterrupt
= UniataAhciStatus(HwDeviceExtension
, lChannel
);
3576 return OurInterrupt
;
3580 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
3581 // Such behavior was observed with Intel ICH-xxx chips
3582 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
3586 case ATA_PROMISE_ID
: {
3590 status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x1c);
3594 ((Channel
) ? 0x00004000 : 0x00000400))) {
3595 KdPrint2((PRINT_PREFIX
" Promise old/new unexpected\n"));
3600 AtapiWritePort1(chan
, IDX_BM_DeviceSpecific0
, 0x0b);
3601 status
= AtapiReadPort1(chan
, IDX_BM_DeviceSpecific1
);
3604 if(!(status
& 0x20)) {
3605 KdPrint2((PRINT_PREFIX
" Promise tx unexpected\n"));
3610 status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x0040);
3611 if(ChipFlags
& PRSATA
) {
3612 pr_status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c);
3613 AtapiWritePortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c, pr_status
& 0x000000ff);
3615 if(pr_status
& (0x11 << Channel
)) {
3616 // TODO: reset channel
3617 KdPrint2((PRINT_PREFIX
" Promise mio unexpected + reset req\n"));
3620 if(!(status
& (0x01 << Channel
))) {
3621 KdPrint2((PRINT_PREFIX
" Promise mio unexpected\n"));
3624 AtapiWritePort4(chan
, IDX_BM_DeviceSpecific0
, 0x00000001);
3628 case ATA_NVIDIA_ID
: {
3629 if(!(ChipFlags
& UNIATA_SATA
))
3632 KdPrint2((PRINT_PREFIX
"NVIDIA\n"));
3634 ULONG offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
3635 ULONG shift
= Channel
<< ((ChipFlags
& NVQ
) ? 4 : 2);
3637 /* get and clear interrupt status */
3638 if(ChipFlags
& NVQ
) {
3639 pr_status
= AtapiReadPortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
3640 AtapiWritePortEx4(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0fUL
<< shift
) | 0x00f000f0);
3642 pr_status
= AtapiReadPortEx1(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
3643 AtapiWritePortEx1(chan
, (ULONG
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0f << shift
));
3645 KdPrint2((PRINT_PREFIX
" pr_status %x\n", pr_status
));
3647 /* check for and handle connect events */
3648 if(((pr_status
& (0x0cUL
<< shift
)) == (0x04UL
<< shift
)) ) {
3649 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
3651 /* check for and handle disconnect events */
3652 if((pr_status
& (0x08UL
<< shift
)) &&
3653 !((pr_status
& (0x04UL
<< shift
) &&
3654 AtapiReadPort4(chan
, IDX_SATA_SStatus
))) ) {
3655 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
3657 /* do we have any device action ? */
3658 if(!(pr_status
& (0x01UL
<< shift
))) {
3659 KdPrint2((PRINT_PREFIX
" nVidia unexpected\n"));
3660 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
)) {
3669 KdPrint2((PRINT_PREFIX
"ATI\n"));
3670 if(ChipType
== SIIMIO
) {
3675 case ATA_SILICON_IMAGE_ID
:
3677 if(ChipType
== SIIMIO
) {
3679 reg32
= AtapiReadPort4(chan
, IDX_BM_DeviceSpecific0
);
3680 KdPrint2((PRINT_PREFIX
" Sii DS0 %x\n", reg32
));
3681 if(reg32
== 0xffffffff) {
3682 KdPrint2((PRINT_PREFIX
" Sii mio unexpected\n"));
3685 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
))) {
3686 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (2)\n"));
3690 if(ChipFlags
& UNIATA_SATA
) {
3691 if(reg32
& (BM_DS0_SII_DMA_SATA_IRQ
| BM_DS0_SII_IRQ
)) {
3693 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
3694 * controllers continue to assert IRQ as long as
3695 * SError bits are pending. Clear SError immediately.
3697 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
)) {
3705 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3706 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (3)\n"));
3707 return OurInterrupt
;
3709 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
& ~BM_STATUS_ERR
);
3710 goto skip_dma_stat_check
;
3713 if(!(deviceExtension
->HwFlags
& SIIINTR
))
3715 GetPciConfig1(0x71, reg8
);
3716 KdPrint2((PRINT_PREFIX
" 0x71 = %#x\n", reg8
));
3718 (Channel
? 0x08 : 0x04))) {
3722 KdPrint2((PRINT_PREFIX
" cmd our\n"));
3725 SetPciConfig1(0x71, (Channel
? 0x08 : 0x04));
3732 //dma_status = GetDmaStatus(deviceExtension, lChannel);
3733 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3734 KdPrint2((PRINT_PREFIX
" Acard unexpected\n"));
3737 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
| BM_STATUS_INTR
);
3738 AtapiStallExecution(1);
3739 AtapiWritePort1(chan
, IDX_BM_Command
,
3740 AtapiReadPort1(chan
, IDX_BM_Command
) & ~BM_COMMAND_START_STOP
);
3741 goto skip_dma_stat_check
;
3743 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
3744 if(ChipFlags
& UNIATA_AHCI
) {
3747 if(ChipFlags
& UNIATA_SATA
) {
3748 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
)) {
3755 KdPrint2((PRINT_PREFIX
" perform generic check\n"));
3757 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
3758 KdPrint2((PRINT_PREFIX
" DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status
));
3759 if(dma_status
& BM_STATUS_ERR
) {
3760 KdPrint2((PRINT_PREFIX
" DmaTransfer + BM_STATUS_ERR -> our\n"));
3763 KdPrint2((PRINT_PREFIX
" getting status...\n"));
3764 GetStatus(chan
, statusByte
);
3765 KdPrint2((PRINT_PREFIX
" status %#x\n", statusByte
));
3766 if(statusByte
& IDE_STATUS_ERROR
) {
3767 KdPrint2((PRINT_PREFIX
" IDE_STATUS_ERROR -> our\n", statusByte
));
3775 if(dma_status
& BM_STATUS_INTR
) {
3776 // bullshit, we have DMA interrupt, but had never initiate DMA operation
3777 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr\n"));
3778 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
3783 skip_dma_stat_check
:
3784 if(!(ChipFlags
& UNIATA_SATA
)) {
3785 AtapiStallExecution(1);
3788 LunExt
= &(deviceExtension
->lun
[c
*2 + chan
->cur_cdev
]);
3789 /* if drive is busy it didn't interrupt */
3790 /* the exception is DCS + BSY state of ATAPI devices */
3791 KdPrint2((PRINT_PREFIX
" getting status...\n"));
3792 GetStatus(chan
, statusByte
);
3793 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3794 KdPrint3((PRINT_PREFIX
" ATAPI status %#x\n", statusByte
));
3796 KdPrint2((PRINT_PREFIX
" IDE status %#x\n", statusByte
));
3798 if (statusByte
== 0xff) {
3799 // interrupt from empty controller ?
3801 if (statusByte
& IDE_STATUS_BUSY
) {
3802 if(!chan
->ExpectingInterrupt
) {
3803 KdPrint3((PRINT_PREFIX
" unexpected intr + BUSY\n"));
3804 return OurInterrupt
;
3807 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3808 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
3810 KdPrint2((PRINT_PREFIX
" expecting intr + BUSY (3), non ATAPI\n"));
3813 if((statusByte
& ~IDE_STATUS_DRQ
) != (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
| IDE_STATUS_DSC
)) {
3814 KdPrint3((PRINT_PREFIX
" unexpected status, seems it is not our\n"));
3817 if(!(LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
) && (statusByte
& IDE_STATUS_DRQ
)) {
3818 KdPrint3((PRINT_PREFIX
" unexpected DRQ, seems it is not our\n"));
3824 if(dma_status
& BM_STATUS_INTR
) {
3825 KdPrint3((PRINT_PREFIX
" our interrupt with BSY set, try wait in ISR or post to DPC\n"));
3826 /* clear interrupt and get status */
3827 GetBaseStatus(chan
, statusByte
);
3828 KdPrint3((PRINT_PREFIX
" base status %#x (+BM_STATUS_INTR)\n", statusByte
));
3832 if(g_WaitBusyInISR
) {
3833 GetStatus(chan
, statusByte
);
3834 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
3835 reg8
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3836 KdPrint2((PRINT_PREFIX
" Error reg (%#x)\n", reg8
));
3837 if (!(statusByte
& IDE_STATUS_BUSY
)) {
3838 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
3840 if (statusByte
& IDE_STATUS_BUSY
) {
3841 KdPrint2((PRINT_PREFIX
" still BUSY, seems it is not our\n"));
3848 /* clear interrupt and get status */
3849 GetBaseStatus(chan
, statusByte
);
3850 KdPrint2((PRINT_PREFIX
" base status %#x\n", statusByte
));
3851 if (statusByte
== 0xff) {
3852 // interrupt from empty controller ?
3854 if(!(statusByte
& (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
))) {
3855 KdPrint2((PRINT_PREFIX
" no DRQ/DRDY set\n"));
3856 return OurInterrupt
;
3859 #ifndef UNIATA_PIO_ONLY
3861 if(!EarlyIntr
|| g_WaitBusyInISR
) {
3862 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
3864 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3865 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
3869 KdPrint2((PRINT_PREFIX
" set REQ_STATE_EARLY_INTR.\n"));
3871 AtaReq
->ReqState
= REQ_STATE_EARLY_INTR
;
3877 if (!(chan
->ExpectingInterrupt
)) {
3879 KdPrint2((PRINT_PREFIX
" Unexpected interrupt.\n"));
3881 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3882 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
3884 KdPrint2((PRINT_PREFIX
" OurInterrupt = %d\n", OurInterrupt
));
3885 return OurInterrupt
;
3887 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
3888 KdPrint3((PRINT_PREFIX
"AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason
));
3889 return OurInterrupt
;
3891 //ASSERT(!chan->queue_depth || chan->cur_req);
3893 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__: exit with TRUE\n"));
3896 } // end AtapiCheckInterrupt__()
3901 IN PVOID HwDeviceExtension
,
3905 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3906 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
3908 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3909 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
3911 ULONG wordCount
= 0, wordsThisInterrupt
= DEV_BSIZE
/2;
3912 ULONG status
= SRB_STATUS_SUCCESS
;
3913 UCHAR dma_status
= 0;
3916 UCHAR statusByte
= 0,interruptReason
;
3918 BOOLEAN atapiDev
= FALSE
;
3923 BOOLEAN DmaTransfer
= FALSE
;
3925 ULONG TimerValue
= 1000;
3926 #ifdef UNIATA_USE_XXableInterrupts
3927 BOOLEAN InDpc
= (KeGetCurrentIrql() == DISPATCH_LEVEL
);
3929 BOOLEAN InDpc
= (chan
->DpcState
!= DPC_STATE_ISR
);
3930 #endif // UNIATA_USE_XXableInterrupts
3931 BOOLEAN UseDpc
= deviceExtension
->UseDpc
;
3932 // BOOLEAN RestoreUseDpc = FALSE;
3933 BOOLEAN DataOverrun
= FALSE
;
3934 BOOLEAN NoStartIo
= TRUE
;
3936 KdPrint2((PRINT_PREFIX
"AtapiInterrupt:\n"));
3938 KdPrint2((PRINT_PREFIX
" InDpc = TRUE\n"));
3939 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
3945 UCHAR OldReqState
= REQ_STATE_NONE
;
3947 PHW_LU_EXTENSION LunExt
;
3950 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
3952 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension
->DevIndex
, Channel
, KeGetCurrentIrql(), c
));
3954 if((chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
3955 (AtaReq
&& (AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
)) ) {
3957 KdPrint2((PRINT_PREFIX
" DmaTransfer = TRUE\n"));
3961 PathId
= srb
->PathId
;
3962 TargetId
= srb
->TargetId
;
3968 goto enqueue_next_req
;
3971 ldev
= GET_LDEV2(PathId
, TargetId
, Lun
);
3972 DeviceNumber
= (UCHAR
)(ldev
& 1);
3973 LunExt
= &(deviceExtension
->lun
[ldev
]);
3974 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
3975 KdPrint2((PRINT_PREFIX
" dev_type %s\n", atapiDev
? "ATAPI" : "IDE"));
3977 // check if we are in ISR DPC
3979 KdPrint2((PRINT_PREFIX
" InDpc -> CTRFLAGS_INTR_DISABLED\n"));
3980 goto ServiceInterrupt
;
3984 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
3987 if (!(chan
->ExpectingInterrupt
)) {
3989 KdPrint2((PRINT_PREFIX
" Unexpected interrupt for this channel.\n"));
3993 // change request state
3995 OldReqState
= AtaReq
->ReqState
;
3996 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
3997 KdPrint2((PRINT_PREFIX
" OldReqState = %x\n", OldReqState
));
4000 // We don't want using DPC for fast operations, like
4001 // DMA completion, sending CDB, short ATAPI transfers, etc.
4003 // We MUST use DPC, because of interprocessor synchronization
4004 // on multiprocessor platforms
4007 goto ServiceInterrupt
;
4009 switch(OldReqState
) {
4010 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR
:
4011 KdPrint3((PRINT_PREFIX
" EXPECTING_CMD_INTR\n"));
4012 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR
:
4013 case REQ_STATE_DPC_WAIT_BUSY0
:
4014 case REQ_STATE_DPC_WAIT_BUSY1
:
4015 KdPrint2((PRINT_PREFIX
" continue service interrupt\n"));
4016 goto ServiceInterrupt
;
4017 case REQ_STATE_ATAPI_DO_NOTHING_INTR
:
4018 KdPrint2((PRINT_PREFIX
" do nothing on interrupt\n"));
4022 if(!DmaTransfer
&& !atapiDev
) {
4023 KdPrint2((PRINT_PREFIX
" service PIO HDD\n"));
4030 goto ServiceInterrupt
;
4032 #ifdef UNIATA_USE_XXableInterrupts
4034 KdPrint2((PRINT_PREFIX
" Unexpected InDpc\n"));
4036 // shall never get here
4041 KdPrint2((PRINT_PREFIX
" this is direct DPC call on DRQL\n"));
4043 AtaReq
->ReqState
= REQ_STATE_DPC_INTR_REQ
;
4044 KdPrint2((PRINT_PREFIX
" ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
4046 KdPrint2((PRINT_PREFIX
" DPC without AtaReq!!!\n"));
4049 KdPrint2((PRINT_PREFIX
"call service interrupt\n"));
4050 goto ServiceInterrupt
;
4051 #endif // UNIATA_USE_XXableInterrupts
4056 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
4057 // We always get here when are called from timer callback, which is invoked on DRQL.
4058 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
4060 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: start DPC init...\n"));
4061 // disable interrupts for this channel,
4062 // but avoid recursion and double-disable
4063 if(OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4064 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4067 chan
->ChannelCtrlFlags
|= CTRFLAGS_DPC_REQ
;
4069 #ifdef UNIATA_USE_XXableInterrupts
4070 // Will lower IRQL to DISPATCH_LEVEL
4071 ScsiPortNotification(CallEnableInterrupts
, HwDeviceExtension
,
4072 /*c ?*/ AtapiInterruptDpc
/*_1 : AtapiInterruptDpc_0*/);
4073 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DPC inited\n"));
4075 // Will raise IRQL to DIRQL
4076 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4079 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
4080 #endif // UNIATA_USE_XXableInterrupts
4085 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4087 // Will raise IRQL to DIRQL
4088 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4092 #endif //UNIATA_CORE
4096 if(AtaReq
&& InDpc
) {
4097 switch(AtaReq
->ReqState
) {
4098 case REQ_STATE_DPC_WAIT_DRQ0
:
4100 case REQ_STATE_DPC_WAIT_BUSY
:
4102 case REQ_STATE_DPC_WAIT_DRQ
:
4104 case REQ_STATE_DPC_WAIT_DRQ_ERR
:
4106 case REQ_STATE_DPC_WAIT_BUSY0
:
4107 case REQ_STATE_DPC_WAIT_BUSY1
:
4108 // continue normal execution
4114 #endif //UNIATA_CORE
4116 // make additional delay for old devices (if we are not in DPC)
4117 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
4121 !(deviceExtension->HwFlags & UNIATA_SATA)
4123 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
4124 AtapiStallExecution(10);
4127 /* clear interrupt and get status */
4128 GetBaseStatus(chan
, statusByte
);
4130 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte
));
4132 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Entered with status (%#x)\n", statusByte
));
4136 KdPrint2((PRINT_PREFIX
" operate like in DPC\n"));
4142 if (statusByte
& IDE_STATUS_BUSY
) {
4143 if (deviceExtension
->DriverMustPoll
) {
4144 // Crashdump is polling and we got caught with busy asserted.
4145 // Just go away, and we will be polled again shortly.
4146 KdPrint2((PRINT_PREFIX
" Hit BUSY while polling during crashdump.\n"));
4147 goto ReturnEnableIntr
;
4150 // Ensure BUSY is non-asserted.
4151 // make a very small idle before falling to DPC
4152 k
= (InDpc
&& UseDpc
) ? 1000 : 2;
4154 for (i
= 0; i
< k
; i
++) {
4156 GetBaseStatus(chan
, statusByte
);
4157 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4160 AtapiStallExecution(10);
4163 if (!InDpc
&& UseDpc
&& i
== 2) {
4165 KdPrint2((PRINT_PREFIX
" BUSY on entry. Status %#x, Base IO %#x\n", statusByte
));
4168 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4173 AtapiStallExecution(TimerValue
);
4174 goto ServiceInterrupt
;
4175 #endif //UNIATA_CORE
4177 if (InDpc
&& i
== k
) {
4178 // reset the controller.
4179 KdPrint2((PRINT_PREFIX
4180 " Resetting due to BUSY on entry - %#x.\n",
4182 goto IntrPrepareResetController
;
4187 if(!LunExt
->IdentifyData
.MajorRevision
&&
4190 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
4192 KdPrint2((PRINT_PREFIX
" additional delay 10us for old devices (2)\n"));
4193 AtapiStallExecution(10);
4195 if (statusByte
& IDE_STATUS_BUSY
) {
4196 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {
4197 KdPrint3((PRINT_PREFIX
" BUSY on ATAPI device, waiting\n"));
4199 GetStatus(chan
, statusByte
);
4200 KdPrint3((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4201 KdPrint3((PRINT_PREFIX
" Error reg (%#x)\n",
4202 AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
4203 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4204 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4208 KdPrint3((PRINT_PREFIX
" too long wait -> DPC\n"));
4210 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC\n"));
4212 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4214 KdPrint2((PRINT_PREFIX
" too long wait: DPC -> DPC\n"));
4216 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY1
;
4221 AtapiStallExecution(TimerValue
);
4222 #endif //UNIATA_CORE
4225 AtapiStallExecution(10);
4227 if (statusByte
& IDE_STATUS_BUSY
) {
4228 KdPrint3((PRINT_PREFIX
" expecting intr + BUSY (2), try DPC wait\n"));
4234 if(AtaReq
&& DmaTransfer
) {
4235 switch(OldReqState
) {
4236 case REQ_STATE_EARLY_INTR
:
4237 case REQ_STATE_DPC_WAIT_BUSY0
:
4239 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4240 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DMA still active\n"));
4241 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4248 // Check for error conditions.
4249 if ((statusByte
& IDE_STATUS_ERROR
) ||
4250 (dma_status
& BM_STATUS_ERR
)) {
4252 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4253 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error %#x\n", error
));
4255 if(error & IDE_STATUS_CORRECTED_ERROR) {
4256 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
4257 statusByte &= ~IDE_STATUS_ERROR;
4262 KdPrint2((PRINT_PREFIX
" Bad Lba %#I64x\n", AtaReq
->lba
));
4264 KdPrint2((PRINT_PREFIX
" Bad Lba unknown\n"));
4269 KdPrint2((PRINT_PREFIX
" wait 100 ready after IDE error\n"));
4270 AtapiStallExecution(100);
4272 KdPrint2((PRINT_PREFIX
" wait 10 ready after ATAPI error\n"));
4273 AtapiStallExecution(10);
4277 KdPrint3((PRINT_PREFIX
" Intr on DRQ %x\n",
4278 LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
));
4280 for (k
= atapiDev
? 0 : 200; k
; k
--) {
4281 GetStatus(chan
, statusByte
);
4282 if (!(statusByte
& IDE_STATUS_DRQ
)) {
4283 AtapiStallExecution(50);
4290 /* if this is a UDMA CRC error, reinject request */
4293 if(AtaReq
->retry
< MAX_RETRIES
) {
4294 #ifdef IO_STATISTICS
4295 chan
->lun
[DeviceNumber
]->ModeErrorCount
[AtaReq
->retry
]++;
4296 #endif //IO_STATISTICS
4298 (error & IDE_ERROR_ICRC)*/) {
4299 if(AtaReq
->retry
< MAX_RETRIES
) {
4301 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
4302 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
4303 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
4304 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
4308 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
4311 KdPrint2((PRINT_PREFIX
"Errors in PIO mode\n"));
4315 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
4316 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason
));
4318 if(DmaTransfer
&& (chan
->lun
[DeviceNumber
]->TransferMode
> ATA_UDMA2
) &&
4319 ((error
>> 4) == SCSI_SENSE_HARDWARE_ERROR
)) {
4320 if(AtaReq
->retry
< MAX_RETRIES
) {
4322 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
4323 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
4324 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
4325 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
4329 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
4332 KdPrint3((PRINT_PREFIX
"Errors in PIO mode\n"));
4336 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error\n"));
4337 if (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
4338 // Fail this request.
4339 status
= SRB_STATUS_ERROR
;
4340 goto CompleteRequest
;
4342 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n"));
4345 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE_LBA48
) {
4346 KdPrint2((PRINT_PREFIX
"DMA doesn't work right with LBA48\n"));
4347 deviceExtension
->HbaCtrlFlags
|= HBAFLAGS_DMA_DISABLED_LBA48
;
4349 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
) {
4350 KdPrint2((PRINT_PREFIX
"Some higher mode doesn't work right :((\n"));
4351 #ifdef IO_STATISTICS
4352 chan
->lun
[DeviceNumber
]->RecoverCount
[AtaReq
->retry
]++;
4353 if(chan
->lun
[DeviceNumber
]->RecoverCount
[AtaReq
->retry
] >= chan
->lun
[DeviceNumber
]->IoCount
/3 ||
4354 (deviceExtension
->HwFlags
& UNIATA_NO80CHK
)
4357 if(deviceExtension
->HwFlags
& UNIATA_NO80CHK
) {
4358 #endif //IO_STATISTICS
4359 KdPrint2((PRINT_PREFIX
"Limit transfer rate to %x\n", deviceExtension
->lun
[DeviceNumber
].TransferMode
));
4360 deviceExtension
->lun
[DeviceNumber
].LimitedTransferMode
=
4361 deviceExtension
->lun
[DeviceNumber
].TransferMode
;
4364 #ifdef IO_STATISTICS
4365 chan
->lun
[DeviceNumber
]->IoCount
++;
4366 #endif //IO_STATISTICS
4370 // check reason for this interrupt.
4373 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI branch\n"));
4376 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
4377 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
4379 wordsThisInterrupt
= DEV_BSIZE
/2*512;
4381 wordsThisInterrupt
= DEV_BSIZE
/2;
4389 // simulate DRQ for DMA transfers
4390 statusByte
|= IDE_STATUS_DRQ
;
4392 if (statusByte
& IDE_STATUS_DRQ
) {
4395 wordsThisInterrupt
= DEV_BSIZE
/2*512;
4397 if (LunExt
->MaximumBlockXfer
) {
4398 wordsThisInterrupt
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
4401 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4403 interruptReason
= 0x2;
4405 } else if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
4406 interruptReason
= 0x0;
4409 status
= SRB_STATUS_ERROR
;
4410 goto CompleteRequest
;
4413 } else if (statusByte
& IDE_STATUS_BUSY
) {
4415 //AtapiEnableInterrupts(deviceExtension, lChannel);
4416 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
4421 if (AtaReq
->WordsLeft
) {
4423 // Funky behaviour seen with PCI IDE (not all, just one).
4425 // The ISR hits with DRQ low, but comes up later.
4426 for (k
= 0; k
< 5000; k
++) {
4427 GetStatus(chan
, statusByte
);
4428 if (statusByte
& IDE_STATUS_DRQ
) {
4433 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ0
;
4435 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq0)\n"));
4439 AtapiStallExecution(TimerValue
);
4440 goto ServiceInterrupt
;
4441 #endif //UNIATA_CORE
4443 AtapiStallExecution(100);
4446 // reset the controller.
4447 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
4449 IntrPrepareResetController
:
4450 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
);
4451 goto ReturnEnableIntr
;
4454 interruptReason
= (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? 0x2 : 0x0;
4458 // Command complete - verify, write, or the SMART enable/disable.
4459 // Also get_media_status
4460 interruptReason
= 0x3;
4465 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason
, statusByte
));
4466 if (interruptReason
== 0x1 && (statusByte
& IDE_STATUS_DRQ
)) {
4467 // Write the packet.
4468 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Writing Atapi packet.\n"));
4469 // Send CDB to device.
4470 WriteBuffer(chan
, (PUSHORT
)srb
->Cdb
, 6, 0);
4471 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4473 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
4474 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: AtapiDmaStart().\n"));
4475 AtapiDmaStart(HwDeviceExtension
, ldev
& 1, lChannel
, srb
);
4478 goto ReturnEnableIntr
;
4480 } else if (interruptReason
== 0x0 && (statusByte
& IDE_STATUS_DRQ
)) {
4485 // Pick up bytes to transfer and convert to words.
4487 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
4490 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
4492 // Covert bytes to words.
4494 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get W wordCount %#x\n", wordCount
));
4496 if (wordCount
!= AtaReq
->WordsLeft
) {
4497 KdPrint2((PRINT_PREFIX
4498 "AtapiInterrupt: %d words requested; %d words xferred\n",
4503 // Verify this makes sense.
4504 if (wordCount
> AtaReq
->WordsLeft
) {
4505 wordCount
= AtaReq
->WordsLeft
;
4506 KdPrint2((PRINT_PREFIX
4507 "AtapiInterrupt: Write underrun\n"));
4513 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
4514 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
4516 // Transfer only words requested.
4517 wordCount
= AtaReq
->WordsLeft
;
4521 // Transfer next block.
4522 wordCount
= wordsThisInterrupt
;
4526 if (DmaTransfer
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
4527 //ASSERT(AtaReq->WordsLeft == wordCount);
4528 AtaReq
->WordsLeft
= 0;
4529 status
= SRB_STATUS_SUCCESS
;
4530 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
4531 goto CompleteRequest
;
4533 // Ensure that this is a write command.
4534 if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
4536 KdPrint2((PRINT_PREFIX
4537 "AtapiInterrupt: Write interrupt\n"));
4539 statusByte
= WaitOnBusy(chan
);
4541 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
4546 UniataGetPioTiming(LunExt
));
4550 (PULONG
)(AtaReq
->DataBuffer
),
4552 UniataGetPioTiming(LunExt
));
4556 KdPrint2((PRINT_PREFIX
4557 "AtapiInterrupt: Int reason %#x, but srb is for a write %#x.\n",
4561 // Fail this request.
4562 status
= SRB_STATUS_ERROR
;
4563 goto CompleteRequest
;
4566 // Advance data buffer pointer and bytes left.
4567 AtaReq
->DataBuffer
+= wordCount
;
4568 AtaReq
->WordsLeft
-= wordCount
;
4571 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4574 goto ReturnEnableIntr
;
4576 } else if (interruptReason
== 0x2 && (statusByte
& IDE_STATUS_DRQ
)) {
4581 // Pick up bytes to transfer and convert to words.
4583 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
) |
4584 (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8);
4586 // Covert bytes to words.
4588 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get R wordCount %#x\n", wordCount
));
4590 if (wordCount
!= AtaReq
->WordsLeft
) {
4591 KdPrint2((PRINT_PREFIX
4592 "AtapiInterrupt: %d words requested; %d words xferred\n",
4597 // Verify this makes sense.
4598 if (wordCount
> AtaReq
->WordsLeft
) {
4599 wordCount
= AtaReq
->WordsLeft
;
4605 // Check if words left is at least 256.
4606 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
4608 // Transfer only words requested.
4609 wordCount
= AtaReq
->WordsLeft
;
4613 // Transfer next block.
4614 wordCount
= wordsThisInterrupt
;
4618 if (DmaTransfer
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
4619 //ASSERT(AtaReq->WordsLeft == wordCount);
4620 AtaReq
->WordsLeft
= 0;
4621 status
= SRB_STATUS_SUCCESS
;
4622 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
4623 goto CompleteRequest
;
4625 // Ensure that this is a read command.
4626 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4629 "AtapiInterrupt: Read interrupt\n"));*/
4631 statusByte
= WaitOnBusy(chan
);
4633 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
4634 KdPrint2((PRINT_PREFIX
4635 "IdeIntr: Read %#x words\n", wordCount
));
4640 UniataGetPioTiming(LunExt
));
4641 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)-1) ));
4642 //KdDump(AtaReq->DataBuffer, wordCount*2);
4643 if(srb
&& atapiDev
&& srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
4644 KdDump(AtaReq
->DataBuffer
, wordCount
*2);
4647 GetStatus(chan
, statusByte
);
4648 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4651 KdPrint2((PRINT_PREFIX
" DataOverrun\n"));
4652 AtapiSuckPort2(chan
);
4656 KdPrint2((PRINT_PREFIX
4657 "IdeIntr: Read %#x Dwords\n", wordCount
/2));
4660 (PULONG
)(AtaReq
->DataBuffer
),
4662 UniataGetPioTiming(LunExt
));
4666 KdPrint3((PRINT_PREFIX
4667 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
4671 // Fail this request.
4672 status
= SRB_STATUS_ERROR
;
4673 goto CompleteRequest
;
4676 // Advance data buffer pointer and bytes left.
4677 AtaReq
->DataBuffer
+= wordCount
;
4678 AtaReq
->WordsLeft
-= wordCount
;
4680 // Check for read command complete.
4681 if (AtaReq
->WordsLeft
== 0) {
4683 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
4686 // Work around to make many atapi devices return correct sector size
4687 // of 2048. Also certain devices will have sector count == 0x00, check
4689 if ((srb
->Cdb
[0] == SCSIOP_READ_CAPACITY
) &&
4690 (LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
)) {
4692 AtaReq
->DataBuffer
-= wordCount
;
4693 if (AtaReq
->DataBuffer
[0] == 0x00) {
4695 *((ULONG
*) &(AtaReq
->DataBuffer
[0])) = 0xFFFFFF7F;
4699 *((ULONG
*) &(AtaReq
->DataBuffer
[2])) = 0x00080000;
4700 AtaReq
->DataBuffer
+= wordCount
;
4705 // Completion for IDE drives.
4706 if (AtaReq->WordsLeft) {
4707 status = SRB_STATUS_DATA_OVERRUN;
4709 status = SRB_STATUS_SUCCESS;
4712 goto CompleteRequest;
4714 status
= SRB_STATUS_SUCCESS
;
4715 goto CompleteRequest
;
4720 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
4724 goto ReturnEnableIntr
;
4726 } else if (interruptReason
== 0x3 && !(statusByte
& IDE_STATUS_DRQ
)) {
4728 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: interruptReason = CompleteRequest\n"));
4729 // Command complete.
4731 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
4732 AtaReq
->WordsLeft
= 0;
4734 if (AtaReq
->WordsLeft
) {
4735 status
= SRB_STATUS_DATA_OVERRUN
;
4737 status
= SRB_STATUS_SUCCESS
;
4740 #ifdef UNIATA_DUMP_ATAPI
4742 srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4746 PCHAR ModeSelectData
;
4748 PSCSI_REQUEST_BLOCK Srb
= srb
;
4750 Cdb
= (PCDB
)(Srb
->Cdb
);
4751 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
4752 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
4753 CdbDataLen
= Srb
->DataTransferLength
;
4755 if(CdbDataLen
> 0x1000) {
4756 CdbDataLen
= 0x1000;
4760 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
4761 KdPrint2(("P:T:D=%d:%d:%d\n",
4765 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand
));
4768 if(ScsiCommand
== SCSIOP_MODE_SENSE
) {
4769 KdPrint(("ModeSense 6\n"));
4770 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
4771 ModeSelectData
= CdbData
+4;
4772 KdDump(CdbData
, CdbDataLen
);
4774 if(ScsiCommand
== SCSIOP_MODE_SENSE10
) {
4775 KdPrint(("ModeSense 10\n"));
4776 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
4777 ModeSelectData
= CdbData
+8;
4778 KdDump(CdbData
, CdbDataLen
);
4780 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4781 KdPrint(("Read buffer from device:\n"));
4782 KdDump(CdbData
, CdbDataLen
);
4787 #endif //UNIATA_DUMP_ATAPI
4791 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest\n"));
4792 // Check and see if we are processing our secret (mechanism status/request sense) srb
4793 if (AtaReq
->OriginalSrb
) {
4797 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: OriginalSrb != NULL\n"));
4798 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
4800 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
4801 if (status
== SRB_STATUS_SUCCESS
) {
4803 AtapiHwInitializeChanger (HwDeviceExtension
,
4805 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
4807 // Get ready to issue the original srb
4808 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
4809 AtaReq
->OriginalSrb
= NULL
;
4812 // failed! Get the sense key and maybe try again
4813 srb
= AtaReq
->Srb
= BuildRequestSenseSrb (
4815 AtaReq
->OriginalSrb
);
4818 // do not enable interrupts in DPC, do not waste time, do it now!
4819 if(UseDpc && chan->DisableIntr) {
4820 AtapiEnableInterrupts(HwDeviceExtension, c);
4822 RestoreUseDpc = TRUE;
4825 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
4827 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
4829 if (srbStatus
== SRB_STATUS_PENDING
) {
4830 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
4831 goto ReturnEnableIntr
;
4835 // restore state on error
4837 AtapiDisableInterrupts(HwDeviceExtension, c);
4841 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
4843 PSENSE_DATA senseData
= (PSENSE_DATA
) srb
->DataBuffer
;
4845 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI command status %#x\n", status
));
4846 if (status
== SRB_STATUS_DATA_OVERRUN
) {
4847 // Check to see if we at least get mininum number of bytes
4848 if ((srb
->DataTransferLength
- AtaReq
->WordsLeft
) >
4849 (offsetof (SENSE_DATA
, AdditionalSenseLength
) + sizeof(senseData
->AdditionalSenseLength
))) {
4850 status
= SRB_STATUS_SUCCESS
;
4854 if (status
== SRB_STATUS_SUCCESS
) {
4856 if ((senseData
->SenseKey
!= SCSI_SENSE_ILLEGAL_REQUEST
) &&
4857 chan
->MechStatusRetryCount
) {
4859 // The sense key doesn't say the last request is illegal, so try again
4860 chan
->MechStatusRetryCount
--;
4861 srb
= AtaReq
->Srb
= BuildMechanismStatusSrb (
4863 AtaReq
->OriginalSrb
);
4866 // last request was illegal. No point trying again
4867 AtapiHwInitializeChanger (HwDeviceExtension
,
4869 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
4871 // Get ready to issue the original srb
4872 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
4873 AtaReq
->OriginalSrb
= NULL
;
4875 #endif //UNIATA_CORE
4877 // do not enable interrupts in DPC, do not waste time, do it now!
4878 if(UseDpc && chan->DisableIntr) {
4879 AtapiEnableInterrupts(HwDeviceExtension, c);
4881 RestoreUseDpc = TRUE;
4884 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
4886 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan
->ExpectingInterrupt
));
4888 if (srbStatus
== SRB_STATUS_PENDING
) {
4889 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
4890 goto ReturnEnableIntr
;
4894 // restore state on error
4896 AtapiDisableInterrupts(HwDeviceExtension, c);
4902 // If we get here, it means AtapiSendCommand() has failed
4903 // Can't recover. Pretend the original srb has failed and complete it.
4905 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. complete OriginalSrb\n"));
4907 if (AtaReq
->OriginalSrb
) {
4908 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
4909 AtapiHwInitializeChanger (HwDeviceExtension
,
4911 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
4912 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
4913 AtaReq
->OriginalSrb
= NULL
;
4916 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan
->ExpectingInterrupt
));
4918 // fake an error and read no data
4919 status
= SRB_STATUS_ERROR
;
4920 srb
->ScsiStatus
= 0;
4921 AtaReq
->DataBuffer
= (PUSHORT
)(srb
->DataBuffer
);
4922 AtaReq
->WordsLeft
= srb
->DataTransferLength
;
4925 } else if (status
== SRB_STATUS_ERROR
) {
4927 // Map error to specific SRB status and handle request sense.
4928 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. Begin mapping...\n"));
4929 status
= MapError(deviceExtension
,
4934 } else if(!DmaTransfer
) {
4936 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion\n"));
4937 // Command complete.
4939 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion, wait BUSY\n"));
4940 // Wait for busy to drop.
4941 for (i
= 0; i
< 5*30; i
++) {
4942 GetStatus(chan
, statusByte
);
4943 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4948 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY
;
4950 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (busy)\n"));
4954 AtapiStallExecution(TimerValue
);
4955 goto ServiceInterrupt
;
4956 #endif //UNIATA_CORE
4958 AtapiStallExecution(100);
4963 // reset the controller.
4964 KdPrint2((PRINT_PREFIX
4965 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
4967 goto IntrPrepareResetController
;
4969 // Check to see if DRQ is still up.
4970 if(statusByte
& IDE_STATUS_DRQ
) {
4971 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DRQ...\n"));
4973 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
4974 KdPrint2((PRINT_PREFIX
"srb %x data in\n", srb
));
4976 KdPrint2((PRINT_PREFIX
"srb %x data out\n", srb
));
4979 KdPrint2((PRINT_PREFIX
"srb NULL\n"));
4982 KdPrint2((PRINT_PREFIX
"AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq
, AtaReq
->WordsLeft
));
4984 KdPrint2((PRINT_PREFIX
"AtaReq NULL\n"));
4986 if(AtaReq
&& AtaReq
->WordsLeft
/*&&
4987 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
4988 KdPrint2((PRINT_PREFIX
"DRQ+AtaReq->WordsLeft -> next portion\n"));
4992 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
4993 //if ((statusByte & IDE_STATUS_DRQ)) {}
4994 if((statusByte
& IDE_STATUS_DRQ
) &&
4995 (LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_TAPE_DEVICE
| DFLAGS_LBA_ENABLED
)) ) {
4998 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO_wait_DRQ\n"));
4999 for (i
= 0; i
< 200; i
++) {
5000 GetStatus(chan
, statusByte
);
5001 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5006 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq)\n"));
5007 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ
;
5012 AtapiStallExecution(TimerValue
);
5013 goto ServiceInterrupt
;
5014 #endif //UNIATA_CORE
5016 AtapiStallExecution(100);
5020 // reset the controller.
5021 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
5023 goto IntrPrepareResetController
;
5027 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
5028 AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)(-1)), srb
->DataTransferLength
));
5029 //KdDump(srb->DataBuffer, srb->DataTransferLength);
5031 if(!AtapiDmaPioSync(HwDeviceExtension
, srb
, (PUCHAR
)(srb
->DataBuffer
), srb
->DataTransferLength
)) {
5032 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
5036 // Clear interrupt expecting flag.
5037 chan
->ExpectingInterrupt
= FALSE
;
5038 InterlockedExchange(&(chan
->CheckIntr
),
5041 // Sanity check that there is a current request.
5043 // Set status in SRB.
5044 srb
->SrbStatus
= (UCHAR
)status
;
5046 // Check for underflow.
5047 if (AtaReq
->WordsLeft
) {
5049 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq
->WordsLeft
));
5050 // Subtract out residual words and update if filemark hit,
5051 // setmark hit , end of data, end of media...
5052 if (!(LunExt
->DeviceFlags
& DFLAGS_TAPE_DEVICE
)) {
5053 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5054 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5056 srb
->DataTransferLength
= 0;
5059 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5062 if(status
== SRB_STATUS_SUCCESS
) {
5063 AtaReq
->WordsTransfered
+= AtaReq
->bcount
* DEV_BSIZE
/2;
5065 AtaReq
->WordsTransfered
*2 < AtaReq
->TransferLength
) {
5066 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
5067 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5068 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5069 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_NEXT
;
5072 KdPrint2((PRINT_PREFIX
" Transfered %x, full size %x\n",
5073 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5077 if (srb
->Function
!= SRB_FUNCTION_IO_CONTROL
) {
5080 // Indicate command complete.
5082 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete\n"));
5085 if (status
== SRB_STATUS_SUCCESS
&&
5086 srb
->SenseInfoBuffer
&&
5087 srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
5089 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)srb
->SenseInfoBuffer
;
5091 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: set AutoSense\n"));
5092 senseBuffer
->ErrorCode
= 0;
5093 senseBuffer
->Valid
= 1;
5094 senseBuffer
->AdditionalSenseLength
= 0xb;
5095 senseBuffer
->SenseKey
= 0;
5096 senseBuffer
->AdditionalSenseCode
= 0;
5097 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
5099 srb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
5101 AtapiDmaDBSync(chan
, srb
);
5102 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove srb %#x, status %x\n", srb
, status
));
5103 UniataRemoveRequest(chan
, srb
);
5104 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete, srb %#x\n", srb
));
5105 ScsiPortNotification(RequestComplete
,
5111 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: IOCTL completion\n"));
5112 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5114 if (status
!= SRB_STATUS_SUCCESS
) {
5115 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5116 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: error %#x\n", error
));
5119 // Build the SMART status block depending upon the completion status.
5120 cmdOutParameters
->cBufferSize
= wordCount
;
5121 cmdOutParameters
->DriverStatus
.bDriverError
= (error
) ? SMART_IDE_ERROR
: 0;
5122 cmdOutParameters
->DriverStatus
.bIDEError
= error
;
5124 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
5126 if (chan
->SmartCommand
== RETURN_SMART_STATUS
) {
5127 cmdOutParameters
->bBuffer
[0] = RETURN_SMART_STATUS
;
5128 cmdOutParameters
->bBuffer
[1] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
);
5129 cmdOutParameters
->bBuffer
[2] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Unused1
);
5130 cmdOutParameters
->bBuffer
[3] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
5131 cmdOutParameters
->bBuffer
[4] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
);
5132 cmdOutParameters
->bBuffer
[5] = AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_DriveSelect
);
5133 cmdOutParameters
->bBuffer
[6] = SMART_CMD
;
5134 cmdOutParameters
->cBufferSize
= 8;
5137 // Indicate command complete.
5138 goto IntrCompleteReq
;
5143 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: No SRB!\n"));
5148 for (i
= 0; i
< 5; i
++) {
5149 GetStatus(chan
, statusByte
);
5150 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5151 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RDP + cleared BUSY\n"));
5155 if (statusByte
& IDE_STATUS_DSC
) {
5156 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Clear RDP\n"));
5160 AtapiStallExecution(50);
5163 // RDP can be cleared since previous check
5165 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestTimerCall 2000\n"));
5171 AtapiStallExecution(TimerValue
);
5172 goto ServiceInterrupt
;
5173 #endif //UNIATA_CORE
5176 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
5179 srb
= UniataGetCurRequest(chan
);
5184 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: NextRequest, srb=%#x\n",srb
));
5186 ScsiPortNotification(NextRequest
,
5190 ScsiPortNotification(NextLuRequest
,
5195 // in simplex mode next command must NOT be sent here
5196 if(!deviceExtension
->simplexOnly
) {
5197 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
5200 // Try to get SRB fron any non-empty queue (later)
5201 if(deviceExtension
->simplexOnly
) {
5204 #endif //UNIATA_CORE
5206 goto ReturnEnableIntr
;
5210 // Unexpected int. Catch it
5211 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
5219 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ReturnEnableIntr\n",srb
));
5221 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
5222 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
5223 #ifdef UNIATA_USE_XXableInterrupts
5224 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
5225 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
5226 // must be called on DISPATCH_LEVEL
5227 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
5228 AtapiEnableInterrupts__
);
5230 AtapiEnableInterrupts(HwDeviceExtension
, c
);
5231 InterlockedExchange(&(chan
->CheckIntr
),
5233 // Will raise IRQL to DIRQL
5235 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
5236 AtapiEnableInterrupts__
,
5238 #endif // UNIATA_CORE
5239 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
5240 #endif // UNIATA_USE_XXableInterrupts
5244 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
5245 // in simplex mode next command must be sent here if
5247 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc
, NoStartIo
));
5250 if(!UseDpc
&& /*deviceExtension->simplexOnly &&*/ !NoStartIo
) {
5251 chan
= UniataGetNextChannel(chan
);
5253 srb
= UniataGetCurRequest(chan
);
5257 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: run srb %x\n", srb
));
5259 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
5262 #endif //UNIATA_CORE
5265 } // end AtapiInterrupt__()
5271 Routine Description:
5273 This routine handles SMART enable, disable, read attributes and threshold commands.
5277 HwDeviceExtension - HBA miniport driver's adapter data storage
5278 Srb - IO request packet
5286 IdeSendSmartCommand(
5287 IN PVOID HwDeviceExtension
,
5288 IN PSCSI_REQUEST_BLOCK Srb
5291 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5292 ULONG c
= GET_CHANNEL(Srb
);
5293 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
5294 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5295 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5296 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5297 PIDEREGS regs
= &cmdInParameters
.irDriveRegs
;
5299 UCHAR statusByte
,targetId
;
5302 if (regs
->bCommandReg
!= SMART_CMD
) {
5303 KdPrint2((PRINT_PREFIX
5304 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
5305 return SRB_STATUS_INVALID_REQUEST
;
5308 targetId
= cmdInParameters
.bDriveNumber
;
5310 //TODO optimize this check
5311 if ((!(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) ||
5312 (deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
5314 return SRB_STATUS_SELECTION_TIMEOUT
;
5317 chan
->SmartCommand
= regs
->bFeaturesReg
;
5319 // Determine which of the commands to carry out.
5320 switch(regs
->bFeaturesReg
) {
5321 case READ_ATTRIBUTES
:
5322 case READ_THRESHOLDS
:
5324 statusByte
= WaitOnBusy(chan
);
5326 if (statusByte
& IDE_STATUS_BUSY
) {
5327 KdPrint2((PRINT_PREFIX
5328 "IdeSendSmartCommand: Returning BUSY status\n"));
5329 return SRB_STATUS_BUSY
;
5332 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
5333 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1);
5335 // Set data buffer pointer and words left.
5336 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
5337 AtaReq
->WordsLeft
= READ_ATTRIBUTE_BUFFER_SIZE
/ 2;
5339 statusByte
= AtaCommand(deviceExtension
, targetId
& 0x1, c
,
5341 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
5343 regs
->bSectorNumberReg
,
5344 regs
->bSectorCountReg
,
5348 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5349 // Wait for interrupt.
5350 return SRB_STATUS_PENDING
;
5352 return SRB_STATUS_ERROR
;
5356 case RETURN_SMART_STATUS
:
5357 case ENABLE_DISABLE_AUTOSAVE
:
5358 case EXECUTE_OFFLINE_DIAGS
:
5359 case SAVE_ATTRIBUTE_VALUES
:
5361 statusByte
= WaitOnBusy(chan
);
5363 if (statusByte
& IDE_STATUS_BUSY
) {
5364 KdPrint2((PRINT_PREFIX
5365 "IdeSendSmartCommand: Returning BUSY status\n"));
5366 return SRB_STATUS_BUSY
;
5369 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
5370 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) - 1);
5372 // Set data buffer pointer and indicate no data transfer.
5373 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
5374 AtaReq
->WordsLeft
= 0;
5376 statusByte
= AtaCommand(deviceExtension
, targetId
& 0x1, c
,
5378 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
5380 regs
->bSectorNumberReg
,
5381 regs
->bSectorCountReg
,
5385 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5386 // Wait for interrupt.
5387 return SRB_STATUS_PENDING
;
5389 return SRB_STATUS_ERROR
;
5390 } // end switch(regs->bFeaturesReg)
5392 return SRB_STATUS_INVALID_REQUEST
;
5394 } // end IdeSendSmartCommand()
5396 #endif //UNIATA_CORE
5399 UniAtaCalculateLBARegs(
5400 PHW_LU_EXTENSION LunExt
,
5401 ULONG startingSector
,
5405 UCHAR drvSelect
,sectorNumber
;
5409 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
5410 if(LunExt
->LimitedTransferMode
>= ATA_DMA
) {
5411 if(LunExt
->DeviceExtension
) {
5412 (*max_bcount
) = LunExt
->DeviceExtension
->MaximumDmaTransferLength
/ DEV_BSIZE
;
5415 return startingSector
;
5417 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
5418 LunExt
->IdentifyData
.NumberOfHeads
;
5420 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
5424 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
;
5426 cylinder
= (USHORT
)(startingSector
/ tmp
);
5427 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
5428 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
5429 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
- sectorNumber
+ 1;
5430 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
5431 cylinder
, drvSelect
, sectorNumber
, (*max_bcount
)));
5435 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
5436 } // end UniAtaCalculateLBARegs()
5439 UniAtaCalculateLBARegsBack(
5440 PHW_LU_EXTENSION LunExt
,
5444 ULONG drvSelect
,sectorNumber
;
5448 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
5451 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
5452 LunExt
->IdentifyData
.NumberOfHeads
;
5454 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
5455 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
5456 sectorNumber
= (UCHAR
)(lba
& 0xff);
5458 lba
= sectorNumber
-1 +
5459 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
5463 } // end UniAtaCalculateLBARegsBack()
5468 Routine Description:
5470 This routine handles IDE read and writes.
5474 HwDeviceExtension - HBA miniport driver's adapter data storage
5475 Srb - IO request packet
5484 IN PVOID HwDeviceExtension
,
5485 IN PSCSI_REQUEST_BLOCK Srb
,
5489 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5490 UCHAR lChannel
= GET_CHANNEL(Srb
);
5491 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5492 PHW_LU_EXTENSION LunExt
;
5493 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5494 ULONG ldev
= GET_LDEV(Srb
);
5495 UCHAR DeviceNumber
= (UCHAR
)(ldev
& 1);
5496 ULONG startingSector
;
5498 ULONG wordCount
= 0;
5499 UCHAR statusByte
,statusByte2
;
5502 BOOLEAN use_dma
= FALSE
;
5504 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
5505 LunExt
= &deviceExtension
->lun
[ldev
];
5507 if((CmdAction
& CMD_ACTION_PREPARE
) &&
5508 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
5510 if(LunExt
->opt_ReadOnly
&&
5511 (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) {
5512 if(LunExt
->opt_ReadOnly
== 1) {
5513 KdPrint2((PRINT_PREFIX
"Abort WRITE (Soft R/O)\n"));
5514 return SRB_STATUS_ERROR
;
5516 KdPrint2((PRINT_PREFIX
"Ignore WRITE (Soft R/O)\n"));
5517 return SRB_STATUS_SUCCESS
;
5521 // Set data buffer pointer and words left.
5522 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5524 if(AtaReq
->WordsTransfered
) {
5525 AtaReq
->DataBuffer
= ((PUSHORT
)(Srb
->DataBuffer
)) + AtaReq
->WordsTransfered
;
5526 startingSector
= (ULONG
)(UniAtaCalculateLBARegsBack(LunExt
, AtaReq
->lba
)) /* latest lba */ + AtaReq
->bcount
/* previous bcount */;
5527 AtaReq
->bcount
= (AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2 + DEV_BSIZE
-1) / DEV_BSIZE
;
5528 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Chained REQ): Starting sector %#x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
5530 AtaReq
->TransferLength
/2,
5531 AtaReq
->WordsTransfered
,
5534 AtaReq
->DataBuffer
= (PUSHORT
)(Srb
->DataBuffer
);
5535 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
5536 // Set up 1st block.
5537 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
5538 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
5539 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Orig REQ): Starting sector %#x, OrigWordsRequested %#x, DevSize %#x\n",
5541 AtaReq
->TransferLength
/2,
5544 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
5547 AtaReq
->bcount
= min(AtaReq
->bcount
, max_bcount
);
5549 AtaReq
->WordsLeft
= min(AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2,
5550 AtaReq
->bcount
* DEV_BSIZE
) / 2;
5552 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %#x, Number of WORDS %#x, DevSize %#x\n",
5559 // assume best case here
5560 // we cannot reinit Dma until previous request is completed
5561 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
5563 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
5564 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
5565 (PUCHAR
)(AtaReq
->DataBuffer
),
5566 AtaReq
->bcount
* DEV_BSIZE
)) {
5570 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
5571 } else { // exec_only
5572 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
5575 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
5579 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
5580 return SRB_STATUS_PENDING
;
5583 // if this is queued request, reinit DMA and check
5584 // if DMA mode is still available
5585 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
5586 if (/*EnableDma &&*/
5587 (LunExt
->TransferMode
>= ATA_DMA
)) {
5590 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5594 // Check if write request.
5595 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5597 // Prepare read command.
5599 cmd
= IDE_COMMAND_READ_DMA
;
5601 if(LunExt
->MaximumBlockXfer
) {
5602 cmd
= IDE_COMMAND_READ_MULTIPLE
;
5604 cmd
= IDE_COMMAND_READ
;
5608 // Prepare write command.
5610 wordCount
= AtaReq
->bcount
*DEV_BSIZE
/2;
5611 cmd
= IDE_COMMAND_WRITE_DMA
;
5613 if (LunExt
->MaximumBlockXfer
) {
5614 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5616 if (AtaReq
->WordsLeft
< wordCount
) {
5617 // Transfer only words requested.
5618 wordCount
= AtaReq
->WordsLeft
;
5620 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
5623 wordCount
= DEV_BSIZE
/2;
5624 cmd
= IDE_COMMAND_WRITE
;
5629 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
5631 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5635 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
5636 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
5638 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
5640 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
5642 (USHORT
)(AtaReq
->bcount
),
5643 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
5645 GetStatus(chan
, statusByte2
);
5646 if(statusByte2
& IDE_STATUS_ERROR
) {
5647 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5648 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
5649 return SRB_STATUS_ERROR
;
5652 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
5654 return SRB_STATUS_PENDING
;
5657 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
5659 (USHORT
)(AtaReq
->bcount
),
5660 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
5663 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5665 KdPrint2((PRINT_PREFIX
5666 "IdeReadWrite: DRQ never asserted (%#x)\n",
5669 AtaReq
->WordsLeft
= 0;
5671 // Clear interrupt expecting flag.
5672 chan
->ExpectingInterrupt
= FALSE
;
5673 InterlockedExchange(&(chan
->CheckIntr
),
5676 // Clear current SRB.
5677 UniataRemoveRequest(chan
, Srb
);
5679 return SRB_STATUS_TIMEOUT
;
5682 chan
->ExpectingInterrupt
= TRUE
;
5683 InterlockedExchange(&(chan
->CheckIntr
),
5686 // Write next DEV_BSIZE/2*N words.
5687 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
)) {
5688 KdPrint2((PRINT_PREFIX
5689 "IdeReadWrite: Write %#x words\n", wordCount
));
5694 UniataGetPioTiming(LunExt
));
5698 KdPrint2((PRINT_PREFIX
5699 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
5702 (PULONG
)(AtaReq
->DataBuffer
),
5704 UniataGetPioTiming(LunExt
));
5707 // Adjust buffer address and words left count.
5708 AtaReq
->WordsLeft
-= wordCount
;
5709 AtaReq
->DataBuffer
+= wordCount
;
5711 // Wait for interrupt.
5712 return SRB_STATUS_PENDING
;
5714 } // end IdeReadWrite()
5720 Routine Description:
5721 This routine handles IDE Verify.
5724 HwDeviceExtension - HBA miniport driver's adapter data storage
5725 Srb - IO request packet
5733 IN PVOID HwDeviceExtension
,
5734 IN PSCSI_REQUEST_BLOCK Srb
5737 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5738 UCHAR lChannel
= GET_CHANNEL(Srb
);
5739 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5740 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5741 PHW_LU_EXTENSION LunExt
;
5742 ULONG ldev
= GET_LDEV(Srb
);
5744 ULONG startingSector
;
5751 LunExt
= &deviceExtension
->lun
[ldev
];
5752 // Drive has these number sectors.
5753 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
5754 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
5755 LunExt
->IdentifyData
.NumberOfHeads
*
5756 LunExt
->IdentifyData
.NumberOfCylinders
;
5759 KdPrint2((PRINT_PREFIX
5760 "IdeVerify: Total sectors %#x\n",
5763 // Get starting sector number from CDB.
5764 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
5765 MOV_DW_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
5767 KdPrint2((PRINT_PREFIX
5768 "IdeVerify: Starting sector %#x. Number of blocks %#x\n",
5772 endSector
= startingSector
+ sectorCount
;
5774 KdPrint2((PRINT_PREFIX
5775 "IdeVerify: Ending sector %#x\n",
5778 if (endSector
> sectors
) {
5780 // Too big, round down.
5781 KdPrint2((PRINT_PREFIX
5782 "IdeVerify: Truncating request to %#x blocks\n",
5783 sectors
- startingSector
- 1));
5785 sectorCount
= (USHORT
)(sectors
- startingSector
- 1);
5789 // Set up sector count register. Round up to next block.
5790 if (sectorCount
> 0xFF) {
5791 sectorCount
= (USHORT
)0xFF;
5795 // Set data buffer pointer and words left.
5796 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
5797 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
5799 // Indicate expecting an interrupt.
5800 InterlockedExchange(&(chan
->CheckIntr
),
5803 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
5805 statusByte
= AtaCommand48(deviceExtension
, ldev
& 0x01, GET_CHANNEL(Srb
),
5806 IDE_COMMAND_VERIFY
, lba
,
5810 if(!(statusByte
& IDE_STATUS_ERROR
)) {
5811 // Wait for interrupt.
5812 return SRB_STATUS_PENDING
;
5814 return SRB_STATUS_ERROR
;
5816 } // end IdeVerify()
5818 #endif //UNIATA_CORE
5822 Routine Description:
5823 Send ATAPI packet command to device.
5826 HwDeviceExtension - HBA miniport driver's adapter data storage
5827 Srb - IO request packet
5834 IN PVOID HwDeviceExtension
,
5835 IN PSCSI_REQUEST_BLOCK Srb
,
5839 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
5840 UCHAR lChannel
= GET_CHANNEL(Srb
);
5841 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
5842 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
5843 ULONG ldev
= GET_LDEV(Srb
);
5846 UCHAR statusByte
,byteCountLow
,byteCountHigh
;
5847 BOOLEAN use_dma
= FALSE
;
5848 BOOLEAN dma_reinited
= FALSE
;
5849 BOOLEAN retried
= FALSE
;
5851 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: req state %#x, Action %x\n", AtaReq
->ReqState
, CmdAction
));
5852 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
5853 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
5855 #ifdef UNIATA_DUMP_ATAPI
5856 if(CmdAction
& CMD_ACTION_PREPARE
) {
5860 PCHAR ModeSelectData
;
5863 Cdb
= (PCDB
)(Srb
->Cdb
);
5864 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
5865 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
5866 CdbDataLen
= Srb
->DataTransferLength
;
5868 if(CdbDataLen
> 0x1000) {
5869 CdbDataLen
= 0x1000;
5873 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
5874 KdPrint2(("P:T:D=%d:%d:%d\n",
5878 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
5881 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
5882 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
5883 Cdb
->WRITE_CD
.LBA
[0],
5884 Cdb
->WRITE_CD
.LBA
[1],
5885 Cdb
->WRITE_CD
.LBA
[2],
5886 Cdb
->WRITE_CD
.LBA
[3]
5889 if(ScsiCommand
== SCSIOP_WRITE12
) {
5890 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
5891 Cdb
->CDB12READWRITE
.LBA
[0],
5892 Cdb
->CDB12READWRITE
.LBA
[1],
5893 Cdb
->CDB12READWRITE
.LBA
[2],
5894 Cdb
->CDB12READWRITE
.LBA
[3]
5897 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
5898 KdPrint(("ModeSelect 6\n"));
5899 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5900 ModeSelectData
= CdbData
+4;
5901 KdDump(CdbData
, CdbDataLen
);
5903 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
5904 KdPrint(("ModeSelect 10\n"));
5905 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5906 ModeSelectData
= CdbData
+8;
5907 KdDump(CdbData
, CdbDataLen
);
5909 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5910 KdPrint(("Send buffer to device:\n"));
5911 KdDump(CdbData
, CdbDataLen
);
5916 #endif //UNIATA_DUMP_ATAPI
5919 if(CmdAction
== CMD_ACTION_PREPARE
) {
5920 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE\n"));
5921 switch (Srb
->Cdb
[0]) {
5925 case SCSIOP_WRITE12
:
5929 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
5930 return SRB_STATUS_BUSY
;
5933 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
5934 !AtaReq
->OriginalSrb
) {
5935 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
5936 return SRB_STATUS_BUSY
;
5940 if((CmdAction
& CMD_ACTION_PREPARE
) &&
5941 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
5943 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x\n", Srb
->Cdb
[0]));
5944 // Set data buffer pointer and words left.
5945 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
5946 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
5947 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
5948 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5950 // check if reorderable
5951 switch(Srb
->Cdb
[0]) {
5953 case SCSIOP_WRITE12
:
5955 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
5961 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
5963 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
5965 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
5966 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
5967 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
|| Srb
->Cdb
[0] == SCSIOP_WRITE12
) ?
5968 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
5972 // check if DMA read/write
5973 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
5974 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
5976 if(AtaReq
->TransferLength
) {
5978 switch(Srb
->Cdb
[0]) {
5980 case SCSIOP_WRITE12
:
5981 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
5987 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
5989 if(AtapiDmaSetup(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
,
5990 (PUCHAR
)(AtaReq
->DataBuffer
),
5991 Srb
->DataTransferLength
5992 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
5994 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
5999 case SCSIOP_READ_CD
:
6000 if(deviceExtension
->opt_AtapiDmaRawRead
)
6001 goto call_dma_setup
;
6005 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
6006 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6011 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
6012 KdPrint2((PRINT_PREFIX
"dma RO\n"));
6023 if(!AtapiDmaSetup(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
,
6024 (PUCHAR
)(AtaReq
->DataBuffer
),
6025 Srb
->DataTransferLength
)) {
6026 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
6029 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
6033 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer, no DMA setup\n"));
6037 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6038 // if this is queued request, reinit DMA and check
6039 // if DMA mode is still available
6040 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
6041 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
6042 if (/*EnableDma &&*/
6043 (deviceExtension
->lun
[ldev
].TransferMode
>= ATA_DMA
)) {
6044 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
6047 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6048 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
6051 dma_reinited
= TRUE
;
6055 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
6056 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
6057 return SRB_STATUS_PENDING
;
6059 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
6060 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6061 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
6064 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
6065 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
6067 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6068 //AtapiDmaReinit(deviceExtension, ldev, AtaReq);
6069 } if(AtaReq
->TransferLength
) {
6071 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
6072 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
6073 if (/*EnableDma &&*/
6074 (deviceExtension
->lun
[ldev
].TransferMode
>= ATA_DMA
)) {
6077 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6082 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
6084 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6085 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
) {
6086 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
6087 AtapiDmaReinit(deviceExtension
, ldev
, AtaReq
);
6090 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
6091 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6092 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
6095 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
6098 // We need to know how many platters our atapi cd-rom device might have.
6099 // Before anyone tries to send a srb to our target for the first time,
6100 // we must "secretly" send down a separate mechanism status srb in order to
6101 // initialize our device extension changer data. That's how we know how
6102 // many platters our target has.
6104 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6105 !AtaReq
->OriginalSrb
) {
6109 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
6110 // Set this flag now. If the device hangs on the mech. status
6111 // command, we will not have the chance to set it.
6112 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_CHANGER_INITED
;
6114 chan
->MechStatusRetryCount
= 3;
6115 AtaReq
->OriginalSrb
= Srb
;
6116 AtaReq
->Srb
= BuildMechanismStatusSrb (
6120 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
6121 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
6122 if (srbStatus
== SRB_STATUS_PENDING
) {
6123 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
6126 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6127 AtaReq
->OriginalSrb
= NULL
;
6128 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiHwInitializeChanger()\n"));
6129 AtapiHwInitializeChanger (HwDeviceExtension
, Srb
,
6130 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
6134 #endif //UNIATA_CORE
6136 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Command %#x to TargetId %d lun %d\n",
6137 Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
6139 // Make sure command is to ATAPI device.
6140 flags
= deviceExtension
->lun
[ldev
].DeviceFlags
;
6141 if (flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
6142 if ((Srb
->Lun
) > (deviceExtension
->lun
[ldev
].DiscsPresent
- 1)) {
6144 // Indicate no device found at this address.
6145 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6146 return SRB_STATUS_SELECTION_TIMEOUT
;
6148 } else if (Srb
->Lun
> 0) {
6149 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6150 return SRB_STATUS_SELECTION_TIMEOUT
;
6153 if (!(flags
& DFLAGS_ATAPI_DEVICE
)) {
6154 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6155 return SRB_STATUS_SELECTION_TIMEOUT
;
6158 // Select device 0 or 1.
6159 SelectDrive(chan
, ldev
& 0x1);
6161 // Verify that controller is ready for next command.
6162 GetStatus(chan
, statusByte
);
6163 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
6165 if (statusByte
== 0xff) {
6166 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
6169 if (statusByte
& IDE_STATUS_BUSY
) {
6170 if(statusByte
& IDE_STATUS_DSC
) {
6171 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
6173 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
6174 // We have to make reset here, since we are expecting device to be available
6175 //return SRB_STATUS_BUSY; // this cause queue freeze
6179 if (statusByte
& IDE_STATUS_ERROR
) {
6180 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
6182 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
6183 // Read the error reg. to clear it and fail this request.
6184 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6185 return MapError(deviceExtension
, Srb
);
6187 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
6190 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
6191 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
6192 if ((!(statusByte
& IDE_STATUS_DSC
)) &&
6193 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
6195 AtapiStallExecution(200);
6196 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
6197 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
6198 return SRB_STATUS_PENDING
;
6201 if (IS_RDP(Srb
->Cdb
[0])) {
6203 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
6207 if (statusByte
& IDE_STATUS_DRQ
) {
6209 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
6211 // Try to drain the data that one preliminary device thinks that it has
6212 // to transfer. Hopefully this random assertion of DRQ will not be present
6213 // in production devices.
6214 for (i
= 0; i
< 0x10000; i
++) {
6215 GetStatus(chan
, statusByte
);
6216 if (statusByte
& IDE_STATUS_DRQ
) {
6217 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
6225 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte
));
6227 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6229 AtapiSoftReset(chan
, ldev
& 1);
6231 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
6232 // Re-initialize Atapi device.
6233 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), ldev
& 1, TRUE
);
6235 IssueIdentify(HwDeviceExtension, ldev & 1, GET_CHANNEL(Srb),
6236 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
6238 // Inform the port driver that the bus has been reset.
6239 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
6240 // Clean up device extension fields that AtapiStartIo won't.
6241 chan
->ExpectingInterrupt
= FALSE
;
6243 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
6246 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6248 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
6249 return SRB_STATUS_BUS_RESET;
6252 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
6256 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
6257 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6258 return SRB_STATUS_SELECTION_TIMEOUT
;
6262 if (flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
6263 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
6264 Srb
->Cdb
[1] &= ~0xE0;
6265 if ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
6266 // Torisan changer. TUR's are overloaded to be platter switches.
6267 Srb
->Cdb
[7] = Srb
->Lun
;
6274 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
6276 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6279 statusByte
= WaitOnBusy(chan
);
6280 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
6283 AtapiWritePort1(chan
, IDX_IO1_o_Feature
,
6284 use_dma
? ATA_F_DMA
: 0);
6286 // Write transfer byte count to registers.
6287 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
6288 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
6290 if (Srb
->DataTransferLength
>= 0x10000) {
6291 byteCountLow
= byteCountHigh
= 0xFF;
6294 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
6295 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
6297 if (flags
& DFLAGS_INT_DRQ
) {
6299 // This device interrupts when ready to receive the packet.
6301 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
6304 chan
->ExpectingInterrupt
= TRUE
;
6305 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
6306 InterlockedExchange(&(chan
->CheckIntr
),
6309 // Write ATAPI packet command.
6310 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
6312 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
6313 return SRB_STATUS_PENDING
;
6317 // This device quickly sets DRQ when ready to receive the packet.
6319 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
6322 chan
->ExpectingInterrupt
= TRUE
;
6323 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
6324 InterlockedExchange(&(chan
->CheckIntr
),
6327 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6329 // Write ATAPI packet command.
6330 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
6334 statusByte
= WaitForDrq(chan
);
6336 // Need to read status register and clear interrupt (if any)
6337 GetBaseStatus(chan
, statusByte
);
6339 if (!(statusByte
& IDE_STATUS_DRQ
)) {
6341 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6342 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte
));
6343 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6344 return SRB_STATUS_ERROR
;
6348 GetStatus(chan
, statusByte
);
6349 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
6351 // Send CDB to device.
6352 statusByte
= WaitOnBaseBusy(chan
);
6354 // Indicate expecting an interrupt and wait for it.
6355 chan
->ExpectingInterrupt
= TRUE
;
6356 InterlockedExchange(&(chan
->CheckIntr
),
6358 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
6360 GetBaseStatus(chan
, statusByte
);
6362 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6369 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
6370 AtapiDmaStart(HwDeviceExtension
, ldev
& 1, lChannel
, Srb
);
6373 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
6375 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
6376 return SRB_STATUS_PENDING
;
6378 } // end AtapiSendCommand()
6385 Routine Description:
6386 Program ATA registers for IDE disk transfer.
6389 HwDeviceExtension - ATAPI driver storage.
6390 Srb - System request block.
6393 SRB status (pending if all goes well).
6398 ULONG check_point
= 0;
6399 #define SetCheckPoint(cp) { check_point = (cp) ; }
6401 #define SetCheckPoint(cp)
6406 IN PVOID HwDeviceExtension
,
6407 IN PSCSI_REQUEST_BLOCK Srb
,
6412 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
6415 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6423 UCHAR statusByte
,errorByte
;
6426 PMODE_PARAMETER_HEADER modeData
;
6430 //ULONG __ebp__ = 0;
6432 SetCheckPoint(0x20);
6433 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
6438 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
6439 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
6440 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
6441 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
6442 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
6444 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
6445 Srb->SrbExtension));
6446 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
6449 SetCheckPoint(0x30);
6450 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6452 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
6454 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
6456 KdPrint2((PRINT_PREFIX
"** --- **\n"));
6458 lChannel
= GET_CHANNEL(Srb
);
6459 chan
= &(deviceExtension
->chan
[lChannel
]);
6460 ldev
= GET_LDEV(Srb
);
6462 SetCheckPoint(0x40);
6463 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
6464 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
6466 if(CmdAction
== CMD_ACTION_PREPARE
) {
6467 switch (Srb
->Cdb
[0]) {
6469 case SCSIOP_INQUIRY
: // now it requires device access
6471 case SCSIOP_READ_CAPACITY
:
6474 case SCSIOP_REQUEST_SENSE
:
6476 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
6481 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
6482 return SRB_STATUS_BUSY
;
6486 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
6487 switch (Srb
->Cdb
[0]) {
6488 case SCSIOP_INQUIRY
:
6490 KdPrint2((PRINT_PREFIX
6491 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
6492 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6493 // Filter out all TIDs but 0 and 1 since this is an IDE interface
6494 // which support up to two devices.
6495 if ((Srb
->Lun
!= 0) ||
6496 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
6497 (Srb
->TargetId
> 2) /*||
6498 (!deviceExtension->lun[ldev].DeviceFlags & DFLAGS_DEVICE_PRESENT)*/) {
6500 KdPrint2((PRINT_PREFIX
6501 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
6502 // Indicate no device found at this address.
6503 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6508 KdPrint2((PRINT_PREFIX
6509 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
6510 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
6511 PIDENTIFY_DATA2 identifyData
= &(deviceExtension
->lun
[ldev
].IdentifyData
);
6513 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
6515 if(!CheckDevice(HwDeviceExtension
, lChannel
, ldev
& 1, FALSE
)) {
6516 KdPrint2((PRINT_PREFIX
6517 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
6518 // Indicate no device found at this address.
6520 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6524 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, ldev
& 1)) {
6525 KdPrint2((PRINT_PREFIX
6526 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
6527 // Indicate no device found at this address.
6528 UniataForgetDevice(&(deviceExtension
->lun
[ldev
]));
6530 status
= SRB_STATUS_SELECTION_TIMEOUT
;
6535 // Zero INQUIRY data structure.
6536 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
6538 // Standard IDE interface only supports disks.
6539 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
6541 // Set the removable bit, if applicable.
6542 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
6543 KdPrint2((PRINT_PREFIX
6544 "RemovableMedia\n"));
6545 inquiryData
->RemovableMedia
= 1;
6547 // Set the Relative Addressing (LBA) bit, if applicable.
6548 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6549 inquiryData
->RelativeAddressing
= 1;
6550 KdPrint2((PRINT_PREFIX
6551 "RelativeAddressing\n"));
6553 // Set the CommandQueue bit
6554 inquiryData
->CommandQueue
= 1;
6556 // Fill in vendor identification fields.
6557 for (i
= 0; i
< 24; i
+= 2) {
6558 MOV_DW_SWP(inquiryData
->VendorId
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
6561 // Initialize unused portion of product id.
6562 for (i = 0; i < 4; i++) {
6563 inquiryData->ProductId[12+i] = ' ';
6566 // Move firmware revision from IDENTIFY data to
6567 // product revision in INQUIRY data.
6568 for (i
= 0; i
< 4; i
+= 2) {
6569 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
6572 status
= SRB_STATUS_SUCCESS
;
6577 case SCSIOP_MODE_SENSE
:
6579 KdPrint2((PRINT_PREFIX
6580 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
6581 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6582 // This is used to determine if the media is write-protected.
6583 // Since IDE does not support mode sense then we will modify just the portion we need
6584 // so the higher level driver can determine if media is protected.
6585 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6587 SelectDrive(chan
, ldev
& 0x1);
6588 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_GET_MEDIA_STATUS
);
6589 statusByte
= WaitOnBusy(chan
);
6591 if (!(statusByte
& IDE_STATUS_ERROR
)){
6593 // no error occured return success, media is not protected
6594 chan
->ExpectingInterrupt
= FALSE
;
6595 InterlockedExchange(&(chan
->CheckIntr
),
6597 status
= SRB_STATUS_SUCCESS
;
6601 // error occured, handle it locally, clear interrupt
6602 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6604 GetBaseStatus(chan
, statusByte
);
6605 chan
->ExpectingInterrupt
= FALSE
;
6606 InterlockedExchange(&(chan
->CheckIntr
),
6608 status
= SRB_STATUS_SUCCESS
;
6610 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
6612 //media is write-protected, set bit in mode sense buffer
6613 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
6615 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
6616 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
6619 status
= SRB_STATUS_SUCCESS
;
6621 status
= SRB_STATUS_INVALID_REQUEST
;
6625 case SCSIOP_TEST_UNIT_READY
:
6627 KdPrint2((PRINT_PREFIX
6628 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
6629 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6630 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6632 // Select device 0 or 1.
6633 SelectDrive(chan
, ldev
& 0x1);
6634 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_GET_MEDIA_STATUS
);
6636 // Wait for busy. If media has not changed, return success
6637 statusByte
= WaitOnBusy(chan
);
6639 if (!(statusByte
& IDE_STATUS_ERROR
)){
6640 chan
->ExpectingInterrupt
= FALSE
;
6641 InterlockedExchange(&(chan
->CheckIntr
),
6643 status
= SRB_STATUS_SUCCESS
;
6645 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6646 if (errorByte
== IDE_ERROR_DATA_ERROR
){
6648 // Special case: If current media is write-protected,
6649 // the 0xDA command will always fail since the write-protect bit
6650 // is sticky,so we can ignore this error
6651 GetBaseStatus(chan
, statusByte
);
6652 chan
->ExpectingInterrupt
= FALSE
;
6653 InterlockedExchange(&(chan
->CheckIntr
),
6655 status
= SRB_STATUS_SUCCESS
;
6659 // Request sense buffer to be build
6660 chan
->ExpectingInterrupt
= TRUE
;
6661 InterlockedExchange(&(chan
->CheckIntr
),
6663 status
= SRB_STATUS_PENDING
;
6667 status
= SRB_STATUS_SUCCESS
;
6672 case SCSIOP_READ_CAPACITY
:
6674 KdPrint2((PRINT_PREFIX
6675 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
6676 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6677 // Claim 512 byte blocks (big-endian).
6678 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
6680 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
6682 // Calculate last sector.
6683 if(!(i
= (ULONG
)deviceExtension
->lun
[ldev
].NumOfSectors
)) {
6684 i
= deviceExtension
->lun
[ldev
].IdentifyData
.SectorsPerTrack
*
6685 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfHeads
*
6686 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfCylinders
;
6690 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
6691 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
6692 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
6694 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
6696 KdPrint2((PRINT_PREFIX
6697 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
6699 deviceExtension
->lun
[ldev
].IdentifyData
.SectorsPerTrack
,
6700 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfHeads
,
6701 deviceExtension
->lun
[ldev
].IdentifyData
.NumberOfCylinders
));
6704 status
= SRB_STATUS_SUCCESS
;
6709 KdPrint2((PRINT_PREFIX
6710 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
6711 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6712 status
= IdeVerify(HwDeviceExtension
,Srb
);
6719 KdPrint2((PRINT_PREFIX
6720 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
6721 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
6722 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6723 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6724 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
6725 status
= IdeReadWrite(HwDeviceExtension
,
6729 case SCSIOP_START_STOP_UNIT
:
6731 KdPrint2((PRINT_PREFIX
6732 "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
6733 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6734 //Determine what type of operation we should perform
6735 cdb
= (PCDB
)Srb
->Cdb
;
6737 if (cdb
->START_STOP
.LoadEject
== 1){
6739 statusByte
= WaitOnBaseBusy(chan
);
6741 // first select device 0 or 1.
6742 SelectDrive(chan
, ldev
& 0x1);
6743 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_MEDIA_EJECT
);
6745 status
= SRB_STATUS_SUCCESS
;
6748 case SCSIOP_MEDIUM_REMOVAL
:
6750 cdb
= (PCDB
)Srb
->Cdb
;
6752 statusByte
= WaitOnBaseBusy(chan
);
6754 SelectDrive(chan
, ldev
& 0x1);
6755 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
6756 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_DOOR_LOCK
);
6758 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_DOOR_UNLOCK
);
6760 status
= SRB_STATUS_SUCCESS
;
6763 // Note: I don't implement this, because NTFS driver too often issues this command
6764 // It causes awful performance degrade. However, if somebody wants, I will implement
6765 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
6768 case SCSIOP_FLUSH_BUFFER
:
6769 case SCSIOP_SYNCHRONIZE_CACHE
:
6771 SelectDrive(chan
, ldev
& 0x1);
6772 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
6773 status
= SRB_STATUS_SUCCESS
;
6774 // status = SRB_STATUS_PENDING;
6775 statusByte
= WaitOnBusy(chan
);
6779 case SCSIOP_REQUEST_SENSE
:
6780 // this function makes sense buffers to report the results
6781 // of the original GET_MEDIA_STATUS command
6783 KdPrint2((PRINT_PREFIX
6784 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
6785 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6786 if (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
6787 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
6790 status
= SRB_STATUS_INVALID_REQUEST
;
6794 case SCSIOP_ATA_PASSTHROUGH
:
6797 BOOLEAN use_dma
= FALSE
;
6800 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
6802 lChannel
= Srb
->TargetId
>> 1;
6804 regs
->bDriveHeadReg
&= 0x0f;
6805 regs
->bDriveHeadReg
|= (UCHAR
) (((Srb
->TargetId
& 0x1) << 4) | 0xA0);
6807 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
6809 KdPrint2((PRINT_PREFIX
6810 "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
6811 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
6814 AtapiDisableInterrupts(deviceExtension
, lChannel
);
6816 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
6817 if((chan
->lun
[Srb
->TargetId
& 0x1]->LimitedTransferMode
>= ATA_DMA
)) {
6819 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6820 if(!AtapiDmaSetup(HwDeviceExtension
, Srb
->TargetId
& 0x1, lChannel
, Srb
,
6821 (PUCHAR
)(Srb
->DataBuffer
),
6822 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
6828 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
6829 AtapiStallExecution(10);
6831 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
6832 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
6833 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
6834 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
6835 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
6836 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
6838 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
6839 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
6840 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
6841 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
6842 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
6843 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
6844 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
6845 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
6846 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
6847 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
6849 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
6852 GetBaseStatus(chan
, statusByte
);
6853 if(statusByte
& IDE_STATUS_ERROR
) {
6854 goto passthrough_err
;
6856 AtapiDmaStart(HwDeviceExtension
, (Srb
->TargetId
& 0x1), lChannel
, Srb
);
6859 ScsiPortStallExecution(1); // wait for busy to be set
6861 if(regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) {
6862 to_lim
= Srb
->TimeOutValue
;
6864 if(Srb
->TimeOutValue
<= 2) {
6865 to_lim
= Srb
->TimeOutValue
*900;
6867 to_lim
= (Srb
->TimeOutValue
*999) - 500;
6870 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
6871 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
6872 GetBaseStatus(chan
, statusByte
);
6873 if(statusByte
& IDE_STATUS_ERROR
) {
6876 if(!(statusByte
& IDE_STATUS_BUSY
)) {
6881 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
6883 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
6884 goto passthrough_err
;
6888 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
6890 AtapiDmaDone(deviceExtension
, (Srb
->TargetId
& 0x1), lChannel
, NULL
);
6891 GetBaseStatus(chan
, statusByte
);
6893 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
6894 AtapiSuckPort2(chan
);
6896 if (Srb
->SenseInfoBuffer
) {
6898 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
6900 senseBuffer
->ErrorCode
= 0x70;
6901 senseBuffer
->Valid
= 1;
6902 senseBuffer
->AdditionalSenseLength
= 0xb;
6903 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
6904 senseBuffer
->AdditionalSenseCode
= 0;
6905 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
6907 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
6908 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
6910 status
= SRB_STATUS_ERROR
;
6914 if (statusByte
& IDE_STATUS_DRQ
) {
6915 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6917 (PUSHORT
) Srb
->DataBuffer
,
6918 Srb
->DataTransferLength
/ 2,
6920 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
6922 (PUSHORT
) Srb
->DataBuffer
,
6923 Srb
->DataTransferLength
/ 2,
6928 status
= SRB_STATUS_SUCCESS
;
6931 AtapiEnableInterrupts(deviceExtension
, lChannel
);
6933 } else { // read task register
6935 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
6937 regs
->bDriveHeadReg
= AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
);
6939 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
6940 regs
->bFeaturesReg
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6941 regs
->bSectorCountReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6942 regs
->bSectorNumberReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6943 regs
->bCylLowReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6944 regs
->bCylHighReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
6946 regs
->bFeaturesReg
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6947 regs
->bFeaturesRegH
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6948 regs
->bSectorCountReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6949 regs
->bSectorCountRegH
= AtapiReadPort1(chan
, IDX_IO1_i_BlockCount
);
6950 regs
->bSectorNumberReg
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6951 regs
->bSectorNumberRegH
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
6952 regs
->bCylLowReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6953 regs
->bCylLowRegH
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
6954 regs
->bCylHighReg
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
6955 regs
->bCylHighRegH
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
6957 regs
->bCommandReg
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
6958 status
= SRB_STATUS_SUCCESS
;
6965 KdPrint2((PRINT_PREFIX
6966 "IdeSendCommand: Unsupported command %#x\n",
6969 status
= SRB_STATUS_INVALID_REQUEST
;
6973 if(status
== SRB_STATUS_PENDING
) {
6974 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
6975 if(CmdAction
& CMD_ACTION_EXEC
) {
6976 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
6977 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
6980 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
6981 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
6986 } // end IdeSendCommand()
6991 Routine Description:
6992 Enables disables media status notification
6995 HwDeviceExtension - ATAPI driver storage.
7001 IN PVOID HwDeviceExtension
,
7005 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7007 UCHAR lChannel
= ldev
>> 1;
7008 UCHAR statusByte
,errorByte
;
7010 chan
= &(deviceExtension
->chan
[lChannel
]);
7012 if (EnableMSN
== TRUE
){
7014 // If supported enable Media Status Notification support
7015 if ((deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
7018 statusByte
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7019 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7020 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
7022 if (statusByte
& IDE_STATUS_ERROR
) {
7023 // Read the error register.
7024 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7026 KdPrint2((PRINT_PREFIX
7027 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
7031 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
7032 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
7033 chan
->ReturningMediaStatus
= 0;
7038 } else { // end if EnableMSN == TRUE
7040 // disable if previously enabled
7041 if ((deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
7043 statusByte
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7044 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7045 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
7046 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
7053 } // end IdeMediaStatus()
7058 Routine Description:
7060 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
7061 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
7064 HwDeviceExtension - ATAPI driver storage.
7065 Srb - System request block.
7069 SRB status (ALWAYS SUCCESS).
7073 IdeBuildSenseBuffer(
7074 IN PVOID HwDeviceExtension
,
7075 IN PSCSI_REQUEST_BLOCK Srb
7078 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7080 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
7081 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
7085 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
7087 senseBuffer
->ErrorCode
= 0x70;
7088 senseBuffer
->Valid
= 1;
7089 senseBuffer
->AdditionalSenseLength
= 0xb;
7090 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
7091 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
7092 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7093 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
7095 senseBuffer
->ErrorCode
= 0x70;
7096 senseBuffer
->Valid
= 1;
7097 senseBuffer
->AdditionalSenseLength
= 0xb;
7098 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
7099 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
7100 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7101 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
7103 senseBuffer
->ErrorCode
= 0x70;
7104 senseBuffer
->Valid
= 1;
7105 senseBuffer
->AdditionalSenseLength
= 0xb;
7106 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
7107 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
7108 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7109 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
7111 senseBuffer
->ErrorCode
= 0x70;
7112 senseBuffer
->Valid
= 1;
7113 senseBuffer
->AdditionalSenseLength
= 0xb;
7114 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
7115 senseBuffer
->AdditionalSenseCode
= 0;
7116 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7118 return SRB_STATUS_SUCCESS
;
7120 return SRB_STATUS_ERROR
;
7122 }// End of IdeBuildSenseBuffer
7125 UniataUserDeviceReset(
7126 PHW_DEVICE_EXTENSION deviceExtension
,
7127 PHW_LU_EXTENSION LunExt
,
7132 AtapiDisableInterrupts(deviceExtension
, PathId
);
7133 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
7134 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
7135 AtapiSoftReset(&(deviceExtension
->chan
[PathId
]), ldev
& 1);
7137 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
7138 AtapiResetController__(deviceExtension
, PathId
, RESET_COMPLETE_NONE
);
7139 deviceExtension
->chan
[PathId
].lun
[0]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
7140 deviceExtension
->chan
[PathId
].lun
[1]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
7142 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
7143 AtapiEnableInterrupts(deviceExtension
, PathId
);
7145 } // end UniataUserDeviceReset()
7149 PHW_DEVICE_EXTENSION deviceExtension
,
7154 BOOLEAN PostReq
= FALSE
;
7156 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
7157 if(chan
->queue_depth
> 0) {
7160 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
7161 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
7162 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
7164 status
= SRB_STATUS_BUSY
;
7173 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
7177 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
7180 } // end UniataNeedQueueing()
7184 Routine Description:
7186 This routine is called from the SCSI port driver synchronized
7187 with the kernel to start an IO request.
7191 HwDeviceExtension - HBA miniport driver's adapter data storage
7192 Srb - IO request packet
7202 IN PVOID HwDeviceExtension
,
7203 IN PSCSI_REQUEST_BLOCK Srb
7206 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
7207 } // end AtapiStartIo()
7211 IN PVOID HwDeviceExtension
,
7212 IN PSCSI_REQUEST_BLOCK Srb
,
7216 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7225 PSCSI_REQUEST_BLOCK tmpSrb
;
7226 BOOLEAN PostReq
= FALSE
;
7228 BOOLEAN commPort
= FALSE
;
7230 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
7231 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
7232 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
7233 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
7235 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
7237 /* KeBugCheckEx(0xc000000e,
7238 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7240 TopLevel, 0x80000001);
7242 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
7243 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
7244 RtlZeroMemory(Srb
->SrbExtension
, sizeof(ATA_REQ
));
7249 lChannel
= GET_CHANNEL(Srb
);
7250 chan
= &(deviceExtension
->chan
[lChannel
]);
7251 ldev
= GET_LDEV(Srb
);
7253 //ASSERT(deviceExtension);
7256 KdPrint2((PRINT_PREFIX
7257 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
7258 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7259 KdPrint2((PRINT_PREFIX
" VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
7261 if(lChannel
== deviceExtension
->NumberChannels
&&
7262 !Srb
->Lun
&& !Srb
->TargetId
&&
7263 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
7264 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
7266 KdPrint2((PRINT_PREFIX
7267 "AtapiStartIo: Communication port\n"));
7268 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
7270 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
7272 KdPrint2((PRINT_PREFIX
7274 // Zero INQUIRY data structure.
7275 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
7277 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
7279 // Fill in vendor identification fields.
7280 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
7282 status
= SRB_STATUS_SUCCESS
;
7286 /* Pass IOCTL request down */
7288 if(GET_CDEV(Srb
) >= 2 ||
7289 ldev
>= deviceExtension
->NumberChannels
*2 ||
7290 lChannel
>= deviceExtension
->NumberChannels
||
7293 if(lChannel
>= deviceExtension
->NumberChannels
) {
7298 //if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) {
7299 KdPrint2((PRINT_PREFIX
7300 "AtapiStartIo: SRB rejected\n"));
7301 // Indicate no device found at this address.
7302 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7303 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7308 atapiDev
= (deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
7311 if(!commPort
&& !(chan
->lun
[ldev
& 1])) {
7313 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
7316 deviceExtension
->NumberChannels
);
7317 PrintNtConsole("lchan = %#x, ldev %#x, cdev %#x, lun0 %#x\n",
7318 lChannel
, ldev
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
7319 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
7320 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
7324 for(i=0; i<1000; i++) {
7325 AtapiStallExecution(3*1000);
7332 // Determine which function.
7333 switch (Srb
->Function
) {
7335 case SRB_FUNCTION_EXECUTE_SCSI
:
7337 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7338 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
7339 // let passthrough go
7341 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
7345 //if(!CheckDevice(HwDeviceExtension, lChannel, ldev & 1, FALSE)) {
7346 KdPrint2((PRINT_PREFIX
7347 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
7348 // Indicate no device found at this address.
7349 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7350 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7357 if(Srb->DataTransferLength) {
7359 a = ((PUCHAR)(Srb->DataBuffer))[0];
7362 } __except(EXCEPTION_EXECUTE_HANDLER) {
7363 KdPrint3((PRINT_PREFIX
7364 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
7365 // Indicate no device found at this address.
7366 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
7367 status = SRB_STATUS_ERROR;
7368 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
7373 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7377 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
7379 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
7380 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
7382 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
7384 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
7385 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
7387 /*KeBugCheckEx(0xc000000e,
7388 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7390 status, 0x80000001);*/
7391 if(status
== SRB_STATUS_BUSY
)
7392 status
= SRB_STATUS_PENDING
;
7393 // Insert requests AFTER they have been initialized on
7394 // CMD_ACTION_PREPARE stage
7395 // we should not check TopLevel here (it is always TRUE)
7396 //ASSERT(chan->lun[GET_LDEV(Srb) & 1]);
7397 UniataQueueRequest(chan
, Srb
);
7399 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7402 // Send command to device.
7403 KdPrint2((PRINT_PREFIX
"Send to device\n"));
7405 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
7406 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7407 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
7408 //ASSERT(!AtaReq->Flags);
7409 //ASSERT(chan->lun[GET_LDEV(Srb) & 1]);
7410 UniataQueueRequest(chan
, Srb
);
7411 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
7412 //ASSERT(!AtaReq->Flags);
7413 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7414 //ASSERT(!AtaReq->Flags);
7418 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7419 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
7420 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, ldev
& 1)) {
7421 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, ldev
& 1, TRUE
)) {
7425 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7429 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
7438 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
7439 KdPrint3((PRINT_PREFIX
"Try ATAPI send\n"));
7440 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
7442 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
7447 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
7454 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
7456 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
7458 /* KeBugCheckEx(0xc000000e,
7459 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
7461 status, 0x80000002);*/
7469 case SRB_FUNCTION_ABORT_COMMAND
:
7471 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
7473 // Verify that SRB to abort is still outstanding.
7474 if((tmpSrb
!= Srb
->NextSrb
) ||
7475 !chan
->queue_depth
) {
7477 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
7479 // Complete abort SRB.
7480 status
= SRB_STATUS_ABORT_FAILED
;
7484 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
7485 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
7486 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
7487 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
7488 // Log reset failure.
7489 KdPrint3((PRINT_PREFIX
7490 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
7491 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
7493 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
7494 status
= SRB_STATUS_ERROR
;
7497 status
= SRB_STATUS_SUCCESS
;
7500 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
7501 if (tmpSrb
->SenseInfoBuffer
&&
7502 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
7504 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
7506 senseBuffer
->ErrorCode
= 0;
7507 senseBuffer
->Valid
= 1;
7508 senseBuffer
->AdditionalSenseLength
= 0xb;
7509 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
7510 senseBuffer
->AdditionalSenseCode
= 0;
7511 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
7513 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
7515 AtapiDmaDBSync(chan
, tmpSrb
);
7516 UniataRemoveRequest(chan
, tmpSrb
);
7517 // Indicate command complete.
7518 ScsiPortNotification(RequestComplete
,
7521 status
= SRB_STATUS_SUCCESS
;
7525 // Abort function indicates that a request timed out.
7526 // Call reset routine. Card will only be reset if
7527 // status indicates something is wrong.
7528 // Fall through to reset code.
7530 case SRB_FUNCTION_RESET_DEVICE
:
7531 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
7533 // Reset single device.
7534 // For now we support only Lun=0
7536 // Note: reset is immediate command, it cannot be queued since it is usually used to
7537 // revert not- responding device to operational state
7538 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
7539 UniataUserDeviceReset(deviceExtension
, &(deviceExtension
->lun
[ldev
]), lChannel
, ldev
);
7540 status
= SRB_STATUS_SUCCESS
;
7543 case SRB_FUNCTION_RESET_BUS
:
7545 // Reset Atapi and SCSI bus.
7547 // Note: reset is immediate command, it cannot be queued since it is usually used to
7548 // revert not- responding device to operational state
7549 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
7550 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
7551 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
7552 // Log reset failure.
7553 KdPrint3((PRINT_PREFIX
7554 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
7555 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
7557 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
7558 status
= SRB_STATUS_ERROR
;
7561 status
= SRB_STATUS_SUCCESS
;
7566 case SRB_FUNCTION_SHUTDOWN
:
7568 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
7569 if(!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7570 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
7573 // FLUSH ATAPI device - do nothing
7574 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
7576 // FLUSH IDE/ATA device
7577 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
7578 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7579 status
= AtaCommand(deviceExtension
, ldev
& 1, GET_CHANNEL(Srb
),
7580 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
7581 // If supported & allowed, reset write cacheing
7582 if(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
7584 // Disable write cache
7585 status
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7586 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7587 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
7588 // Check for errors.
7589 if (status
& IDE_STATUS_ERROR
) {
7590 KdPrint2((PRINT_PREFIX
7591 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
7594 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
7596 // Re-enable write cache
7597 status
= AtaCommand(deviceExtension
, ldev
& 1, lChannel
,
7598 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
7599 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
7600 // Check for errors.
7601 if (status
& IDE_STATUS_ERROR
) {
7602 KdPrint2((PRINT_PREFIX
7603 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
7605 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
7607 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
7611 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7613 status
= SRB_STATUS_SUCCESS
;
7617 case SRB_FUNCTION_FLUSH
:
7619 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
7620 status
= SRB_STATUS_SUCCESS
;
7623 /* case SRB_FUNCTION_SHUTDOWN:
7624 case SRB_FUNCTION_FLUSH:
7626 // Flush device's cache.
7627 KdPrint2((PRINT_PREFIX "AtapiStartIo: Device flush received\n"));
7629 if (chan->CurrentSrb) {
7631 KdPrint2((PRINT_PREFIX "AtapiStartIo (SRB_FUNCTION_FLUSH): Already have a request!\n"));
7632 Srb->SrbStatus = SRB_STATUS_BUSY;
7633 ScsiPortNotification(RequestComplete,
7639 if (deviceExtension->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE) {
7640 status = SRB_STATUS_SUCCESS;
7642 status = AtaCommand(deviceExtension, ldev & 1, GET_CHANNEL(Srb),
7643 IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_INTR);
7644 if (status & IDE_STATUS_DRQ) {
7645 status = SRB_STATUS_SUCCESS;
7647 status = SRB_STATUS_SELECTION_TIMEOUT;
7652 case SRB_FUNCTION_IO_CONTROL
: {
7656 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
7658 len
= Srb
->DataTransferLength
;
7660 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
7662 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
7663 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
7665 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7668 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
7670 // Version and revision per SMART 1.03
7672 versionParameters
->bVersion
= 1;
7673 versionParameters
->bRevision
= 1;
7674 versionParameters
->bReserved
= 0;
7676 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
7677 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
7679 // This is done because of how the IOCTL_SCSI_MINIPORT
7680 // determines 'targetid's'. Disk.sys places the real target id value
7681 // in the DeviceMap field. Once we do some parameter checking, the value passed
7682 // back to the application will be determined.
7684 deviceNumber
= versionParameters
->bIDEDeviceMap
;
7687 KdPrint2((PRINT_PREFIX
7688 "AtapiStartIo: SCSIDISK IOCTL for commPort -> EXECUTE_SCSI rejected (2)\n"));
7689 // Indicate no device found at this address.
7690 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7691 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7695 if (!(deviceExtension
->lun
[ldev
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
) ||
7698 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7702 // NOTE: This will only set the bit
7703 // corresponding to this drive's target id.
7704 // The bit mask is as follows:
7710 if (deviceExtension
->NumberChannels
== 1) {
7711 if (chan
->PrimaryAddress
) {
7712 deviceNumber
= 1 << ldev
;
7714 deviceNumber
= 4 << ldev
;
7717 deviceNumber
= 1 << ldev
;
7720 versionParameters
->bIDEDeviceMap
= deviceNumber
;
7722 status
= SRB_STATUS_SUCCESS
;
7726 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
7728 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7729 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
7732 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
7733 // Extract the target.
7734 targetId
= cmdInParameters
.bDriveNumber
;
7735 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
7736 if((targetId
>= deviceExtension
->NumberChannels
*2) ||
7737 !(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7738 KdPrint2((PRINT_PREFIX
"Error: xxx_ID_CMD for non-existant device\n"));
7739 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7743 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
7745 if((deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
7746 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
7747 status
= SRB_STATUS_INVALID_REQUEST
;
7753 if(!(deviceExtension
->lun
[targetId
].DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
7754 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
7755 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
7756 status
= SRB_STATUS_INVALID_REQUEST
;
7760 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
7761 // Zero the output buffer
7762 RtlZeroMemory(cmdOutParameters
, len
);
7763 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
7764 ((PUCHAR)cmdOutParameters)[i] = 0;
7767 // Build status block.
7768 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
7769 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
7770 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
7772 // Extract the identify data from the device extension.
7773 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &deviceExtension
->lun
[targetId
].IdentifyData
,
7774 cmdOutParameters
->cBufferSize
);
7776 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
7778 status
= SRB_STATUS_SUCCESS
;
7782 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
7783 cmdInParameters
.irDriveRegs
.bCommandReg
));
7784 status
= SRB_STATUS_INVALID_REQUEST
;
7790 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
7791 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
7792 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
7793 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
7794 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
7795 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
7796 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
7797 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
7800 KdPrint2((PRINT_PREFIX
7801 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
7802 // Indicate no device found at this address.
7803 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
7804 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7808 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7810 if(PostReq
|| TopLevel
) {
7811 UniataQueueRequest(chan
, Srb
);
7812 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7813 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7818 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
7819 status
= SRB_STATUS_PENDING
;
7821 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7824 status
= IdeSendSmartCommand(HwDeviceExtension
,Srb
);
7829 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
7830 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
7831 status
= SRB_STATUS_INVALID_REQUEST
;
7836 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
7838 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
7839 ULONG ldev
= GET_LDEV2(AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
, 0);
7840 PHW_LU_EXTENSION LunExt
;
7843 //chan = &(deviceExtension->chan[lChannel]);
7845 if(AtaCtl
->addr
.Lun
||
7846 ldev
>= deviceExtension
->NumberChannels
*2 ||
7847 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
7854 LunExt
= &(deviceExtension
->lun
[ldev
]);
7855 lChannel
= AtaCtl
->addr
.PathId
;
7856 chan
= &(deviceExtension
->chan
[lChannel
]);
7859 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, ldev %#x\n", AtaCtl
->hdr
.ControlCode
, ldev
));
7861 /* check for valid LUN */
7862 switch (AtaCtl
->hdr
.ControlCode
) {
7863 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7864 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
7866 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
7867 AtaCtl
->addr
.TargetId
!= 0xff ||
7868 AtaCtl
->addr
.Lun
!= 0
7870 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
7871 ldev
< deviceExtension
->NumberChannels
*2) { // AtaCtl->addr.TargetId != 0xff
7872 LunExt
= &(deviceExtension
->lun
[ldev
]);
7875 goto handle_bad_ldev
;
7878 // this would be BUS reset
7879 lChannel
= AtaCtl
->addr
.PathId
;
7880 chan
= &(deviceExtension
->chan
[lChannel
]);
7882 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
7883 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
7884 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
7885 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
7886 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
7889 KdPrint2((PRINT_PREFIX
7890 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
7891 // Indicate no device found at this address.
7896 /* check if queueing is necessary */
7897 switch (AtaCtl
->hdr
.ControlCode
) {
7898 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
7899 if(!LunExt
->nBadBlocks
) {
7902 goto uata_ctl_queue
;
7903 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
7904 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
7907 goto uata_ctl_queue
;
7908 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7909 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
7911 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
7912 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
7914 if(PostReq
|| TopLevel
) {
7915 UniataQueueRequest(chan
, Srb
);
7916 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7917 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7920 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
7921 status
= SRB_STATUS_PENDING
;
7923 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
7926 } // end switch (AtaCtl->hdr.ControlCode)
7928 /* process request */
7929 switch (AtaCtl
->hdr
.ControlCode
) {
7930 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
7932 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
7934 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
7935 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
7936 if(AtaCtl
->addr
.TargetId
!= 0xff) {
7937 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_HIDDEN
;
7942 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
7943 AtapiStallExecution(1000 * 1000);
7946 FindDevices(HwDeviceExtension
,
7947 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
7948 ? UNIATA_FIND_DEV_UNHIDE
: 0,
7949 AtaCtl
->addr
.PathId
);
7950 status
= SRB_STATUS_SUCCESS
;
7954 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
7956 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
7958 deviceExtension
->lun
[ldev
].DeviceFlags
= 0;
7959 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
7960 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
7961 deviceExtension
->lun
[ldev
].DeviceFlags
|= DFLAGS_HIDDEN
;
7964 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
7965 AtapiStallExecution(1000 * 1000);
7968 status
= SRB_STATUS_SUCCESS
;
7971 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
7973 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
7975 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
7976 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
7978 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
7979 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
7980 if(LunExt
->LimitedTransferMode
>
7981 LunExt
->OrigTransferMode
) {
7982 // check for incorrect value
7983 LunExt
->LimitedTransferMode
=
7984 LunExt
->OrigTransferMode
;
7987 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
7989 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
7990 if(AtaCtl
->SetMode
.ApplyImmediately
) {
7991 AtapiDmaInit__(deviceExtension
, ldev
);
7993 /* deviceExtension->lun[ldev].TransferMode =
7994 deviceExtension->lun[ldev].LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
7995 status
= SRB_STATUS_SUCCESS
;
7998 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
8000 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
8002 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
8003 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
8004 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
8006 status
= SRB_STATUS_SUCCESS
;
8009 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
8011 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
8013 AtaCtl
->AdapterInfo
.HeaderLength
= offsetof(ADAPTERINFO
, Chan
);
8015 if(len
< AtaCtl
->AdapterInfo
.HeaderLength
+ sizeof(AtaCtl
->AdapterInfo
.Chan
)) {
8016 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", len
,
8017 AtaCtl
->AdapterInfo
.HeaderLength
+ sizeof(AtaCtl
->AdapterInfo
.Chan
)));
8018 status
= SRB_STATUS_DATA_OVERRUN
;
8022 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
8023 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
8024 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
8025 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
8026 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
8027 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
8028 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
8029 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
8030 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
8031 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
8032 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
8033 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
8034 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
8035 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
8036 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
8037 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
8038 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
8039 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
8040 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
8041 if(deviceExtension
->FullDevName
) {
8042 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
8044 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
8046 RtlZeroMemory(&AtaCtl
->AdapterInfo
.Chan
, sizeof(AtaCtl
->AdapterInfo
.Chan
));
8048 status
= SRB_STATUS_SUCCESS
;
8051 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
8053 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
8055 ForgetBadBlocks(LunExt
);
8057 status
= SRB_STATUS_SUCCESS
;
8060 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
8062 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
8067 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
, ldev
);
8070 status
= SRB_STATUS_SUCCESS
;
8074 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
8075 AtaCtl
->hdr
.ControlCode
));
8076 status
= SRB_STATUS_INVALID_REQUEST
;
8081 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
8082 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
8083 "SCSIDISK", "-UNIATA-"));
8085 status
= SRB_STATUS_INVALID_REQUEST
;
8090 } // end SRB_FUNCTION_IO_CONTROL
8093 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
8094 // Indicate unsupported command.
8095 status
= SRB_STATUS_INVALID_REQUEST
;
8103 PathId
= Srb
->PathId
;
8104 TargetId
= Srb
->TargetId
;
8107 if (status
!= SRB_STATUS_PENDING
) {
8109 KdPrint2((PRINT_PREFIX
8110 "AtapiStartIo: Srb %#x complete with status %#x\n",
8114 // Set status in SRB.
8115 Srb
->SrbStatus
= (UCHAR
)status
;
8117 AtapiDmaDBSync(chan
, Srb
);
8118 UniataRemoveRequest(chan
, Srb
);
8119 // Indicate command complete.
8120 ScsiPortNotification(RequestComplete
,
8124 // Remove current Srb & get next one
8125 if((Srb
= UniataGetCurRequest(chan
))) {
8126 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8127 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
8128 // current request is under precessing, thus
8129 // we should do nothing here
8137 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
8139 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
8141 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
8142 // Indicate ready for next request.
8143 ScsiPortNotification(NextRequest
,
8147 ScsiPortNotification(NextLuRequest
,
8155 } // end AtapiStartIo__()
8159 UniataInitAtaCommands()
8165 for(i
=0, command
=0; i
<256; i
++, command
++) {
8168 case IDE_COMMAND_READ_DMA48
:
8169 case IDE_COMMAND_READ_DMA_Q48
:
8170 case IDE_COMMAND_READ_STREAM_DMA48
:
8171 case IDE_COMMAND_READ_STREAM48
:
8172 case IDE_COMMAND_WRITE_DMA48
:
8173 case IDE_COMMAND_WRITE_DMA_Q48
:
8174 case IDE_COMMAND_READ_DMA_Q
:
8175 case IDE_COMMAND_READ_DMA
:
8176 case IDE_COMMAND_WRITE_DMA
:
8177 case IDE_COMMAND_WRITE_DMA_Q
:
8178 case IDE_COMMAND_WRITE_STREAM_DMA48
:
8179 case IDE_COMMAND_WRITE_STREAM48
:
8180 case IDE_COMMAND_WRITE_FUA_DMA48
:
8181 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
8182 case IDE_COMMAND_READ_LOG_DMA48
:
8183 case IDE_COMMAND_WRITE_LOG_DMA48
:
8184 case IDE_COMMAND_TRUSTED_RCV_DMA
:
8185 case IDE_COMMAND_TRUSTED_SEND_DMA
:
8186 flags
|= ATA_CMD_FLAG_DMA
;
8190 case IDE_COMMAND_READ48
:
8191 case IDE_COMMAND_READ_DMA48
:
8192 case IDE_COMMAND_READ_DMA_Q48
:
8193 case IDE_COMMAND_READ_MUL48
:
8194 case IDE_COMMAND_READ_STREAM_DMA48
:
8195 case IDE_COMMAND_READ_STREAM48
:
8196 case IDE_COMMAND_WRITE48
:
8197 case IDE_COMMAND_WRITE_DMA48
:
8198 case IDE_COMMAND_WRITE_DMA_Q48
:
8199 case IDE_COMMAND_WRITE_MUL48
:
8200 case IDE_COMMAND_WRITE_STREAM_DMA48
:
8201 case IDE_COMMAND_WRITE_STREAM48
:
8202 case IDE_COMMAND_WRITE_FUA_DMA48
:
8203 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
8204 case IDE_COMMAND_WRITE_MUL_FUA48
:
8205 case IDE_COMMAND_FLUSH_CACHE48
:
8206 case IDE_COMMAND_VERIFY48
:
8208 flags
|= ATA_CMD_FLAG_48
;
8211 case IDE_COMMAND_READ
:
8212 case IDE_COMMAND_READ_MULTIPLE
:
8213 case IDE_COMMAND_READ_DMA
:
8214 case IDE_COMMAND_READ_DMA_Q
:
8215 case IDE_COMMAND_WRITE
:
8216 case IDE_COMMAND_WRITE_MULTIPLE
:
8217 case IDE_COMMAND_WRITE_DMA
:
8218 case IDE_COMMAND_WRITE_DMA_Q
:
8219 case IDE_COMMAND_FLUSH_CACHE
:
8220 case IDE_COMMAND_VERIFY
:
8222 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
8225 flags
|= ATA_CMD_FLAG_48supp
;
8228 case IDE_COMMAND_READ
:
8229 command
= IDE_COMMAND_READ48
; break;
8230 case IDE_COMMAND_READ_MULTIPLE
:
8231 command
= IDE_COMMAND_READ_MUL48
; break;
8232 case IDE_COMMAND_READ_DMA
:
8233 command
= IDE_COMMAND_READ_DMA48
; break;
8234 case IDE_COMMAND_READ_DMA_Q
:
8235 command
= IDE_COMMAND_READ_DMA_Q48
; break;
8236 case IDE_COMMAND_WRITE
:
8237 command
= IDE_COMMAND_WRITE48
; break;
8238 case IDE_COMMAND_WRITE_MULTIPLE
:
8239 command
= IDE_COMMAND_WRITE_MUL48
; break;
8240 case IDE_COMMAND_WRITE_DMA
:
8241 command
= IDE_COMMAND_WRITE_DMA48
; break;
8242 case IDE_COMMAND_WRITE_DMA_Q
:
8243 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
8244 case IDE_COMMAND_FLUSH_CACHE
:
8245 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
8246 // case IDE_COMMAND_READ_NATIVE_SIZE:
8247 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
8248 case IDE_COMMAND_SET_NATIVE_SIZE
:
8249 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
8250 case IDE_COMMAND_VERIFY
:
8251 command
= IDE_COMMAND_VERIFY48
; break;
8253 flags
&= ~ATA_CMD_FLAG_48supp
;
8256 AtaCommands48
[i
] = command
;
8257 AtaCommandFlags
[i
] = flags
;
8259 } // end UniataInitAtaCommands()
8263 Routine Description:
8265 Installable driver initialization entry point for system.
8273 Status from ScsiPortInitialize()
8280 IN PVOID DriverObject
,
8284 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
8287 ULONG statusToReturn
, newStatus
;
8288 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
8289 BOOLEAN ReEnter
= FALSE
;
8292 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
8293 BOOLEAN PrimaryClaimed
= FALSE
;
8294 BOOLEAN SecondaryClaimed
= FALSE
;
8296 LARGE_INTEGER t0
, t1
;
8299 KdPrint2((PRINT_PREFIX (PCCHAR
)ver_string
));
8300 a
= (WCHAR
)strlen(ver_string
);
8302 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
8304 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
8307 if(!SavedDriverObject
) {
8308 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
8309 KdPrint(("UniATA Init: OS should be ReactOS\n"));
8311 KeQuerySystemTime(&t0
);
8313 KeQuerySystemTime(&t1
);
8314 } while(t0
.QuadPart
== t1
.QuadPart
);
8318 KeQuerySystemTime(&t1
);
8320 } while(t0
.QuadPart
== t1
.QuadPart
);
8321 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
8322 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
8325 KdPrint(("UniATA Init: ReEnter\n"));
8329 // (re)read bad block list
8330 InitBadBlocks(NULL
);
8333 // init ATA command translation table
8334 UniataInitAtaCommands();
8335 // get registry path to settings
8336 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
8337 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
8338 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
8339 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
8340 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
8341 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
8344 if(WinVer_Id() >= WinVer_2k
) {
8345 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
8346 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
8347 WinVer_WDM_Model
= TRUE
;
8349 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
8350 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
8351 WinVer_WDM_Model
= TRUE
;
8355 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
8356 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
8358 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
8361 statusToReturn
= 0xffffffff;
8363 // Zero out structure.
8364 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
8366 // Set size of hwInitializationData.
8367 hwInitializationData
.comm
.HwInitializationDataSize
=
8368 sizeof(hwInitializationData
.comm
) +
8369 // sizeof(hwInitializationData.nt4) +
8370 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
8371 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
8373 // Set entry points.
8374 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
8375 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
8376 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
8377 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
8379 // Specify size of extensions.
8380 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
8381 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
8382 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
8384 // Indicate PIO device.
8385 hwInitializationData
.comm
.MapBuffers
= TRUE
;
8386 // Set PnP-specific API
8387 if(WinVer_Id() > WinVer_NT
) {
8388 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
8389 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
8390 KdPrint(("set AtapiAdapterControl() ptr\n"));
8391 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
8394 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE enum supported BusMaster Devices\n"));
8397 UniataEnumBusMasterController(DriverObject
, Argument2
);
8400 // Look for legacy ISA-bridged PCI IDE controller (onboard)
8401 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
8402 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
8403 for (i
=0; i
<BMListLen
; i
++) {
8405 if(!BMList
[i
].MasterDev
) {
8406 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
8409 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
8413 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
8414 if(BMList
[i
].ChanInitOk
& 0x03) {
8415 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
8417 newStatus
= STATUS_SUCCESS
;
8421 BMList
[i
].AltInitMasterDev
= (UCHAR
)0xff;
8423 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
8424 PrimaryClaimed
= TRUE
;
8425 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
8426 SecondaryClaimed
= TRUE
;
8429 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
8431 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
8433 for(c
=0; c
<2; c
++) {
8435 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
8439 if(PrimaryClaimed
) {
8440 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
8445 if(SecondaryClaimed
) {
8446 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
8451 if((WinVer_Id() < WinVer_2k
)) {
8452 // do not even try if already claimed
8454 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
8457 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
8460 if(!WinVer_WDM_Model
) {
8461 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
8463 // in WDM model things are different....
8464 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
8465 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
8467 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
8468 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
8470 if(!WinVer_WDM_Model
) {
8471 BMList
[i
].channel
= (UCHAR
)c
;
8474 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
8475 newStatus
= ScsiPortInitialize(DriverObject
,
8477 &hwInitializationData
.comm
,
8478 (PVOID
)(i
| (alt
? 0x80000000 : 0)));
8479 KdPrint2((PRINT_PREFIX
"Status %#x\n", newStatus
));
8480 if (newStatus
< statusToReturn
) {
8481 statusToReturn
= newStatus
;
8483 if (newStatus
== STATUS_SUCCESS
) {
8484 BMList
[i
].ChanInitOk
|= 0x01 << c
;
8486 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
8487 c = 1; // this will break our for()
8488 BMList[i].ChanInitOk |= 0x01 << c;
8493 if(WinVer_Id() >= WinVer_2k
) {
8494 // the following doesn't work under higher OSes
8495 KdPrint2((PRINT_PREFIX
"make still one attempt\n"));
8498 if(BMList
[i
].ChanInitOk
& 0x03) {
8499 // under NT we receive status immediately, so
8500 // we can omit alternative init method id STATUS_SUCCESS returned
8501 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
8504 // if (WinVer_Id() == WinVer_NT) and some error occured
8505 // try alternative init method
8508 if(WinVer_WDM_Model
) {
8509 hwInitializationData
.comm
.HwFindAdapter
= UniataFindFakeBusMasterController
;
8510 hwInitializationData
.comm
.NumberOfAccessRanges
= 5;
8511 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
8513 hwInitializationData
.comm
.VendorId
= BMList
[i
].VendorId
;
8514 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
8515 hwInitializationData
.comm
.DeviceId
= BMList
[i
].DeviceId
;
8516 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
8518 //BMList[i].channel = 0/*(UCHAR)c*/;
8520 KdPrint2((PRINT_PREFIX
"Try init fake: %4.4s %4.4s \n",
8521 hwInitializationData
.comm
.VendorId
,
8522 hwInitializationData
.comm
.DeviceId
));
8523 newStatus
= ScsiPortInitialize(DriverObject
,
8525 &hwInitializationData
.comm
,
8527 KdPrint2((PRINT_PREFIX
"Status %#x\n", newStatus
));
8531 if(BMList
[i
].ChanInitOk
& 0x03) {
8532 _PrintNtConsole(" OK\n");
8534 _PrintNtConsole(" failed\n");
8540 /* KeBugCheckEx(0xc000000e,
8541 (i << 16) | BMList[0].ChanInitOk,
8543 newStatus, statusToReturn);*/
8545 // Look for PCI IDE controller
8546 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
8547 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
8548 for (; i
<BMListLen
; i
++) {
8550 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", 0)) {
8553 /* if(BMList[i].MasterDev)
8556 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
8557 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
8558 BMList
[i
].busNumber
,
8559 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
8560 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
8563 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
8564 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
8565 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
8567 hwInitializationData
.comm
.VendorId
= BMList
[i
].VendorId
;
8568 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
8569 hwInitializationData
.comm
.DeviceId
= BMList
[i
].DeviceId
;
8570 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
8572 BMList
[i
].channel
= 0/*(UCHAR)c*/;
8574 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
8575 hwInitializationData
.comm
.VendorId
,
8576 hwInitializationData
.comm
.DeviceId
));
8577 newStatus
= ScsiPortInitialize(DriverObject
,
8579 &hwInitializationData
.comm
,
8581 if (newStatus
< statusToReturn
)
8582 statusToReturn
= newStatus
;
8585 if(newStatus
== STATUS_SUCCESS
) {
8586 _PrintNtConsole(" OK\n");
8588 _PrintNtConsole(" failed\n");
8594 /* KeBugCheckEx(0xc000000e,
8597 newStatus, statusToReturn);*/
8601 hwInitializationData
.comm
.VendorId
= 0;
8602 hwInitializationData
.comm
.VendorIdLength
= 0;
8603 hwInitializationData
.comm
.DeviceId
= 0;
8604 hwInitializationData
.comm
.DeviceIdLength
= 0;
8606 // The adapter count is used by the find adapter routine to track how
8607 // which adapter addresses have been tested.
8609 // Indicate 2 access ranges and reset FindAdapter.
8610 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
8611 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindController
;
8613 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
8614 // Indicate ISA bustype.
8615 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
8618 // Call initialization for ISA bustype.
8619 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
8620 newStatus
= ScsiPortInitialize(DriverObject
,
8622 &hwInitializationData
.comm
,
8624 if (newStatus
< statusToReturn
)
8625 statusToReturn
= newStatus
;
8627 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
8629 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
8630 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
8633 newStatus
= ScsiPortInitialize(DriverObject
,
8635 &hwInitializationData
.comm
,
8637 if (newStatus
< statusToReturn
)
8638 statusToReturn
= newStatus
;
8640 InDriverEntry
= FALSE
;
8642 KdPrint2((PRINT_PREFIX
"\n\nLeave ATAPI IDE MiniPort DriverEntry with status %#x\n", statusToReturn
));
8644 return statusToReturn
;
8646 } // end DriverEntry()
8650 BuildMechanismStatusSrb(
8651 IN PVOID HwDeviceExtension
,
8652 IN PSCSI_REQUEST_BLOCK Srb
8655 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8656 PSCSI_REQUEST_BLOCK srb
;
8658 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8660 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
8662 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
8664 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
8665 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
8666 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
8667 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
8669 // Set flags to disable synchronous negociation.
8670 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
8672 // Set timeout to 4 seconds.
8673 srb
->TimeOutValue
= 4;
8676 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
8677 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
8678 srb
->SrbExtension
= AtaReq
;
8680 // Set CDB operation code.
8681 cdb
= (PCDB
)srb
->Cdb
;
8682 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
8683 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
8686 } // end BuildMechanismStatusSrb()
8688 #endif //UNIATA_CORE
8691 BuildRequestSenseSrb (
8692 IN PVOID HwDeviceExtension
,
8693 IN PSCSI_REQUEST_BLOCK Srb
8696 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8697 PSCSI_REQUEST_BLOCK srb
;
8699 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8701 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
8703 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
8705 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
8706 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
8707 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
8708 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
8710 // Set flags to disable synchronous negociation.
8711 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
8713 // Set timeout to 2 seconds.
8714 srb
->TimeOutValue
= 4;
8717 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
8718 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
8719 srb
->SrbExtension
= AtaReq
;
8721 // Set CDB operation code.
8722 cdb
= (PCDB
)srb
->Cdb
;
8723 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
8724 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
8727 } // end BuildRequestSenseSrb()
8732 AtapiRegCheckDevLunValue(
8733 IN PVOID HwDeviceExtension
,
8734 IN PWCHAR NamePrefix
,
8742 ULONG val
= Default
;
8744 val
= AtapiRegCheckParameterValue(
8745 HwDeviceExtension
, NamePrefix
, Name
, val
);
8747 if(chan
!= CHAN_NOT_SPECIFIED
) {
8748 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
8749 val
= AtapiRegCheckParameterValue(
8750 HwDeviceExtension
, namex
, Name
, val
);
8751 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
8752 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
8753 val
= AtapiRegCheckParameterValue(
8754 HwDeviceExtension
, namex
, Name
, val
);
8758 } // end AtapiRegCheckDevLunValue()
8770 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
8789 swprintf(Buffer
+j
, L
"%2.2x", a
);
8797 } // end EncodeVendorStr()
8800 AtapiRegCheckDevValue(
8801 IN PVOID HwDeviceExtension
,
8808 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8810 // WCHAR name1[11+4+5];
8811 // WCHAR name2[11+4+4+10];
8812 // WCHAR name3[11+4+4+5+20];
8813 // WCHAR name3[11+4+4+5+20+1];
8822 IN ULONG SlotNumber
;
8824 ULONG val
= Default
;
8826 KdPrint(( " Parameter %ws\n", Name
));
8828 if(deviceExtension
) {
8829 VendorID
= deviceExtension
->DevID
& 0xffff;
8830 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
8831 SlotNumber
= deviceExtension
->slotNumber
;
8835 SlotNumber
= 0xffffffff;
8838 val
= AtapiRegCheckDevLunValue(
8839 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
8841 if(deviceExtension
) {
8842 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
8844 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
8845 swprintf(namex
, L
"Parameters%s", namev
);
8846 val
= AtapiRegCheckDevLunValue(
8847 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8850 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
8851 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
8852 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
8854 swprintf(namex
, L
"Parameters%s", namev
);
8855 val
= AtapiRegCheckDevLunValue(
8856 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8858 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
8859 val
= AtapiRegCheckDevLunValue(
8860 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8862 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
8863 val
= AtapiRegCheckDevLunValue(
8864 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8866 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
8868 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
8869 swprintf(namex
, L
"Parameters%s", namev
);
8870 val
= AtapiRegCheckDevLunValue(
8871 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8873 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
8874 swprintf(namex
, L
"Parameters%s", namev
);
8875 val
= AtapiRegCheckDevLunValue(
8876 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8879 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
8881 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
8882 swprintf(namex
, L
"Parameters%s", namev
);
8883 val
= AtapiRegCheckDevLunValue(
8884 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8886 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
8887 swprintf(namex
, L
"Parameters%s", namev
);
8888 val
= AtapiRegCheckDevLunValue(
8889 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
8894 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
8897 } // end AtapiRegCheckDevValue()
8900 The user must specify that Xxx is to run on the platform
8901 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
8902 Services\UniATA\Xxx:REG_DWORD:Zzz.
8904 The user can override the global setting to enable or disable Xxx on a
8905 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
8906 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
8908 If this registry value does not exist or contains the value zero then
8909 the timer to check for media change does not run.
8913 RegistryPath - pointer to the unicode string inside
8914 ...\CurrentControlSet\Services\UniATA
8915 DeviceNumber - The number of the HBA device object
8917 Returns: Registry Key value
8920 AtapiRegCheckParameterValue(
8921 IN PVOID HwDeviceExtension
,
8922 IN PWSTR PathSuffix
,
8927 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
8929 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
8931 LONG zero
= Default
;
8933 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
8936 LONG doRun
= Default
;
8938 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
8940 UNICODE_STRING paramPath
;
8942 // <SavedRegPath>\<PathSuffix> -> <Name>
8943 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
8944 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
8946 paramPath
.Length
= 0;
8947 paramPath
.MaximumLength
= RegistryPath
->Length
+ (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
8948 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
8949 if(!paramPath
.Buffer
) {
8950 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
8954 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
8955 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
8956 RtlAppendUnicodeToString(¶mPath
, L
"\\");
8957 RtlAppendUnicodeToString(¶mPath
, PathSuffix
);
8959 // Check for the Xxx value.
8960 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
8962 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
8963 parameters
[0].Name
= Name
;
8964 parameters
[0].EntryContext
= &doRun
;
8965 parameters
[0].DefaultType
= REG_DWORD
;
8966 parameters
[0].DefaultData
= &zero
;
8967 parameters
[0].DefaultLength
= sizeof(ULONG
);
8969 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
8970 paramPath
.Buffer
, parameters
, NULL
, NULL
);
8971 //KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun));
8973 ExFreePool(paramPath
.Buffer
);
8975 if(!NT_SUCCESS(status
)) {
8981 #undef ITEMS_TO_QUERY
8983 } // end AtapiRegCheckParameterValue()
8986 SCSI_ADAPTER_CONTROL_STATUS
8988 AtapiAdapterControl(
8989 IN PVOID HwDeviceExtension
,
8990 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
8994 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8995 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
8996 ULONG numberChannels
= deviceExtension
->NumberChannels
;
9000 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
9002 switch(ControlType
) {
9003 case ScsiQuerySupportedControlTypes
: {
9004 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
9005 TRUE
, // ScsiQuerySupportedControlTypes
9006 TRUE
, // ScsiStopAdapter
9007 TRUE
, // ScsiRestartAdapter
9008 FALSE
, // ScsiSetBootConfig
9009 FALSE
// ScsiSetRunningConfig
9012 ULONG lim
= ScsiAdapterControlMax
;
9015 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
9017 if(pControlTypeList
->MaxControlType
< lim
) {
9018 lim
= pControlTypeList
->MaxControlType
;
9021 for(i
= 0; i
< lim
; i
++) {
9022 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
9028 case ScsiStopAdapter
: {
9030 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
9031 // Shut down all interrupts on the adapter. They'll get re-enabled
9032 // by the initialization routines.
9033 for (c
= 0; c
< numberChannels
; c
++) {
9034 AtapiResetController(deviceExtension
, c
);
9035 AtapiDisableInterrupts(deviceExtension
, c
);
9037 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
9038 // we must never get here for non-PCI
9039 status
= UniataDisconnectIntr2(HwDeviceExtension
);
9040 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
9044 case ScsiRestartAdapter
: {
9046 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
9047 // Enable all the interrupts on the adapter while port driver call
9048 // for power up an HBA that was shut down for power management
9050 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
9051 status
= UniataConnectIntr2(HwDeviceExtension
);
9052 for (c
= 0; c
< numberChannels
; c
++) {
9053 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
9054 FindDevices(HwDeviceExtension
, FALSE
, c
);
9055 AtapiEnableInterrupts(deviceExtension
, c
);
9056 AtapiHwInitialize__(deviceExtension
, c
);
9058 if(deviceExtension
->Isr2DevObj
) {
9059 // we must never get here for non-PCI
9060 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
9067 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
9068 return ScsiAdapterControlUnsuccessful
;
9072 return ScsiAdapterControlSuccess
;
9073 } // end AtapiAdapterControl()
9075 #endif //UNIATA_CORE
9094 UCHAR dbg_print_tmp_buff
[512];
9095 // UNICODE_STRING msgBuff;
9097 va_start(ap
, DebugMessage
);
9099 len
= _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], 511, DebugMessage
, ap
);
9101 dbg_print_tmp_buff
[511] = 0;
9103 HalDisplayString(dbg_print_tmp_buff
);
9107 } // end PrintNtConsole()