3 Copyright (c) 2002-2015 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 significantly changed/updated by
41 Alter, Copyright (c) 2002-2014:
43 1. Internal command queueing/reordering
44 2. Drive identification
45 3. Support for 2 _independent_ channels in a single PCI device
46 4. Smart host<->drive transfer rate slowdown (for bad cable)
47 5. W2k support (binary compatibility)
48 6. HDD hot swap under NT4
49 7. XP support (binary compatibility)
50 8. Serial ATA (SATA/SATA2/SATA3) support
51 9. NT 3.51 support (binary compatibility)
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 ULONG g_opt_WaitBusyCount
= 200; // 20000
87 ULONG g_opt_WaitBusyDelay
= 10; // 150
88 ULONG g_opt_WaitDrqDelay
= 10; // 100
89 ULONG g_opt_WaitBusyLongCount
= 2000; // 2000
90 ULONG g_opt_WaitBusyLongDelay
= 250; // 250
91 ULONG g_opt_MaxIsrWait
= 40; //
92 BOOLEAN g_opt_AtapiSendDisableIntr
= 0; // 0
93 BOOLEAN g_opt_AtapiDmaRawRead
= 1; // 0
94 BOOLEAN hasPCI
= FALSE
;
96 ULONG g_opt_VirtualMachine
= 0; // Auto
98 BOOLEAN InDriverEntry
= TRUE
;
100 BOOLEAN g_opt_Verbose
= 0;
102 BOOLEAN WinVer_WDM_Model
= FALSE
;
104 //UCHAR EnableDma = FALSE;
105 //UCHAR EnableReorder = FALSE;
111 AtapiResetController__(
112 IN PVOID HwDeviceExtension
,
114 IN UCHAR CompleteType
120 IN PHW_DEVICE_EXTENSION deviceExtension
,
126 UniataUserDeviceReset(
127 PHW_DEVICE_EXTENSION deviceExtension
,
128 PHW_LU_EXTENSION LunExt
,
132 #define RESET_COMPLETE_CURRENT 0x00
133 #define RESET_COMPLETE_ALL 0x01
134 #define RESET_COMPLETE_NONE 0x02
141 IN PVOID HwDeviceExtension
144 #ifdef UNIATA_USE_XXableInterrupts
145 #define RETTYPE_XXableInterrupts BOOLEAN
146 #define RETVAL_XXableInterrupts TRUE
148 #define RETTYPE_XXableInterrupts VOID
149 #define RETVAL_XXableInterrupts
152 RETTYPE_XXableInterrupts
155 IN PVOID HwDeviceExtension
158 RETTYPE_XXableInterrupts
160 AtapiEnableInterrupts__(
161 IN PVOID HwDeviceExtension
167 IN PVOID HwDeviceExtension
,
169 IN PHW_TIMER HwScsiTimer
,
170 IN ULONG MiniportTimerValue
173 SCSI_ADAPTER_CONTROL_STATUS
176 IN PVOID HwDeviceExtension
,
177 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
187 AtapiRegGetStringParameterValue(
188 IN PWSTR RegistryPath
,
194 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
196 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
201 ustr
.MaximumLength
= (USHORT
)MaxLen
;
202 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
204 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
205 parameters
[0].Name
= Name
;
206 parameters
[0].EntryContext
= &ustr
;
207 parameters
[0].DefaultType
= REG_SZ
;
208 parameters
[0].DefaultData
= Str
;
209 parameters
[0].DefaultLength
= MaxLen
;
211 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
212 RegistryPath
, parameters
, NULL
, NULL
);
214 if(!NT_SUCCESS(status
))
219 #undef ITEMS_TO_QUERY
220 } // end AtapiRegGetStringParameterValue()
238 if(!nano
|| !g_Perf
|| !g_PerfDt
)
240 t
= (g_Perf
* nano
) / g_PerfDt
/ 1000;
245 KeQuerySystemTime(&t0
);
248 } // end UniataNanoSleep()
250 #define AtapiWritePortN_template(_type, _Type, sz) \
253 AtapiWritePort##sz( \
254 IN PHW_CHANNEL chan, \
255 IN ULONGIO_PTR _port, \
260 if(_port >= IDX_MAX_REG) { \
261 res = (PIORES)(_port); \
264 res = &chan->RegTranslation[_port]; \
266 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
272 ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
274 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
275 ScsiPortWriteRegister##_Type((_type*)(res->Addr), data); \
280 AtapiWritePortN_template(ULONG
, Ulong
, 4);
281 AtapiWritePortN_template(USHORT
, Ushort
, 2);
282 AtapiWritePortN_template(UCHAR
, Uchar
, 1);
284 #define AtapiWritePortExN_template(_type, _Type, sz) \
287 AtapiWritePortEx##sz( \
288 IN PHW_CHANNEL chan, \
289 IN ULONGIO_PTR _port, \
295 if(_port >= IDX_MAX_REG) { \
296 res = (PIORES)(_port); \
299 res = &chan->RegTranslation[_port]; \
301 KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
307 ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
309 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
310 ScsiPortWriteRegister##_Type((_type*)(res->Addr+offs), data); \
315 AtapiWritePortExN_template(ULONG
, Ulong
, 4);
316 //AtapiWritePortExN_template(USHORT, Ushort, 2);
317 AtapiWritePortExN_template(UCHAR
, Uchar
, 1);
319 #define AtapiReadPortN_template(_type, _Type, sz) \
323 IN PHW_CHANNEL chan, \
324 IN ULONGIO_PTR _port \
328 if(_port >= IDX_MAX_REG) { \
329 res = (PIORES)(_port); \
332 res = &chan->RegTranslation[_port]; \
334 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
335 return (_type)(-1); \
341 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
342 return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
344 /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
345 return ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
349 AtapiReadPortN_template(ULONG
, Ulong
, 4);
350 AtapiReadPortN_template(USHORT
, Ushort
, 2);
351 AtapiReadPortN_template(UCHAR
, Uchar
, 1);
353 #define AtapiReadPortExN_template(_type, _Type, sz) \
356 AtapiReadPortEx##sz( \
357 IN PHW_CHANNEL chan, \
358 IN ULONGIO_PTR _port, \
363 if(_port >= IDX_MAX_REG) { \
364 res = (PIORES)(_port); \
367 res = &chan->RegTranslation[_port]; \
369 KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
370 return (_type)(-1); \
376 return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
378 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
379 return ScsiPortReadRegister##_Type((_type*)(res->Addr+offs)); \
383 AtapiReadPortExN_template(ULONG
, Ulong
, 4);
384 //AtapiReadPortExN_template(USHORT, Ushort, 2);
385 AtapiReadPortExN_template(UCHAR
, Uchar
, 1);
387 #define AtapiReadPortBufferN_template(_type, _Type, sz) \
390 AtapiReadBuffer##sz( \
391 IN PHW_CHANNEL chan, \
392 IN ULONGIO_PTR _port, \
402 (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
404 Buffer = ((_type*)Buffer)+1; \
405 UniataNanoSleep(Timing); \
410 if(_port >= IDX_MAX_REG) { \
411 res = (PIORES)(_port); \
414 res = &chan->RegTranslation[_port]; \
416 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
420 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
421 ScsiPortReadPortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
425 (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
427 Buffer = ((_type*)Buffer)+1; \
432 #define AtapiWritePortBufferN_template(_type, _Type, sz) \
435 AtapiWriteBuffer##sz( \
436 IN PHW_CHANNEL chan, \
437 IN ULONGIO_PTR _port, \
447 AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
448 Buffer = ((_type*)Buffer)+1; \
450 UniataNanoSleep(Timing); \
455 if(_port >= IDX_MAX_REG) { \
456 res = (PIORES)(_port); \
459 res = &chan->RegTranslation[_port]; \
461 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
465 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
466 ScsiPortWritePortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
470 ScsiPortWriteRegister##_Type((_type*)(res->Addr), *((_type*)Buffer)); \
472 Buffer = ((_type*)Buffer)+1; \
477 AtapiWritePortBufferN_template(ULONG
, Ulong
, 4);
478 AtapiWritePortBufferN_template(USHORT
, Ushort
, 2);
480 AtapiReadPortBufferN_template(ULONG
, Ulong
, 4);
481 AtapiReadPortBufferN_template(USHORT
, Ushort
, 2);
493 // Assume, proper drive is already seleted
494 WaitOnBusyLong(chan
);
495 for (i
= 0; i
< 0x10000; i
++) {
497 GetStatus(chan
, statusByte
);
498 if (statusByte
& IDE_STATUS_DRQ
) {
499 // Suck out any remaining bytes and throw away.
500 AtapiReadPort2(chan
, IDX_IO1_i_Data
);
501 UniataNanoSleep(PIO0_TIMING
);
507 KdPrint2((PRINT_PREFIX
"AtapiSuckPort2: overrun detected (%#x words)\n", i
));
510 } // AtapiSuckPort2()
514 AtapiSuckPortBuffer2(
523 BOOLEAN retry
= FALSE
;
525 // Assume, proper drive is already seleted
526 WaitOnBusyLong(chan
);
527 for (i
= 0; i
< Count
; i
++) {
529 GetStatus(chan
, statusByte
);
530 if (statusByte
& IDE_STATUS_DRQ
) {
531 // Suck out any remaining bytes and throw away.
532 data
= AtapiReadPort2(chan
, IDX_IO1_i_Data
);
536 UniataNanoSleep(PIO0_TIMING
);
539 if(i
<Count
&& !retry
) {
540 KdPrint2((PRINT_PREFIX
" wait...\n"));
548 KdPrint2((PRINT_PREFIX
"AtapiSuckPortBuffer2: %#x words\n", i
));
550 AtapiSuckPort2(chan
);
554 } // AtapiSuckPortBuffer2()
565 GetStatus(chan
, Status
);
566 for (i
=0; i
<g_opt_WaitBusyCount
; i
++) {
567 if (Status
& IDE_STATUS_BUSY
) {
568 AtapiStallExecution(g_opt_WaitBusyDelay
);
569 GetStatus(chan
, Status
);
576 } // end WaitOnBusy()
587 Status
= WaitOnBusy(chan
);
588 if(!(Status
& IDE_STATUS_BUSY
))
590 for (i
=0; i
<g_opt_WaitBusyLongCount
; i
++) {
591 GetStatus(chan
, Status
);
592 if (Status
& IDE_STATUS_BUSY
) {
593 AtapiStallExecution(g_opt_WaitBusyLongDelay
);
600 } // end WaitOnBusyLong()
609 UCHAR Status
= IDE_STATUS_WRONG
;
610 for (i
=0; i
<g_opt_WaitBusyCount
; i
++) {
611 GetBaseStatus(chan
, Status
);
612 if (Status
& IDE_STATUS_BUSY
) {
613 AtapiStallExecution(g_opt_WaitBusyDelay
);
620 } // end WaitOnBaseBusy()
631 Status
= WaitOnBaseBusy(chan
);
632 if(!(Status
& IDE_STATUS_BUSY
))
634 for (i
=0; i
<2000; i
++) {
635 GetBaseStatus(chan
, Status
);
636 if (Status
& IDE_STATUS_BUSY
) {
637 AtapiStallExecution(250);
644 } // end WaitOnBaseBusyLong()
649 IN
struct _HW_DEVICE_EXTENSION
* deviceExtension
,
655 if(Status
== IDE_STATUS_WRONG
) {
656 return IDE_STATUS_WRONG
;
658 if(Status
& IDE_STATUS_BUSY
) {
661 // if(deviceExtension->HwFlags & UNIATA_SATA) {
662 if(UniataIsSATARangeAvailable(deviceExtension
, 0)) {
663 if(Status
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
667 Status2
= Status
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
);
668 if ((Status
& IDE_STATUS_BUSY
) ||
669 (Status2
!= IDE_STATUS_IDLE
&& Status2
!= IDE_STATUS_DRDY
)) {
673 return IDE_STATUS_IDLE
;
674 } // end UniataIsIdle()
685 for (i
=0; i
<20000; i
++) {
686 GetStatus(chan
, Status
);
687 Status2
= UniataIsIdle(chan
->DeviceExtension
, Status
);
688 if(Status2
== IDE_STATUS_WRONG
) {
692 if(Status2
& IDE_STATUS_BUSY
) {
693 AtapiStallExecution(10);
700 } // end WaitForIdleLong()
710 for (i
=0; i
<1000; i
++) {
711 GetStatus(chan
, Status
);
712 if (Status
& IDE_STATUS_BUSY
) {
713 AtapiStallExecution(g_opt_WaitDrqDelay
);
714 } else if (Status
& IDE_STATUS_DRQ
) {
717 AtapiStallExecution(g_opt_WaitDrqDelay
*2);
721 } // end WaitForDrq()
731 for (i
=0; i
<2; i
++) {
732 GetStatus(chan
, Status
);
733 if (Status
& IDE_STATUS_BUSY
) {
734 AtapiStallExecution(g_opt_WaitDrqDelay
);
735 } else if (Status
& IDE_STATUS_DRQ
) {
738 AtapiStallExecution(g_opt_WaitDrqDelay
);
742 } // end WaitShortForDrq()
751 //ULONG c = chan->lChannel;
753 UCHAR dma_status
= 0;
754 KdPrint2((PRINT_PREFIX
"AtapiSoftReset:\n"));
757 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
758 UniataAhciSoftReset(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
);
762 GetBaseStatus(chan
, statusByte2
);
763 KdPrint2((PRINT_PREFIX
" statusByte2 %x:\n", statusByte2
));
764 SelectDrive(chan
, DeviceNumber
);
765 if(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
767 AtapiStallExecution(10000);
768 for (i
= 0; i
< 1000; i
++) {
769 AtapiStallExecution(999);
772 AtapiStallExecution(500);
773 GetBaseStatus(chan
, statusByte2
);
774 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_RESET
);
776 // Do not wait for BUSY assertion if it was initially set, jump to
777 // BUSY release wait loop
778 if(!(statusByte2
& IDE_STATUS_BUSY
)) {
779 // Wait for BUSY assertion, in some cases delay may occure
780 // 100ms should be enough
782 while (!(AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
785 AtapiStallExecution(10);
790 // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
791 // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
792 // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
793 // implementation. (which is around 1 second)
794 while ((AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
797 AtapiStallExecution(30);
801 SelectDrive(chan
, DeviceNumber
);
803 GetBaseStatus(chan
, statusByte2
);
804 AtapiStallExecution(500);
806 GetBaseStatus(chan
, statusByte2
);
807 if(chan
&& chan
->DeviceExtension
) {
808 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
809 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
811 KdPrint2((PRINT_PREFIX
" can't get DMA status\n"));
813 if(dma_status
& BM_STATUS_INTR
) {
814 // bullshit, we have DMA interrupt, but had never initiate DMA operation
815 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr on ATAPI reset\n"));
816 AtapiDmaDone(chan
->DeviceExtension
, DeviceNumber
, chan
->lChannel
, NULL
);
817 GetBaseStatus(chan
, statusByte2
);
819 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
820 UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, DeviceNumber
);
821 /* if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
822 UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1);
827 } // end AtapiSoftReset()
830 Send command to device.
831 Translate to 48-Lba form if required
836 IN PHW_DEVICE_EXTENSION deviceExtension
,
837 IN ULONG DeviceNumber
,
846 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
851 KdPrint2((PRINT_PREFIX
"AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
852 deviceExtension
->DevIndex
, deviceExtension
->Channel
, DeviceNumber
, command
, lba
, count
, feature
));
854 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
855 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
857 KdPrint3((" (ahci)\n"));
859 statusByte
= UniataAhciSendPIOCommand(deviceExtension
, lChannel
, DeviceNumber
,
860 (PSCSI_REQUEST_BLOCK
)NULL
,
868 1000 /* timeout 1 sec */
874 SelectDrive(chan
, DeviceNumber
);
876 statusByte
= WaitOnBusy(chan
);
878 /* ready to issue command ? */
879 if (statusByte
& IDE_STATUS_BUSY
) {
880 KdPrint2((PRINT_PREFIX
" Returning BUSY status\n"));
883 // !!! We should not check ERROR condition here
884 // ERROR bit may be asserted durring previous operation
885 // and not cleared after SELECT
887 //>>>>>> NV: 2006/08/03
888 if(((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
|ATA_CMD_FLAG_FUA
)) == ATA_CMD_FLAG_LBAIOsupp
) &&
889 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
890 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
891 return IDE_STATUS_ERROR
;
892 //return SRB_STATUS_ERROR;
894 //<<<<<< NV: 2006/08/03
896 /* only use 48bit addressing if needed because of the overhead */
897 if (UniAta_need_lba48(command
, lba
, count
,
898 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
)) {
900 KdPrint2((PRINT_PREFIX
" dev %#x USE_LBA_48\n", DeviceNumber
));
901 /* translate command into 48bit version */
902 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
903 command
= AtaCommands48
[command
];
905 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
909 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
912 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)(feature
>>8));
913 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
914 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)(count
>>8));
915 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
916 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[3]));
917 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[0]));
918 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[4]));
919 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[1]));
920 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[5]));
921 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[2]));
923 //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber ));
924 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
) );
927 plba
= (PUCHAR
)&lba
; //ktp
928 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
931 // (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
932 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
934 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
935 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)plba
[0]);
936 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)plba
[1]);
937 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)plba
[2]);
938 if(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
939 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber ));
940 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
942 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber ));
943 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
947 // write command code to device
948 AtapiWritePort1(chan
, IDX_IO1_o_Command
, command
);
950 switch (wait_flags
) {
953 // caller requested wait for interrupt
956 statusByte
= WaitForDrq(chan
);
957 if (statusByte
& IDE_STATUS_DRQ
)
959 AtapiStallExecution(500);
960 KdPrint2((PRINT_PREFIX
" retry waiting DRQ, status %#x\n", statusByte
));
967 // caller requested wait for entering Wait state
968 for (i
=0; i
<30 * 1000; i
++) {
970 GetStatus(chan
, statusByte
);
971 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
972 if(statusByte
== IDE_STATUS_WRONG
) {
976 if(statusByte
& IDE_STATUS_ERROR
) {
979 if(statusByte
& IDE_STATUS_BUSY
) {
980 AtapiStallExecution(100);
983 if(statusByte
== IDE_STATUS_IDLE
) {
986 //if(deviceExtension->HwFlags & UNIATA_SATA) {
987 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
990 AtapiStallExecution(100);
993 //statusByte |= IDE_STATUS_BUSY;
997 statusByte
= WaitOnBusyLong(chan
);
999 case ATA_WAIT_BASE_READY
:
1000 statusByte
= WaitOnBaseBusyLong(chan
);
1003 GetStatus(chan
, statusByte
);
1004 if (statusByte
& IDE_STATUS_ERROR
) {
1005 KdPrint2((PRINT_PREFIX
" Warning: Immed Status %#x :(\n", statusByte
));
1006 if(statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_ERROR
)) {
1009 KdPrint2((PRINT_PREFIX
" try to continue\n"));
1010 statusByte
&= ~IDE_STATUS_ERROR
;
1012 UniataExpectChannelInterrupt(chan
, TRUE
);
1014 InterlockedExchange(&(chan
->CheckIntr
),
1020 KdPrint2((PRINT_PREFIX
" Status %#x\n", statusByte
));
1023 } // end AtaCommand48()
1026 Send command to device.
1027 This is simply wrapper for AtaCommand48()
1032 IN PHW_DEVICE_EXTENSION deviceExtension
,
1033 IN ULONG DeviceNumber
,
1044 if(!(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
1045 return AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1047 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
1048 count
, feature
, wait_flags
);
1050 return UniataAhciSendPIOCommand(deviceExtension
, lChannel
, DeviceNumber
,
1051 (PSCSI_REQUEST_BLOCK
)NULL
,
1055 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
1058 0 /* ahci flags */ ,
1060 1000 /* timeout 1 sec */
1064 } // end AtaCommand()
1068 AtaPio2Mode(LONG pio
)
1071 default: return ATA_PIO
;
1072 case 0: return ATA_PIO0
;
1073 case 1: return ATA_PIO1
;
1074 case 2: return ATA_PIO2
;
1075 case 3: return ATA_PIO3
;
1076 case 4: return ATA_PIO4
;
1077 case 5: return ATA_PIO5
;
1079 } // end AtaPio2Mode()
1083 AtaPioMode(PIDENTIFY_DATA2 ident
)
1085 if (ident
->PioTimingsValid
) {
1086 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_5
)
1088 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_4
)
1090 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_3
)
1093 if (ident
->PioCycleTimingMode
== 2)
1095 if (ident
->PioCycleTimingMode
== 1)
1097 if (ident
->PioCycleTimingMode
== 0)
1099 return IOMODE_NOT_SPECIFIED
;
1100 } // end AtaPioMode()
1104 AtaWmode(PIDENTIFY_DATA2 ident
)
1106 if (ident
->MultiWordDMASupport
& 0x04)
1108 if (ident
->MultiWordDMASupport
& 0x02)
1110 if (ident
->MultiWordDMASupport
& 0x01)
1112 return IOMODE_NOT_SPECIFIED
;
1117 AtaUmode(PIDENTIFY_DATA2 ident
)
1119 if (!ident
->UdmaModesValid
)
1120 return IOMODE_NOT_SPECIFIED
;
1121 if (ident
->UltraDMASupport
& 0x40)
1123 if (ident
->UltraDMASupport
& 0x20)
1125 if (ident
->UltraDMASupport
& 0x10)
1127 if (ident
->UltraDMASupport
& 0x08)
1129 if (ident
->UltraDMASupport
& 0x04)
1131 if (ident
->UltraDMASupport
& 0x02)
1133 if (ident
->UltraDMASupport
& 0x01)
1135 return IOMODE_NOT_SPECIFIED
;
1140 AtaSAmode(PIDENTIFY_DATA2 ident
) {
1141 if(!ident
->SataCapabilities
||
1142 ident
->SataCapabilities
== 0xffff) {
1143 return IOMODE_NOT_SPECIFIED
;
1145 if(ident
->SataCapabilities
& ATA_SATA_GEN3
) {
1148 if(ident
->SataCapabilities
& ATA_SATA_GEN2
) {
1151 if(ident
->SataCapabilities
& ATA_SATA_GEN1
) {
1154 return IOMODE_NOT_SPECIFIED
;
1155 } // end AtaSAmode()
1162 IN PVOID HwDeviceExtension
1165 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1166 PHW_TIMER HwScsiTimer
;
1168 ULONG MiniportTimerValue
;
1169 BOOLEAN recall
= FALSE
;
1173 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc:\n"));
1175 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1176 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1177 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no items\n"));
1180 chan
= &(deviceExtension
->chan
[lChannel
]);
1184 HwScsiTimer
= chan
->HwScsiTimer
;
1185 chan
->HwScsiTimer
= NULL
;
1187 deviceExtension
->FirstDpcChan
= chan
->NextDpcChan
;
1188 if(deviceExtension
->FirstDpcChan
!= CHAN_NOT_SPECIFIED
) {
1192 HwScsiTimer(HwDeviceExtension
);
1194 chan
->NextDpcChan
= CHAN_NOT_SPECIFIED
;
1196 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1197 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1198 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no more items\n"));
1199 deviceExtension
->FirstDpcChan
=
1200 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1204 KeQuerySystemTime(&time
);
1205 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1207 chan
= &deviceExtension
->chan
[lChannel
];
1208 if(time
.QuadPart
>= chan
->DpcTime
- 10) {
1210 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1211 (ULONG
)(chan
->DpcTime
>> 32), (ULONG
)(chan
->DpcTime
)));
1218 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1219 MiniportTimerValue
= (ULONG
)(time
.QuadPart
- chan
->DpcTime
)/10;
1220 if(!MiniportTimerValue
)
1221 MiniportTimerValue
= 1;
1223 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: recall AtapiTimerDpc\n"));
1224 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1231 } // end AtapiTimerDpc()
1234 Wrapper for ScsiPort, that implements smart Dpc
1235 queueing. We need it to allow parallel functioning
1236 of IDE channles with shared interrupt. Standard Dpc mechanism
1237 cancels previous Dpc request (if any), but we need Dpc queue.
1242 IN PVOID HwDeviceExtension
,
1244 IN PHW_TIMER HwScsiTimer
,
1245 IN ULONG MiniportTimerValue
1248 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1250 LARGE_INTEGER time2
;
1252 PHW_CHANNEL prev_chan
;
1254 // BOOLEAN UseRequestTimerCall = TRUE;
1256 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1257 KeQuerySystemTime(&time
);
1259 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1260 time
.QuadPart
+= MiniportTimerValue
*10;
1261 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1263 KdPrint2((PRINT_PREFIX
" ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension
->ActiveDpcChan
, deviceExtension
->FirstDpcChan
));
1265 i
= deviceExtension
->FirstDpcChan
;
1266 chan
= prev_chan
= NULL
;
1267 while(i
!= CHAN_NOT_SPECIFIED
) {
1269 chan
= &(deviceExtension
->chan
[i
]);
1270 if(chan
->DpcTime
> time
.QuadPart
) {
1273 i
= chan
->NextDpcChan
;
1275 chan
= &(deviceExtension
->chan
[lChannel
]);
1277 deviceExtension
->FirstDpcChan
= lChannel
;
1279 prev_chan
->NextDpcChan
= lChannel
;
1281 chan
->NextDpcChan
= i
;
1282 chan
->HwScsiTimer
= HwScsiTimer
;
1283 chan
->DpcTime
= time
.QuadPart
;
1285 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2
.HighPart
, time2
.LowPart
));
1286 if(time
.QuadPart
<= time2
.QuadPart
) {
1287 MiniportTimerValue
= 1;
1289 MiniportTimerValue
= (ULONG
)((time
.QuadPart
- time2
.QuadPart
) / 10);
1292 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1293 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1295 MiniportTimerValue
);
1297 } // end AtapiQueueTimerDpc()
1299 #endif //UNIATA_CORE
1309 UCHAR statusByteAlt
;
1311 GetStatus(chan
, statusByteAlt
);
1312 KdPrint2((PRINT_PREFIX
" AltStatus (%#x)\n", statusByteAlt
));
1314 for(j
=1; j
<IDX_IO1_SZ
; j
++) {
1315 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1316 KdPrint2((PRINT_PREFIX
1317 " Reg_%#x (%#x) = %#x\n",
1319 chan
->RegTranslation
[IDX_IO1
+j
].Addr
,
1322 for(j
=0; j
<IDX_BM_IO_SZ
-1; j
++) {
1323 statusByteAlt
= AtapiReadPort1(chan
, IDX_BM_IO
+j
);
1324 KdPrint2((PRINT_PREFIX
1325 " BM_%#x (%#x) = %#x\n",
1327 chan
->RegTranslation
[IDX_BM_IO
+j
].Addr
,
1331 } // end UniataDumpATARegs()
1337 IN PHW_CHANNEL chan
,
1338 IN ULONG DeviceNumber
,
1339 IN OUT PIDEREGS_EX regs
1342 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
1344 UniataAhciSnapAtaRegs(chan
, DeviceNumber
, regs
);
1346 // SATA/PATA, assume drive is selected
1348 UCHAR statusByteAlt
;
1350 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) {
1351 for(j
=IDX_IO1_i_Error
; j
<=IDX_IO1_i_Status
; j
++) {
1352 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1353 ((PUCHAR
)regs
)[j
-1] = statusByteAlt
;
1357 regs
->bDriveHeadReg
= AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
);
1358 for(j
=IDX_IO1_i_Error
; j
<IDX_IO1_i_DriveSelect
; j
++) {
1359 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1360 ((PUCHAR
)regs
)[j
-1] = statusByteAlt
;
1361 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1362 ((PUCHAR
)regs
)[j
+8-1] = statusByteAlt
;
1364 regs
->bCommandReg
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
1368 } // end UniataSnapAtaRegs()
1372 Routine Description:
1374 Issue IDENTIFY command to a device.
1378 HwDeviceExtension - HBA miniport driver's adapter data storage
1379 DeviceNumber - Indicates which device.
1380 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1384 TRUE if all goes well.
1390 IN PVOID HwDeviceExtension
,
1391 IN ULONG DeviceNumber
,
1397 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1398 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
1399 ULONG waitCount
= 50000;
1402 //UCHAR statusByte2;
1405 BOOLEAN atapiDev
= FALSE
;
1406 BOOLEAN use_ahci
= FALSE
;
1407 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
1409 use_ahci
= UniataIsSATARangeAvailable(deviceExtension
, lChannel
) &&
1410 (deviceExtension
->HwFlags
& UNIATA_AHCI
);
1412 if(chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) {
1413 if(chan
->PmLunMap
& (1 << DeviceNumber
)) {
1416 KdPrint2((PRINT_PREFIX
"IssueIdentify: PM empty port\n"));
1420 if(DeviceNumber
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
1421 KdPrint2((PRINT_PREFIX
"IssueIdentify: NO SLAVE\n"));
1424 if(LunExt
->DeviceFlags
& DFLAGS_HIDDEN
) {
1425 KdPrint2((PRINT_PREFIX
"IssueIdentify: HIDDEN\n"));
1430 statusByte
= WaitOnBusyLong(chan
);
1432 if(!chan
->AhciInternalAtaReq
) {
1433 KdPrint2((PRINT_PREFIX
"!AhciInternalAtaReq\n"));
1437 SelectDrive(chan
, DeviceNumber
);
1438 AtapiStallExecution(10);
1439 statusByte
= WaitOnBusyLong(chan
);
1440 // Check that the status register makes sense.
1441 GetBaseStatus(chan
, statusByte
);
1444 if (Command
== IDE_COMMAND_IDENTIFY
) {
1445 // Mask status byte ERROR bits.
1446 statusByte
= UniataIsIdle(deviceExtension
, statusByte
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
));
1447 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte
));
1448 // Check if register value is reasonable.
1450 if(statusByte
!= IDE_STATUS_IDLE
) {
1452 // No reset here !!!
1453 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1455 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1456 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1457 SelectDrive(chan
, DeviceNumber
);
1458 WaitOnBusyLong(chan
);
1460 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1461 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1463 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1464 signatureHigh
== ATAPI_MAGIC_MSB
) {
1466 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber
));
1470 // We really should wait up to 31 seconds
1471 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1472 // (30 seconds for device 1)
1474 // Wait for Busy to drop.
1475 AtapiStallExecution(100);
1476 GetStatus(chan
, statusByte
);
1477 if(statusByte
== IDE_STATUS_WRONG
) {
1478 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_WRONG (dev %d)\n", DeviceNumber
));
1482 } while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
--);
1483 GetBaseStatus(chan
, statusByte
);
1485 SelectDrive(chan
, DeviceNumber
);
1487 GetBaseStatus(chan
, statusByte
);
1489 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1491 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1492 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1494 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1495 signatureHigh
== ATAPI_MAGIC_MSB
) {
1496 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber
));
1501 statusByte
= UniataIsIdle(deviceExtension
, statusByte
) & ~IDE_STATUS_INDEX
;
1502 if (statusByte
!= IDE_STATUS_IDLE
) {
1504 KdPrint2((PRINT_PREFIX
"IssueIdentify: no dev (dev %d)\n", DeviceNumber
));
1509 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte
));
1510 if(statusByte
== IDE_STATUS_WRONG
) {
1513 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1514 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1515 statusByte
= WaitForIdleLong(chan
);
1516 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte
));
1521 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1523 statusByte
= UniataAhciSendPIOCommand(HwDeviceExtension
, lChannel
, DeviceNumber
,
1524 (PSCSI_REQUEST_BLOCK
)NULL
,
1525 (PUCHAR
)(&deviceExtension
->FullIdentifyData
),
1530 0 /* ahci flags */ ,
1532 1000 /* timeout 1 sec */
1534 j
= 9; // AHCI is rather different, skip loop at all
1536 if(LunExt
->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
1537 j
= 9; // don't send IDENTIFY, assume it is not supported
1538 KdPrint2((PRINT_PREFIX
"IssueIdentify: Manual CHS\n"));
1539 RtlZeroMemory(&(deviceExtension
->FullIdentifyData
), sizeof(deviceExtension
->FullIdentifyData
));
1540 RtlCopyMemory(&(deviceExtension
->FullIdentifyData
), &(LunExt
->IdentifyData
), sizeof(LunExt
->IdentifyData
));
1542 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1543 j
= 4; // skip old-style checks
1547 for (; j
< 4*2; j
++) {
1548 // Send IDENTIFY command.
1550 // Load CylinderHigh and CylinderLow with number bytes to transfer for old devices, use 0 for newer.
1552 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, Command
, (j
< 4) ? DEV_BSIZE
: 0 /* cyl */, 0, 0, 0, 0, ATA_WAIT_INTR
);
1555 if (statusByte
& IDE_STATUS_DRQ
) {
1556 // Read status to acknowledge any interrupts generated.
1557 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte
));
1558 GetBaseStatus(chan
, statusByte
);
1559 // One last check for Atapi.
1560 if (Command
== IDE_COMMAND_IDENTIFY
) {
1561 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1562 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1564 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1565 signatureHigh
== ATAPI_MAGIC_MSB
) {
1566 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber
));
1573 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte
));
1574 if (Command
== IDE_COMMAND_IDENTIFY
) {
1575 // Check the signature. If DRQ didn't come up it's likely Atapi.
1576 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1577 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1579 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1580 signatureHigh
== ATAPI_MAGIC_MSB
) {
1582 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber
));
1586 if(!(statusByte
& IDE_STATUS_ERROR
) && (statusByte
& IDE_STATUS_BUSY
)) {
1587 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n"));
1591 // Device didn't respond correctly. It will be given one more chance.
1592 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1593 statusByte
, AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
1594 GetBaseStatus(chan
, statusByte
);
1595 AtapiSoftReset(chan
,DeviceNumber
);
1597 AtapiDisableInterrupts(deviceExtension
, lChannel
);
1598 AtapiEnableInterrupts(deviceExtension
, lChannel
);
1600 GetBaseStatus(chan
, statusByte
);
1601 //GetStatus(chan, statusByte);
1602 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after soft reset (%#x)\n", statusByte
));
1605 // Check for error on really stupid master devices that assert random
1606 // patterns of bits in the status register at the slave address.
1607 if ((Command
== IDE_COMMAND_IDENTIFY
) && (statusByte
& IDE_STATUS_ERROR
)) {
1608 KdPrint2((PRINT_PREFIX
"IssueIdentify: Exit on error (%#x)\n", statusByte
));
1613 // everything should already be done by controller
1615 if(LunExt
->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
1616 j
= 9; // don't send IDENTIFY, assume it is not supported
1617 KdPrint2((PRINT_PREFIX
"IssueIdentify: Manual CHS (2)\n"));
1618 statusByte
= WaitForDrq(chan
);
1619 statusByte
= WaitOnBusyLong(chan
);
1620 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1621 GetBaseStatus(chan
, statusByte
);
1624 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status before read words %#x\n", statusByte
));
1625 // Suck out 256 words. After waiting for one model that asserts busy
1626 // after receiving the Packet Identify command.
1627 statusByte
= WaitForDrq(chan
);
1628 statusByte
= WaitOnBusyLong(chan
);
1629 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1631 if (!(statusByte
& IDE_STATUS_DRQ
)) {
1632 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte
));
1633 GetBaseStatus(chan
, statusByte
);
1636 GetBaseStatus(chan
, statusByte
);
1637 KdPrint2((PRINT_PREFIX
"IssueIdentify: BASE statusByte %#x\n", statusByte
));
1639 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
1641 KdPrint2((PRINT_PREFIX
" use 16bit IO\n"));
1644 j
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
1645 KdPrint3((PRINT_PREFIX
"IssueIdentify: iReason %x\n", j
));
1648 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
1651 (USHORT
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
1652 KdPrint3((PRINT_PREFIX
"IssueIdentify: wCount %x\n", j
));
1656 // ATI/SII chipsets with memory-mapped IO hangs when
1657 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1658 // Unfortunately, I don't know yet how to workaround it except
1659 // specifying manual delay in the way you see below.
1660 ReadBuffer(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256, PIO0_TIMING
);
1662 // Work around for some IDE and one model Atapi that will present more than
1663 // 256 bytes for the Identify data.
1664 KdPrint2((PRINT_PREFIX
"IssueIdentify: suck data port\n", statusByte
));
1665 statusByte
= AtapiSuckPort2(chan
);
1667 KdPrint2((PRINT_PREFIX
" use 32bit IO\n"));
1668 ReadBuffer2(chan
, (PULONG
)&deviceExtension
->FullIdentifyData
, 256/2, PIO0_TIMING
);
1671 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1672 statusByte
= WaitForDrq(chan
);
1673 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1674 GetBaseStatus(chan
, statusByte
);
1676 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after read words %#x\n", statusByte
));
1679 KdPrint2((PRINT_PREFIX
"IssueIdentify: no setup, exiting\n"));
1683 KdPrint2((PRINT_PREFIX
"Model: %20.20s\n", deviceExtension
->FullIdentifyData
.ModelNumber
));
1684 KdPrint2((PRINT_PREFIX
"FW: %4.4s\n", deviceExtension
->FullIdentifyData
.FirmwareRevision
));
1685 KdPrint2((PRINT_PREFIX
"S/N: %20.20s\n", deviceExtension
->FullIdentifyData
.SerialNumber
));
1686 KdPrint2((PRINT_PREFIX
"Pio: %x\n", deviceExtension
->FullIdentifyData
.PioCycleTimingMode
));
1687 if(deviceExtension
->FullIdentifyData
.PioTimingsValid
) {
1688 KdPrint2((PRINT_PREFIX
"APio: %x\n", deviceExtension
->FullIdentifyData
.AdvancedPIOModes
));
1690 KdPrint2((PRINT_PREFIX
"SWDMA: %x\n", deviceExtension
->FullIdentifyData
.SingleWordDMAActive
));
1691 KdPrint2((PRINT_PREFIX
"MWDMA: %x\n", deviceExtension
->FullIdentifyData
.MultiWordDMAActive
));
1692 if(deviceExtension
->FullIdentifyData
.UdmaModesValid
) {
1693 KdPrint2((PRINT_PREFIX
"UDMA: %x/%x\n", deviceExtension
->FullIdentifyData
.UltraDMAActive
, deviceExtension
->FullIdentifyData
.UltraDMASupport
));
1695 KdPrint2((PRINT_PREFIX
"SATA: %x\n", deviceExtension
->FullIdentifyData
.SataEnable
));
1696 KdPrint2((PRINT_PREFIX
"SATA support: %x, CAPs %#x\n",
1697 deviceExtension
->FullIdentifyData
.SataSupport
,
1698 deviceExtension
->FullIdentifyData
.SataCapabilities
));
1700 LunExt
->LimitedTransferMode
=
1701 LunExt
->OrigTransferMode
=
1702 (UCHAR
)ata_cur_mode_from_ident(&(deviceExtension
->FullIdentifyData
), IDENT_MODE_MAX
);
1703 LunExt
->TransferMode
=
1704 (UCHAR
)ata_cur_mode_from_ident(&(deviceExtension
->FullIdentifyData
), IDENT_MODE_ACTIVE
);
1706 KdPrint2((PRINT_PREFIX
"OrigTransferMode: %x, Active: %x\n", LunExt
->OrigTransferMode
, LunExt
->TransferMode
));
1707 KdPrint2((PRINT_PREFIX
"Accoustic %d, cur %d\n",
1708 deviceExtension
->FullIdentifyData
.VendorAcoustic
,
1709 deviceExtension
->FullIdentifyData
.CurrentAcoustic
1711 KdPrint2((PRINT_PREFIX
"AdvPowerMode %d, cur %d\n",
1712 deviceExtension
->FullIdentifyData
.CfAdvPowerMode
1715 // Check out a few capabilities / limitations of the device.
1716 if (deviceExtension
->FullIdentifyData
.RemovableStatus
& 1) {
1717 // Determine if this drive supports the MSN functions.
1718 KdPrint2((PRINT_PREFIX
"IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1720 deviceExtension
->FullIdentifyData
.RemovableStatus
));
1721 LunExt
->DeviceFlags
|= DFLAGS_REMOVABLE_DRIVE
;
1724 // AHCI doesn't recommend using PIO and multiblock
1725 LunExt
->MaximumBlockXfer
= 0;
1727 if (deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
) {
1728 // Determine max. block transfer for this device.
1729 LunExt
->MaximumBlockXfer
=
1730 (UCHAR
)(deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
& 0xFF);
1732 LunExt
->NumOfSectors
= 0;
1733 if (Command
== IDE_COMMAND_IDENTIFY
) {
1734 ULONGLONG NumOfSectors
=0;
1735 ULONGLONG NativeNumOfSectors
=0;
1736 ULONGLONG cylinders
=0;
1737 ULONGLONG tmp_cylinders
=0;
1739 KdPrint2((PRINT_PREFIX
"PhysLogSectorSize %#x, %#x, offset %#x\n",
1740 deviceExtension
->FullIdentifyData
.PhysLogSectorSize
,
1741 deviceExtension
->FullIdentifyData
.LargeSectorSize
,
1742 deviceExtension
->FullIdentifyData
.LogicalSectorOffset
1745 KdPrint2((PRINT_PREFIX
"NV PM_Sup %d, PM_En %d, En %d, PM ver %#x ver %#x\n",
1746 deviceExtension
->FullIdentifyData
.NVCache_PM_Supported
,
1747 deviceExtension
->FullIdentifyData
.NVCache_PM_Enabled
,
1748 deviceExtension
->FullIdentifyData
.NVCache_Enabled
,
1749 deviceExtension
->FullIdentifyData
.NVCache_PM_Version
,
1750 deviceExtension
->FullIdentifyData
.NVCache_Version
1753 KdPrint2((PRINT_PREFIX
"R-rate %d\n",
1754 deviceExtension
->FullIdentifyData
.NominalMediaRotationRate
1757 // Read very-old-style drive geometry
1758 KdPrint2((PRINT_PREFIX
"CHS %#x:%#x:%#x\n",
1759 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1760 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1761 deviceExtension
->FullIdentifyData
.SectorsPerTrack
1763 NumOfSectors
= deviceExtension
->FullIdentifyData
.NumberOfCylinders
*
1764 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1765 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1766 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1767 // Check for HDDs > 8Gb
1768 if ((deviceExtension
->FullIdentifyData
.NumberOfCylinders
== 0x3fff) &&
1769 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1770 (NumOfSectors
< deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1771 KdPrint2((PRINT_PREFIX
"NumberOfCylinders == 0x3fff\n"));
1773 (deviceExtension
->FullIdentifyData
.UserAddressableSectors
/
1774 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1775 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1777 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1779 NumOfSectors
= cylinders
*
1780 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1781 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1783 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1787 // Check for LBA mode
1788 KdPrint2((PRINT_PREFIX
"SupportLba flag %#x\n", deviceExtension
->FullIdentifyData
.SupportLba
));
1789 KdPrint2((PRINT_PREFIX
"MajorRevision %#x\n", deviceExtension
->FullIdentifyData
.MajorRevision
));
1790 KdPrint2((PRINT_PREFIX
"UserAddressableSectors %#x\n", deviceExtension
->FullIdentifyData
.UserAddressableSectors
));
1791 if ( deviceExtension
->FullIdentifyData
.SupportLba
1793 (deviceExtension
->FullIdentifyData
.MajorRevision
&&
1794 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1795 deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1796 KdPrint2((PRINT_PREFIX
"LBA mode\n"));
1797 LunExt
->DeviceFlags
|= DFLAGS_LBA_ENABLED
;
1799 KdPrint2((PRINT_PREFIX
"Keep orig geometry\n"));
1800 LunExt
->DeviceFlags
|= DFLAGS_ORIG_GEOMETRY
;
1801 goto skip_lba_staff
;
1803 // Check for LBA48 support
1804 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1805 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
&&
1806 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Address48
&&
1807 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
> NumOfSectors
)
1809 KdPrint2((PRINT_PREFIX
"LBA48\n"));
1811 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
/
1812 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1813 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1815 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1817 NativeNumOfSectors
= cylinders
*
1818 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1819 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1821 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1823 if(NativeNumOfSectors
> NumOfSectors
) {
1824 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1825 NumOfSectors
= NativeNumOfSectors
;
1829 // Check drive capacity report for LBA48-capable drives.
1830 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
) {
1831 ULONG hNativeNumOfSectors
;
1832 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1834 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1835 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1837 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1839 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1841 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1842 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1843 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) ;
1845 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
1848 KdPrint2((PRINT_PREFIX
"Read high order bytes\n"));
1849 NativeNumOfSectors
|=
1850 (ULONG
)((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24 );
1851 hNativeNumOfSectors
=
1852 (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) |
1853 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 8) ;
1854 ((PULONG
)&NativeNumOfSectors
)[1] = hNativeNumOfSectors
;
1856 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1858 // Some drives report LBA48 capability while has capacity below 128Gb
1859 // Probably they support large block-counters.
1860 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
1861 // Here we check this
1862 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1863 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!!\n"));
1865 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1866 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1868 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1870 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1872 NativeNumOfSectors
= (ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1873 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24) |
1874 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8 ) |
1875 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 32) |
1876 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1877 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 40)
1882 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1883 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!! (2)\n"));
1884 NativeNumOfSectors
= 0;
1888 if(NumOfSectors
<= ATA_MAX_LBA28
&&
1889 NativeNumOfSectors
> NumOfSectors
) {
1891 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
1892 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1894 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1895 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1896 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1897 NumOfSectors
= NativeNumOfSectors
;
1903 if(NumOfSectors
< 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
1904 // check for native LBA size
1905 // some drives report ~32Gb in Identify Block
1906 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
1908 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_READ_NATIVE_SIZE
,
1909 0, IDE_USE_LBA
, 0, 0, 0, ATA_WAIT_READY
);
1911 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1913 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1915 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1916 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1917 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1918 (((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
) & 0xf) << 24);
1920 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1922 if(NativeNumOfSectors
> NumOfSectors
) {
1924 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
1925 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1927 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1928 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1929 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1930 NumOfSectors
= NativeNumOfSectors
;
1936 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
1938 // fill IdentifyData with bogus geometry
1939 KdPrint2((PRINT_PREFIX
"requested LunExt->GeomType=%x\n", LunExt
->opt_GeomType
));
1940 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*
1941 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
);
1942 KdPrint2((PRINT_PREFIX
"tmp_cylinders = %#I64x\n", tmp_cylinders
));
1943 if((tmp_cylinders
< 0xffff) || (LunExt
->opt_GeomType
== GEOM_ORIG
)) {
1944 // ok, we can keep original values
1945 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1946 LunExt
->opt_GeomType
= GEOM_ORIG
;
1949 tmp_cylinders
= NumOfSectors
/ (255*63);
1950 if(tmp_cylinders
< 0xffff) {
1951 // we can use generic values for H/S for generic geometry approach
1952 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1953 LunExt
->opt_GeomType
= GEOM_STD
;
1956 // we should use UNIATA geometry approach
1957 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1958 LunExt
->opt_GeomType
= GEOM_UNIATA
;
1963 if(LunExt
->opt_GeomType
== GEOM_STD
) {
1964 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
=
1965 deviceExtension
->FullIdentifyData
.SectorsPerTrack
= 63;
1967 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
=
1968 deviceExtension
->FullIdentifyData
.NumberOfHeads
= 255;
1970 cylinders
= NumOfSectors
/ (255*63);
1971 KdPrint2((PRINT_PREFIX
"Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders
, 255, 63));
1973 if(LunExt
->opt_GeomType
== GEOM_UNIATA
) {
1974 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x80)) {
1976 KdPrint2((PRINT_PREFIX
"cylinders /= 2\n"));
1977 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1978 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1980 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x80)) {
1982 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (2)\n"));
1983 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1984 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1986 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x8000)) {
1988 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (3)\n"));
1989 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1990 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1992 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x8000)) {
1994 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (4)\n"));
1995 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1996 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1998 KdPrint2((PRINT_PREFIX
"Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders
,
1999 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
,
2000 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
));
2003 KdPrint2((PRINT_PREFIX
"cylinders = tmp_cylinders (%x = %x)\n", cylinders
, tmp_cylinders
));
2004 cylinders
= tmp_cylinders
;
2006 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
=
2007 deviceExtension
->FullIdentifyData
.NumberOfCylinders
= (USHORT
)cylinders
;
2011 KdPrint2((PRINT_PREFIX
"Geometry: C %#x (%#x)\n",
2012 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
2013 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
2015 KdPrint2((PRINT_PREFIX
"Geometry: H %#x (%#x)\n",
2016 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
2017 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
2019 KdPrint2((PRINT_PREFIX
"Geometry: S %#x (%#x)\n",
2020 deviceExtension
->FullIdentifyData
.SectorsPerTrack
,
2021 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
2025 LunExt
->NumOfSectors
= NumOfSectors
;
2026 /* if(deviceExtension->FullIdentifyData.MajorRevision &&
2027 deviceExtension->FullIdentifyData.DoubleWordIo) {
2028 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
2032 ScsiPortMoveMemory(&LunExt
->IdentifyData
,
2033 &deviceExtension
->FullIdentifyData
,sizeof(IDENTIFY_DATA2
));
2035 InitBadBlocks(LunExt
);
2037 if ((LunExt
->IdentifyData
.DrqType
& ATAPI_DRQT_INTR
) &&
2038 (Command
!= IDE_COMMAND_IDENTIFY
)) {
2040 // This device interrupts with the assertion of DRQ after receiving
2041 // Atapi Packet Command
2042 LunExt
->DeviceFlags
|= DFLAGS_INT_DRQ
;
2043 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
2046 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
2049 if(Command
!= IDE_COMMAND_IDENTIFY
) {
2051 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_TAPE
) {
2053 LunExt
->DeviceFlags
|= DFLAGS_TAPE_DEVICE
;
2054 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is a tape drive.\n"));
2056 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
||
2057 LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_OPTICAL
) {
2058 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is CD/Optical drive.\n"));
2059 // set CD default costs
2060 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_CD
;
2061 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_CD
;
2062 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_CD
;
2063 statusByte
= WaitForDrq(chan
);
2066 KdPrint2((PRINT_PREFIX
"IssueIdentify: ATAPI drive type %#x.\n",
2067 LunExt
->IdentifyData
.DeviceType
));
2069 KdPrint2((PRINT_PREFIX
"IssueIdentify: AtapiCmdSize %#x\n", deviceExtension
->FullIdentifyData
.AtapiCmdSize
));
2071 KdPrint2((PRINT_PREFIX
"IssueIdentify: hard drive.\n"));
2074 GetBaseStatus(chan
, statusByte
);
2075 KdPrint2((PRINT_PREFIX
"IssueIdentify: final Status on exit (%#x)\n", statusByte
));
2078 } // end IssueIdentify()
2083 Routine Description:
2084 Set drive parameters using the IDENTIFY data.
2087 HwDeviceExtension - HBA miniport driver's adapter data storage
2088 DeviceNumber - Indicates which device.
2091 TRUE if all goes well.
2097 IN PVOID HwDeviceExtension
,
2098 IN ULONG DeviceNumber
,
2102 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2103 PIDENTIFY_DATA2 identifyData
;
2104 PHW_LU_EXTENSION LunExt
;
2109 LunExt
= deviceExtension
->chan
[lChannel
].lun
[DeviceNumber
];
2110 identifyData
= &(LunExt
->IdentifyData
);
2112 if(LunExt
->DeviceFlags
&
2113 (DFLAGS_LBA_ENABLED
| DFLAGS_ORIG_GEOMETRY
))
2116 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Number of heads %#x\n", identifyData
->NumberOfHeads
));
2117 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Sectors per track %#x\n", identifyData
->SectorsPerTrack
));
2119 // Send SET PARAMETER command.
2120 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
2121 IDE_COMMAND_SET_DRIVE_PARAMETERS
, 0,
2122 (identifyData
->NumberOfHeads
- 1), 0,
2123 (UCHAR
)identifyData
->SectorsPerTrack
, 0, ATA_WAIT_IDLE
);
2125 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2126 if(statusByte
& IDE_STATUS_ERROR
) {
2127 errorByte
= AtapiReadPort1(&deviceExtension
->chan
[lChannel
], IDX_IO1_i_Error
);
2128 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Error bit set. Status %#x, error %#x\n",
2129 errorByte
, statusByte
));
2133 if(statusByte
== IDE_STATUS_IDLE
) {
2139 } // end SetDriveParameters()
2144 PHW_LU_EXTENSION LunExt
2147 // keep only DFLAGS_HIDDEN flag
2148 LunExt
->DeviceFlags
&= DFLAGS_HIDDEN
;
2149 LunExt
->AtapiReadyWaitDelay
= 0;
2150 } // end UniataForgetDevice()
2155 Routine Description:
2156 Reset IDE controller and/or Atapi device.
2160 HwDeviceExtension - HBA miniport driver's adapter data storage
2169 AtapiResetController(
2170 IN PVOID HwDeviceExtension
,
2174 KdPrint2((PRINT_PREFIX
"AtapiResetController(%x)\n", PathId
));
2175 return AtapiResetController__(HwDeviceExtension
, PathId
, RESET_COMPLETE_ALL
);
2176 } // end AtapiResetController()
2180 AtapiResetController__(
2181 IN PVOID HwDeviceExtension
,
2183 IN BOOLEAN CompleteType
2186 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2187 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2188 PHW_CHANNEL chan
= NULL
;
2192 PSCSI_REQUEST_BLOCK CurSrb
;
2193 ULONG ChannelCtrlFlags
;
2194 UCHAR dma_status
= 0;
2196 ULONG slotNumber
= deviceExtension
->slotNumber
;
2197 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
2198 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
2200 ULONG DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
2202 //ULONG RevID = deviceExtension->RevID;
2203 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
2207 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID
, DeviceID
, slotNumber
));
2208 KdPrint2((PRINT_PREFIX
"simplexOnly %d\n", deviceExtension
->simplexOnly
));
2210 if(!deviceExtension
->simplexOnly
&& (PathId
!= CHAN_NOT_SPECIFIED
)) {
2211 // we shall reset both channels on SimplexOnly devices,
2212 // It's not worth doing so on normal controllers
2214 numberChannels
= min(j
+1, deviceExtension
->NumberChannels
);
2217 numberChannels
= deviceExtension
->NumberChannels
;
2220 for (; j
< numberChannels
; j
++) {
2222 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset channel %d\n", j
));
2223 chan
= &(deviceExtension
->chan
[j
]);
2224 MaxLuns
= chan
->NumberLuns
;
2225 KdPrint2((PRINT_PREFIX
" CompleteType %#x, Luns %d, chan %#x, sptr %#x\n", CompleteType
, MaxLuns
, chan
, &chan
));
2226 //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
2227 if(CompleteType
!= RESET_COMPLETE_NONE
) {
2229 while((CurSrb
= UniataGetCurRequest(chan
))) {
2231 PATA_REQ AtaReq
= (PATA_REQ
)(CurSrb
->SrbExtension
);
2233 KdPrint2((PRINT_PREFIX
"AtapiResetController: pending SRB %#x, chan %#x\n", CurSrb
, chan
));
2234 if(CurSrb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
2235 PHW_LU_EXTENSION LunExt
;
2236 KdPrint2((PRINT_PREFIX
" was MechStatus\n"));
2238 i
= GET_CDEV(CurSrb
);
2239 KdPrint2((PRINT_PREFIX
" Lun %x\n", i
));
2240 LunExt
= chan
->lun
[i
];
2242 if(!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)) {
2243 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
2244 KdPrint2((PRINT_PREFIX
" set DFLAGS_CHANGER_INITED\n"));
2247 // Check and see if we are processing an internal srb
2248 if (AtaReq
->OriginalSrb
) {
2249 KdPrint2((PRINT_PREFIX
" restore original SRB %#x\n", AtaReq
->OriginalSrb
));
2250 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
2251 CurSrb
->SrbExtension
= NULL
;
2252 AtaReq
->OriginalSrb
= NULL
;
2253 // NOTE: internal SRB doesn't get to SRB queue !!!
2254 CurSrb
= AtaReq
->Srb
;
2257 // Remove current request from queue
2258 UniataRemoveRequest(chan
, CurSrb
);
2260 // Check if request is in progress.
2261 ASSERT(AtaReq
->Srb
== CurSrb
);
2263 // Complete outstanding request with SRB_STATUS_BUS_RESET.
2264 UCHAR PathId
= CurSrb
->PathId
;
2265 UCHAR TargetId
= CurSrb
->TargetId
;
2266 UCHAR Lun
= CurSrb
->Lun
;
2268 CurSrb
->SrbStatus
= ((CompleteType
== RESET_COMPLETE_ALL
) ? SRB_STATUS_BUS_RESET
: SRB_STATUS_ABORTED
) | SRB_STATUS_AUTOSENSE_VALID
;
2269 CurSrb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2271 if (CurSrb
->SenseInfoBuffer
) {
2273 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)CurSrb
->SenseInfoBuffer
;
2274 KdPrint2((PRINT_PREFIX
" senseBuffer %#x, chan %#x\n", senseBuffer
, chan
));
2276 senseBuffer
->ErrorCode
= 0x70;
2277 senseBuffer
->Valid
= 1;
2278 senseBuffer
->AdditionalSenseLength
= 0xb;
2279 if(CompleteType
== RESET_COMPLETE_ALL
) {
2280 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
2281 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2282 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_BUS_RESET
;
2283 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_SCSI_BUS
;
2285 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
2286 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2287 senseBuffer
->AdditionalSenseCode
= 0;
2288 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2292 // Clear request tracking fields.
2293 AtaReq
->WordsLeft
= 0;
2294 AtaReq
->DataBuffer
= NULL
;
2295 AtaReq
->TransferLength
= 0;
2296 KdPrint2((PRINT_PREFIX
"chan %#x\n", chan
));
2298 ScsiPortNotification(RequestComplete
,
2302 // Indicate ready for next request.
2303 ScsiPortNotification(NextLuRequest
,
2309 if(CompleteType
!= RESET_COMPLETE_ALL
)
2312 #endif //UNIATA_CORE
2313 } // end if (!CompleteType != RESET_COMPLETE_NONE)
2315 // Save control flags
2316 ChannelCtrlFlags
= chan
->ChannelCtrlFlags
;
2317 // Clear expecting interrupt flag.
2318 UniataExpectChannelInterrupt(chan
, FALSE
);
2320 chan
->ChannelCtrlFlags
= 0;
2321 InterlockedExchange(&(chan
->CheckIntr
),
2324 for (i
= 0; i
< MaxLuns
; i
++) {
2325 chan
->lun
[i
]->PowerState
= 0;
2328 if(ChipFlags
& UNIATA_AHCI
) {
2329 KdPrint2((PRINT_PREFIX
" AHCI path\n"));
2330 if(UniataAhciChanImplemented(deviceExtension
, j
)) {
2332 UniataDumpAhciPortRegs(chan
);
2334 AtapiDisableInterrupts(deviceExtension
, j
);
2335 UniataAhciReset(HwDeviceExtension
, j
);
2337 KdPrint2((PRINT_PREFIX
" skip not implemented\n"));
2341 KdPrint2((PRINT_PREFIX
" ATA path, chan %#x\n", chan
));
2342 KdPrint2((PRINT_PREFIX
" disable intr (0)\n"));
2343 AtapiDisableInterrupts(deviceExtension
, j
);
2344 KdPrint2((PRINT_PREFIX
" done\n"));
2346 case ATA_INTEL_ID
: {
2350 if(!(ChipFlags
& UNIATA_SATA
)) {
2353 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2358 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2359 if(ChipFlags
& UNIATA_AHCI
) {
2362 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2363 GetPciConfig1(0x90, tmp8
);
2371 mask
= 1 << chan
->lun
[0]->SATA_lun_map
;
2373 mask
|= (1 << chan
->lun
[1]->SATA_lun_map
);
2376 ChangePciConfig2(0x92, a
& ~mask
);
2377 AtapiStallExecution(10);
2378 ChangePciConfig2(0x92, a
| mask
);
2381 /* Wait up to 1 sec for "connect well". */
2382 if (ChipFlags
& (I6CH
| I6CH2
)) {
2388 GetPciConfig2(0x92, tmp16
);
2389 if (((tmp16
>> pshift
) & mask
) == mask
) {
2390 GetBaseStatus(chan
, statusByte
);
2391 if(statusByte
!= IDE_STATUS_WRONG
) {
2395 AtapiStallExecution(10000);
2399 case ATA_NVIDIA_ID
: {
2401 ULONG Channel
= deviceExtension
->Channel
+ j
;
2402 KdPrint2((PRINT_PREFIX
" SIS/nVidia\n"));
2403 if(!(ChipFlags
& UNIATA_SATA
)) {
2406 offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
2408 KdPrint2((PRINT_PREFIX
" disable Phy intr, offs %#x, c %u\n", offs
, Channel
));
2409 /* disable device and PHY state change interrupts */
2410 if(ChipFlags
& NVQ
) {
2411 KdPrint2((PRINT_PREFIX
" NVQ, 32bits reg\n"));
2412 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4,
2413 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4) & ((~(ULONG
)0x0000000d) << (!Channel
*16)) );
2415 AtapiWritePortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1,
2416 AtapiReadPortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1) & ((~(UCHAR
)0x0d) << (!Channel
*4)) );
2418 tmp16
= UniataSataPhyEnable(HwDeviceExtension
, j
, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE
);
2420 KdPrint2((PRINT_PREFIX
" enable Phy intr, offs %#x\n", offs
));
2421 /* enable device and PHY state change interrupts */
2422 if(ChipFlags
& NVQ
) {
2423 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4,
2424 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+4) | (((ULONG
)0x0000000d) << (!Channel
*16)) );
2426 AtapiWritePortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1,
2427 AtapiReadPortEx1(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
+1) | (((UCHAR
)0x0d) << (!Channel
*4)) );
2430 KdPrint2((PRINT_PREFIX
" dev status %#x\n", tmp16
));
2431 if(tmp16
!= IDE_STATUS_WRONG
) {
2435 case ATA_SILICON_IMAGE_ID
: {
2437 ULONG Channel
= deviceExtension
->Channel
+ j
;
2438 if(!(ChipFlags
& UNIATA_SATA
))
2440 offset
= ((Channel
& 1) << 7) + ((Channel
& 2) << 8);
2441 /* disable PHY state change interrupt */
2442 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x148 + offset
, 0);
2444 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2446 /* reset controller part for this channel */
2447 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2448 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) | (0xc0 >> Channel
));
2449 AtapiStallExecution(1000);
2450 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2451 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) & ~(0xc0 >> Channel
));
2455 case ATA_PROMISE_ID
: {
2458 if(ChipFlags
& UNIATA_SATA
) {
2459 KdPrint2((PRINT_PREFIX
" SATA generic reset\n"));
2460 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2463 KdPrint2((PRINT_PREFIX
" send reset\n"));
2464 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
|
2465 IDE_DC_RESET_CONTROLLER
);
2466 KdPrint2((PRINT_PREFIX
" wait a little\n"));
2467 AtapiStallExecution(10000);
2468 // Disable interrupts
2469 KdPrint2((PRINT_PREFIX
" disable intr\n"));
2470 AtapiDisableInterrupts(deviceExtension
, j
);
2471 AtapiStallExecution(100);
2472 KdPrint2((PRINT_PREFIX
" re-enable intr\n"));
2473 AtapiEnableInterrupts(deviceExtension
, j
);
2474 KdPrint2((PRINT_PREFIX
" wait a little (2)\n"));
2475 AtapiStallExecution(100000);
2476 KdPrint2((PRINT_PREFIX
" done\n"));
2481 //if(!(ChipFlags & UNIATA_SATA)) {}
2482 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2483 // Reset DMA engine if active
2484 KdPrint2((PRINT_PREFIX
" check DMA engine\n"));
2485 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
2486 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
2487 if((ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
2488 (dma_status
& BM_STATUS_INTR
)) {
2489 AtapiDmaDone(HwDeviceExtension
, 0, j
, NULL
);
2494 // all these shall be performed inside AtapiHwInitialize__() ?
2496 KdPrint2((PRINT_PREFIX
" process connected devices 0 - %d\n", MaxLuns
-1));
2497 // Do special processing for ATAPI and IDE disk devices.
2498 for (i
= 0; i
< MaxLuns
; i
++) {
2500 // Check if device present.
2501 KdPrint2((PRINT_PREFIX
" Chan %#x\n", chan
));
2502 KdPrint2((PRINT_PREFIX
" Lun %#x\n", i
));
2503 KdPrint2((PRINT_PREFIX
" Lun ptr %#x\n", chan
->lun
[i
]));
2504 if (!(chan
->lun
[i
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2505 if(ChipFlags
& UNIATA_AHCI
) {
2506 // everything is done in UniataAhciReset()
2507 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2513 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2514 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2517 if(!CheckDevice(HwDeviceExtension
, j
, i
, TRUE
)) {
2521 if(ChipFlags
& UNIATA_AHCI
) {
2522 // everything is done in UniataAhciReset()
2523 KdPrint2((PRINT_PREFIX
" found some device\n"));
2525 if(!IssueIdentify(HwDeviceExtension
,
2527 ATAPI_DEVICE(chan
, i
) ?
2528 IDE_COMMAND_ATAPI_IDENTIFY
: IDE_COMMAND_IDENTIFY
,
2530 KdPrint2((PRINT_PREFIX
" identify failed !\n"));
2531 UniataForgetDevice(chan
->lun
[i
]);
2535 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2536 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2537 UniataForgetDevice(chan
->lun
[i
]);
2542 SelectDrive(chan
, i
);
2543 AtapiStallExecution(10);
2544 statusByte
= WaitOnBusyLong(chan
);
2545 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2546 if(statusByte
== IDE_STATUS_WRONG
) {
2547 KdPrint2((PRINT_PREFIX
2548 "no drive, status %#x\n",
2550 UniataForgetDevice(chan
->lun
[i
]);
2552 // Check for ATAPI disk.
2553 if (ATAPI_DEVICE(chan
, i
)) {
2554 // Issue soft reset and issue identify.
2555 GetStatus(chan
, statusByte
);
2556 KdPrint2((PRINT_PREFIX
"AtapiResetController: Status before Atapi reset (%#x).\n",
2559 AtapiDisableInterrupts(deviceExtension
, j
);
2560 AtapiSoftReset(chan
, i
);
2561 AtapiEnableInterrupts(deviceExtension
, j
);
2563 GetStatus(chan
, statusByte
);
2565 if(statusByte
!= IDE_STATUS_SUCCESS
) {
2567 k
= UniataAnybodyHome(deviceExtension
, j
, i
);
2568 if(k
== ATA_AT_HOME_HDD
) {
2569 // device reset in progress, perform additional wait
2570 KdPrint2((PRINT_PREFIX
" long reset, wait up to 4.5 s\n"));
2572 while ((AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
2575 AtapiStallExecution(150);
2577 KdPrint2((PRINT_PREFIX
" exit after %u loops\n", k
));
2578 GetStatus(chan
, statusByte
);
2581 if(statusByte
== IDE_STATUS_SUCCESS
) {
2583 IssueIdentify(HwDeviceExtension
,
2585 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
2588 KdPrint2((PRINT_PREFIX
2589 "AtapiResetController: Status after soft reset %#x\n",
2592 GetBaseStatus(chan
, statusByte
);
2595 // Issue identify and reinit after channel reset.
2597 if (statusByte
!= IDE_STATUS_IDLE
&&
2598 statusByte
!= IDE_STATUS_SUCCESS
&&
2599 statusByte
!= IDE_STATUS_DRDY
) {
2601 KdPrint2((PRINT_PREFIX
"AtapiResetController: IdeHardReset failed\n"));
2603 if(!IssueIdentify(HwDeviceExtension
,
2605 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2607 KdPrint2((PRINT_PREFIX
"AtapiResetController: IDE IssueIdentify failed\n"));
2609 // Set disk geometry parameters.
2610 if (!SetDriveParameters(HwDeviceExtension
, i
, j
)) {
2611 KdPrint2((PRINT_PREFIX
"AtapiResetController: SetDriveParameters failed\n"));
2613 GetBaseStatus(chan
, statusByte
);
2615 // force DMA mode reinit
2616 chan
->lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
2620 // Enable interrupts, note, we can have here recursive disable
2621 AtapiStallExecution(10);
2622 KdPrint2((PRINT_PREFIX
"AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2624 chan
->DisableIntr
));
2625 AtapiEnableInterrupts(deviceExtension
, j
);
2627 // Call the HwInitialize routine to setup multi-block.
2628 AtapiHwInitialize__(deviceExtension
, j
);
2630 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
2634 } // end AtapiResetController__()
2639 Routine Description:
2640 This routine maps ATAPI and IDE errors to specific SRB statuses.
2643 HwDeviceExtension - HBA miniport driver's adapter data storage
2644 Srb - IO request packet
2653 IN PVOID HwDeviceExtension
,
2654 IN PSCSI_REQUEST_BLOCK Srb
2657 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2658 ULONG lChannel
= GET_CHANNEL(Srb
);
2659 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2661 UCHAR errorByte
= 0;
2662 UCHAR srbStatus
= SRB_STATUS_SUCCESS
;
2664 ULONG DeviceNumber
= GET_CDEV(Srb
);
2665 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
2667 // Read the error register.
2669 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
2670 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2672 errorByte
= AtaReq
->ahci
.in_error
;
2676 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2678 KdPrint2((PRINT_PREFIX
2679 "MapError: Error register is %#x\n",
2682 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2684 switch (errorByte
>> 4) {
2685 case SCSI_SENSE_NO_SENSE
:
2687 KdPrint2((PRINT_PREFIX
2688 "ATAPI: No sense information\n"));
2689 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2690 srbStatus
= SRB_STATUS_ERROR
;
2693 case SCSI_SENSE_RECOVERED_ERROR
:
2695 KdPrint2((PRINT_PREFIX
2696 "ATAPI: Recovered error\n"));
2698 srbStatus
= SRB_STATUS_SUCCESS
;
2701 case SCSI_SENSE_NOT_READY
:
2703 KdPrint2((PRINT_PREFIX
2704 "ATAPI: Device not ready\n"));
2705 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2706 srbStatus
= SRB_STATUS_ERROR
;
2709 case SCSI_SENSE_MEDIUM_ERROR
:
2711 KdPrint2((PRINT_PREFIX
2712 "ATAPI: Media error\n"));
2713 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2714 srbStatus
= SRB_STATUS_ERROR
;
2717 case SCSI_SENSE_HARDWARE_ERROR
:
2719 KdPrint2((PRINT_PREFIX
2720 "ATAPI: Hardware error\n"));
2721 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2722 srbStatus
= SRB_STATUS_ERROR
;
2725 case SCSI_SENSE_ILLEGAL_REQUEST
:
2727 KdPrint2((PRINT_PREFIX
2728 "ATAPI: Illegal request\n"));
2729 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2730 srbStatus
= SRB_STATUS_ERROR
;
2733 case SCSI_SENSE_UNIT_ATTENTION
:
2735 KdPrint2((PRINT_PREFIX
2736 "ATAPI: Unit attention\n"));
2737 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2738 srbStatus
= SRB_STATUS_ERROR
;
2741 case SCSI_SENSE_DATA_PROTECT
:
2743 KdPrint2((PRINT_PREFIX
2744 "ATAPI: Data protect\n"));
2745 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2746 srbStatus
= SRB_STATUS_ERROR
;
2749 case SCSI_SENSE_BLANK_CHECK
:
2751 KdPrint2((PRINT_PREFIX
2752 "ATAPI: Blank check\n"));
2753 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2754 srbStatus
= SRB_STATUS_ERROR
;
2757 case SCSI_SENSE_ABORTED_COMMAND
:
2758 KdPrint2((PRINT_PREFIX
2759 "Atapi: Command Aborted\n"));
2760 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2761 srbStatus
= SRB_STATUS_ERROR
;
2766 KdPrint2((PRINT_PREFIX
2767 "ATAPI: Invalid sense information\n"));
2769 srbStatus
= SRB_STATUS_ERROR
;
2777 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
2778 chan
->ReturningMediaStatus
= errorByte
;
2780 if (errorByte
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
2781 KdPrint2((PRINT_PREFIX
2782 "IDE: Media change\n"));
2783 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2784 srbStatus
= SRB_STATUS_ERROR
;
2786 if (Srb
->SenseInfoBuffer
) {
2788 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2790 senseBuffer
->ErrorCode
= 0x70;
2791 senseBuffer
->Valid
= 1;
2792 senseBuffer
->AdditionalSenseLength
= 0xb;
2793 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2794 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2795 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2797 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2800 } else if (errorByte
& IDE_ERROR_COMMAND_ABORTED
) {
2801 KdPrint2((PRINT_PREFIX
2802 "IDE: Command abort\n"));
2803 srbStatus
= SRB_STATUS_ABORTED
;
2804 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2806 if (Srb
->SenseInfoBuffer
) {
2808 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2810 senseBuffer
->ErrorCode
= 0x70;
2811 senseBuffer
->Valid
= 1;
2812 senseBuffer
->AdditionalSenseLength
= 0xb;
2813 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2814 senseBuffer
->AdditionalSenseCode
= 0;
2815 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2817 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2820 LunExt
->ErrorCount
++;
2822 } else if (errorByte
& IDE_ERROR_END_OF_MEDIA
) {
2824 KdPrint2((PRINT_PREFIX
2825 "IDE: End of media\n"));
2826 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2827 srbStatus
= SRB_STATUS_ERROR
;
2829 if (Srb
->SenseInfoBuffer
) {
2831 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2833 senseBuffer
->ErrorCode
= 0x70;
2834 senseBuffer
->Valid
= 1;
2835 senseBuffer
->AdditionalSenseLength
= 0xb;
2836 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2837 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIA_STATE
;
2838 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_END_OF_MEDIUM
;
2839 senseBuffer
->EndOfMedia
= 1;
2841 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2844 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2845 LunExt
->ErrorCount
++;
2848 } else if (errorByte
& IDE_ERROR_ILLEGAL_LENGTH
) {
2850 KdPrint2((PRINT_PREFIX
2851 "IDE: Illegal length\n"));
2852 srbStatus
= SRB_STATUS_INVALID_REQUEST
;
2854 if (Srb
->SenseInfoBuffer
) {
2856 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2858 senseBuffer
->ErrorCode
= 0x70;
2859 senseBuffer
->Valid
= 1;
2860 senseBuffer
->AdditionalSenseLength
= 0xb;
2861 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
2862 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_VALUE
;
2863 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_PARAM_INVALID_VALUE
;
2864 senseBuffer
->IncorrectLength
= 1;
2866 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2869 } else if (errorByte
& IDE_ERROR_BAD_BLOCK
) {
2871 KdPrint2((PRINT_PREFIX
2872 "IDE: Bad block\n"));
2873 srbStatus
= SRB_STATUS_ERROR
;
2874 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2875 if (Srb
->SenseInfoBuffer
) {
2877 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2879 senseBuffer
->ErrorCode
= 0x70;
2880 senseBuffer
->Valid
= 1;
2881 senseBuffer
->AdditionalSenseLength
= 0xb;
2882 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2883 senseBuffer
->AdditionalSenseCode
= 0;
2884 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2886 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2889 } else if (errorByte
& IDE_ERROR_ID_NOT_FOUND
) {
2891 KdPrint2((PRINT_PREFIX
2892 "IDE: Id not found\n"));
2893 srbStatus
= SRB_STATUS_ERROR
;
2894 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2896 if (Srb
->SenseInfoBuffer
) {
2898 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2900 senseBuffer
->ErrorCode
= 0x70;
2901 senseBuffer
->Valid
= 1;
2902 senseBuffer
->AdditionalSenseLength
= 0xb;
2903 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2904 senseBuffer
->AdditionalSenseCode
= 0;
2905 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2907 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2910 LunExt
->ErrorCount
++;
2912 } else if (errorByte
& IDE_ERROR_MEDIA_CHANGE
) {
2914 KdPrint2((PRINT_PREFIX
2915 "IDE: Media change\n"));
2916 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2917 srbStatus
= SRB_STATUS_ERROR
;
2919 if (Srb
->SenseInfoBuffer
) {
2921 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2923 senseBuffer
->ErrorCode
= 0x70;
2924 senseBuffer
->Valid
= 1;
2925 senseBuffer
->AdditionalSenseLength
= 0xb;
2926 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2927 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2928 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2930 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2933 } else if (errorByte
& IDE_ERROR_DATA_ERROR
) {
2935 KdPrint2((PRINT_PREFIX
2936 "IDE: Data error\n"));
2937 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2938 srbStatus
= SRB_STATUS_ERROR
;
2940 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2941 LunExt
->ErrorCount
++;
2944 // Build sense buffer
2945 if (Srb
->SenseInfoBuffer
) {
2947 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2949 senseBuffer
->ErrorCode
= 0x70;
2950 senseBuffer
->Valid
= 1;
2951 senseBuffer
->AdditionalSenseLength
= 0xb;
2952 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2953 senseBuffer
->AdditionalSenseCode
= 0;
2954 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2956 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2960 if (LunExt
->ErrorCount
>= MAX_ERRORS
) {
2961 // deviceExtension->DWordIO = FALSE;
2963 KdPrint2((PRINT_PREFIX
2964 "MapError: ErrorCount >= MAX_ERRORS\n"));
2966 LunExt
->DeviceFlags
&= ~DFLAGS_DWORDIO_ENABLED
;
2967 LunExt
->MaximumBlockXfer
= 0;
2970 KdPrint2((PRINT_PREFIX
2971 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
2974 KdPrint2((PRINT_PREFIX
2975 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
2984 ScsiPortLogError( HwDeviceExtension
,
2992 // Reprogram to not use Multi-sector.
2995 if (LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
&&
2996 !(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
2998 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY
);
3000 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
3001 // command was aborted.
3002 if (statusByte
& IDE_STATUS_ERROR
) {
3004 // Read the error register.
3005 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3007 KdPrint2((PRINT_PREFIX
"MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
3011 // Adjust the devExt. value, if necessary.
3012 LunExt
->MaximumBlockXfer
= 0;
3020 // Set SCSI status to indicate a check condition.
3021 Srb
->ScsiStatus
= scsiStatus
;
3030 Routine Description:
3033 HwDeviceExtension - HBA miniport driver's adapter data storage
3037 TRUE - if initialization successful.
3038 FALSE - if initialization unsuccessful.
3044 IN PVOID HwDeviceExtension
3047 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3048 ULONG numberChannels
= deviceExtension
->NumberChannels
;
3051 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base)\n"));
3053 if(WinVer_WDM_Model
) {
3054 AtapiResetController__(HwDeviceExtension
, CHAN_NOT_SPECIFIED
, RESET_COMPLETE_ALL
);
3056 if(deviceExtension
->MasterDev
) {
3057 KdPrint2((PRINT_PREFIX
" mark chan %d of master controller [%x] as inited\n",
3058 deviceExtension
->Channel
, deviceExtension
->DevIndex
));
3059 BMList
[deviceExtension
->DevIndex
].ChanInitOk
|= 0x01 << deviceExtension
->Channel
;
3062 /* do extra chipset specific setups */
3063 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
3065 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
3066 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
3067 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
3070 for (c
= 0; c
< numberChannels
; c
++) {
3071 AtapiHwInitialize__(deviceExtension
, c
);
3073 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base) done\n"));
3075 } // end AtapiHwInitialize()
3079 AtapiHwInitialize__(
3080 IN PHW_DEVICE_EXTENSION deviceExtension
,
3085 UCHAR statusByte
, errorByte
;
3086 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3087 PHW_LU_EXTENSION LunExt
;
3089 ULONG PreferedMode
= 0xffffffff;
3091 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
3092 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
3096 AtapiChipInit(deviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
);
3097 FindDevices(deviceExtension
, 0, lChannel
);
3099 for (i
= 0; i
< chan
->NumberLuns
; i
++) {
3101 KdPrint3((PRINT_PREFIX
"AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel
, i
));
3103 LunExt
= chan
->lun
[i
];
3105 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
3109 AtapiDisableInterrupts(deviceExtension
, lChannel
);
3110 AtapiStallExecution(1);
3112 if (!(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
3114 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: IDE branch\n"));
3115 // Enable media status notification
3116 IdeMediaStatus(TRUE
,deviceExtension
,lChannel
,(UCHAR
)i
);
3118 // If supported, setup Multi-block transfers.
3119 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3120 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
3121 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
3123 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
3124 // command was aborted.
3125 if (statusByte
& IDE_STATUS_ERROR
) {
3127 // Read the error register.
3128 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3130 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
3134 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3135 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
3136 0, 0, ATA_WAIT_BASE_READY
);
3138 if (statusByte
& IDE_STATUS_ERROR
) {
3139 // Read the error register.
3140 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3142 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
3146 // Adjust the devExt. value, if necessary.
3147 LunExt
->MaximumBlockXfer
= 0;
3150 KdPrint2((PRINT_PREFIX
3151 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
3153 LunExt
->MaximumBlockXfer
));
3156 if(LunExt
->IdentifyData
.MajorRevision
) {
3158 if(LunExt
->opt_ReadCacheEnable
) {
3159 KdPrint2((PRINT_PREFIX
" Try Enable Read Cache\n"));
3160 // If supported, setup read/write cacheing
3161 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3162 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3163 0, ATA_C_F_ENAB_RCACHE
, ATA_WAIT_BASE_READY
);
3165 // Check for errors.
3166 if (statusByte
& IDE_STATUS_ERROR
) {
3167 KdPrint2((PRINT_PREFIX
3168 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
3170 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3172 LunExt
->DeviceFlags
|= DFLAGS_RCACHE_ENABLED
;
3175 KdPrint2((PRINT_PREFIX
" Disable Read Cache\n"));
3176 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3177 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3178 0, ATA_C_F_DIS_RCACHE
, ATA_WAIT_BASE_READY
);
3179 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3181 if(LunExt
->opt_WriteCacheEnable
) {
3182 KdPrint2((PRINT_PREFIX
" Try Enable Write Cache\n"));
3183 // If supported & allowed, setup write cacheing
3184 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3185 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3186 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
3187 // Check for errors.
3188 if (statusByte
& IDE_STATUS_ERROR
) {
3189 KdPrint2((PRINT_PREFIX
3190 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
3192 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3194 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
3197 KdPrint2((PRINT_PREFIX
" Disable Write Cache\n"));
3198 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3199 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3200 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
3201 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3204 if(LunExt
->IdentifyData
.FeaturesSupport
.PowerMngt
||
3205 LunExt
->IdentifyData
.FeaturesSupport
.APM
) {
3207 if(LunExt
->opt_AdvPowerMode
) {
3208 KdPrint2((PRINT_PREFIX
" Try Enable Adv. Power Mgmt\n"));
3210 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3211 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3212 LunExt
->opt_AdvPowerMode
, ATA_C_F_ENAB_APM
, ATA_WAIT_BASE_READY
);
3213 // Check for errors.
3214 if (statusByte
& IDE_STATUS_ERROR
) {
3215 KdPrint2((PRINT_PREFIX
3216 "AtapiHwInitialize: Enable APM on Device %d failed\n",
3220 KdPrint2((PRINT_PREFIX
" Disable Adv. Power Mgmt\n"));
3221 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3222 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3223 0, ATA_C_F_DIS_APM
, ATA_WAIT_BASE_READY
);
3226 if(LunExt
->IdentifyData
.FeaturesSupport
.AutoAcoustic
) {
3227 if(LunExt
->opt_AcousticMode
) {
3228 KdPrint2((PRINT_PREFIX
" Try Enable Acoustic Mgmt\n"));
3229 // setup acoustic mgmt
3230 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3231 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3232 LunExt
->opt_AcousticMode
, ATA_C_F_ENAB_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3233 // Check for errors.
3234 if (statusByte
& IDE_STATUS_ERROR
) {
3235 KdPrint2((PRINT_PREFIX
3236 "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n",
3240 KdPrint2((PRINT_PREFIX
" Disable Acoustic Mgmt\n"));
3241 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3242 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3243 0, ATA_C_F_DIS_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3246 if(LunExt
->IdentifyData
.FeaturesSupport
.Standby
) {
3247 KdPrint2((PRINT_PREFIX
" Try init standby timer: %d\n"));
3248 // setup standby timer
3249 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3250 IDE_COMMAND_IDLE
, 0, 0, 0,
3251 LunExt
->opt_StandbyTimer
, 0, ATA_WAIT_BASE_READY
);
3252 // Check for errors.
3253 if (statusByte
& IDE_STATUS_ERROR
) {
3254 KdPrint2((PRINT_PREFIX
3255 "AtapiHwInitialize: standby timer on Device %d failed\n",
3261 } else if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)){
3264 //BOOLEAN isSanyo = FALSE;
3267 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: ATAPI/Changer branch\n"));
3269 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
3270 for (j
= 0; j
< 26; j
+= 2) {
3272 // Build a buffer based on the identify data.
3273 MOV_DW_SWP(vendorId
[j
], ((PUCHAR
)LunExt
->IdentifyData
.ModelNumber
)[j
]);
3276 if (!AtapiStringCmp (vendorId
, "CD-ROM CDR", 11)) {
3278 // Inquiry string for older model had a '-', newer is '_'
3279 if (vendorId
[12] == 'C') {
3281 // Torisan changer. Set the bit. This will be used in several places
3282 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
3283 LunExt
->DeviceFlags
|= (DFLAGS_CHANGER_INITED
| DFLAGS_SANYO_ATAPI_CHANGER
);
3284 LunExt
->DiscsPresent
= 3;
3290 PreferedMode
= LunExt
->opt_MaxTransferMode
;
3291 if((PreferedMode
== 0xffffffff) || (PreferedMode
> chan
->MaxTransferMode
)) {
3292 KdPrint2((PRINT_PREFIX
"MaxTransferMode (overriden): %#x\n", chan
->MaxTransferMode
));
3293 PreferedMode
= chan
->MaxTransferMode
;
3296 if(LunExt
->opt_PreferedTransferMode
!= 0xffffffff) {
3297 KdPrint2((PRINT_PREFIX
"PreferedTransferMode: %#x\n", PreferedMode
));
3298 PreferedMode
= min(LunExt
->opt_PreferedTransferMode
, PreferedMode
);
3301 KdPrint2((PRINT_PREFIX
" try mode %#x\n", PreferedMode
));
3302 LunExt
->LimitedTransferMode
=
3303 LunExt
->TransferMode
=
3306 AtapiDmaInit__(deviceExtension
, LunExt
);
3308 LunExt
->LimitedTransferMode
=
3309 LunExt
->TransferMode
;
3310 KdPrint2((PRINT_PREFIX
"Using %#x mode\n", LunExt
->TransferMode
));
3312 // We need to get our device ready for action before
3313 // returning from this function
3315 // According to the atapi spec 2.5 or 2.6, an atapi device
3316 // clears its status BSY bit when it is ready for atapi commands.
3317 // However, some devices (Panasonic SQ-TC500N) are still
3318 // not ready even when the status BSY is clear. They don't react
3319 // to atapi commands.
3321 // Since there is really no other indication that tells us
3322 // the drive is really ready for action. We are going to check BSY
3323 // is clear and then just wait for an arbitrary amount of time!
3325 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3328 // have to get out of the loop sometime!
3329 // 10000 * 100us = 1000,000us = 1000ms = 1s
3331 GetStatus(chan
, statusByte
);
3332 if(statusByte
== IDE_STATUS_WRONG
) {
3335 while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
) {
3337 KdPrint2((PRINT_PREFIX
"Wait for ATAPI (status %x)\n", statusByte
));
3338 // Wait for Busy to drop.
3339 AtapiStallExecution(100);
3340 GetStatus(chan
, statusByte
);
3344 // 5000 * 100us = 500,000us = 500ms = 0.5s
3345 if(statusByte
!= IDE_STATUS_WRONG
) {
3348 AtapiStallExecution(100);
3349 } while (waitCount
--);
3352 GetBaseStatus(chan
, statusByte
);
3353 AtapiEnableInterrupts(deviceExtension
, lChannel
);
3354 AtapiStallExecution(10);
3359 } // end AtapiHwInitialize__()
3366 AtapiHwInitializeChanger(
3367 IN PVOID HwDeviceExtension
,
3368 IN PSCSI_REQUEST_BLOCK Srb
,
3369 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus
)
3371 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3372 ULONG lChannel
= GET_CHANNEL(Srb
);
3373 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3374 ULONG DeviceNumber
= GET_CDEV(Srb
);
3375 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
3377 if (MechanismStatus
) {
3378 LunExt
->DiscsPresent
= MechanismStatus
->NumberAvailableSlots
;
3379 if (LunExt
->DiscsPresent
> 1) {
3380 LunExt
->DeviceFlags
|= DFLAGS_ATAPI_CHANGER
;
3384 } // end AtapiHwInitializeChanger()
3389 Routine Description:
3390 This routine will parse the string for a match on the keyword, then
3391 calculate the value for the keyword and return it to the caller.
3394 String - The ASCII string to parse.
3395 KeyWord - The keyword for the value desired.
3398 Zero if value not found
3399 Value converted from ASCII to binary.
3404 AtapiParseArgumentString(
3412 ULONG stringLength
= 0;
3413 ULONG keyWordLength
= 0;
3423 // Calculate the string length and lower case all characters.
3429 // Calculate the keyword length.
3435 if (keyWordLength
> stringLength
) {
3437 // Can't possibly have a match.
3441 // Now setup and start the compare.
3446 // The input string may start with white space. Skip it.
3447 while (*cptr
== ' ' || *cptr
== '\t') {
3451 if (*cptr
== '\0') {
3457 while ((*cptr
== *kptr
) ||
3458 (*cptr
>= 'A' && *cptr
<= 'Z' && *cptr
+ ('a' - 'A') == *kptr
) ||
3459 (*cptr
>= 'a' && *cptr
<= 'z' && *cptr
- ('a' - 'A') == *kptr
)) {
3463 if (*cptr
== '\0') {
3469 if (*kptr
== '\0') {
3471 // May have a match backup and check for blank or equals.
3472 while (*cptr
== ' ' || *cptr
== '\t') {
3476 // Found a match. Make sure there is an equals.
3479 // Not a match so move to the next semicolon.
3481 if (*cptr
++ == ';') {
3482 goto ContinueSearch
;
3487 // Skip the equals sign.
3490 // Skip white space.
3491 while ((*cptr
== ' ') || (*cptr
== '\t')) {
3495 if (*cptr
== '\0') {
3496 // Early end of string, return not found
3501 // This isn't it either.
3503 goto ContinueSearch
;
3507 if ((*cptr
== '0') && ((*(cptr
+ 1) == 'x') || (*(cptr
+ 1) == 'X'))) {
3508 // Value is in Hex. Skip the "0x"
3510 for (index
= 0; *(cptr
+ index
); index
++) {
3512 if (*(cptr
+ index
) == ' ' ||
3513 *(cptr
+ index
) == '\t' ||
3514 *(cptr
+ index
) == ';') {
3518 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3519 value
= (16 * value
) + (*(cptr
+ index
) - '0');
3521 if ((*(cptr
+ index
) >= 'a') && (*(cptr
+ index
) <= 'f')) {
3522 value
= (16 * value
) + (*(cptr
+ index
) - 'a' + 10);
3523 } else if ((*(cptr
+ index
) >= 'A') && (*(cptr
+ index
) <= 'F')) {
3524 value
= (16 * value
) + (*(cptr
+ index
) - 'A' + 10);
3526 // Syntax error, return not found.
3533 // Value is in Decimal.
3534 for (index
= 0; *(cptr
+ index
); index
++) {
3536 if (*(cptr
+ index
) == ' ' ||
3537 *(cptr
+ index
) == '\t' ||
3538 *(cptr
+ index
) == ';') {
3542 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3543 value
= (10 * value
) + (*(cptr
+ index
) - '0');
3546 // Syntax error return not found.
3555 // Not a match check for ';' to continue search.
3557 if (*cptr
++ == ';') {
3558 goto ContinueSearch
;
3564 } // end AtapiParseArgumentString()_
3572 IN PVOID HwDeviceExtension
,
3577 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3578 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3581 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3584 KdPrint2((PRINT_PREFIX
"AtapiCallBack:\n"));
3585 // If the last command was DSC restrictive, see if it's set. If so, the device is
3586 // ready for a new request. Otherwise, reset the timer and come back to here later.
3588 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3589 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3590 // we shall have no problem with interrupt handler.
3591 if (!srb
|| chan
->ExpectingInterrupt
) {
3592 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Calling ISR directly due to BUSY\n"));
3593 chan
->DpcState
= DPC_STATE_TIMER
;
3594 if(!AtapiInterrupt__(HwDeviceExtension
, lChannel
)) {
3595 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3596 KdPrint2((PRINT_PREFIX
"AtapiCallBack: What's fucking this ???\n"));
3598 goto ReturnCallback
;
3602 if (!IS_RDP((srb
->Cdb
[0]))) {
3603 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb
->Cdb
[0]));
3607 goto ReturnEnableIntr
;
3609 GetStatus(chan
, statusByte
);
3610 if (statusByte
& IDE_STATUS_DSC
) {
3612 UCHAR PathId
= srb
->PathId
;
3613 UCHAR TargetId
= srb
->TargetId
;
3614 UCHAR Lun
= srb
->Lun
;
3616 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Found DSC for RDP - %#x\n", srb
->Cdb
[0]));
3617 AtapiDmaDBSync(chan
, srb
);
3618 UniataRemoveRequest(chan
, srb
);
3619 ScsiPortNotification(RequestComplete
, deviceExtension
, srb
);
3620 // Clear current SRB.
3621 if(!deviceExtension
->simplexOnly
) {
3622 srb
= UniataGetCurRequest(chan
);
3628 // Ask for next request.
3629 ScsiPortNotification(NextLuRequest
,
3634 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
3637 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3641 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Requesting another timer for Op %#x\n",
3644 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3648 goto ReturnCallback
;
3653 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
3654 KdPrint2((PRINT_PREFIX
"AtapiCallBack: CallDisableInterrupts\n"));
3655 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3656 #ifdef UNIATA_USE_XXableInterrupts
3657 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
3658 // must be called on DISPATCH_LEVEL
3659 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
3660 AtapiEnableInterrupts__
);
3662 AtapiEnableInterrupts(HwDeviceExtension
, lChannel
);
3663 InterlockedExchange(&(chan
->CheckIntr
),
3665 // Will raise IRQL to DIRQL
3666 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3667 AtapiEnableInterrupts__
,
3669 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
3670 #endif // UNIATA_USE_XXableInterrupts
3672 //ASSERT(!deviceExtension->simplexOnly);
3677 // Check other channel
3678 // In simplex mode no interrupts must appear on other channels
3679 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3680 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3686 chan
= &(deviceExtension
->chan
[c
]);
3688 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
3689 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3690 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) == CHECK_INTR_DETECTED
)
3692 //ASSERT(!deviceExtension->simplexOnly);
3693 chan
->DpcState
= DPC_STATE_ISR
;
3694 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3695 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3699 KdPrint2((PRINT_PREFIX
"AtapiCallBack: return\n"));
3702 } // end AtapiCallBack__()
3707 IN PVOID HwDeviceExtension
3710 AtapiCallBack__(HwDeviceExtension
, (UCHAR
)((PHW_DEVICE_EXTENSION
)HwDeviceExtension
)->ActiveDpcChan
);
3711 } // end AtapiCallBack_X()
3713 #endif //UNIATA_CORE
3717 Routine Description:
3719 This is the interrupt service routine for ATAPI IDE miniport driver.
3723 HwDeviceExtension - HBA miniport driver's adapter data storage
3727 TRUE if expecting an interrupt.
3733 IN PVOID HwDeviceExtension
3736 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3738 BOOLEAN status
= FALSE
;
3742 //BOOLEAN checked[AHCI_MAX_PORT];
3746 KdPrint2((PRINT_PREFIX
"Intr: VendorID+DeviceID/Rev %#x/%#x (ex %d)\n",
3747 deviceExtension
->DevID
, deviceExtension
->RevID
, deviceExtension
->ExpectingInterrupt
));
3749 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3750 // AHCI may generate state change notification, never skip this check
3751 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
3752 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3756 // assume all non-interrupted ports to be already checked
3758 // assume all not implemented ports to be already checked
3759 checked
|= ~deviceExtension
->AHCI_PI
;
3761 checked
= 0; // assume all ports are not checked
3764 if(!deviceExtension
->ExpectingInterrupt
) {
3765 // if we do not expect interrupt, exit now,
3766 // but keep in mind that it can be unexpected one
3767 // Note: this is just a hint, not exact counter
3768 KdPrint2((PRINT_PREFIX
"unexpected, 1st chance\n"));
3769 //deviceExtension->ExpectingInterrupt++;
3772 // clear this flag now, it can be set again in sub-calls
3773 deviceExtension
->ExpectingInterrupt
=0;
3776 // for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
3777 // checked[_c] = (UCHAR)((hIS >> _c) & 0x01);
3781 for(pass
=0; pass
<2; pass
++) {
3782 //KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): pass %d\n", pass));
3783 if(status
&& pass
) {
3784 // we catched some expected interrupts now.
3785 // do not touch unexpected until next ISR call
3788 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3790 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3792 if((checked
>>c
) & 0x01)
3795 // check non-empty and expecting interrupt channels first
3796 if(!pass
&& !deviceExtension
->chan
[c
].ExpectingInterrupt
)
3799 checked
|= (ULONG
)1 << c
;
3801 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3803 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3804 // we get here on idle channels or when ISR is posted to DPC
3805 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): disabled INTR on ch %d\n", c
));
3808 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
3810 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): try lock\n"));
3811 // c_state = deviceExtension->chan[c].CheckIntr;
3812 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
3813 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
3816 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3817 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3818 CRNT_ILK_TYPE CHECK_INTR_DETECTED
);
3819 if(c_state
== CHECK_INTR_IDLE
) {
3820 // c_state = deviceExtension->chan[c].CheckIntr;
3821 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
3822 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
3825 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3826 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3827 CRNT_ILK_TYPE CHECK_INTR_IDLE
);
3829 } while(c_state
== CHECK_INTR_CHECK
);
3830 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): locked\n"));
3831 // check if already serviced
3832 if(c_state
== CHECK_INTR_ACTIVE
) {
3833 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
3837 if((c_state
== CHECK_INTR_DETECTED
) ||
3838 (i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3840 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
3841 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): Catch unexpected\n"));
3842 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3847 // disable interrupts on other channel of legacy mode
3848 // ISA-bridged onboard controller
3849 if(deviceExtension
->simplexOnly
/*||
3850 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3851 AtapiDisableInterrupts(deviceExtension
, !c
);
3854 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_ISR
;
3855 if(AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3856 deviceExtension
->LastInterruptedChannel
= (UCHAR
)c
;
3857 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): return status TRUE\n"));
3860 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
3861 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3864 // re-enable interrupts on other channel
3865 if(deviceExtension
->simplexOnly
/*||
3866 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3867 AtapiEnableInterrupts(deviceExtension
, !c
);
3871 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
3872 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3877 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): exit with status %#x\n", status
));
3879 deviceExtension
->FirstChannelToCheck
++;
3880 if(deviceExtension
->FirstChannelToCheck
>= deviceExtension
->NumberChannels
)
3881 deviceExtension
->FirstChannelToCheck
= 0;
3884 } // end AtapiInterrupt()
3892 IN PKINTERRUPT Interrupt
,
3893 IN PVOID Isr2HwDeviceExtension
3896 // This ISR is intended to catch interrupts when we are already in other ISR instance
3897 // for the same device. This may happen when we have multiple channels,
3898 // especially on SMP machines
3900 PISR2_DEVICE_EXTENSION Isr2DeviceExtension
= (PISR2_DEVICE_EXTENSION
)Isr2HwDeviceExtension
;
3901 PHW_DEVICE_EXTENSION deviceExtension
= Isr2DeviceExtension
->HwDeviceExtension
;
3903 BOOLEAN status
= FALSE
;
3909 // we should never get here for ISA/MCA
3910 if(!BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
3911 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3915 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3916 // AHCI may generate state change notification, never skip this check
3917 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
3918 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3922 // assume all non-interrupted ports to be already checked
3924 // assume all not implemented ports to be already checked
3925 checked
|= ~deviceExtension
->AHCI_PI
;
3928 checked
= 0; // assume all ports are not checked
3930 if(!deviceExtension
->ExpectingInterrupt
) {
3931 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !deviceExtension->ExpectingInterrupt\n"));
3932 deviceExtension
->ExpectingInterrupt
++;
3935 //deviceExtension->ExpectingInterrupt = 0;
3937 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3938 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3940 if((checked
>>c
) & 0x01)
3943 checked
|= (ULONG
)1 << c
;
3945 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3946 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: disabled INTR\n"));
3950 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3951 CRNT_ILK_TYPE CHECK_INTR_CHECK
,
3952 CRNT_ILK_TYPE CHECK_INTR_IDLE
) != CHECK_INTR_IDLE
)
3954 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
3955 // hunt on unexpected intr (Some devices generate double interrupts,
3956 // some controllers (at least CMD649) interrupt twice with small delay.
3957 // If interrupts are disabled, they queue interrupt and re-issue it later,
3958 // when we do not expect it.
3963 if((i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3965 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: intr\n"));
3966 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
3967 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: Catch unexpected\n"));
3968 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3973 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_DETECTED
);
3975 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3978 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: status %d, c_count %d\n", status
, c_count
));
3979 if(status
&& (c_count
!= deviceExtension
->NumberChannels
)) {
3980 // there is an active ISR/DPC for one channel, but
3981 // we have an interrupt from another one
3982 // Lets inform current ISR/DPC about new interrupt
3983 InterlockedExchange(&(deviceExtension
->ReCheckIntr
), CHECK_INTR_DETECTED
);
3987 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: return %d\n", status
));
3990 } // end AtapiInterrupt2()
3992 RETTYPE_XXableInterrupts
3995 IN PVOID HwDeviceExtension
3998 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4001 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
4002 KdPrint2((PRINT_PREFIX
"AtapiInterruptDpc: %#x\n",c
));
4004 if(!(deviceExtension
->chan
[c
].ChannelCtrlFlags
& CTRFLAGS_DPC_REQ
)) {
4006 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
4007 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
4008 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
)
4014 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_DPC_REQ
;
4017 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
4018 AtapiDisableInterrupts(deviceExtension, lChannel);
4021 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_DPC
;
4022 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
4023 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
4026 return RETVAL_XXableInterrupts
;
4027 } // end AtapiInterruptDpc()
4030 RETTYPE_XXableInterrupts
4032 AtapiEnableInterrupts__(
4033 IN PVOID HwDeviceExtension
4036 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4037 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__():\n"));
4039 PHW_CHANNEL chan
= NULL
;
4041 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
4042 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__(2): %#x\n",c
));
4043 chan
= &(deviceExtension
->chan
[c
]);
4045 if(chan
->ChannelCtrlFlags
& CTRFLAGS_ENABLE_INTR_REQ
) {
4046 // enable intrs on requested channel
4047 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_ENABLE_INTR_REQ
;
4048 AtapiEnableInterrupts(HwDeviceExtension
, c
);
4049 InterlockedExchange(&(chan
->CheckIntr
),
4052 // check if current or other channel(s) interrupted
4053 //AtapiInterrupt(HwDeviceExtension);
4055 if(deviceExtension
->simplexOnly
) {
4059 // check if other channel(s) interrupted
4060 // must do nothing in simplex mode
4061 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
4062 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
4063 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
4066 //ASSERT(!deviceExtension->simplexOnly);
4067 chan
->DpcState
= DPC_STATE_ISR
;
4068 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
4069 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
4073 // In simplex mode next command must be sent to device here
4074 if(deviceExtension
->simplexOnly
&& chan
) {
4075 PSCSI_REQUEST_BLOCK srb
;
4076 chan
= UniataGetNextChannel(chan
);
4078 srb
= UniataGetCurRequest(chan
);
4083 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
4087 return RETVAL_XXableInterrupts
;
4089 } // end AtapiEnableInterrupts__()
4091 #endif //UNIATA_CORE
4096 AtapiEnableInterrupts(
4097 IN PVOID HwDeviceExtension
,
4101 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4105 if(c
>= deviceExtension
->NumberChannels
) {
4106 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c
));
4109 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
4110 !UniataAhciChanImplemented(deviceExtension
, c
)) {
4111 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c
));
4115 chan
= &(deviceExtension
->chan
[c
]);
4116 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
4117 if(!InterlockedDecrement(&chan
->DisableIntr
)) {
4118 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4119 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
4120 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
4121 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_INF
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
4122 ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
: 0) |
4123 ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
| /* DEBUG */
4125 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
4126 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
)
4129 //SelectDrive(chan, 0);
4130 //GetBaseStatus(chan, statusByte);
4131 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4133 //if(chan->NumberLuns) {
4134 // SelectDrive(chan, 1);
4135 // GetBaseStatus(chan, statusByte);
4136 // AtapiWritePort1(chan, IDX_IO2_o_Control,
4138 // SelectDrive(chan, chan->cur_cdev);
4141 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_INTR_DISABLED
;
4143 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4144 // keep interrupts disabled
4145 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
4147 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4148 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4152 } // end AtapiEnableInterrupts()
4156 AtapiDisableInterrupts(
4157 IN PVOID HwDeviceExtension
,
4161 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4163 if(c
>= deviceExtension
->NumberChannels
) {
4164 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c
));
4167 chan
= &(deviceExtension
->chan
[c
]);
4168 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
4169 // mark channel as busy
4170 if(InterlockedIncrement(&chan
->DisableIntr
)) {
4171 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4172 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
4174 //SelectDrive(chan, 0);
4175 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4176 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4177 //if(chan->NumberLuns) {
4178 // SelectDrive(chan, 1);
4179 // AtapiWritePort1(chan, IDX_IO2_o_Control,
4180 // IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4181 // SelectDrive(chan, chan->cur_cdev);
4184 chan
->ChannelCtrlFlags
|= CTRFLAGS_INTR_DISABLED
;
4188 } // end AtapiDisableInterrupts()
4191 UniataExpectChannelInterrupt(
4192 IN
struct _HW_CHANNEL
* chan
,
4193 IN BOOLEAN Expecting
4196 chan
->ExpectingInterrupt
= Expecting
;
4198 chan
->DeviceExtension
->ExpectingInterrupt
++;
4200 if(chan
->DeviceExtension
->ExpectingInterrupt
) {
4201 chan
->DeviceExtension
->ExpectingInterrupt
--;
4204 } // end UniataExpectChannelInterrupt()
4207 Check hardware for interrupt state
4211 AtapiCheckInterrupt__(
4212 IN PVOID HwDeviceExtension
,
4213 IN UCHAR c
// logical channel
4216 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4217 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4218 PHW_LU_EXTENSION LunExt
;
4220 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
4221 ULONG ChipType
= deviceExtension
->HwFlags
& CHIPTYPE_MASK
;
4224 ULONG pr_status
= 0;
4225 UCHAR dma_status
= 0;
4228 UCHAR statusByte
= 0;
4229 ULONG slotNumber
= deviceExtension
->slotNumber
;
4230 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
4231 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
4234 BOOLEAN DmaTransfer
= FALSE
;
4235 BOOLEAN OurInterrupt
= FALSE
;
4236 BOOLEAN StatusValid
= FALSE
;
4238 UCHAR interruptReason
;
4239 BOOLEAN EarlyIntr
= FALSE
;
4240 BOOLEAN SingleBlockIntr
= FALSE
;
4242 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__:\n"));
4245 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4246 LunExt
= chan
->lun
[chan
->cur_cdev
];
4248 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ chan %#x:\n", chan));
4249 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ (%d/%d):\n", Channel, chan->cur_cdev));
4251 if((ChipFlags
& UNIATA_AHCI
) &&
4252 UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4254 if(!UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
4255 return OurInterrupt
;
4258 OurInterrupt
= UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
4259 if((OurInterrupt
== INTERRUPT_REASON_UNEXPECTED
) &&
4260 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
4261 UniataAhciWaitCommandReady(chan
, 2 /* ms */ );
4262 statusByte
= (UCHAR
)UniataAhciWaitReady(chan
, 0 /* immediate */);
4263 if(!(statusByte
& (IDE_STATUS_BUSY
)) ) {
4264 KdPrint2((PRINT_PREFIX
"ATAPI special case READY\n"));
4265 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
4266 OurInterrupt
= INTERRUPT_REASON_OUR
;
4268 if((statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
)) == (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
) ) {
4269 KdPrint2((PRINT_PREFIX
"ATAPI special case pre ERR-READY\n"));
4270 OurInterrupt
= INTERRUPT_REASON_OUR
;
4272 if(statusByte
& IDE_STATUS_ERROR
) {
4273 KdPrint2((PRINT_PREFIX
"ATAPI special case ERR-READY\n"));
4274 OurInterrupt
= INTERRUPT_REASON_OUR
;
4276 KdPrint2((PRINT_PREFIX
"ATAPI special case ? %x\n", statusByte
));
4277 OurInterrupt
= INTERRUPT_REASON_OUR
;
4280 return OurInterrupt
;
4283 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4285 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension
->DevIndex
,
4286 deviceExtension
->Channel
+ c
, c
));
4288 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension
->DevIndex
,
4289 deviceExtension
->Channel
+ c
, c
));
4290 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4291 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
4294 // do controller-specific interrupt servicing staff
4295 if(deviceExtension
->UnknownDev
) {
4296 KdPrint2((PRINT_PREFIX
" UnknownDev\n"));
4301 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
4302 // Such behavior was observed with Intel ICH-xxx chips
4303 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
4307 case ATA_PROMISE_ID
: {
4311 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x1c);
4315 ((Channel
) ? 0x00004000 : 0x00000400))) {
4316 KdPrint2((PRINT_PREFIX
" Promise old/new unexpected\n"));
4317 return INTERRUPT_REASON_IGNORE
;
4321 AtapiWritePort1(chan
, IDX_BM_DeviceSpecific0
, 0x0b);
4322 status
= AtapiReadPort1(chan
, IDX_BM_DeviceSpecific1
);
4325 if(!(status
& 0x20)) {
4326 KdPrint2((PRINT_PREFIX
" Promise tx unexpected\n"));
4327 return INTERRUPT_REASON_IGNORE
;
4331 ULONG stat_reg
= (ChipFlags
& PRG2
) ? 0x60 : 0x6c;
4332 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x40);
4333 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x40, status
);
4335 if(status
& (1 << (Channel
+1))) {
4338 KdPrint2((PRINT_PREFIX
" Promise mio unexpected\n"));
4339 return INTERRUPT_REASON_IGNORE
;
4342 if(!(ChipFlags
& UNIATA_SATA
))
4345 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),stat_reg
);
4346 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),stat_reg
, (pr_status
& (0x11 << Channel
)));
4347 if(pr_status
& (0x11 << Channel
)) {
4348 // TODO: reset channel
4349 KdPrint2((PRINT_PREFIX
" Promise mio unexpected + reset req\n"));
4350 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, 0);
4352 if(!(status
& (0x01 << Channel
))) {
4354 KdPrint2((PRINT_PREFIX
" Promise mio unexpected attach\n"));
4355 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, 0);
4357 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4358 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4360 return INTERRUPT_REASON_IGNORE
;
4363 AtapiWritePort4(chan
, IDX_BM_DeviceSpecific0
, 0x00000001);
4367 case ATA_NVIDIA_ID
: {
4368 if(!(ChipFlags
& UNIATA_SATA
))
4371 KdPrint2((PRINT_PREFIX
"NVIDIA\n"));
4373 ULONG offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
4374 ULONG shift
= Channel
<< ((ChipFlags
& NVQ
) ? 4 : 2);
4376 /* get and clear interrupt status */
4377 if(ChipFlags
& NVQ
) {
4378 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4379 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0fUL
<< shift
) | 0x00f000f0);
4381 pr_status
= AtapiReadPortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4382 AtapiWritePortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0f << shift
));
4384 KdPrint2((PRINT_PREFIX
" pr_status %x, shift %x\n", pr_status
, shift
));
4386 /* check for and handle connect events */
4387 if(((pr_status
& (0x0cUL
<< shift
)) == (0x04UL
<< shift
)) ) {
4388 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, 0);
4390 /* check for and handle disconnect events */
4391 if((pr_status
& (0x08UL
<< shift
)) &&
4392 !((pr_status
& (0x04UL
<< shift
) &&
4393 UniataSataReadPort4(chan
, IDX_SATA_SStatus
, 0))) ) {
4394 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, 0);
4396 /* do we have any device action ? */
4397 if(!(pr_status
& (0x01UL
<< shift
))) {
4398 KdPrint2((PRINT_PREFIX
" nVidia unexpected\n"));
4399 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4400 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4402 return INTERRUPT_REASON_IGNORE
;
4408 KdPrint2((PRINT_PREFIX
"ATI\n"));
4409 if(ChipType
== SIIMIO
) {
4414 case ATA_SILICON_IMAGE_ID
:
4416 if(ChipType
== SIIMIO
) {
4418 reg32
= AtapiReadPort4(chan
, IDX_BM_DeviceSpecific0
);
4419 KdPrint2((PRINT_PREFIX
" Sii DS0 %x\n", reg32
));
4420 if(reg32
== 0xffffffff) {
4421 KdPrint2((PRINT_PREFIX
" Sii mio unexpected\n"));
4422 return INTERRUPT_REASON_IGNORE
;
4424 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
))) {
4425 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (2)\n"));
4426 return INTERRUPT_REASON_IGNORE
;
4429 if(ChipFlags
& UNIATA_SATA
) {
4430 if(reg32
& (BM_DS0_SII_DMA_SATA_IRQ
| BM_DS0_SII_IRQ
)) {
4432 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
4433 * controllers continue to assert IRQ as long as
4434 * SError bits are pending. Clear SError immediately.
4436 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4437 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4444 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4445 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (3)\n"));
4446 return OurInterrupt
;
4448 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
& ~BM_STATUS_ERR
);
4449 goto skip_dma_stat_check
;
4452 if(!(deviceExtension
->HwFlags
& SIIINTR
))
4454 GetPciConfig1(0x71, reg8
);
4455 KdPrint2((PRINT_PREFIX
" 0x71 = %#x\n", reg8
));
4457 (Channel
? 0x08 : 0x04))) {
4458 return INTERRUPT_REASON_IGNORE
;
4461 KdPrint2((PRINT_PREFIX
" cmd our\n"));
4462 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4464 SetPciConfig1(0x71, (Channel
? 0x08 : 0x04));
4471 //dma_status = GetDmaStatus(deviceExtension, lChannel);
4472 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4473 KdPrint2((PRINT_PREFIX
" Acard unexpected\n"));
4474 return INTERRUPT_REASON_IGNORE
;
4476 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
| BM_STATUS_INTR
);
4477 AtapiStallExecution(1);
4478 AtapiWritePort1(chan
, IDX_BM_Command
,
4479 AtapiReadPort1(chan
, IDX_BM_Command
) & ~BM_COMMAND_START_STOP
);
4480 goto skip_dma_stat_check
;
4482 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4483 if(ChipFlags
& UNIATA_AHCI
) {
4486 if(ChipFlags
& UNIATA_SATA
) {
4487 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4488 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4490 if(!(chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
4491 if(UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, 1)) {
4492 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4499 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4500 if(ChipFlags
& UNIATA_AHCI
) {
4503 if(ChipFlags
& UNIATA_SATA
) {
4504 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4505 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4511 KdPrint2((PRINT_PREFIX
" perform generic check\n"));
4513 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4514 KdPrint2((PRINT_PREFIX
" DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status
));
4515 if(dma_status
& BM_STATUS_ERR
) {
4516 KdPrint2((PRINT_PREFIX
" DmaTransfer + BM_STATUS_ERR -> our\n"));
4517 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4519 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4520 GetStatus(chan
, statusByte
);
4522 KdPrint2((PRINT_PREFIX
" status %#x\n", statusByte
));
4523 if(statusByte
& IDE_STATUS_ERROR
) {
4524 KdPrint2((PRINT_PREFIX
" IDE_STATUS_ERROR -> our\n", statusByte
));
4525 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4527 if ((statusByte
& IDE_STATUS_DSC
) &&
4528 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
4529 (dma_status
== BM_STATUS_ACTIVE
)) {
4530 KdPrint2((PRINT_PREFIX
" special case DMA + ATAPI + IDE_STATUS_DSC -> our\n", statusByte
));
4531 // some devices interrupts on each block transfer even in DMA mode
4532 if(LunExt
->TransferMode
>= ATA_SDMA
&& LunExt
->TransferMode
<= ATA_WDMA2
) {
4533 KdPrint2((PRINT_PREFIX
" wait for completion\n"));
4534 ///* clear interrupt and get status */
4535 //GetBaseStatus(chan, statusByte);
4536 //return INTERRUPT_REASON_IGNORE;
4537 SingleBlockIntr
= TRUE
;
4540 return INTERRUPT_REASON_IGNORE
;
4545 if(dma_status
& BM_STATUS_INTR
) {
4546 // bullshit, we have DMA interrupt, but had never initiate DMA operation
4547 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr\n"));
4548 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4550 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4553 skip_dma_stat_check
:
4554 if(!(ChipFlags
& UNIATA_SATA
) && chan
->ExpectingInterrupt
) {
4555 AtapiStallExecution(1);
4558 /* if drive is busy it didn't interrupt */
4559 /* the exception is DCS + BSY state of ATAPI devices */
4561 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4562 GetStatus(chan
, statusByte
);
4564 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4565 KdPrint3((PRINT_PREFIX
" ATAPI status %#x\n", statusByte
));
4567 KdPrint2((PRINT_PREFIX
" IDE status %#x\n", statusByte
));
4569 if (statusByte
== IDE_STATUS_WRONG
) {
4570 // interrupt from empty controller ?
4572 if (statusByte
& IDE_STATUS_BUSY
) {
4573 if(!chan
->ExpectingInterrupt
) {
4574 KdPrint3((PRINT_PREFIX
" unexpected intr + BUSY\n"));
4575 return OurInterrupt
;
4578 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4579 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4581 KdPrint2((PRINT_PREFIX
" expecting intr + BUSY (3), non ATAPI\n"));
4582 return INTERRUPT_REASON_IGNORE
;
4584 if((statusByte
& ~IDE_STATUS_DRQ
) != (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
| IDE_STATUS_DSC
)) {
4585 KdPrint3((PRINT_PREFIX
" unexpected status, seems it is not our\n"));
4586 return INTERRUPT_REASON_IGNORE
;
4588 if(!(LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
) && (statusByte
& IDE_STATUS_DRQ
)) {
4589 KdPrint3((PRINT_PREFIX
" unexpected DRQ, seems it is not our\n"));
4590 return INTERRUPT_REASON_IGNORE
;
4595 if(dma_status
& BM_STATUS_INTR
) {
4596 KdPrint3((PRINT_PREFIX
" our interrupt with BSY set, try wait in ISR or post to DPC\n"));
4597 /* clear interrupt and get status */
4598 GetBaseStatus(chan
, statusByte
);
4599 if(!(dma_status
& BM_STATUS_ACTIVE
)) {
4600 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4602 KdPrint3((PRINT_PREFIX
" base status %#x (+BM_STATUS_INTR)\n", statusByte
));
4603 return INTERRUPT_REASON_OUR
;
4606 if(g_WaitBusyInISR
) {
4607 GetStatus(chan
, statusByte
);
4608 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4609 reg8
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4610 KdPrint2((PRINT_PREFIX
" Error reg (%#x)\n", reg8
));
4611 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4612 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4614 if (statusByte
& IDE_STATUS_BUSY
) {
4615 KdPrint2((PRINT_PREFIX
" still BUSY, seems it is not our\n"));
4616 return INTERRUPT_REASON_IGNORE
;
4622 /* clear interrupt and get status */
4623 GetBaseStatus(chan
, statusByte
);
4624 KdPrint2((PRINT_PREFIX
" base status %#x\n", statusByte
));
4625 if (statusByte
== IDE_STATUS_WRONG
) {
4626 // interrupt from empty controller ?
4628 if(!(statusByte
& (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
))) {
4629 KdPrint2((PRINT_PREFIX
" no DRQ/DRDY set\n"));
4630 return OurInterrupt
;
4633 #ifndef UNIATA_PIO_ONLY
4635 if(!SingleBlockIntr
&& (!EarlyIntr
|| g_WaitBusyInISR
)) {
4636 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4638 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4639 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4643 if(SingleBlockIntr
) {
4644 KdPrint2((PRINT_PREFIX
" set REQ_STATE_ATAPI_EXPECTING_DATA_INTR2.\n"));
4646 KdPrint2((PRINT_PREFIX
" set REQ_STATE_EARLY_INTR.\n"));
4649 AtaReq
->ReqState
= SingleBlockIntr
? REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
: REQ_STATE_EARLY_INTR
;
4655 if (!(chan
->ExpectingInterrupt
)) {
4657 KdPrint2((PRINT_PREFIX
" Unexpected interrupt.\n"));
4659 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4660 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4662 KdPrint2((PRINT_PREFIX
" OurInterrupt = %d\n", OurInterrupt
));
4663 return OurInterrupt
;
4665 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
4666 KdPrint3((PRINT_PREFIX
"AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason
));
4667 return OurInterrupt
;
4669 //ASSERT(!chan->queue_depth || chan->cur_req);
4671 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__: exit with TRUE\n"));
4672 return INTERRUPT_REASON_OUR
;
4674 } // end AtapiCheckInterrupt__()
4680 IN PVOID HwDeviceExtension
,
4684 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4685 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4687 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4688 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4690 ULONG wordCount
= 0, wordsThisInterrupt
= DEV_BSIZE
/2;
4691 ULONG status
= SRB_STATUS_SUCCESS
;
4692 UCHAR dma_status
= 0;
4695 UCHAR statusByte
= 0,interruptReason
;
4697 BOOLEAN atapiDev
= FALSE
;
4704 BOOLEAN DmaTransfer
= FALSE
;
4706 ULONG TimerValue
= 1000;
4707 ULONG TotalTimerValue
= 0;
4708 #ifdef UNIATA_USE_XXableInterrupts
4709 BOOLEAN InDpc
= (KeGetCurrentIrql() == DISPATCH_LEVEL
);
4711 BOOLEAN InDpc
= (chan
->DpcState
!= DPC_STATE_ISR
);
4712 #endif // UNIATA_USE_XXableInterrupts
4713 BOOLEAN UseDpc
= deviceExtension
->UseDpc
;
4714 // BOOLEAN RestoreUseDpc = FALSE;
4715 BOOLEAN DataOverrun
= FALSE
;
4716 BOOLEAN NoStartIo
= TRUE
;
4717 BOOLEAN NoRetry
= FALSE
;
4719 KdPrint2((PRINT_PREFIX
"AtapiInterrupt:\n"));
4721 KdPrint2((PRINT_PREFIX
" InDpc = TRUE\n"));
4722 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
4728 UCHAR OldReqState
= REQ_STATE_NONE
;
4730 PHW_LU_EXTENSION LunExt
;
4735 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4737 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension
->DevIndex
, Channel
, KeGetCurrentIrql(), c
));
4740 if((chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
4741 (AtaReq
&& (AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
)) ||
4742 (deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
4744 KdPrint2((PRINT_PREFIX
" DmaTransfer = TRUE\n"));
4748 PathId
= srb
->PathId
;
4749 TargetId
= srb
->TargetId
;
4755 goto enqueue_next_req
;
4758 //ldev = GET_LDEV2(PathId, TargetId, Lun);
4759 DeviceNumber
= (UCHAR
)(TargetId
);
4760 LunExt
= chan
->lun
[DeviceNumber
];
4761 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
4762 KdPrint2((PRINT_PREFIX
" dev_type %s\n", atapiDev
? "ATAPI" : "IDE"));
4764 // check if we are in ISR DPC
4766 KdPrint2((PRINT_PREFIX
" InDpc -> CTRFLAGS_INTR_DISABLED\n"));
4767 goto ServiceInterrupt
;
4771 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4774 if (!(chan
->ExpectingInterrupt
)) {
4776 KdPrint2((PRINT_PREFIX
" Unexpected interrupt for this channel.\n"));
4780 // change request state
4782 OldReqState
= AtaReq
->ReqState
;
4783 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4784 KdPrint2((PRINT_PREFIX
" OldReqState = %x\n", OldReqState
));
4787 // We don't want using DPC for fast operations, like
4788 // DMA completion, sending CDB, short ATAPI transfers, etc.
4790 // We MUST use DPC, because of interprocessor synchronization
4791 // on multiprocessor platforms
4794 goto ServiceInterrupt
;
4796 switch(OldReqState
) {
4797 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR
:
4798 KdPrint3((PRINT_PREFIX
" EXPECTING_CMD_INTR\n"));
4799 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR
:
4800 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
:
4801 case REQ_STATE_DPC_WAIT_BUSY0
:
4802 case REQ_STATE_DPC_WAIT_BUSY1
:
4803 KdPrint2((PRINT_PREFIX
" continue service interrupt\n"));
4804 goto ServiceInterrupt
;
4805 case REQ_STATE_ATAPI_DO_NOTHING_INTR
:
4806 KdPrint2((PRINT_PREFIX
" do nothing on interrupt\n"));
4810 if(!DmaTransfer
&& !atapiDev
) {
4811 KdPrint2((PRINT_PREFIX
" service PIO HDD\n"));
4818 goto ServiceInterrupt
;
4820 #ifdef UNIATA_USE_XXableInterrupts
4822 KdPrint2((PRINT_PREFIX
" Unexpected InDpc\n"));
4824 // shall never get here
4829 KdPrint2((PRINT_PREFIX
" this is direct DPC call on DRQL\n"));
4831 AtaReq
->ReqState
= REQ_STATE_DPC_INTR_REQ
;
4832 KdPrint2((PRINT_PREFIX
" ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
4834 KdPrint2((PRINT_PREFIX
" DPC without AtaReq!!!\n"));
4837 KdPrint2((PRINT_PREFIX
"call service interrupt\n"));
4838 goto ServiceInterrupt
;
4839 #endif // UNIATA_USE_XXableInterrupts
4844 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
4845 // We always get here when are called from timer callback, which is invoked on DRQL.
4846 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
4848 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: start DPC init...\n"));
4849 // disable interrupts for this channel,
4850 // but avoid recursion and double-disable
4851 if(OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4852 UniataExpectChannelInterrupt(chan
, FALSE
);
4853 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4856 chan
->ChannelCtrlFlags
|= CTRFLAGS_DPC_REQ
;
4858 #ifdef UNIATA_USE_XXableInterrupts
4859 // Will lower IRQL to DISPATCH_LEVEL
4860 ScsiPortNotification(CallEnableInterrupts
, HwDeviceExtension
,
4861 /*c ?*/ AtapiInterruptDpc
/*_1 : AtapiInterruptDpc_0*/);
4862 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DPC inited\n"));
4864 // Will raise IRQL to DIRQL
4865 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4868 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
4869 #endif // UNIATA_USE_XXableInterrupts
4874 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4876 if(!InDpc
&& OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4877 // we must block interrupts from this channel
4878 // If device generate new interrupt before we get to DPC,
4879 // ISR will assume, that it is NOT our interrupt
4880 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4881 // We should not clean ExpectingInterrupt flag on channel, since it is used in DPC
4883 // Will raise IRQL to DIRQL
4884 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4888 #endif //UNIATA_CORE
4892 if(AtaReq
&& InDpc
) {
4893 switch(AtaReq
->ReqState
) {
4894 case REQ_STATE_DPC_WAIT_DRQ0
:
4896 case REQ_STATE_DPC_WAIT_BUSY
:
4898 case REQ_STATE_DPC_WAIT_DRQ
:
4900 case REQ_STATE_DPC_WAIT_DRQ_ERR
:
4902 case REQ_STATE_DPC_WAIT_BUSY0
:
4903 case REQ_STATE_DPC_WAIT_BUSY1
:
4904 // continue normal execution
4910 #endif //UNIATA_CORE
4912 // make additional delay for old devices (if we are not in DPC)
4913 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
4917 !(deviceExtension->HwFlags & UNIATA_SATA)
4919 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
4920 AtapiStallExecution(10);
4924 /* clear interrupt and get status */
4925 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4926 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, srb
);
4927 statusByte
= (UCHAR
)(AtaReq
->ahci
.in_status
& IDE_STATUS_MASK
);
4929 if(chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
)) {
4930 KdPrint3((PRINT_PREFIX
"Err intr (%#x), SE (%#x)\n",
4931 chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
),
4932 chan
->AhciLastSError
));
4933 if(chan
->AhciLastIS
& ~ATA_AHCI_P_IX_OF
) {
4934 //KdPrint3((PRINT_PREFIX "Err mask (%#x)\n", chan->AhciLastIS & ~ATA_AHCI_P_IX_OF));
4935 // We have some other error except Overflow
4936 // Just signal ERROR, operation will be aborted in ERROR branch.
4937 statusByte
|= IDE_STATUS_ERROR
;
4938 AtaReq
->ahci
.in_serror
= chan
->AhciLastSError
;
4939 if(chan
->AhciLastSError
& (ATA_SE_HANDSHAKE_ERR
| ATA_SE_LINKSEQ_ERR
| ATA_SE_TRANSPORT_ERR
| ATA_SE_UNKNOWN_FIS
)) {
4940 KdPrint2((PRINT_PREFIX
"Unrecoverable\n"));
4944 // We have only Overflow. Abort operation and continue
4946 UniataDumpAhciPortRegs(chan
);
4948 if(!UniataAhciAbortOperation(chan
)) {
4949 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
4952 UniataDumpAhciPortRegs(chan
);
4954 UniataAhciWaitCommandReady(chan
, 10);
4959 GetBaseStatus(chan
, statusByte
);
4962 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte
));
4964 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Entered with status (%#x)\n", statusByte
));
4968 KdPrint2((PRINT_PREFIX
" operate like in DPC\n"));
4974 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4975 KdPrint3((PRINT_PREFIX
" AHCI branch (IDE)\n"));
4977 if (statusByte
& IDE_STATUS_BUSY
) {
4978 if (deviceExtension
->DriverMustPoll
) {
4979 // Crashdump is polling and we got caught with busy asserted.
4980 // Just go away, and we will be polled again shortly.
4981 KdPrint2((PRINT_PREFIX
" Hit BUSY while polling during crashdump.\n"));
4982 goto ReturnEnableIntr
;
4985 // Ensure BUSY is non-asserted.
4986 // make a very small idle before falling to DPC
4987 k
= (InDpc
&& UseDpc
) ? 1000 : 2;
4989 for (i
= 0; i
< k
; i
++) {
4991 GetBaseStatus(chan
, statusByte
);
4992 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4995 AtapiStallExecution(10);
4998 if (!InDpc
&& UseDpc
&& i
== 2) {
5000 KdPrint2((PRINT_PREFIX
" BUSY on entry. Status %#x, Base IO %#x\n", statusByte
));
5003 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
5008 AtapiStallExecution(TimerValue
);
5009 goto ServiceInterrupt
;
5010 #endif //UNIATA_CORE
5012 if (InDpc
&& i
== k
) {
5013 // reset the controller.
5014 KdPrint2((PRINT_PREFIX
5015 " Resetting due to BUSY on entry - %#x.\n",
5017 goto IntrPrepareResetController
;
5022 if(!LunExt
->IdentifyData
.MajorRevision
&&
5025 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
5027 //KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n"));
5028 //AtapiStallExecution(10);
5030 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5031 KdPrint3((PRINT_PREFIX
" AHCI branch (ATAPI)\n"));
5033 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5034 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
5037 if (statusByte
& IDE_STATUS_BUSY
) {
5038 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
5041 // This is just workaround
5042 // We should DISABLE interrupts before entering WAIT state
5043 UniataExpectChannelInterrupt(chan, TRUE);
5044 #endif //UNIATA_CORE
5046 KdPrint3((PRINT_PREFIX
" BUSY on ATAPI device, waiting %d us\n", LunExt
->AtapiReadyWaitDelay
));
5048 if(LunExt
->AtapiReadyWaitDelay
&& (LunExt
->AtapiReadyWaitDelay
> g_opt_MaxIsrWait
) && !InDpc
&& UseDpc
) {
5049 TimerValue
= LunExt
->AtapiReadyWaitDelay
;
5050 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC (0)\n"));
5051 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
5054 #endif //UNIATA_CORE
5057 GetBaseStatus(chan
, statusByte
);
5058 KdPrint3((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
5059 KdPrint3((PRINT_PREFIX
" Error reg (%#x)\n",
5060 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Error
)));
5061 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5062 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
5065 TotalTimerValue
+= TimerValue
;
5067 KdPrint3((PRINT_PREFIX
" too long wait -> DPC\n"));
5069 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC\n"));
5071 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
5073 KdPrint2((PRINT_PREFIX
" too long wait: DPC -> DPC\n"));
5075 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY1
;
5079 if(!LunExt
->AtapiReadyWaitDelay
) {
5080 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
5084 #endif //UNIATA_CORE
5087 AtapiStallExecution(TimerValue
);
5090 if(!LunExt
->AtapiReadyWaitDelay
) {
5091 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
5092 KdPrint2((PRINT_PREFIX
" store AtapiReadyWaitDelay: %d\n", LunExt
->AtapiReadyWaitDelay
));
5094 if (statusByte
& IDE_STATUS_BUSY
) {
5095 KdPrint3((PRINT_PREFIX
" expecting intr + BUSY (2), try DPC wait\n"));
5101 if(AtaReq
&& DmaTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
5102 switch(OldReqState
) {
5103 case REQ_STATE_EARLY_INTR
:
5104 case REQ_STATE_DPC_WAIT_BUSY0
:
5106 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
5107 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DMA still active\n"));
5108 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5115 // Check for error conditions.
5116 if ((statusByte
& IDE_STATUS_ERROR
) ||
5117 (dma_status
& BM_STATUS_ERR
)) {
5119 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5120 error
= AtaReq
->ahci
.in_error
;
5123 UniataDumpAhciPortRegs(chan
);
5125 if(!UniataAhciAbortOperation(chan
)) {
5126 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
5128 // clear interrupts again
5129 UniataAhciWaitCommandReady(chan
, 10);
5131 UniataDumpAhciPortRegs(chan
);
5133 UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
5135 AtaReq
->retry
+= MAX_RETRIES
;
5136 if(!error
&& (statusByte
& IDE_STATUS_ERROR
)) {
5137 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: force error status\n"));
5138 error
|= IDE_STATUS_ERROR
;
5142 UniataDumpAhciPortRegs(chan
);
5145 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5147 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error %#x\n", error
));
5149 if(error & IDE_STATUS_CORRECTED_ERROR) {
5150 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
5151 statusByte &= ~IDE_STATUS_ERROR;
5156 KdPrint2((PRINT_PREFIX
" Bad Lba %#I64x\n", AtaReq
->lba
));
5158 KdPrint2((PRINT_PREFIX
" Bad Lba unknown\n"));
5161 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5162 KdPrint2((PRINT_PREFIX
" no wait ready after error\n"));
5165 KdPrint2((PRINT_PREFIX
" wait 100 ready after IDE error\n"));
5166 AtapiStallExecution(100);
5168 KdPrint2((PRINT_PREFIX
" wait 10 ready after ATAPI error\n"));
5169 AtapiStallExecution(10);
5173 KdPrint3((PRINT_PREFIX
" Intr on DRQ %x\n",
5174 LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
));
5176 for (k
= atapiDev
? 0 : 200; k
; k
--) {
5177 GetBaseStatus(chan
, statusByte
);
5178 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5179 AtapiStallExecution(50);
5186 /* if this is a UDMA CRC error, reinject request */
5189 if(AtaReq
->retry
< MAX_RETRIES
) {
5190 #ifdef IO_STATISTICS
5191 chan
->lun
[DeviceNumber
]->ModeErrorCount
[AtaReq
->retry
]++;
5192 #endif //IO_STATISTICS
5194 (error & IDE_ERROR_ICRC)*/) {
5195 KdPrint2((PRINT_PREFIX
"Errors in DMA mode\n"));
5196 if(AtaReq
->retry
< MAX_RETRIES
) {
5198 if(!(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
5199 //AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
5200 // Downrate will happen in AtapiDmaReinit(), try UDMA-2 for HDD only
5201 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5203 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5207 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5210 KdPrint2((PRINT_PREFIX
"Errors in PIO mode\n"));
5214 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5215 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason
));
5217 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
5218 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5221 if(deviceExtension
->HwFlags
& UNIATA_SATA
) {
5222 UniataSataClearErr(HwDeviceExtension
, lChannel
, UNIATA_SATA_IGNORE_CONNECT
, 0);
5226 if(DmaTransfer
&& (chan
->lun
[DeviceNumber
]->TransferMode
> ATA_UDMA2
) &&
5227 ((error
>> 4) == SCSI_SENSE_HARDWARE_ERROR
)) {
5228 if(AtaReq
->retry
< MAX_RETRIES
) {
5230 // Downrate will happen in AtapiDmaReinit(), use PIO immediately for ATAPI
5231 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5232 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5233 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5234 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5238 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5241 KdPrint3((PRINT_PREFIX
"Errors in PIO mode\n"));
5245 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error\n"));
5246 if (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
5247 // Fail this request.
5248 status
= SRB_STATUS_ERROR
;
5249 goto CompleteRequest
;
5251 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n"));
5254 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE_LBA48
) {
5255 KdPrint2((PRINT_PREFIX
"DMA doesn't work right with LBA48\n"));
5256 deviceExtension
->HbaCtrlFlags
|= HBAFLAGS_DMA_DISABLED_LBA48
;
5258 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
) {
5259 #ifdef IO_STATISTICS
5260 KdPrint2((PRINT_PREFIX
"Some higher mode doesn't work right :((\n"));
5261 KdPrint2((PRINT_PREFIX
"Recovery stats[%d]: %d vs %d\n",
5263 LunExt
->RecoverCount
[AtaReq
->retry
],
5264 LunExt
->BlockIoCount
5266 LunExt
->RecoverCount
[AtaReq
->retry
]++;
5267 if(LunExt
->RecoverCount
[AtaReq
->retry
] >= chan
->lun
[DeviceNumber
]->BlockIoCount
/3 ||
5268 (deviceExtension
->HwFlags
& UNIATA_NO80CHK
)
5271 if(deviceExtension
->HwFlags
& UNIATA_NO80CHK
) {
5272 #endif //IO_STATISTICS
5273 KdPrint2((PRINT_PREFIX
"Limit transfer rate to %x\n", LunExt
->TransferMode
));
5274 LunExt
->LimitedTransferMode
=
5275 LunExt
->TransferMode
;
5278 #ifdef IO_STATISTICS
5279 if(AtaReq
->bcount
) {
5280 // we need stats for Read/Write operations
5281 LunExt
->BlockIoCount
++;
5284 #endif //IO_STATISTICS
5288 // check reason for this interrupt.
5291 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI branch\n"));
5294 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5295 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
5297 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5299 wordsThisInterrupt
= DEV_BSIZE
/2;
5307 // simulate DRQ for DMA transfers
5308 statusByte
|= IDE_STATUS_DRQ
;
5310 if (statusByte
& IDE_STATUS_DRQ
) {
5313 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5315 if (LunExt
->MaximumBlockXfer
) {
5316 wordsThisInterrupt
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5319 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5321 interruptReason
= ATAPI_IR_IO_toHost
;
5323 } else if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5324 interruptReason
= ATAPI_IR_IO_toDev
;
5327 status
= SRB_STATUS_ERROR
;
5328 goto CompleteRequest
;
5331 } else if (statusByte
& IDE_STATUS_BUSY
) {
5333 //AtapiEnableInterrupts(deviceExtension, lChannel);
5334 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
5339 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: !DRQ, !BUSY, WordsLeft %#x\n", AtaReq
->WordsLeft
));
5340 if (AtaReq
->WordsLeft
) {
5342 // Funky behaviour seen with PCI IDE (not all, just one).
5344 // The ISR hits with DRQ low, but comes up later.
5345 for (k
= 0; k
< 5000; k
++) {
5346 GetBaseStatus(chan
, statusByte
);
5347 if (statusByte
& IDE_STATUS_DRQ
) {
5352 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ0
;
5354 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq0)\n"));
5358 AtapiStallExecution(TimerValue
);
5359 goto ServiceInterrupt
;
5360 #endif //UNIATA_CORE
5362 AtapiStallExecution(100);
5365 // reset the controller.
5366 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
5368 IntrPrepareResetController
:
5369 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
);
5370 goto ReturnEnableIntr
;
5373 interruptReason
= (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? ATAPI_IR_IO_toHost
: ATAPI_IR_IO_toDev
;
5377 // Command complete - verify, write, or the SMART enable/disable.
5378 // Also get_media_status
5379 interruptReason
= ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
;
5384 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason
, statusByte
));
5385 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5386 KdPrint2((PRINT_PREFIX
" AHCI path, WordsTransfered %x, WordsLeft %x\n", AtaReq
->WordsTransfered
, AtaReq
->WordsLeft
));
5387 /* if(chan->AhciLastIS & ATA_AHCI_P_IX_OF) {
5388 //status = SRB_STATUS_DATA_OVERRUN;
5391 status = SRB_STATUS_SUCCESS;
5393 if(AtaReq
->WordsTransfered
>= AtaReq
->WordsLeft
) {
5394 AtaReq
->WordsLeft
= 0;
5396 AtaReq
->WordsLeft
-= AtaReq
->WordsTransfered
;
5398 //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
5399 // status = SRB_STATUS_DATA_OVERRUN;
5401 status
= SRB_STATUS_SUCCESS
;
5402 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5403 goto CompleteRequest
;
5405 if (interruptReason
== ATAPI_IR_COD_Cmd
&& (statusByte
& IDE_STATUS_DRQ
)) {
5406 // Write the packet.
5407 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Writing Atapi packet.\n"));
5408 // Send CDB to device.
5409 WriteBuffer(chan
, (PUSHORT
)srb
->Cdb
,
5410 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
5412 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5414 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
5415 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: AtapiDmaStart().\n"));
5416 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, srb
);
5419 goto ReturnEnableIntr
;
5421 } else if (interruptReason
== ATAPI_IR_IO_toDev
&& (statusByte
& IDE_STATUS_DRQ
)) {
5426 // Pick up bytes to transfer and convert to words.
5428 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
5431 (USHORT
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
5433 // Covert bytes to words.
5435 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get W wordCount %#x\n", wordCount
));
5437 if (wordCount
!= AtaReq
->WordsLeft
) {
5438 KdPrint2((PRINT_PREFIX
5439 "AtapiInterrupt: %d words requested; %d words xferred\n",
5444 // Verify this makes sense.
5445 if (wordCount
> AtaReq
->WordsLeft
) {
5446 wordCount
= AtaReq
->WordsLeft
;
5447 KdPrint2((PRINT_PREFIX
5448 "AtapiInterrupt: Write underrun\n"));
5454 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
5455 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5456 // Transfer only words requested.
5457 wordCount
= AtaReq
->WordsLeft
;
5459 // Transfer next block.
5460 wordCount
= wordsThisInterrupt
;
5465 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5466 //ASSERT(AtaReq->WordsLeft == wordCount);
5467 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5468 KdPrint2((PRINT_PREFIX
5469 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5470 if(AtaReq
->WordsLeft
> wordCount
) {
5471 AtaReq
->WordsLeft
-= wordCount
;
5472 AtaReq
->WordsTransfered
+= wordCount
;
5473 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5474 goto ReturnEnableIntr
;
5476 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5478 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5479 AtaReq
->WordsLeft
= 0;
5480 status
= SRB_STATUS_SUCCESS
;
5481 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5482 goto CompleteRequest
;
5485 // Ensure that this is a write command.
5486 if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5488 KdPrint2((PRINT_PREFIX
5489 "AtapiInterrupt: Write interrupt\n"));
5491 statusByte
= WaitOnBusy(chan
);
5493 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
5498 UniataGetPioTiming(LunExt
));
5502 (PULONG
)(AtaReq
->DataBuffer
),
5504 UniataGetPioTiming(LunExt
));
5508 KdPrint3((PRINT_PREFIX
5509 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5513 if(!wordCount
&& atapiDev
&&
5514 !(statusByte
& (IDE_STATUS_ERROR
| IDE_STATUS_BUSY
)) &&
5515 (statusByte
& IDE_STATUS_DRQ
)) {
5516 // this can be late Packet interrupt after packet sending
5517 KdPrint2((PRINT_PREFIX
" unreliable wordCount ?\n"));
5519 wordCount
= AtapiSuckPortBuffer2(chan
,
5522 KdPrint2((PRINT_PREFIX
" transferred %#x\n", wordCount
));
5523 GetBaseStatus(chan
, statusByte
);
5524 KdPrint2((PRINT_PREFIX
" status %#x, statusByte\n"));
5526 interruptReason
= ATAPI_IR_IO_toHost
;
5528 UniataDumpATARegs(chan
);
5531 if(wordCount
&& AtaReq
->WordsLeft
) {
5532 goto continue_atapi_pio_read
;
5535 // Fail this request.
5536 status
= SRB_STATUS_ERROR
;
5537 if(!wordCount
&& atapiDev
&& (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
)) {
5538 // some devices feel bad after incorrect commands and may need reset
5539 KdPrint2((PRINT_PREFIX
5540 "AtapiInterrupt: Try ATAPI reset\n"));
5542 AtapiDisableInterrupts(deviceExtension
, lChannel
);
5543 AtapiSoftReset(chan
, DeviceNumber
);
5544 AtapiEnableInterrupts(deviceExtension
, lChannel
);
5545 status
= SRB_STATUS_BUS_RESET
;
5546 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
5548 // goto IntrPrepareResetController;
5550 goto CompleteRequest
;
5552 // Advance data buffer pointer and bytes left.
5553 AtaReq
->DataBuffer
+= wordCount
;
5554 AtaReq
->WordsLeft
-= wordCount
;
5555 AtaReq
->WordsTransfered
+= wordCount
;
5558 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5561 goto ReturnEnableIntr
;
5563 } else if (interruptReason
== ATAPI_IR_IO_toHost
&& (statusByte
& IDE_STATUS_DRQ
)) {
5568 // Pick up bytes to transfer and convert to words.
5570 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
) |
5571 (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8);
5573 // Convert bytes to words.
5575 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get R wordCount %#x\n", wordCount
));
5577 if (wordCount
!= AtaReq
->WordsLeft
) {
5578 KdPrint2((PRINT_PREFIX
5579 "AtapiInterrupt: %d words requested; %d words xferred\n",
5584 // Verify this makes sense.
5585 if (wordCount
> AtaReq
->WordsLeft
) {
5586 wordCount
= AtaReq
->WordsLeft
;
5592 // Check if words left is at least 256.
5593 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5594 // Transfer only words requested.
5595 wordCount
= AtaReq
->WordsLeft
;
5597 // Transfer next block.
5598 wordCount
= wordsThisInterrupt
;
5603 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5604 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5605 KdPrint2((PRINT_PREFIX
5606 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5607 if(AtaReq
->WordsLeft
> wordCount
) {
5608 AtaReq
->WordsLeft
-= wordCount
;
5609 AtaReq
->WordsTransfered
+= wordCount
;
5610 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5611 goto ReturnEnableIntr
;
5613 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5615 //ASSERT(AtaReq->WordsLeft == wordCount);
5616 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5617 AtaReq
->WordsLeft
= 0;
5618 status
= SRB_STATUS_SUCCESS
;
5619 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5620 goto CompleteRequest
;
5623 // Ensure that this is a read command.
5624 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5627 "AtapiInterrupt: Read interrupt\n"));*/
5629 statusByte
= WaitOnBusy(chan
);
5631 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
5632 KdPrint2((PRINT_PREFIX
5633 "IdeIntr: Read %#x words\n", wordCount
));
5638 UniataGetPioTiming(LunExt
));
5639 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)-1) ));
5640 //KdDump(AtaReq->DataBuffer, wordCount*2);
5641 if(srb
&& atapiDev
&& srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
5642 KdDump(AtaReq
->DataBuffer
, wordCount
*2);
5645 GetBaseStatus(chan
, statusByte
);
5646 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
5649 KdPrint2((PRINT_PREFIX
" DataOverrun\n"));
5650 AtapiSuckPort2(chan
);
5651 GetBaseStatus(chan
, statusByte
);
5654 if(statusByte
& IDE_STATUS_BUSY
) {
5655 for (i
= 0; i
< 2; i
++) {
5656 AtapiStallExecution(10);
5657 GetBaseStatus(chan
, statusByte
);
5658 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5664 KdPrint2((PRINT_PREFIX
5665 "IdeIntr: Read %#x Dwords\n", wordCount
/2));
5668 (PULONG
)(AtaReq
->DataBuffer
),
5670 UniataGetPioTiming(LunExt
));
5674 KdPrint3((PRINT_PREFIX
5675 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5679 // Fail this request.
5680 status
= SRB_STATUS_ERROR
;
5681 goto CompleteRequest
;
5683 continue_atapi_pio_read
:
5684 // Advance data buffer pointer and bytes left.
5685 AtaReq
->DataBuffer
+= wordCount
;
5686 AtaReq
->WordsLeft
-= wordCount
;
5687 AtaReq
->WordsTransfered
+= wordCount
;
5689 // Check for read command complete.
5690 if (AtaReq
->WordsLeft
== 0) {
5692 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
5695 // Work around to make many atapi devices return correct sector size
5696 // of 2048. Also certain devices will have sector count == 0x00, check
5698 if ((srb
->Cdb
[0] == SCSIOP_READ_CAPACITY
) &&
5699 (LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
)) {
5701 AtaReq
->DataBuffer
-= wordCount
;
5702 if (AtaReq
->DataBuffer
[0] == 0x00) {
5704 *((ULONG
*) &(AtaReq
->DataBuffer
[0])) = 0xFFFFFF7F;
5708 *((ULONG
*) &(AtaReq
->DataBuffer
[2])) = 0x00080000;
5709 AtaReq
->DataBuffer
+= wordCount
;
5712 GetStatus(chan
, statusByte
);
5713 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5714 // Assume command is completed if BUSY is cleared
5715 // and all data read
5716 // Optionally, we may receive COMPLETE interrupt later and
5717 // treat it as unexpected
5718 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete ? status %x\n", statusByte
));
5720 status
= SRB_STATUS_SUCCESS
;
5721 goto CompleteRequest
;
5727 // Completion for IDE drives.
5728 if (AtaReq->WordsLeft) {
5729 status = SRB_STATUS_DATA_OVERRUN;
5731 status = SRB_STATUS_SUCCESS;
5734 goto CompleteRequest;
5736 status
= SRB_STATUS_SUCCESS
;
5737 goto CompleteRequest
;
5742 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5743 GetStatus(chan
, statusByte
);
5744 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5745 // Assume command is completed if BUSY is cleared
5746 // even if NOT all data read
5747 // Optionally, we may receive COMPLETE interrupt later and
5748 // treat it as unexpected
5749 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete + underrun ? status %x\n", statusByte
));
5751 status
= SRB_STATUS_SUCCESS
;
5752 goto CompleteRequest
;
5755 if(!atapiDev
&& !DataOverrun
&& (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) &&
5756 (statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_DRQ
))) {
5757 KdPrint2((PRINT_PREFIX
" HDD read data ready \n"));
5758 goto continue_read_drq
;
5763 goto ReturnEnableIntr
;
5765 } else if (interruptReason
== (ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
) && !(statusByte
& IDE_STATUS_DRQ
)) {
5767 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: interruptReason = CompleteRequest\n"));
5768 // Command complete. We exactly know this because of IReason.
5771 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
5772 AtaReq
->WordsTransfered
+= AtaReq
->WordsLeft
;
5773 AtaReq
->WordsLeft
= 0;
5775 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was PIO\n"));
5777 wordCount
= AtaReq
->WordsLeft
;
5778 // Advance data buffer pointer and bytes left.
5779 AtaReq
->DataBuffer
+= wordCount
;
5780 AtaReq
->WordsLeft
-= wordCount
;
5781 AtaReq
->WordsTransfered
+= wordCount
;
5783 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: wordCount %#x, WordsTransfered %#x\n", wordCount
, AtaReq
->WordsTransfered
));
5786 //if (AtaReq->WordsLeft) {
5787 // status = SRB_STATUS_DATA_OVERRUN;
5789 status
= SRB_STATUS_SUCCESS
;
5792 #ifdef UNIATA_DUMP_ATAPI
5794 srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5798 PCHAR ModeSelectData
;
5800 PSCSI_REQUEST_BLOCK Srb
= srb
;
5802 Cdb
= (PCDB
)(Srb
->Cdb
);
5803 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
5804 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
5805 CdbDataLen
= Srb
->DataTransferLength
;
5807 if(CdbDataLen
> 0x1000) {
5808 CdbDataLen
= 0x1000;
5812 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
5813 KdPrint2(("P:T:D=%d:%d:%d\n",
5817 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand
));
5820 if(ScsiCommand
== SCSIOP_MODE_SENSE
) {
5821 KdPrint(("ModeSense 6\n"));
5822 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5823 ModeSelectData
= CdbData
+4;
5824 KdDump(CdbData
, CdbDataLen
);
5826 if(ScsiCommand
== SCSIOP_MODE_SENSE10
) {
5827 KdPrint(("ModeSense 10\n"));
5828 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5829 ModeSelectData
= CdbData
+8;
5830 KdDump(CdbData
, CdbDataLen
);
5832 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5833 KdPrint(("Read buffer from device:\n"));
5834 KdDump(CdbData
, CdbDataLen
);
5839 #endif //UNIATA_DUMP_ATAPI
5843 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, srbstatus %x\n", status
));
5844 // Check and see if we are processing our secret (mechanism status/request sense) srb
5846 if(AtaReq
->WordsLeft
&& (status
== SRB_STATUS_SUCCESS
)) {
5847 KdPrint2((PRINT_PREFIX
"WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq
->WordsLeft
));
5848 status
= SRB_STATUS_DATA_OVERRUN
;
5851 if (AtaReq
->OriginalSrb
) {
5855 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: OriginalSrb != NULL\n"));
5856 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
5858 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
5859 if (status
== SRB_STATUS_SUCCESS
) {
5861 AtapiHwInitializeChanger (HwDeviceExtension
,
5863 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
5865 // Get ready to issue the original srb
5866 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5867 AtaReq
->OriginalSrb
= NULL
;
5870 // failed! Get the sense key and maybe try again
5871 srb
= AtaReq
->Srb
= BuildRequestSenseSrb (
5873 AtaReq
->OriginalSrb
);
5876 // do not enable interrupts in DPC, do not waste time, do it now!
5877 if(UseDpc && chan->DisableIntr) {
5878 AtapiEnableInterrupts(HwDeviceExtension, c);
5880 RestoreUseDpc = TRUE;
5883 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
5885 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
5887 if (srbStatus
== SRB_STATUS_PENDING
) {
5888 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
5889 goto ReturnEnableIntr
;
5893 // restore state on error
5895 AtapiDisableInterrupts(HwDeviceExtension, c);
5899 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
5901 PSENSE_DATA senseData
= (PSENSE_DATA
) srb
->DataBuffer
;
5903 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI command status %#x\n", status
));
5904 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5905 // Check to see if we at least get mininum number of bytes
5906 if ((srb
->DataTransferLength
- AtaReq
->WordsLeft
) >
5907 (FIELD_OFFSET (SENSE_DATA
, AdditionalSenseLength
) + sizeof(senseData
->AdditionalSenseLength
))) {
5908 status
= SRB_STATUS_SUCCESS
;
5912 if (status
== SRB_STATUS_SUCCESS
) {
5914 if ((senseData
->SenseKey
!= SCSI_SENSE_ILLEGAL_REQUEST
) &&
5915 chan
->MechStatusRetryCount
) {
5917 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: MechStatusRetryCount %#x\n", chan
->MechStatusRetryCount
));
5918 // The sense key doesn't say the last request is illegal, so try again
5919 chan
->MechStatusRetryCount
--;
5920 srb
= AtaReq
->Srb
= BuildMechanismStatusSrb (
5922 AtaReq
->OriginalSrb
);
5925 // last request was illegal. No point trying again.
5926 // Do-nothing call ?
5927 AtapiHwInitializeChanger (HwDeviceExtension
,
5929 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
5931 // Get ready to issue the original srb
5932 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5933 AtaReq
->OriginalSrb
= NULL
;
5935 #endif //UNIATA_CORE
5937 // do not enable interrupts in DPC, do not waste time, do it now!
5938 if(UseDpc && chan->DisableIntr) {
5939 AtapiEnableInterrupts(HwDeviceExtension, c);
5941 RestoreUseDpc = TRUE;
5944 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
5946 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan
->ExpectingInterrupt
));
5948 if (srbStatus
== SRB_STATUS_PENDING
) {
5949 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
5950 goto ReturnEnableIntr
;
5954 // restore state on error
5956 AtapiDisableInterrupts(HwDeviceExtension, c);
5962 // If we get here, it means AtapiSendCommand() has failed
5963 // Can't recover. Pretend the original srb has failed and complete it.
5965 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. complete OriginalSrb\n"));
5967 if (AtaReq
->OriginalSrb
) {
5968 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
5969 // Do-nothing call ?
5970 AtapiHwInitializeChanger (HwDeviceExtension
,
5972 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
5973 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5974 AtaReq
->OriginalSrb
= NULL
;
5977 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan
->ExpectingInterrupt
));
5979 // fake an error and read no data
5980 status
= SRB_STATUS_ERROR
;
5981 srb
->ScsiStatus
= 0;
5982 AtaReq
->DataBuffer
= (PUSHORT
)(srb
->DataBuffer
);
5983 AtaReq
->WordsLeft
= srb
->DataTransferLength
;
5986 } else if (status
== SRB_STATUS_ERROR
) {
5988 // Map error to specific SRB status and handle request sense.
5989 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. Begin mapping...\n"));
5990 status
= MapError(deviceExtension
,
5995 } else if(!DmaTransfer
) {
5997 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion\n"));
5998 // Command complete.
6000 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion, wait BUSY\n"));
6001 // Wait for busy to drop.
6002 for (i
= 0; i
< 5*30; i
++) {
6003 GetBaseStatus(chan
, statusByte
);
6004 if (!(statusByte
& IDE_STATUS_BUSY
)) {
6009 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY
;
6011 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (busy)\n"));
6015 AtapiStallExecution(TimerValue
);
6016 goto ServiceInterrupt
;
6017 #endif //UNIATA_CORE
6019 AtapiStallExecution(100);
6024 // reset the controller.
6025 KdPrint2((PRINT_PREFIX
6026 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
6028 goto IntrPrepareResetController
;
6030 // Check to see if DRQ is still up.
6031 if(statusByte
& IDE_STATUS_DRQ
) {
6032 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DRQ...\n"));
6034 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6035 KdPrint2((PRINT_PREFIX
"srb %x data in\n", srb
));
6037 KdPrint2((PRINT_PREFIX
"srb %x data out\n", srb
));
6040 KdPrint2((PRINT_PREFIX
"srb NULL\n"));
6043 KdPrint2((PRINT_PREFIX
"AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq
, AtaReq
->WordsLeft
));
6045 KdPrint2((PRINT_PREFIX
"AtaReq NULL\n"));
6047 if(AtaReq
&& AtaReq
->WordsLeft
/*&&
6048 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
6049 KdPrint2((PRINT_PREFIX
"DRQ+AtaReq->WordsLeft -> next portion\n"));
6053 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
6054 //if ((statusByte & IDE_STATUS_DRQ)) {}
6055 if((statusByte
& IDE_STATUS_DRQ
) &&
6056 (LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_TAPE_DEVICE
| DFLAGS_LBA_ENABLED
)) ) {
6059 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO_wait_DRQ\n"));
6060 for (i
= 0; i
< 200; i
++) {
6061 GetBaseStatus(chan
, statusByte
);
6062 if (!(statusByte
& IDE_STATUS_DRQ
)) {
6067 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq)\n"));
6068 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ
;
6073 AtapiStallExecution(TimerValue
);
6074 goto ServiceInterrupt
;
6075 #endif //UNIATA_CORE
6077 AtapiStallExecution(100);
6081 // reset the controller.
6082 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
6084 goto IntrPrepareResetController
;
6088 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
6089 AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)(-1)), srb
->DataTransferLength
));
6090 //KdDump(srb->DataBuffer, srb->DataTransferLength);
6092 if(!AtapiDmaPioSync(HwDeviceExtension
, srb
, (PUCHAR
)(srb
->DataBuffer
), srb
->DataTransferLength
)) {
6093 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
6097 // Clear interrupt expecting flag.
6098 UniataExpectChannelInterrupt(chan
, FALSE
);
6099 // clear this flag now, it can be set again in sub-calls
6100 InterlockedExchange(&(chan
->CheckIntr
),
6103 // Sanity check that there is a current request.
6105 // Set status in SRB.
6106 srb
->SrbStatus
= (UCHAR
)status
;
6108 // Check for underflow.
6109 if(AtaReq
->WordsLeft
) {
6111 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq
->WordsLeft
));
6112 // Subtract out residual words and update if filemark hit,
6113 // setmark hit , end of data, end of media...
6114 if (!(LunExt
->DeviceFlags
& DFLAGS_TAPE_DEVICE
)) {
6115 if (status
== SRB_STATUS_DATA_OVERRUN
) {
6116 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
6118 srb
->DataTransferLength
= 0;
6121 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
6124 if(status
== SRB_STATUS_SUCCESS
) {
6125 //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) {
6126 // // This should be set in UniataAhciEndTransaction() for AHCI
6127 // AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
6130 AtaReq
->WordsTransfered
*2 < AtaReq
->TransferLength
) {
6131 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
6132 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
6133 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6134 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_NEXT
;
6137 KdPrint2((PRINT_PREFIX
" Transfered %x, full size %x\n",
6138 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
6142 if (srb
->Function
!= SRB_FUNCTION_IO_CONTROL
) {
6145 // Indicate command complete.
6147 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete\n"));
6150 if (status
== SRB_STATUS_SUCCESS
&&
6151 srb
->SenseInfoBuffer
&&
6152 srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
6154 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)srb
->SenseInfoBuffer
;
6156 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: set AutoSense\n"));
6157 senseBuffer
->ErrorCode
= 0;
6158 senseBuffer
->Valid
= 1;
6159 senseBuffer
->AdditionalSenseLength
= 0xb;
6160 senseBuffer
->SenseKey
= 0;
6161 senseBuffer
->AdditionalSenseCode
= 0;
6162 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
6164 srb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
6166 AtapiDmaDBSync(chan
, srb
);
6167 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove srb %#x, status %x\n", srb
, status
));
6168 UniataRemoveRequest(chan
, srb
);
6169 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete, srb %#x\n", srb
));
6170 ScsiPortNotification(RequestComplete
,
6176 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: IOCTL completion\n"));
6178 if (status
!= SRB_STATUS_SUCCESS
) {
6179 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6180 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: error %#x\n", error
));
6183 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
6185 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6186 // Build the SMART status block depending upon the completion status.
6187 cmdOutParameters
->cBufferSize
= wordCount
;
6188 cmdOutParameters
->DriverStatus
.bDriverError
= (error
) ? SMART_IDE_ERROR
: 0;
6189 cmdOutParameters
->DriverStatus
.bIDEError
= error
;
6191 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
6193 if (chan
->SmartCommand
== RETURN_SMART_STATUS
) {
6194 PIDEREGS_EX regs
= (PIDEREGS_EX
)&(cmdOutParameters
->bBuffer
);
6197 UniataSnapAtaRegs(chan
, 0, regs
);
6199 regs
->bCommandReg
= SMART_CMD
;
6200 regs
->bFeaturesReg
= RETURN_SMART_STATUS
;
6202 cmdOutParameters
->cBufferSize
= 8;
6204 chan
->SmartCommand
= 0; // cleanup after execution
6206 // Indicate command complete.
6207 goto IntrCompleteReq
;
6212 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: No SRB!\n"));
6217 for (i
= 0; i
< 5; i
++) {
6218 GetBaseStatus(chan
, statusByte
);
6219 if(!(statusByte
& IDE_STATUS_BUSY
)) {
6220 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RDP + cleared BUSY\n"));
6224 if (statusByte
& IDE_STATUS_DSC
) {
6225 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Clear RDP\n"));
6229 AtapiStallExecution(50);
6232 // RDP can be cleared since previous check
6234 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestTimerCall 2000\n"));
6240 AtapiStallExecution(TimerValue
);
6241 goto ServiceInterrupt
;
6242 #endif //UNIATA_CORE
6245 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
6248 srb
= UniataGetCurRequest(chan
);
6253 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: NextRequest, srb=%#x\n",srb
));
6255 ScsiPortNotification(NextRequest
,
6259 ScsiPortNotification(NextLuRequest
,
6264 // in simplex mode next command must NOT be sent here
6265 if(!deviceExtension
->simplexOnly
) {
6266 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6269 // Try to get SRB fron any non-empty queue (later)
6270 if(deviceExtension
->simplexOnly
) {
6273 #endif //UNIATA_CORE
6275 goto ReturnEnableIntr
;
6279 // Unexpected int. Catch it
6280 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
6284 if(OldReqState
== REQ_STATE_DPC_WAIT_BUSY0
&&
6285 AtaReq
->WordsLeft
== 0) {
6286 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: pending WAIT_BUSY0. Complete.\n"));
6287 status
= SRB_STATUS_SUCCESS
;
6288 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6289 goto CompleteRequest
;
6295 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ReturnEnableIntr\n",srb
));
6296 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6297 deviceExtension
->ExpectingInterrupt
= TRUE
;
6299 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
6300 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
6301 #ifdef UNIATA_USE_XXableInterrupts
6302 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
6303 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
6304 // must be called on DISPATCH_LEVEL
6305 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
6306 AtapiEnableInterrupts__
);
6308 AtapiEnableInterrupts(HwDeviceExtension
, c
);
6309 InterlockedExchange(&(chan
->CheckIntr
),
6311 // Will raise IRQL to DIRQL
6313 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
6314 AtapiEnableInterrupts__
,
6316 #endif // UNIATA_CORE
6317 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
6318 #endif // UNIATA_USE_XXableInterrupts
6322 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
6323 // in simplex mode next command must be sent here if
6325 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc
, NoStartIo
));
6328 if(!UseDpc
&& /*deviceExtension->simplexOnly &&*/ !NoStartIo
) {
6329 chan
= UniataGetNextChannel(chan
);
6331 srb
= UniataGetCurRequest(chan
);
6335 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: run srb %x\n", srb
));
6337 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6340 #endif //UNIATA_CORE
6343 } // end AtapiInterrupt__()
6349 Routine Description:
6351 This routine handles SMART enable, disable, read attributes and threshold commands.
6355 HwDeviceExtension - HBA miniport driver's adapter data storage
6356 Srb - IO request packet
6365 IdeSendSmartCommand(
6366 IN PVOID HwDeviceExtension
,
6367 IN PSCSI_REQUEST_BLOCK Srb
,
6368 IN ULONG targetId
// assume it is always valid
6371 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6372 ULONG c
; // = GET_CHANNEL(Srb); may be invalid
6373 PHW_CHANNEL chan
; // = &(deviceExtension->chan[c]);
6374 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6375 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6376 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6377 PIDEREGS regs
= &cmdInParameters
.irDriveRegs
;
6382 if (regs
->bCommandReg
!= SMART_CMD
) {
6383 KdPrint2((PRINT_PREFIX
6384 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
6385 return SRB_STATUS_INVALID_REQUEST
;
6388 c
= targetId
/ deviceExtension
->NumberLuns
;
6389 DeviceNumber
= targetId
% deviceExtension
->NumberLuns
;
6390 KdPrint2((PRINT_PREFIX
" c %d, dev %d\n", c
, DeviceNumber
));
6392 chan
= &(deviceExtension
->chan
[c
]);
6394 chan
->SmartCommand
= regs
->bFeaturesReg
;
6396 // Determine which of the commands to carry out.
6397 switch(regs
->bFeaturesReg
) {
6398 case READ_ATTRIBUTES
:
6399 case READ_THRESHOLDS
:
6400 case READ_LOG_SECTOR
:
6401 case WRITE_LOG_SECTOR
:
6403 if(Srb
->DataTransferLength
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1) {
6404 KdPrint2((PRINT_PREFIX
6405 "IdeSendSmartCommand: wrong buffer size\n"));
6406 return SRB_STATUS_DATA_OVERRUN
;
6409 statusByte
= WaitOnBusy(chan
);
6411 if (statusByte
& IDE_STATUS_BUSY
) {
6412 KdPrint2((PRINT_PREFIX
6413 "IdeSendSmartCommand: Returning BUSY status\n"));
6414 return SRB_STATUS_BUSY
;
6417 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6418 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1);
6420 // Set data buffer pointer and words left.
6421 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6422 AtaReq
->WordsLeft
= READ_ATTRIBUTE_BUFFER_SIZE
/ 2;
6424 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6426 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6428 regs
->bSectorNumberReg
,
6429 regs
->bSectorCountReg
,
6433 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6434 // Wait for interrupt.
6435 return SRB_STATUS_PENDING
;
6437 return SRB_STATUS_ERROR
;
6441 case RETURN_SMART_STATUS
:
6442 case ENABLE_DISABLE_AUTOSAVE
:
6443 case EXECUTE_OFFLINE_DIAGS
:
6444 case SAVE_ATTRIBUTE_VALUES
:
6447 statusByte
= WaitOnBusy(chan
);
6449 if (statusByte
& IDE_STATUS_BUSY
) {
6450 KdPrint2((PRINT_PREFIX
6451 "IdeSendSmartCommand: Returning BUSY status\n"));
6452 return SRB_STATUS_BUSY
;
6455 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6456 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) - 1);
6458 // Set data buffer pointer and indicate no data transfer.
6459 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6460 AtaReq
->WordsLeft
= 0;
6462 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6464 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6466 regs
->bSectorNumberReg
,
6467 regs
->bSectorCountReg
,
6471 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6472 // Wait for interrupt.
6473 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6474 return SRB_STATUS_PENDING
;
6476 return SRB_STATUS_ERROR
;
6477 } // end switch(regs->bFeaturesReg)
6479 return SRB_STATUS_INVALID_REQUEST
;
6481 } // end IdeSendSmartCommand()
6483 #endif //UNIATA_CORE
6487 UniAtaCalculateLBARegs(
6488 PHW_LU_EXTENSION LunExt
,
6489 ULONGLONG startingSector
,
6493 UCHAR drvSelect
,sectorNumber
;
6497 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6498 if(LunExt
->LimitedTransferMode
>= ATA_DMA
) {
6499 if(LunExt
->DeviceExtension
) {
6500 (*max_bcount
) = LunExt
->DeviceExtension
->MaximumDmaTransferLength
/ DEV_BSIZE
;
6503 return startingSector
;
6505 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6506 LunExt
->IdentifyData
.NumberOfHeads
;
6508 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
6512 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
;
6514 cylinder
= (USHORT
)(startingSector
/ tmp
);
6515 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
6516 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
6517 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
- sectorNumber
+ 1;
6518 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
6519 cylinder
, drvSelect
, sectorNumber
, (*max_bcount
)));
6523 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
6524 } // end UniAtaCalculateLBARegs()
6528 UniAtaCalculateLBARegsBack(
6529 PHW_LU_EXTENSION LunExt
,
6533 ULONG drvSelect
,sectorNumber
;
6537 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6540 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6541 LunExt
->IdentifyData
.NumberOfHeads
;
6543 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
6544 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
6545 sectorNumber
= (UCHAR
)(lba
& 0xff);
6547 lba
= sectorNumber
-1 +
6548 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
6552 } // end UniAtaCalculateLBARegsBack()
6557 Routine Description:
6559 This routine handles IDE read and writes.
6563 HwDeviceExtension - HBA miniport driver's adapter data storage
6564 Srb - IO request packet
6574 IN PVOID HwDeviceExtension
,
6575 IN PSCSI_REQUEST_BLOCK Srb
,
6579 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6580 UCHAR lChannel
= GET_CHANNEL(Srb
);
6581 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6582 PHW_LU_EXTENSION LunExt
;
6583 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6584 //ULONG ldev = GET_LDEV(Srb);
6585 UCHAR DeviceNumber
= GET_CDEV(Srb
);;
6586 ULONGLONG startingSector
=0;
6588 ULONG wordCount
= 0;
6589 UCHAR statusByte
,statusByte2
;
6592 BOOLEAN use_dma
= FALSE
;
6595 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6596 LunExt
= chan
->lun
[DeviceNumber
];
6598 if((CmdAction
& CMD_ACTION_PREPARE
) &&
6599 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
6601 if(LunExt
->opt_ReadOnly
&&
6602 (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) {
6603 if(LunExt
->opt_ReadOnly
== 1) {
6604 KdPrint2((PRINT_PREFIX
"Abort WRITE (Soft R/O)\n"));
6605 return SRB_STATUS_ERROR
;
6607 KdPrint2((PRINT_PREFIX
"Ignore WRITE (Soft R/O)\n"));
6608 return SRB_STATUS_SUCCESS
;
6612 // Set data buffer pointer and words left.
6613 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6615 if(AtaReq
->WordsTransfered
) {
6616 AtaReq
->DataBuffer
= ((PUSHORT
)(Srb
->DataBuffer
)) + AtaReq
->WordsTransfered
;
6617 startingSector
= (UniAtaCalculateLBARegsBack(LunExt
, AtaReq
->lba
)) /* latest lba */ + AtaReq
->bcount
/* previous bcount */;
6618 AtaReq
->bcount
= (AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2 + DEV_BSIZE
-1) / DEV_BSIZE
;
6619 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Chained REQ): Starting sector %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
6621 AtaReq
->TransferLength
/2,
6622 AtaReq
->WordsTransfered
,
6625 AtaReq
->DataBuffer
= (PUSHORT
)(Srb
->DataBuffer
);
6626 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
6627 // Set up 1st block.
6628 switch(Srb
->Cdb
[0]) {
6631 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6632 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6635 case SCSIOP_WRITE12
:
6636 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
6637 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6640 case SCSIOP_WRITE16
:
6641 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6642 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6645 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Orig REQ): Starting sector %I64x, OrigWordsRequested %#x, DevSize %#x\n",
6647 AtaReq
->TransferLength
/2,
6650 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6653 AtaReq
->bcount
= min(AtaReq
->bcount
, max_bcount
);
6655 AtaReq
->WordsLeft
= min(AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2,
6656 AtaReq
->bcount
* DEV_BSIZE
) / 2;
6658 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n",
6665 // assume best case here
6666 // we cannot reinit Dma until previous request is completed
6667 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6668 UniataAhciSetupCmdPtr(AtaReq
);
6669 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6670 (PUCHAR
)(AtaReq
->DataBuffer
),
6671 AtaReq
->bcount
* DEV_BSIZE
)) {
6672 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !DMA\n"));
6673 return SRB_STATUS_ERROR
;
6676 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
6678 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6679 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6680 (PUCHAR
)(AtaReq
->DataBuffer
),
6681 AtaReq
->bcount
* DEV_BSIZE
)) {
6686 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6687 KdPrint2((PRINT_PREFIX
"IdeReadWrite: setup AHCI FIS\n"));
6688 RtlZeroMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
), sizeof(AtaReq
->ahci_cmd0
.cfis
));
6690 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
6691 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
6692 (AtaReq
->Flags
& REQ_FLAG_READ
) ? IDE_COMMAND_READ_DMA
: IDE_COMMAND_WRITE_DMA
,
6694 (USHORT
)(AtaReq
->bcount
),
6696 /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/
6700 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !FIS\n"));
6701 return SRB_STATUS_ERROR
;
6704 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0, (AtaReq
->Flags
& REQ_FLAG_READ
) ? 0 : ATA_AHCI_CMD_WRITE
, fis_size
, DeviceNumber
);
6705 KdPrint2((PRINT_PREFIX
"IdeReadWrite ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
6708 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
6710 } else { // exec_only
6711 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
6714 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6718 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
6720 return SRB_STATUS_PENDING
;
6723 // if this is queued request, reinit DMA and check
6724 // if DMA mode is still available
6725 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
6726 if (/*EnableDma &&*/
6727 (LunExt
->TransferMode
>= ATA_DMA
)) {
6730 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6734 // Check if write request.
6735 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6737 // Prepare read command.
6739 cmd
= IDE_COMMAND_READ_DMA
;
6741 if(LunExt
->MaximumBlockXfer
) {
6742 cmd
= IDE_COMMAND_READ_MULTIPLE
;
6744 cmd
= IDE_COMMAND_READ
;
6748 // Prepare write command.
6750 wordCount
= AtaReq
->bcount
*DEV_BSIZE
/2;
6751 cmd
= IDE_COMMAND_WRITE_DMA
;
6753 if (LunExt
->MaximumBlockXfer
) {
6754 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
6756 if (AtaReq
->WordsLeft
< wordCount
) {
6757 // Transfer only words requested.
6758 wordCount
= AtaReq
->WordsLeft
;
6760 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
6763 wordCount
= DEV_BSIZE
/2;
6764 cmd
= IDE_COMMAND_WRITE
;
6769 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
6770 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
6772 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
6774 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6777 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6778 // AHCI doesn't distinguish DMA and PIO
6779 //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
6780 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
6781 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6782 InterlockedExchange(&(chan
->CheckIntr
),
6784 return SRB_STATUS_PENDING
;
6787 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
6789 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
6791 (USHORT
)(AtaReq
->bcount
),
6792 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6794 if(statusByte2
!= IDE_STATUS_WRONG
) {
6795 GetStatus(chan
, statusByte2
);
6797 if(statusByte2
& IDE_STATUS_ERROR
) {
6798 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6799 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
6800 return SRB_STATUS_ERROR
;
6803 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
6805 return SRB_STATUS_PENDING
;
6808 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
6810 (USHORT
)(AtaReq
->bcount
),
6811 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6814 if (!(statusByte
& IDE_STATUS_DRQ
) ||
6815 statusByte
== IDE_STATUS_WRONG
) {
6817 if(statusByte
== IDE_STATUS_WRONG
) {
6818 KdPrint2((PRINT_PREFIX
6819 "IdeReadWrite: error sending command (%#x)\n",
6822 KdPrint2((PRINT_PREFIX
6823 "IdeReadWrite: DRQ never asserted (%#x)\n",
6827 AtaReq
->WordsLeft
= 0;
6829 // Clear interrupt expecting flag.
6830 UniataExpectChannelInterrupt(chan
, FALSE
);
6831 InterlockedExchange(&(chan
->CheckIntr
),
6834 // Clear current SRB.
6835 UniataRemoveRequest(chan
, Srb
);
6837 return (statusByte
== IDE_STATUS_WRONG
) ? SRB_STATUS_ERROR
: SRB_STATUS_TIMEOUT
;
6840 UniataExpectChannelInterrupt(chan
, TRUE
);
6841 InterlockedExchange(&(chan
->CheckIntr
),
6844 // Write next DEV_BSIZE/2*N words.
6845 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
)) {
6846 KdPrint2((PRINT_PREFIX
6847 "IdeReadWrite: Write %#x words\n", wordCount
));
6852 UniataGetPioTiming(LunExt
));
6856 KdPrint2((PRINT_PREFIX
6857 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
6860 (PULONG
)(AtaReq
->DataBuffer
),
6862 UniataGetPioTiming(LunExt
));
6865 // Adjust buffer address and words left count.
6866 AtaReq
->WordsLeft
-= wordCount
;
6867 AtaReq
->DataBuffer
+= wordCount
;
6868 AtaReq
->WordsTransfered
+= wordCount
;
6870 // Wait for interrupt.
6871 return SRB_STATUS_PENDING
;
6873 } // end IdeReadWrite()
6879 Routine Description:
6880 This routine handles IDE Verify.
6883 HwDeviceExtension - HBA miniport driver's adapter data storage
6884 Srb - IO request packet
6893 IN PVOID HwDeviceExtension
,
6894 IN PSCSI_REQUEST_BLOCK Srb
6897 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6898 UCHAR lChannel
= GET_CHANNEL(Srb
);
6899 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6900 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6901 PHW_LU_EXTENSION LunExt
;
6902 //ULONG ldev = GET_LDEV(Srb);
6903 ULONG DeviceNumber
= GET_CDEV(Srb
);
6905 ULONGLONG startingSector
=0;
6908 ULONGLONG endSector
;
6909 ULONG sectorCount
=0;
6912 LunExt
= chan
->lun
[DeviceNumber
];
6913 // Drive has these number sectors.
6914 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
6915 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
6916 LunExt
->IdentifyData
.NumberOfHeads
*
6917 LunExt
->IdentifyData
.NumberOfCylinders
;
6920 KdPrint2((PRINT_PREFIX
6921 "IdeVerify: Total sectors %#x\n",
6924 // Get starting sector number from CDB.
6925 switch(Srb
->Cdb
[0]) {
6927 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6928 MOV_SWP_DW2DD(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6930 case SCSIOP_VERIFY12
:
6931 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
6932 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6934 case SCSIOP_VERIFY16
:
6935 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6936 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6940 KdPrint2((PRINT_PREFIX
6941 "IdeVerify: Starting sector %#I64x. Number of blocks %#x\n",
6945 endSector
= startingSector
+ sectorCount
;
6947 KdPrint2((PRINT_PREFIX
6948 "IdeVerify: Ending sector %#I64x\n",
6951 if (endSector
> sectors
) {
6953 // Too big, round down.
6954 KdPrint2((PRINT_PREFIX
6955 "IdeVerify: Truncating request to %#x blocks\n",
6956 sectors
- startingSector
- 1));
6958 sectorCount
= (ULONG
)(sectors
- startingSector
- 1);
6962 // Set up sector count register. Round up to next block.
6963 if (sectorCount
> 0xFF) {
6964 sectorCount
= (USHORT
)0xFF;
6968 // Set data buffer pointer and words left.
6969 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
6970 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
6972 // Indicate expecting an interrupt.
6973 InterlockedExchange(&(chan
->CheckIntr
),
6976 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6978 statusByte
= AtaCommand48(deviceExtension
, LunExt
->Lun
, GET_CHANNEL(Srb
),
6979 IDE_COMMAND_VERIFY
, lba
,
6980 (USHORT
)sectorCount
,
6983 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6984 // Wait for interrupt.
6985 return SRB_STATUS_PENDING
;
6987 return SRB_STATUS_ERROR
;
6989 } // end IdeVerify()
6991 #endif //UNIATA_CORE
6995 Routine Description:
6996 Send ATAPI packet command to device.
6999 HwDeviceExtension - HBA miniport driver's adapter data storage
7000 Srb - IO request packet
7008 IN PVOID HwDeviceExtension
,
7009 IN PSCSI_REQUEST_BLOCK Srb
,
7013 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7014 UCHAR lChannel
= GET_CHANNEL(Srb
);
7015 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
7016 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7017 PHW_LU_EXTENSION LunExt
;
7018 //ULONG ldev = GET_LDEV(Srb);
7019 ULONG DeviceNumber
= GET_CDEV(Srb
);
7021 UCHAR statusByte
,statusByte0
,byteCountLow
,byteCountHigh
;
7022 BOOLEAN use_dma
= FALSE
;
7023 BOOLEAN dma_reinited
= FALSE
;
7024 BOOLEAN retried
= FALSE
;
7028 LunExt
= chan
->lun
[DeviceNumber
];
7030 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: req state %#x, Action %x\n", AtaReq
->ReqState
, CmdAction
));
7031 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
7032 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
7035 #ifdef UNIATA_DUMP_ATAPI
7036 if(CmdAction
& CMD_ACTION_PREPARE
) {
7040 PCHAR ModeSelectData
;
7043 Cdb
= (PCDB
)(Srb
->Cdb
);
7044 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
7045 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
7046 CdbDataLen
= Srb
->DataTransferLength
;
7048 if(CdbDataLen
> 0x1000) {
7049 CdbDataLen
= 0x1000;
7053 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
7054 KdPrint2(("P:T:D=%d:%d:%d\n",
7058 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
7061 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
7062 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
7063 Cdb
->WRITE_CD
.LBA
[0],
7064 Cdb
->WRITE_CD
.LBA
[1],
7065 Cdb
->WRITE_CD
.LBA
[2],
7066 Cdb
->WRITE_CD
.LBA
[3]
7069 if(ScsiCommand
== SCSIOP_WRITE12
) {
7070 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
7071 Cdb
->CDB12READWRITE
.LBA
[0],
7072 Cdb
->CDB12READWRITE
.LBA
[1],
7073 Cdb
->CDB12READWRITE
.LBA
[2],
7074 Cdb
->CDB12READWRITE
.LBA
[3]
7077 if(ScsiCommand
== SCSIOP_WRITE16
) {
7078 KdPrint(("Write16, LBA %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
7079 Cdb
->CDB16READWRITE
.LBA
[0],
7080 Cdb
->CDB16READWRITE
.LBA
[1],
7081 Cdb
->CDB16READWRITE
.LBA
[2],
7082 Cdb
->CDB16READWRITE
.LBA
[3],
7083 Cdb
->CDB16READWRITE
.LBA
[4],
7084 Cdb
->CDB16READWRITE
.LBA
[5],
7085 Cdb
->CDB16READWRITE
.LBA
[6],
7086 Cdb
->CDB16READWRITE
.LBA
[7]
7089 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
7090 KdPrint(("ModeSelect 6\n"));
7091 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
7092 ModeSelectData
= CdbData
+4;
7093 KdDump(CdbData
, CdbDataLen
);
7095 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
7096 KdPrint(("ModeSelect 10\n"));
7097 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
7098 ModeSelectData
= CdbData
+8;
7099 KdDump(CdbData
, CdbDataLen
);
7101 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
7102 KdPrint(("Send buffer to device:\n"));
7103 KdDump(CdbData
, CdbDataLen
);
7108 #endif //UNIATA_DUMP_ATAPI
7111 if(CmdAction
== CMD_ACTION_PREPARE
) {
7112 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb
->Cdb
)));
7114 switch (Srb
->Cdb
[0]) {
7115 case SCSIOP_RECEIVE
:
7120 case SCSIOP_WRITE12
:
7122 case SCSIOP_WRITE16
:
7125 case SCSIOP_READ_CD
:
7126 case SCSIOP_READ_CD_MSF
:
7127 if(deviceExtension
->opt_AtapiDmaRawRead
) {
7133 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
7134 return SRB_STATUS_BUSY
;
7137 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
7138 !AtaReq
->OriginalSrb
) {
7139 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
7140 return SRB_STATUS_BUSY
;
7145 // We need to know how many platters our atapi cd-rom device might have.
7146 // Before anyone tries to send a srb to our target for the first time,
7147 // we must "secretly" send down a separate mechanism status srb in order to
7148 // initialize our device extension changer data. That's how we know how
7149 // many platters our target has.
7151 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
7152 !AtaReq
->OriginalSrb
) {
7156 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
7157 // Set this flag now. If the device hangs on the mech. status
7158 // command, we will not have the chance to set it.
7159 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
7161 chan
->MechStatusRetryCount
= 3;
7162 AtaReq
->OriginalSrb
= Srb
;
7163 AtaReq
->Srb
= BuildMechanismStatusSrb (
7167 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
7168 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
7169 if (srbStatus
== SRB_STATUS_PENDING
) {
7170 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
7174 // failed! Get the sense key and maybe try again
7175 AtaReq
->Srb
= BuildRequestSenseSrb ( HwDeviceExtension
,
7176 AtaReq
->OriginalSrb
);
7178 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
7180 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
7182 if (srbStatus
== SRB_STATUS_PENDING
) {
7183 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n"));
7187 // failed again ? should not get here
7189 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
7190 AtaReq
->OriginalSrb
= NULL
;
7192 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiHwInitializeChanger()\n"));
7193 // Do-nothing call ?
7194 AtapiHwInitializeChanger (HwDeviceExtension
, Srb
,
7195 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
7199 #endif //UNIATA_CORE
7201 if((CmdAction
& CMD_ACTION_PREPARE
) &&
7202 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
7204 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb
->Cdb
[0], &(Srb
->Cdb
)));
7206 if(!LunExt
->IdentifyData
.AtapiCmdSize
&&
7207 (Srb
->CdbLength
> 12)) {
7208 KdPrint2((PRINT_PREFIX
"Cdb16 not supported\n"));
7209 return SRB_STATUS_INVALID_REQUEST
;
7212 // Set data buffer pointer and words left.
7213 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
7214 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
7215 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
7216 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7217 // reset this to force PRD init. May be already setup by recursive SRB
7218 AtaReq
->dma_entries
= 0;
7220 // check if reorderable
7221 switch(Srb
->Cdb
[0]) {
7223 case SCSIOP_WRITE16
:
7225 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
7226 MOV_QD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
7230 case SCSIOP_WRITE12
:
7232 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
7238 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
7240 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
7242 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
7243 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7244 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
7245 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
7246 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ?
7247 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
7250 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7251 if(!AtaReq
->TransferLength
) {
7252 KdPrint((" assume 0-transfer\n"));
7254 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
7255 KdPrint((" assume OUT\n"));
7256 AtaReq
->Flags
|= REQ_FLAG_WRITE
;
7258 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7259 KdPrint((" assume IN\n"));
7260 AtaReq
->Flags
|= REQ_FLAG_READ
;
7265 // check if DMA read/write
7266 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7267 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: force use dma (ahci)\n"));
7271 /* if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) {
7272 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n"));
7276 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
7277 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
7279 if(AtaReq
->TransferLength
) {
7281 switch(Srb
->Cdb
[0]) {
7283 case SCSIOP_WRITE12
:
7284 case SCSIOP_WRITE16
:
7286 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
7289 case SCSIOP_RECEIVE
:
7294 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
7296 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7297 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7300 if(AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7301 (PUCHAR
)(AtaReq
->DataBuffer
),
7302 Srb
->DataTransferLength
7303 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
7305 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7310 case SCSIOP_READ_CD
:
7311 case SCSIOP_READ_CD_MSF
:
7312 if(deviceExtension
->opt_AtapiDmaRawRead
)
7313 goto call_dma_setup
;
7317 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
7318 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7323 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
7324 KdPrint2((PRINT_PREFIX
"dma RO\n"));
7336 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7337 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7340 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7341 (PUCHAR
)(AtaReq
->DataBuffer
),
7342 Srb
->DataTransferLength
)) {
7343 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
7346 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7350 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer, no DMA setup\n"));
7354 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7356 UniataAhciSetupCmdPtr(AtaReq
);
7358 if(!Srb
->DataTransferLength
) {
7359 KdPrint2((PRINT_PREFIX
"zero-transfer\n"));
7362 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7363 (PUCHAR
)(AtaReq
->DataBuffer
),
7364 Srb
->DataTransferLength
)) {
7365 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no AHCI dma!\n"));
7366 return SRB_STATUS_ERROR
;
7369 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7371 FeatureReg
|= ATA_F_DMA
;
7372 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7373 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7374 FeatureReg
|= ATA_F_DMAREAD
;
7378 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: setup AHCI FIS\n"));
7379 // this is done in UniataAhciSetupFIS_H2D()
7380 //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
7381 RtlCopyMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), Srb
->Cdb
, Srb
->CdbLength
);
7383 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
7384 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
7385 IDE_COMMAND_ATAPI_PACKET
/* command */,
7387 (Srb
->DataTransferLength
>= 0x10000) ? (USHORT
)(0xffff) : (USHORT
)(Srb
->DataTransferLength
),
7388 FeatureReg
/* feature */
7392 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AHCI !FIS\n"));
7393 return SRB_STATUS_ERROR
;
7396 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0,
7397 ((Srb
->DataTransferLength
&& (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) ? ATA_AHCI_CMD_WRITE
: 0) |
7398 (ATA_AHCI_CMD_ATAPI
| ATA_AHCI_CMD_PREFETCH
),
7399 fis_size
, DeviceNumber
);
7401 KdPrint2((PRINT_PREFIX
"AtapiSendCommand ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
7405 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7406 // if this is queued request, reinit DMA and check
7407 // if DMA mode is still available
7408 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
7409 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7410 if (/*EnableDma &&*/
7411 (LunExt
->TransferMode
>= ATA_DMA
)) {
7412 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
7415 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7416 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
7419 dma_reinited
= TRUE
;
7423 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
7424 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
7425 return SRB_STATUS_PENDING
;
7427 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma
, Srb
->Cdb
[0]));
7428 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7429 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7432 if((Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) && !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7433 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
7435 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7436 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7437 } if(AtaReq
->TransferLength
) {
7439 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
7440 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7441 if (/*EnableDma &&*/
7442 (LunExt
->TransferMode
>= ATA_DMA
)) {
7445 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7450 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
7452 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7453 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7454 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
7455 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7458 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
7459 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7460 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7463 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
7465 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
7466 &(Srb
->Cdb
), Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
7468 // Make sure command is to ATAPI device.
7469 flags
= LunExt
->DeviceFlags
;
7470 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7471 if((Srb
->Lun
) > (LunExt
->DiscsPresent
- 1)) {
7473 // Indicate no device found at this address.
7474 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7475 return SRB_STATUS_SELECTION_TIMEOUT
;
7477 } else if(Srb
->Lun
> 0) {
7478 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7479 return SRB_STATUS_SELECTION_TIMEOUT
;
7482 if(!(flags
& DFLAGS_ATAPI_DEVICE
)) {
7483 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7484 return SRB_STATUS_SELECTION_TIMEOUT
;
7487 // Select device 0 or 1. Or more for PM
7488 SelectDrive(chan
, DeviceNumber
);
7490 // Verify that controller is ready for next command.
7491 GetStatus(chan
, statusByte
);
7492 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
7494 if(statusByte
== IDE_STATUS_WRONG
) {
7495 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
7498 if(statusByte
& IDE_STATUS_BUSY
) {
7499 if(statusByte
& IDE_STATUS_DSC
) {
7500 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
7502 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
7503 // We have to make reset here, since we are expecting device to be available
7504 //return SRB_STATUS_BUSY; // this cause queue freeze
7508 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7510 // Check if command list is free
7511 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
7513 // controller is busy, however we expect it to be free
7514 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI
));
7518 if(statusByte
& IDE_STATUS_ERROR
) {
7519 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
7521 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
7522 // Read the error reg. to clear it and fail this request.
7523 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7524 return MapError(deviceExtension
, Srb
);
7526 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
7529 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
7530 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
7531 if((!(statusByte
& IDE_STATUS_DSC
)) &&
7532 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
7534 AtapiStallExecution(200);
7535 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
7536 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7537 return SRB_STATUS_PENDING
;
7540 if(IS_RDP(Srb
->Cdb
[0])) {
7542 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
7546 if(statusByte
& IDE_STATUS_DRQ
) {
7548 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
7550 // Try to drain the data that one preliminary device thinks that it has
7551 // to transfer. Hopefully this random assertion of DRQ will not be present
7552 // in production devices.
7553 statusByte
= AtapiSuckPort2(chan
);
7555 for (i = 0; i < 0x10000; i++) {
7556 GetStatus(chan, statusByte);
7557 if(statusByte & IDE_STATUS_DRQ) {
7558 AtapiReadPort2(chan, IDX_IO1_i_Data);
7564 if (statusByte
& IDE_STATUS_DRQ
) {
7566 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte
));
7568 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7570 AtapiSoftReset(chan
, DeviceNumber
);
7572 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
7573 // Re-initialize Atapi device.
7574 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), DeviceNumber
, TRUE
);
7576 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
7577 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
7579 // Inform the port driver that the bus has been reset.
7580 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
7581 // Clean up device extension fields that AtapiStartIo won't.
7582 UniataExpectChannelInterrupt(chan
, FALSE
);
7584 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
7587 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7589 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7590 return SRB_STATUS_BUS_RESET;
7593 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
7597 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
7598 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7599 return SRB_STATUS_SELECTION_TIMEOUT
;
7603 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7604 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
7605 Srb
->Cdb
[1] &= ~0xE0;
7606 if((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
7607 // Torisan changer. TUR's are overloaded to be platter switches.
7608 Srb
->Cdb
[7] = Srb
->Lun
;
7615 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
7617 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
7620 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7621 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AHCI, begin transaction\n"));
7622 //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
7623 UniataExpectChannelInterrupt(chan
, TRUE
);
7624 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
7625 return SRB_STATUS_PENDING
;
7628 statusByte
= WaitOnBusy(chan
);
7629 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
7633 FeatureReg
|= ATA_F_DMA
;
7634 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7635 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7636 FeatureReg
|= ATA_F_DMAREAD
;
7640 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, FeatureReg
);
7642 // Write transfer byte count to registers.
7643 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
7644 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
7646 if (Srb
->DataTransferLength
>= 0x10000) {
7647 byteCountLow
= byteCountHigh
= 0xFF;
7650 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
7651 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
7653 if (flags
& DFLAGS_INT_DRQ
) {
7655 // This device interrupts when ready to receive the packet.
7657 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
7660 UniataExpectChannelInterrupt(chan
, TRUE
);
7661 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
7662 InterlockedExchange(&(chan
->CheckIntr
),
7665 // Write ATAPI packet command.
7666 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7668 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
7669 return SRB_STATUS_PENDING
;
7673 // This device quickly sets DRQ when ready to receive the packet.
7675 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
7678 UniataExpectChannelInterrupt(chan
, TRUE
);
7679 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
7680 InterlockedExchange(&(chan
->CheckIntr
),
7683 if(g_opt_AtapiSendDisableIntr
) {
7684 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7686 // remember status. Later we may check if error appeared after cmd packet
7687 statusByte0
= statusByte
;
7689 // Write ATAPI packet command.
7690 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7694 statusByte
= WaitForDrq(chan
);
7696 // Need to read status register and clear interrupt (if any)
7697 GetBaseStatus(chan
, statusByte
);
7699 if (!(statusByte
& IDE_STATUS_DRQ
)) {
7701 if(g_opt_AtapiSendDisableIntr
) {
7702 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7704 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte
));
7705 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7706 return SRB_STATUS_ERROR
;
7709 GetStatus(chan
, statusByte
);
7710 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
7712 // Send CDB to device.
7713 statusByte
= WaitOnBaseBusy(chan
);
7715 // Indicate expecting an interrupt and wait for it.
7716 UniataExpectChannelInterrupt(chan
, TRUE
);
7717 InterlockedExchange(&(chan
->CheckIntr
),
7719 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
7722 GetBaseStatus(chan
, statusByte
);
7725 statusByte
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
7726 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: iReason %x\n", statusByte
));
7729 if(g_opt_AtapiSendDisableIntr
) {
7730 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7735 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
7738 GetStatus(chan
, statusByte
);
7739 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: cmd status (%#x)\n", statusByte
));
7741 // When we operate in DMA mode, we should not start transfer when there is an error on entry
7742 // Interrupt may never come in such case.
7743 if(statusByte
& IDE_STATUS_ERROR
) {
7744 UCHAR interruptReason
;
7746 GetBaseStatus(chan
, statusByte
);
7747 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on cmd: (%#x)\n", statusByte
));
7749 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
7750 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: iReason %x\n", interruptReason
));
7752 // TODO: we should check interruptReason and decide what to do now
7754 // Read the error reg. to clear it and fail this request.
7755 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7756 return MapError(deviceExtension
, Srb
);
7758 /* if(statusByte & IDE_STATUS_DSC) {
7759 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DSC on cmd: (%#x)\n", statusByte));
7760 // Read the error reg. to clear it and fail this request.
7761 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7762 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte));
7763 if(statusByte >> 4) {
7764 GetBaseStatus(chan, statusByte);
7765 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7766 return MapError(deviceExtension, Srb);
7770 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
7771 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
7774 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
7776 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
7777 return SRB_STATUS_PENDING
;
7779 } // end AtapiSendCommand()
7786 Routine Description:
7787 Program ATA registers for IDE disk transfer.
7790 HwDeviceExtension - ATAPI driver storage.
7791 Srb - System request block.
7794 SRB status (pending if all goes well).
7799 ULONG check_point
= 0;
7800 #define SetCheckPoint(cp) { check_point = (cp) ; }
7802 #define SetCheckPoint(cp)
7808 IN PVOID HwDeviceExtension
,
7809 IN PSCSI_REQUEST_BLOCK Srb
,
7814 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
7817 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7822 PHW_LU_EXTENSION LunExt
;
7826 UCHAR statusByte
,errorByte
;
7827 ULONG status
= SRB_STATUS_INVALID_REQUEST
;
7830 PMODE_PARAMETER_HEADER modeData
;
7837 //ULONG __ebp__ = 0;
7839 SetCheckPoint(0x20);
7840 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
7845 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
7846 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
7847 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
7848 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
7849 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
7851 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
7852 Srb->SrbExtension));
7853 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
7856 SetCheckPoint(0x30);
7857 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7859 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
7861 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
7863 KdPrint2((PRINT_PREFIX
"** --- **\n"));
7865 lChannel
= GET_CHANNEL(Srb
);
7866 chan
= &(deviceExtension
->chan
[lChannel
]);
7867 //ldev = GET_LDEV(Srb);
7868 DeviceNumber
= GET_CDEV(Srb
);
7869 LunExt
= chan
->lun
[DeviceNumber
];
7871 SetCheckPoint(0x40);
7872 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
7873 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
7875 cdb
= (PCDB
)(Srb
->Cdb
);
7877 if(CmdAction
== CMD_ACTION_PREPARE
) {
7878 switch (Srb
->Cdb
[0]) {
7879 case SCSIOP_SERVICE_ACTION16
:
7880 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
7883 goto default_no_prep
;
7886 case SCSIOP_INQUIRY
: // now it requires device access
7888 case SCSIOP_READ_CAPACITY
:
7892 case SCSIOP_WRITE12
:
7894 case SCSIOP_WRITE16
:
7895 case SCSIOP_REQUEST_SENSE
:
7897 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
7903 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
7904 return SRB_STATUS_BUSY
;
7908 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
7909 switch (Srb
->Cdb
[0]) {
7910 case SCSIOP_INQUIRY
:
7912 KdPrint2((PRINT_PREFIX
7913 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
7914 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7915 // Filter out wrong TIDs.
7916 if ((Srb
->Lun
!= 0) ||
7917 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
7918 (Srb
->TargetId
>= deviceExtension
->NumberLuns
)) {
7920 KdPrint2((PRINT_PREFIX
7921 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
7922 // Indicate no device found at this address.
7923 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7928 KdPrint2((PRINT_PREFIX
7929 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
7930 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
7931 PIDENTIFY_DATA2 identifyData
= &(LunExt
->IdentifyData
);
7933 if (!(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7935 if(!CheckDevice(HwDeviceExtension
, lChannel
, DeviceNumber
, FALSE
)) {
7936 KdPrint2((PRINT_PREFIX
7937 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
7938 // Indicate no device found at this address.
7940 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7944 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, DeviceNumber
)) {
7945 KdPrint2((PRINT_PREFIX
7946 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
7947 // Indicate no device found at this address.
7948 UniataForgetDevice(chan
->lun
[DeviceNumber
]);
7950 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7955 // Zero INQUIRY data structure.
7956 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
7958 // Standard IDE interface only supports disks.
7959 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
7961 // Set the removable bit, if applicable.
7962 if (LunExt
->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
7963 KdPrint2((PRINT_PREFIX
7964 "RemovableMedia\n"));
7965 inquiryData
->RemovableMedia
= 1;
7967 // Set the Relative Addressing (LBA) bit, if applicable.
7968 if (LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
7969 inquiryData
->RelativeAddressing
= 1;
7970 KdPrint2((PRINT_PREFIX
7971 "RelativeAddressing\n"));
7973 // Set the CommandQueue bit
7974 inquiryData
->CommandQueue
= 1;
7976 // Fill in vendor identification fields.
7977 for (i
= 0; i
< 24; i
+= 2) {
7978 MOV_DW_SWP(inquiryData
->DeviceIdentificationString
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
7981 // Initialize unused portion of product id.
7982 for (i = 0; i < 4; i++) {
7983 inquiryData->ProductId[12+i] = ' ';
7986 // Move firmware revision from IDENTIFY data to
7987 // product revision in INQUIRY data.
7988 for (i
= 0; i
< 4; i
+= 2) {
7989 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
7992 status
= SRB_STATUS_SUCCESS
;
7997 case SCSIOP_REPORT_LUNS
: {
8000 PREPORT_LUNS_INFO_HDR LunInfo
;
8002 KdPrint2((PRINT_PREFIX
8003 "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
8004 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8006 MOV_DD_SWP(alen
, cdb
->REPORT_LUNS
.AllocationLength
);
8013 LunInfo
= (PREPORT_LUNS_INFO_HDR
)(Srb
->DataBuffer
);
8014 RtlZeroMemory(LunInfo
, 16);
8016 MOV_DD_SWP( LunInfo
->ListLength
, alen
);
8017 Srb
->DataTransferLength
= 16;
8018 status
= SRB_STATUS_SUCCESS
;
8022 case SCSIOP_MODE_SENSE
:
8024 KdPrint2((PRINT_PREFIX
8025 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8026 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8028 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_POWER_CONDITION
) {
8029 PMODE_POWER_CONDITION_PAGE modeData
;
8031 KdPrint2((PRINT_PREFIX
"MODE_PAGE_POWER_CONDITION\n"));
8032 modeData
= (PMODE_POWER_CONDITION_PAGE
)(Srb
->DataBuffer
);
8033 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_POWER_CONDITION_PAGE
)) {
8034 status
= SRB_STATUS_DATA_OVERRUN
;
8036 RtlZeroMemory(modeData
, sizeof(MODE_POWER_CONDITION_PAGE
));
8037 modeData
->PageCode
= MODE_PAGE_POWER_CONDITION
;
8038 modeData
->PageLength
= sizeof(MODE_PAGE_POWER_CONDITION
)-sizeof(MODE_PARAMETER_HEADER
);
8039 modeData
->Byte3
.Fields
.Idle
= LunExt
->PowerState
<= StartStop_Power_Idle
;
8040 modeData
->Byte3
.Fields
.Standby
= LunExt
->PowerState
== StartStop_Power_Standby
;
8041 Srb
->DataTransferLength
= sizeof(MODE_POWER_CONDITION_PAGE
);
8042 status
= SRB_STATUS_SUCCESS
;
8045 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_CACHING
) {
8046 PMODE_CACHING_PAGE modeData
;
8048 KdPrint2((PRINT_PREFIX
"MODE_PAGE_CACHING\n"));
8049 modeData
= (PMODE_CACHING_PAGE
)(Srb
->DataBuffer
);
8050 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_CACHING_PAGE
)) {
8051 status
= SRB_STATUS_DATA_OVERRUN
;
8053 RtlZeroMemory(modeData
, sizeof(MODE_CACHING_PAGE
));
8054 modeData
->PageCode
= MODE_PAGE_CACHING
;
8055 modeData
->PageLength
= sizeof(MODE_CACHING_PAGE
)-sizeof(MODE_PARAMETER_HEADER
);
8056 modeData
->ReadDisableCache
= (LunExt
->DeviceFlags
& DFLAGS_RCACHE_ENABLED
) ? 0 : 1;
8057 modeData
->WriteCacheEnable
= (LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) ? 1 : 0;
8058 Srb
->DataTransferLength
= sizeof(MODE_CACHING_PAGE
);
8059 status
= SRB_STATUS_SUCCESS
;
8062 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8064 // This is used to determine if the media is write-protected.
8065 // Since IDE does not support mode sense then we will modify just the portion we need
8066 // so the higher level driver can determine if media is protected.
8068 //SelectDrive(chan, DeviceNumber);
8069 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
8070 //statusByte = WaitOnBusy(chan);
8071 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
8073 if (!(statusByte
& IDE_STATUS_ERROR
)) {
8075 // no error occured return success, media is not protected
8076 UniataExpectChannelInterrupt(chan
, FALSE
);
8077 InterlockedExchange(&(chan
->CheckIntr
),
8079 status
= SRB_STATUS_SUCCESS
;
8083 // error occured, handle it locally, clear interrupt
8084 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8086 GetBaseStatus(chan
, statusByte
);
8087 UniataExpectChannelInterrupt(chan
, FALSE
);
8088 InterlockedExchange(&(chan
->CheckIntr
),
8090 status
= SRB_STATUS_SUCCESS
;
8092 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
8094 //media is write-protected, set bit in mode sense buffer
8095 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
8097 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
8098 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
8101 status
= SRB_STATUS_SUCCESS
;
8103 status
= SRB_STATUS_INVALID_REQUEST
;
8107 case SCSIOP_TEST_UNIT_READY
:
8109 KdPrint2((PRINT_PREFIX
8110 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
8111 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8112 if (chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8114 // Select device 0 or 1.
8115 //SelectDrive(chan, DeviceNumber);
8116 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
8117 // Wait for busy. If media has not changed, return success
8118 //statusByte = WaitOnBusy(chan);
8119 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
8121 if (!(statusByte
& IDE_STATUS_ERROR
)){
8122 UniataExpectChannelInterrupt(chan
, FALSE
);
8123 InterlockedExchange(&(chan
->CheckIntr
),
8125 status
= SRB_STATUS_SUCCESS
;
8127 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8128 if (errorByte
== IDE_ERROR_DATA_ERROR
){
8130 // Special case: If current media is write-protected,
8131 // the 0xDA command will always fail since the write-protect bit
8132 // is sticky,so we can ignore this error
8133 GetBaseStatus(chan
, statusByte
);
8134 UniataExpectChannelInterrupt(chan
, FALSE
);
8135 InterlockedExchange(&(chan
->CheckIntr
),
8137 status
= SRB_STATUS_SUCCESS
;
8141 // Request sense buffer to be build
8142 UniataExpectChannelInterrupt(chan
, TRUE
);
8143 InterlockedExchange(&(chan
->CheckIntr
),
8145 status
= SRB_STATUS_PENDING
;
8149 status
= SRB_STATUS_SUCCESS
;
8154 case SCSIOP_READ_CAPACITY
:
8156 KdPrint2((PRINT_PREFIX
8157 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
8158 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8159 // Claim 512 byte blocks (big-endian).
8160 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
8162 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY_DATA
));
8163 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
8165 // Calculate last sector.
8166 if(!(i
= (ULONG
)LunExt
->NumOfSectors
)) {
8167 i
= LunExt
->IdentifyData
.SectorsPerTrack
*
8168 LunExt
->IdentifyData
.NumberOfHeads
*
8169 LunExt
->IdentifyData
.NumberOfCylinders
;
8173 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
8174 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
8175 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
8177 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
8179 KdPrint2((PRINT_PREFIX
8180 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
8182 LunExt
->IdentifyData
.SectorsPerTrack
,
8183 LunExt
->IdentifyData
.NumberOfHeads
,
8184 LunExt
->IdentifyData
.NumberOfCylinders
));
8187 status
= SRB_STATUS_SUCCESS
;
8190 case SCSIOP_SERVICE_ACTION16
:
8192 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
8193 KdPrint2((PRINT_PREFIX
8194 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
8195 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8196 // Claim 512 byte blocks (big-endian).
8197 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
8199 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY16_DATA
));
8200 MOV_DD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
8202 // Calculate last sector.
8203 if(!(lba
= LunExt
->NumOfSectors
)) {
8204 lba
= LunExt
->IdentifyData
.SectorsPerTrack
*
8205 LunExt
->IdentifyData
.NumberOfHeads
*
8206 LunExt
->IdentifyData
.NumberOfCylinders
;
8209 MOV_QD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, lba
);
8211 KdPrint2((PRINT_PREFIX
8212 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n",
8214 LunExt
->IdentifyData
.SectorsPerTrack
,
8215 LunExt
->IdentifyData
.NumberOfHeads
,
8216 LunExt
->IdentifyData
.NumberOfCylinders
));
8218 status
= SRB_STATUS_SUCCESS
;
8225 case SCSIOP_VERIFY12
:
8226 case SCSIOP_VERIFY16
:
8228 KdPrint2((PRINT_PREFIX
8229 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
8230 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8231 status
= IdeVerify(HwDeviceExtension
,Srb
);
8238 case SCSIOP_WRITE12
:
8240 case SCSIOP_WRITE16
:
8242 KdPrint2((PRINT_PREFIX
8243 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
8244 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
8245 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8246 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
8247 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
8248 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
8249 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
8250 status
= IdeReadWrite(HwDeviceExtension
,
8254 case SCSIOP_START_STOP_UNIT
:
8256 KdPrint2((PRINT_PREFIX
8257 "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
8258 cdb
->START_STOP
.Immediate
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8259 //Determine what type of operation we should perform
8263 if(cdb
->START_STOP
.FL
||
8264 cdb
->START_STOP
.FormatLayerNumber
||
8265 cdb
->START_STOP
.Reserved2
||
8266 cdb
->START_STOP
.Reserved2_2
||
8267 cdb
->START_STOP
.Reserved3
||
8272 if (cdb
->START_STOP
.PowerConditions
) {
8273 KdPrint2((PRINT_PREFIX
"START_STOP Power %d\n", cdb
->START_STOP
.PowerConditions
));
8274 switch(cdb
->START_STOP
.PowerConditions
) {
8275 case StartStop_Power_Idle
:
8276 command
= IDE_COMMAND_IDLE_IMMED
;
8278 case StartStop_Power_Standby
:
8279 command
= IDE_COMMAND_STANDBY_IMMED
;
8281 case StartStop_Power_Sleep
:
8282 // TODO: we should save power state in order to know
8283 // that RESET sould be issued to revert device into
8286 command
= IDE_COMMAND_SLEEP
;
8291 LunExt
->PowerState
= cdb
->START_STOP
.PowerConditions
;
8293 if (cdb
->START_STOP
.LoadEject
== 1) {
8294 KdPrint2((PRINT_PREFIX
"START_STOP eject\n"));
8296 // first select device 0 or 1.
8297 //SelectDrive(chan, DeviceNumber);
8298 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
8299 command
= IDE_COMMAND_MEDIA_EJECT
;
8301 if (cdb
->START_STOP
.Start
== 0) {
8302 KdPrint2((PRINT_PREFIX
"START_STOP standby\n"));
8303 command
= IDE_COMMAND_STANDBY_IMMED
;
8305 // TODO: we may need to perform hard reset (after sleep) or
8306 // issue IDE_COMMAND_IDLE_IMMED in order to activate device
8307 KdPrint2((PRINT_PREFIX
"START_STOP activate\n"));
8309 if(LunExt
->PowerState
== StartStop_Power_Sleep
) {
8310 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
8311 status
= SRB_STATUS_SUCCESS
;
8314 if(LunExt
->PowerState
> StartStop_Power_Idle
) {
8315 KdPrint2((PRINT_PREFIX
" issue IDLE\n"));
8316 command
= IDE_COMMAND_IDLE_IMMED
;
8318 KdPrint2((PRINT_PREFIX
" do nothing\n"));
8319 status
= SRB_STATUS_SUCCESS
;
8324 statusByte
= WaitOnBaseBusy(chan
);
8325 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, command
, 0, 0, 0, 0, 0,
8326 cdb
->START_STOP
.Immediate
? ATA_IMMEDIATE
: ATA_WAIT_READY
);
8327 status
= (statusByte
& IDE_STATUS_ERROR
) ? SRB_STATUS_ERROR
: SRB_STATUS_SUCCESS
;
8328 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
8332 KdPrint2((PRINT_PREFIX
"START_STOP invalid\n"));
8333 if (Srb
->SenseInfoBuffer
) {
8335 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8337 senseBuffer
->ErrorCode
= 0x70;
8338 senseBuffer
->Valid
= 1;
8339 senseBuffer
->AdditionalSenseLength
= 0xb;
8340 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
8341 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_CDB
;
8342 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8344 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8345 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8347 status
= SRB_STATUS_ERROR
;
8351 case SCSIOP_MEDIUM_REMOVAL
:
8353 cdb
= (PCDB
)Srb
->Cdb
;
8355 if(LunExt
->IdentifyData
.Removable
) {
8356 statusByte
= WaitOnBaseBusy(chan
);
8358 //SelectDrive(chan, DeviceNumber);
8359 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
8360 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
8361 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_LOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8363 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
8364 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_UNLOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8366 status
= SRB_STATUS_SUCCESS
;
8368 status
= SRB_STATUS_INVALID_REQUEST
;
8373 // Note: I don't implement this, because NTFS driver too often issues this command
8374 // It causes awful performance degrade. However, if somebody wants, I will implement
8375 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
8376 case SCSIOP_FLUSH_BUFFER
:
8377 case SCSIOP_SYNCHRONIZE_CACHE
:
8379 SelectDrive(chan
, DeviceNumber
);
8380 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
8381 status
= SRB_STATUS_SUCCESS
;
8382 // status = SRB_STATUS_PENDING;
8383 statusByte
= WaitOnBusy(chan
);
8387 case SCSIOP_REQUEST_SENSE
:
8388 // this function makes sense buffers to report the results
8389 // of the original GET_MEDIA_STATUS command
8391 KdPrint2((PRINT_PREFIX
8392 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8393 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8394 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8395 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
8398 status
= SRB_STATUS_INVALID_REQUEST
;
8402 case SCSIOP_ATA_PASSTHROUGH
:
8405 BOOLEAN use_dma
= FALSE
;
8408 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
8410 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
8411 //lChannel = Srb->TargetId >> 1;
8413 DeviceNumber
= max(DeviceNumber
, 1);
8414 regs
->bDriveHeadReg
&= 0x0f;
8415 regs
->bDriveHeadReg
|= (UCHAR
) (((DeviceNumber
& 0x1) << 4) | 0xA0);
8418 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
8420 KdPrint2((PRINT_PREFIX
8421 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
8422 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8424 if((regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) == UNIATA_SPTI_EX_SPEC_TO
) {
8425 to_lim
= Srb
->TimeOutValue
;
8427 if(Srb
->TimeOutValue
<= 2) {
8428 to_lim
= Srb
->TimeOutValue
*900;
8430 to_lim
= (Srb
->TimeOutValue
*999) - 500;
8434 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8436 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
8438 statusByte
= UniataAhciSendPIOCommandDirect(
8447 if(statusByte
== IDE_STATUS_WRONG
) {
8448 goto passthrough_err
;
8450 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8451 UniataAhciAbortOperation(chan
);
8452 goto passthrough_err
;
8454 goto passthrough_done
;
8458 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
8459 if((chan
->lun
[DeviceNumber
]->LimitedTransferMode
>= ATA_DMA
)) {
8461 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
8462 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
8463 (PUCHAR
)(Srb
->DataBuffer
),
8464 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
8470 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
8471 AtapiStallExecution(10);
8473 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
8474 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8475 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8476 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8477 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8478 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8480 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
8481 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8482 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
8483 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8484 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
8485 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8486 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
8487 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8488 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
8489 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8491 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
8494 GetBaseStatus(chan
, statusByte
);
8495 if(statusByte
& IDE_STATUS_ERROR
) {
8496 goto passthrough_err
;
8498 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
8501 ScsiPortStallExecution(1); // wait for busy to be set
8503 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
8504 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
8505 GetBaseStatus(chan
, statusByte
);
8506 if(statusByte
& IDE_STATUS_ERROR
) {
8509 if(!(statusByte
& IDE_STATUS_BUSY
)) {
8514 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
8516 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8517 goto passthrough_err
;
8521 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
8523 AtapiDmaDone(deviceExtension
, DeviceNumber
, lChannel
, NULL
);
8524 GetBaseStatus(chan
, statusByte
);
8526 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8527 AtapiSuckPort2(chan
);
8529 if (Srb
->SenseInfoBuffer
) {
8531 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8533 senseBuffer
->ErrorCode
= 0x70;
8534 senseBuffer
->Valid
= 1;
8535 senseBuffer
->AdditionalSenseLength
= 0xb;
8536 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
8537 senseBuffer
->AdditionalSenseCode
= 0;
8538 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8540 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8541 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8543 status
= SRB_STATUS_ERROR
;
8547 if (statusByte
& IDE_STATUS_DRQ
) {
8548 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
8550 (PUSHORT
) Srb
->DataBuffer
,
8551 Srb
->DataTransferLength
/ 2,
8553 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
8555 (PUSHORT
) Srb
->DataBuffer
,
8556 Srb
->DataTransferLength
/ 2,
8561 status
= SRB_STATUS_SUCCESS
;
8564 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8566 } else { // read task register
8569 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
8571 KdPrint2((PRINT_PREFIX
8572 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
8573 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8575 if((Srb
->DataTransferLength
>= sizeof(IDEREGS_EX
)) &&
8576 (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
)) {
8579 if(Srb
->DataTransferLength
>= sizeof(IDEREGS
)) {
8582 KdPrint2((PRINT_PREFIX
" buffer too small \n"));
8583 status
= SRB_STATUS_DATA_OVERRUN
;
8586 RtlZeroMemory(regs
, use48
? sizeof(IDEREGS_EX
) : sizeof(IDEREGS
));
8587 regs
->bOpFlags
= use48
? ATA_FLAGS_48BIT_COMMAND
: 0;
8588 UniataSnapAtaRegs(chan
, 0, regs
);
8590 status
= SRB_STATUS_SUCCESS
;
8597 KdPrint2((PRINT_PREFIX
8598 "IdeSendCommand: Unsupported command %#x\n",
8601 status
= SRB_STATUS_INVALID_REQUEST
;
8605 if(status
== SRB_STATUS_PENDING
) {
8606 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
8607 if(CmdAction
& CMD_ACTION_EXEC
) {
8608 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
8609 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
8612 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
8613 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8618 } // end IdeSendCommand()
8623 Routine Description:
8624 Enables disables media status notification
8627 HwDeviceExtension - ATAPI driver storage.
8634 IN PVOID HwDeviceExtension
,
8636 IN ULONG DeviceNumber
8639 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8641 UCHAR statusByte
,errorByte
;
8643 chan
= &(deviceExtension
->chan
[lChannel
]);
8644 SelectDrive(chan
, DeviceNumber
);
8646 if (EnableMSN
== TRUE
){
8648 // If supported enable Media Status Notification support
8649 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
8652 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8653 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8654 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8656 if (statusByte
& IDE_STATUS_ERROR
) {
8657 // Read the error register.
8658 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8660 KdPrint2((PRINT_PREFIX
8661 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
8665 chan
->lun
[DeviceNumber
]->DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
8666 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
8667 chan
->ReturningMediaStatus
= 0;
8672 } else { // end if EnableMSN == TRUE
8674 // disable if previously enabled
8675 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
8677 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8678 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8679 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8680 chan
->lun
[DeviceNumber
]->DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
8687 } // end IdeMediaStatus()
8692 Routine Description:
8694 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
8695 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
8698 HwDeviceExtension - ATAPI driver storage.
8699 Srb - System request block.
8703 SRB status (ALWAYS SUCCESS).
8708 IdeBuildSenseBuffer(
8709 IN PVOID HwDeviceExtension
,
8710 IN PSCSI_REQUEST_BLOCK Srb
8713 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8715 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
8716 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
8720 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
8722 senseBuffer
->ErrorCode
= 0x70;
8723 senseBuffer
->Valid
= 1;
8724 senseBuffer
->AdditionalSenseLength
= 0xb;
8725 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8726 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8727 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8728 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
8730 senseBuffer
->ErrorCode
= 0x70;
8731 senseBuffer
->Valid
= 1;
8732 senseBuffer
->AdditionalSenseLength
= 0xb;
8733 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8734 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8735 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8736 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
8738 senseBuffer
->ErrorCode
= 0x70;
8739 senseBuffer
->Valid
= 1;
8740 senseBuffer
->AdditionalSenseLength
= 0xb;
8741 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
8742 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
8743 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8744 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
8746 senseBuffer
->ErrorCode
= 0x70;
8747 senseBuffer
->Valid
= 1;
8748 senseBuffer
->AdditionalSenseLength
= 0xb;
8749 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
8750 senseBuffer
->AdditionalSenseCode
= 0;
8751 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8753 return SRB_STATUS_SUCCESS
;
8755 return SRB_STATUS_ERROR
;
8757 }// End of IdeBuildSenseBuffer
8761 UniataUserDeviceReset(
8762 PHW_DEVICE_EXTENSION deviceExtension
,
8763 PHW_LU_EXTENSION LunExt
,
8768 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8769 if ((LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
8770 (LunExt
->PowerState
!= StartStop_Power_Sleep
)) {
8771 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
8772 AtapiSoftReset(&(deviceExtension
->chan
[lChannel
]), LunExt
->Lun
);
8774 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
8775 AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8776 for(i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
8777 deviceExtension
->chan
[lChannel
].lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
8780 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
8781 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8783 } // end UniataUserDeviceReset()
8788 PHW_DEVICE_EXTENSION deviceExtension
,
8793 BOOLEAN PostReq
= FALSE
;
8795 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
8796 if(chan
->queue_depth
> 0) {
8799 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
8800 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
8801 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
8803 status
= SRB_STATUS_BUSY
;
8812 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
8816 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
8819 } // end UniataNeedQueueing()
8823 Routine Description:
8825 This routine is called from the SCSI port driver synchronized
8826 with the kernel to start an IO request.
8831 HwDeviceExtension - HBA miniport driver's adapter data storage
8832 Srb - IO request packet
8842 IN PVOID HwDeviceExtension
,
8843 IN PSCSI_REQUEST_BLOCK Srb
8846 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
8847 } // end AtapiStartIo()
8852 IN PVOID HwDeviceExtension
,
8853 IN PSCSI_REQUEST_BLOCK Srb
,
8857 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8860 PHW_LU_EXTENSION LunExt
;
8868 PSCSI_REQUEST_BLOCK tmpSrb
;
8869 BOOLEAN PostReq
= FALSE
;
8871 BOOLEAN commPort
= FALSE
;
8873 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
8874 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
8875 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
8876 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
8878 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
8880 /* KeBugCheckEx(0xc000000e,
8881 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8883 TopLevel, 0x80000001);
8885 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
8886 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
8887 //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
8888 UniAtaClearAtaReq(Srb
->SrbExtension
);
8891 do { // fetch all queued commands for the channel (if valid)
8893 lChannel
= GET_CHANNEL(Srb
);
8894 //ldev = GET_LDEV(Srb);
8897 DeviceNumber
= GET_CDEV(Srb
);
8900 //ASSERT(deviceExtension);
8903 KdPrint2((PRINT_PREFIX
8904 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8905 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8906 KdPrint2((PRINT_PREFIX
" VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
8908 if(lChannel
== deviceExtension
->NumberChannels
&&
8909 !Srb
->Lun
&& !Srb
->TargetId
&&
8910 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
8911 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
8913 // This is our virtual device
8914 KdPrint2((PRINT_PREFIX
8915 "AtapiStartIo: Communication port\n"));
8916 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
8918 if(Srb
->DataTransferLength
< sizeof(PINQUIRYDATA
)) {
8919 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", Srb
->DataTransferLength
,
8920 sizeof(PINQUIRYDATA
) ));
8922 status
= SRB_STATUS_DATA_OVERRUN
;
8926 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
8928 KdPrint2((PRINT_PREFIX
8930 // Zero INQUIRY data structure.
8931 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
8933 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
8935 // Fill in vendor identification fields.
8936 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
8938 status
= SRB_STATUS_SUCCESS
;
8942 /* Pass IOCTL request down */
8944 if(lChannel
>= deviceExtension
->NumberChannels
||
8945 Srb
->TargetId
/*DeviceNumber*/ >= deviceExtension
->NumberLuns
||
8948 if(lChannel
>= deviceExtension
->NumberChannels
) {
8953 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8954 KdPrint3((PRINT_PREFIX
8955 "AtapiStartIo: SRB rejected\n"));
8956 // Indicate no device found at this address.
8957 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
8958 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8962 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
8963 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
8968 chan
= &(deviceExtension
->chan
[lChannel
]);
8969 LunExt
= chan
->lun
[DeviceNumber
];
8973 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
8979 if(!commPort
&& !LunExt
) {
8981 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
8984 deviceExtension
->NumberChannels
);
8985 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
8986 lChannel
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
8987 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8988 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
8992 for(i=0; i<1000; i++) {
8993 AtapiStallExecution(3*1000);
9000 // Determine which function.
9001 switch (Srb
->Function
) {
9003 case SRB_FUNCTION_EXECUTE_SCSI
:
9005 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9006 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
9007 // let passthrough go
9009 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
9013 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
9014 KdPrint2((PRINT_PREFIX
9015 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
9016 // Indicate no device found at this address.
9017 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
9018 status
= SRB_STATUS_SELECTION_TIMEOUT
;
9023 KdPrint2((PRINT_PREFIX
9024 " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb
, &(Srb
->Cdb
), Srb
->SrbExtension
, Srb
->Cdb
[0]));
9028 if(Srb->DataTransferLength) {
9030 a = ((PUCHAR)(Srb->DataBuffer))[0];
9033 } __except(EXCEPTION_EXECUTE_HANDLER) {
9034 KdPrint3((PRINT_PREFIX
9035 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
9036 // Indicate no device found at this address.
9037 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
9038 status = SRB_STATUS_ERROR;
9039 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
9044 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9048 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
9050 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
9051 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
9053 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
9055 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
9056 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
9058 /*KeBugCheckEx(0xc000000e,
9059 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
9061 status, 0x80000001);*/
9062 if(status
== SRB_STATUS_BUSY
)
9063 status
= SRB_STATUS_PENDING
;
9064 // Insert requests AFTER they have been initialized on
9065 // CMD_ACTION_PREPARE stage
9066 // we should not check TopLevel here (it is always TRUE)
9067 //ASSERT(chan->lun[GET_CDEV(Srb)]);
9068 UniataQueueRequest(chan
, Srb
);
9070 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9074 // Send command to device.
9075 KdPrint2((PRINT_PREFIX
"Send to device %x\n", Srb
->Cdb
[0]));
9077 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
9078 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9079 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
9080 //ASSERT(!AtaReq->Flags);
9081 //ASSERT(chan->lun[GET_CDEV(Srb)]);
9082 UniataQueueRequest(chan
, Srb
);
9083 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
9084 //ASSERT(!AtaReq->Flags);
9085 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9086 //ASSERT(!AtaReq->Flags);
9090 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9094 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
9095 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, DeviceNumber
)) {
9096 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, DeviceNumber
, TRUE
)) {
9100 if(!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9104 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
9113 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)/* &&
9114 (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
9115 KdPrint3((PRINT_PREFIX
"Try ATAPI send %x\n", Srb
->Cdb
[0]));
9116 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
9118 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
9123 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
9130 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
9132 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
9134 /* KeBugCheckEx(0xc000000e,
9135 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
9137 status, 0x80000002);*/
9145 case SRB_FUNCTION_ABORT_COMMAND
:
9147 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
9149 // Verify that SRB to abort is still outstanding.
9150 if((tmpSrb
!= Srb
->NextSrb
) ||
9151 !chan
->queue_depth
) {
9153 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
9155 // Complete abort SRB.
9156 status
= SRB_STATUS_ABORT_FAILED
;
9160 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
9161 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
9162 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
9163 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
9164 // Log reset failure.
9165 KdPrint3((PRINT_PREFIX
9166 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
9167 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
9169 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
9170 status
= SRB_STATUS_ERROR
;
9173 status
= SRB_STATUS_SUCCESS
;
9176 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
9177 if (tmpSrb
->SenseInfoBuffer
&&
9178 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
9180 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
9182 senseBuffer
->ErrorCode
= 0;
9183 senseBuffer
->Valid
= 1;
9184 senseBuffer
->AdditionalSenseLength
= 0xb;
9185 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
9186 senseBuffer
->AdditionalSenseCode
= 0;
9187 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
9189 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
9191 AtapiDmaDBSync(chan
, tmpSrb
);
9192 UniataRemoveRequest(chan
, tmpSrb
);
9193 // Indicate command complete.
9194 ScsiPortNotification(RequestComplete
,
9197 status
= SRB_STATUS_SUCCESS
;
9201 // Abort function indicates that a request timed out.
9202 // Call reset routine. Card will only be reset if
9203 // status indicates something is wrong.
9204 // Fall through to reset code.
9206 case SRB_FUNCTION_RESET_DEVICE
:
9207 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
9209 // Reset single device.
9210 // For now we support only Lun=0
9212 // Note: reset is immediate command, it cannot be queued since it is usually used to
9213 // revert not-responding device to operational state
9214 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
9215 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
9216 status
= SRB_STATUS_SUCCESS
;
9219 case SRB_FUNCTION_RESET_BUS
:
9221 // Reset Atapi and SCSI bus.
9223 // Note: reset is immediate command, it cannot be queued since it is usually used to
9224 // revert not- responding device to operational state
9225 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
9226 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
9227 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
9228 // Log reset failure.
9229 KdPrint3((PRINT_PREFIX
9230 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
9231 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
9233 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
9234 status
= SRB_STATUS_ERROR
;
9237 status
= SRB_STATUS_SUCCESS
;
9242 case SRB_FUNCTION_SHUTDOWN
:
9244 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
9245 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9246 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
9249 // FLUSH ATAPI device - do nothing
9250 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
9252 // FLUSH IDE/ATA device
9253 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
9254 AtapiDisableInterrupts(deviceExtension
, lChannel
);
9255 status
= AtaCommand(deviceExtension
, DeviceNumber
, GET_CHANNEL(Srb
),
9256 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
9257 // If supported & allowed, reset write cacheing
9258 if(LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
9260 // Disable write cache
9261 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9262 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9263 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
9264 // Check for errors.
9265 if (status
& IDE_STATUS_ERROR
) {
9266 KdPrint2((PRINT_PREFIX
9267 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
9270 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9272 // Re-enable write cache
9273 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9274 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9275 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
9276 // Check for errors.
9277 if (status
& IDE_STATUS_ERROR
) {
9278 KdPrint2((PRINT_PREFIX
9279 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
9281 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9283 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
9287 AtapiEnableInterrupts(deviceExtension
, lChannel
);
9289 status
= SRB_STATUS_SUCCESS
;
9293 case SRB_FUNCTION_FLUSH
:
9295 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
9296 status
= SRB_STATUS_SUCCESS
;
9299 case SRB_FUNCTION_IO_CONTROL
: {
9303 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
9305 len
= Srb
->DataTransferLength
;
9307 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
9309 ULONG targetId
= (ULONG
)(-1);
9311 if(len
< sizeof(SRB_IO_CONTROL
)) {
9312 goto wrong_buffer_size
;
9315 // extract bogus bus address
9316 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9317 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9318 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9320 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(GETVERSIONINPARAMS
)) {
9321 goto wrong_buffer_size
;
9324 targetId
= versionParameters
->bIDEDeviceMap
;
9325 KdPrint2((PRINT_PREFIX
"targetId (smart ver) %d\n", targetId
));
9327 case IOCTL_SCSI_MINIPORT_IDENTIFY
:
9328 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
9329 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
9330 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
9331 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
9332 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
9333 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
9334 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
9335 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
9336 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE
:
9337 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG
:
9338 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG
:
9340 PSENDCMDINPARAMS cmdInParameters
= (PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9342 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDINPARAMS
) - 1) {
9343 goto wrong_buffer_size
;
9346 targetId
= cmdInParameters
->bDriveNumber
;
9347 KdPrint2((PRINT_PREFIX
"targetId (smart/ident) %d\n", targetId
));
9351 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9352 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
9353 status
= SRB_STATUS_INVALID_REQUEST
;
9357 // adjust (if necessary) bus address
9358 if(targetId
!= (ULONG
)(-1)) {
9360 // This is done because of how the IOCTL_SCSI_MINIPORT
9361 // determines 'targetid's'. Disk.sys places the real target id value
9362 // in the DeviceMap field. Once we do some parameter checking, the value passed
9363 // back to the application will be determined.
9365 if (deviceExtension
->NumberChannels
== 1) {
9366 // do this for legacy controllers and legacy callers
9367 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call\n"));
9368 DeviceNumber
= (targetId
& 0x01);
9372 // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
9373 // due to DISK.SYS design bug, we have invalid SCSI address in SRB
9374 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call (2)\n"));
9375 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
9376 lChannel
= (UCHAR
)targetId
/ 2;
9379 lChannel
= (UCHAR
)(targetId
/ 2);
9380 DeviceNumber
= targetId
& 0x01;
9383 // otherwise assume lChannel and DeviceNumber from Srb are ok
9385 if(lChannel
>= deviceExtension
->NumberChannels
||
9386 DeviceNumber
>= deviceExtension
->NumberLuns
) {
9387 KdPrint2((PRINT_PREFIX
9388 "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
9390 // Indicate no device found at this address.
9393 targetId
= lChannel
*deviceExtension
->NumberLuns
+DeviceNumber
;
9394 chan
= &(deviceExtension
->chan
[lChannel
]);
9395 LunExt
= chan
->lun
[DeviceNumber
];
9399 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
9401 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9406 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9407 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9409 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9410 UCHAR deviceNumberMap
;
9412 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
9414 // Version and revision per SMART 1.03
9416 versionParameters
->bVersion
= 1;
9417 versionParameters
->bRevision
= 1;
9418 versionParameters
->bReserved
= 0;
9420 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
9421 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
9424 goto invalid_request
;
9427 // NOTE: This will only set the bit
9428 // corresponding to this drive's target id.
9429 // The bit mask is as follows:
9435 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
9436 deviceNumberMap
= 1 << lChannel
;
9439 if (deviceExtension
->NumberChannels
== 1) {
9440 if (chan
->PrimaryAddress
) {
9441 deviceNumberMap
= 1 << DeviceNumber
;
9443 deviceNumberMap
= 4 << DeviceNumber
;
9446 deviceNumberMap
= 1 << (DeviceNumber
+lChannel
*2);
9449 versionParameters
->bIDEDeviceMap
= deviceNumberMap
;
9451 status
= SRB_STATUS_SUCCESS
;
9455 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
9457 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9458 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9460 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
9461 // Extract the target.
9462 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
9464 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
9467 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
9468 goto invalid_request
;
9474 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
9475 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
9476 goto invalid_request
;
9479 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
9480 // Zero the output buffer
9481 RtlZeroMemory(cmdOutParameters
, len
);
9482 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
9483 ((PUCHAR)cmdOutParameters)[i] = 0;
9486 // Build status block.
9487 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
9488 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
9489 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
9491 // Extract the identify data from the device extension.
9492 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &(LunExt
->IdentifyData
),
9493 cmdOutParameters
->cBufferSize
);
9495 if((cmdOutParameters
->cBufferSize
== IDENTIFY_BUFFER_SIZE
) &&
9496 (LunExt
->IdentifyData
.ChecksumValid
== ATA_ChecksumValid
)) {
9497 // adjust checksum if it is possible
9501 for(i
=0; i
< IDENTIFY_BUFFER_SIZE
-1; i
++) {
9502 csum
+= (CHAR
)(cmdOutParameters
->bBuffer
[i
]);
9504 cmdOutParameters
->bBuffer
[i
] = -csum
;
9505 KdPrint2((PRINT_PREFIX
"AtapiStartIo: adjust checksum %d\n"));
9507 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
9509 status
= SRB_STATUS_SUCCESS
;
9513 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
9514 cmdInParameters
.irDriveRegs
.bCommandReg
));
9515 status
= SRB_STATUS_INVALID_REQUEST
;
9521 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9522 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9523 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9524 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9525 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9526 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9527 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9528 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9531 // *all* IOCTLs here are SMART
9533 KdPrint2((PRINT_PREFIX
9534 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
9537 goto invalid_request
;
9540 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9542 if(PostReq
|| TopLevel
) {
9543 UniataQueueRequest(chan
, Srb
);
9544 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9545 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9550 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
9551 status
= SRB_STATUS_PENDING
;
9553 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9556 status
= IdeSendSmartCommand(HwDeviceExtension
, Srb
, targetId
);
9560 // we should not get here, checked above
9562 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9563 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9564 status = SRB_STATUS_INVALID_REQUEST;
9569 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
9571 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
9572 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
9573 ULONG DeviceNumber
= AtaCtl
->addr
.TargetId
;
9577 pos
= FIELD_OFFSET(UNIATA_CTL
, RawData
);
9578 //chan = &(deviceExtension->chan[lChannel]);
9580 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9581 FIELD_OFFSET(UNIATA_CTL
, RawData
) ));
9582 goto wrong_buffer_size
;
9585 if(AtaCtl
->addr
.Lun
||
9586 AtaCtl
->addr
.TargetId
>= deviceExtension
->NumberLuns
||
9587 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
9595 lChannel
= AtaCtl
->addr
.PathId
;
9596 chan
= &(deviceExtension
->chan
[lChannel
]);
9597 LunExt
= chan
->lun
[DeviceNumber
];
9600 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl
->hdr
.ControlCode
, DeviceNumber
));
9602 /* check for valid LUN */
9603 switch (AtaCtl
->hdr
.ControlCode
) {
9604 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9605 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
9606 // this would be BUS reset
9608 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
9609 AtaCtl
->addr
.TargetId
!= 0xff ||
9610 AtaCtl
->addr
.Lun
!= 0
9612 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
9613 DeviceNumber
< deviceExtension
->NumberLuns
) { // AtaCtl->addr.TargetId != 0xff
9614 lChannel
= AtaCtl
->addr
.PathId
;
9615 chan
= &(deviceExtension
->chan
[lChannel
]);
9616 LunExt
= chan
->lun
[DeviceNumber
];
9619 goto handle_bad_ldev
;
9622 lChannel
= AtaCtl
->addr
.PathId
;
9623 chan
= &(deviceExtension
->chan
[lChannel
]);
9626 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
9627 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9628 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
9629 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9630 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
9633 KdPrint2((PRINT_PREFIX
9634 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
9635 // Indicate no device found at this address.
9640 /* check if queueing is necessary */
9641 switch (AtaCtl
->hdr
.ControlCode
) {
9642 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9643 if(!LunExt
->nBadBlocks
) {
9646 goto uata_ctl_queue
;
9647 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9648 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9649 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9650 pos
+sizeof(AtaCtl
->SetMode
) ));
9651 goto wrong_buffer_size
;
9653 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
9656 goto uata_ctl_queue
;
9657 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9658 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
9660 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
9661 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9663 if(PostReq
|| TopLevel
) {
9664 UniataQueueRequest(chan
, Srb
);
9665 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9666 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9669 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
9670 status
= SRB_STATUS_PENDING
;
9672 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9675 } // end switch (AtaCtl->hdr.ControlCode)
9677 /* process request */
9678 switch (AtaCtl
->hdr
.ControlCode
) {
9679 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9681 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
9683 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9684 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9685 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9686 goto wrong_buffer_size
;
9688 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
9689 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
9690 if(AtaCtl
->addr
.TargetId
!= 0xff) {
9691 LunExt
->DeviceFlags
&= ~DFLAGS_HIDDEN
;
9696 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9697 AtapiStallExecution(1000 * 1000);
9700 FindDevices(HwDeviceExtension
,
9701 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
9702 ? UNIATA_FIND_DEV_UNHIDE
: 0,
9703 AtaCtl
->addr
.PathId
);
9704 status
= SRB_STATUS_SUCCESS
;
9708 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
9710 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
9712 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9713 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9714 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9715 goto wrong_buffer_size
;
9717 LunExt
->DeviceFlags
= 0;
9718 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
9719 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
9720 //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
9721 UniataForgetDevice(LunExt
);
9724 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9725 AtapiStallExecution(1000 * 1000);
9728 status
= SRB_STATUS_SUCCESS
;
9731 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
9733 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
9735 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9736 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9737 pos
+sizeof(AtaCtl
->SetMode
) ));
9738 goto wrong_buffer_size
;
9740 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
9741 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
9743 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
9744 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
9745 if(LunExt
->LimitedTransferMode
>
9746 LunExt
->OrigTransferMode
) {
9747 // check for incorrect value
9748 LunExt
->LimitedTransferMode
=
9749 LunExt
->OrigTransferMode
;
9752 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
9754 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
9755 if(AtaCtl
->SetMode
.ApplyImmediately
) {
9756 AtapiDmaInit__(deviceExtension
, LunExt
);
9758 /* LunExt->TransferMode =
9759 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
9760 status
= SRB_STATUS_SUCCESS
;
9763 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
9765 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
9767 if(len
< pos
+sizeof(AtaCtl
->GetMode
)) {
9768 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9769 pos
+sizeof(AtaCtl
->GetMode
) ));
9770 goto wrong_buffer_size
;
9772 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
9773 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
9774 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
9775 AtaCtl
->GetMode
.PhyMode
= LunExt
->PhyTransferMode
;
9777 status
= SRB_STATUS_SUCCESS
;
9780 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION
: {
9782 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get version\n"));
9784 if(len
< pos
+sizeof(AtaCtl
->Version
)) {
9785 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9786 pos
+sizeof(AtaCtl
->Version
) ));
9787 goto wrong_buffer_size
;
9789 AtaCtl
->Version
.Length
= sizeof(GETDRVVERSION
);
9790 AtaCtl
->Version
.VersionMj
= UNIATA_VER_MJ
;
9791 AtaCtl
->Version
.VersionMn
= UNIATA_VER_MN
;
9792 AtaCtl
->Version
.SubVerMj
= UNIATA_VER_SUB_MJ
;
9793 AtaCtl
->Version
.SubVerMn
= UNIATA_VER_SUB_MN
;
9795 status
= SRB_STATUS_SUCCESS
;
9798 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
9800 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
9802 if(len
< pos
+sizeof(AtaCtl
->AdapterInfo
)) {
9803 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9804 pos
+sizeof(AtaCtl
->AdapterInfo
) ));
9805 goto wrong_buffer_size
;
9807 AtaCtl
->AdapterInfo
.HeaderLength
= sizeof(ADAPTERINFO
);
9809 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
9810 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
9811 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
9812 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
9813 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
9814 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
9815 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
9816 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
9817 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
9818 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
9819 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
9820 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
9821 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
9822 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
9823 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
9824 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
9825 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
9826 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
9827 AtaCtl
->AdapterInfo
.NumberLuns
= (UCHAR
)deviceExtension
->NumberLuns
;
9828 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
9829 if(deviceExtension
->FullDevName
) {
9830 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
9832 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
9833 AtaCtl
->AdapterInfo
.LunInfoValid
= FALSE
;
9834 AtaCtl
->AdapterInfo
.ChanHeaderLengthValid
= TRUE
;
9836 pos
+= AtaCtl
->AdapterInfo
.HeaderLength
;
9839 RtlZeroMemory(((PCHAR
)AtaCtl
)+pos
,
9842 if(len
>= pos
+AtaCtl
->AdapterInfo
.NumberChannels
*sizeof(CHANINFO
)) {
9843 PCHANINFO ChanInfo
= (PCHANINFO
)( ((PCHAR
)AtaCtl
)+pos
);
9844 PHW_CHANNEL cur_chan
;
9845 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Fill channel info\n"));
9846 for(i
=0;i
<AtaCtl
->AdapterInfo
.NumberChannels
;i
++) {
9847 KdPrint2((PRINT_PREFIX
"chan[%d] %x\n", i
, cur_chan
));
9848 cur_chan
= &(deviceExtension
->chan
[i
]);
9849 ChanInfo
->MaxTransferMode
= cur_chan
->MaxTransferMode
;
9850 ChanInfo
->ChannelCtrlFlags
= cur_chan
->ChannelCtrlFlags
;
9851 RtlCopyMemory(&(ChanInfo
->QueueStat
), &(cur_chan
->QueueStat
), sizeof(ChanInfo
->QueueStat
));
9852 ChanInfo
->ReorderCount
= cur_chan
->ReorderCount
;
9853 ChanInfo
->IntersectCount
= cur_chan
->IntersectCount
;
9854 ChanInfo
->TryReorderCount
= cur_chan
->TryReorderCount
;
9855 ChanInfo
->TryReorderHeadCount
= cur_chan
->TryReorderHeadCount
;
9856 ChanInfo
->TryReorderTailCount
= cur_chan
->TryReorderTailCount
;
9857 //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
9860 AtaCtl
->AdapterInfo
.ChanInfoValid
= TRUE
;
9861 AtaCtl
->AdapterInfo
.ChanHeaderLength
= sizeof(*ChanInfo
);
9864 status
= SRB_STATUS_SUCCESS
;
9867 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
9869 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
9871 ForgetBadBlocks(LunExt
);
9873 status
= SRB_STATUS_SUCCESS
;
9876 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
9878 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
9883 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
);
9886 status
= SRB_STATUS_SUCCESS
;
9890 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
9891 AtaCtl
->hdr
.ControlCode
));
9892 status
= SRB_STATUS_INVALID_REQUEST
;
9897 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
9898 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
9899 "SCSIDISK", "-UNIATA-"));
9901 status
= SRB_STATUS_INVALID_REQUEST
;
9906 } // end SRB_FUNCTION_IO_CONTROL
9909 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
9910 // Indicate unsupported command.
9911 status
= SRB_STATUS_INVALID_REQUEST
;
9919 PathId
= Srb
->PathId
;
9920 TargetId
= Srb
->TargetId
;
9923 if (status
!= SRB_STATUS_PENDING
) {
9925 KdPrint2((PRINT_PREFIX
9926 "AtapiStartIo: Srb %#x complete with status %#x\n",
9930 // Set status in SRB.
9931 Srb
->SrbStatus
= (UCHAR
)status
;
9934 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan
, Srb
));
9935 AtapiDmaDBSync(chan
, Srb
);
9937 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan
, Srb
));
9938 UniataRemoveRequest(chan
, Srb
);
9939 // Indicate command complete.
9940 KdPrint2((PRINT_PREFIX
"AtapiStartIo: ScsiPortNotification\n"));
9941 ScsiPortNotification(RequestComplete
,
9945 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataGetCurRequest\n"));
9946 // Remove current Srb & get next one
9947 if((Srb
= UniataGetCurRequest(chan
))) {
9948 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9949 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
9950 // current request is under precessing, thus
9951 // we should do nothing here
9955 KdPrint2((PRINT_PREFIX
"AtapiStartIo: chan %x, Src %x\n", chan
, Srb
));
9960 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
9962 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
9964 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
9965 // Indicate ready for next request.
9966 ScsiPortNotification(NextRequest
,
9970 ScsiPortNotification(NextLuRequest
,
9978 } // end AtapiStartIo__()
9983 UniataInitAtaCommands()
9989 KdPrint2((PRINT_PREFIX
"UniataInitAtaCommands:\n"));
9991 for(i
=0; i
<256; i
++) {
9996 //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
9999 case IDE_COMMAND_READ_DMA48
:
10000 case IDE_COMMAND_READ_DMA_Q48
:
10001 case IDE_COMMAND_READ_STREAM_DMA48
:
10002 case IDE_COMMAND_READ_STREAM48
:
10003 case IDE_COMMAND_WRITE_DMA48
:
10004 case IDE_COMMAND_WRITE_DMA_Q48
:
10005 case IDE_COMMAND_READ_DMA_Q
:
10006 case IDE_COMMAND_READ_DMA
:
10007 case IDE_COMMAND_WRITE_DMA
:
10008 case IDE_COMMAND_WRITE_DMA_Q
:
10009 case IDE_COMMAND_WRITE_STREAM_DMA48
:
10010 case IDE_COMMAND_WRITE_STREAM48
:
10011 case IDE_COMMAND_WRITE_FUA_DMA48
:
10012 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
10013 case IDE_COMMAND_READ_LOG_DMA48
:
10014 case IDE_COMMAND_WRITE_LOG_DMA48
:
10015 case IDE_COMMAND_TRUSTED_RCV_DMA
:
10016 case IDE_COMMAND_TRUSTED_SEND_DMA
:
10017 case IDE_COMMAND_DATA_SET_MGMT
:
10018 //KdPrint2((PRINT_PREFIX "DMA "));
10019 flags
|= ATA_CMD_FLAG_DMA
;
10023 case IDE_COMMAND_WRITE_FUA_DMA48
:
10024 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
10025 case IDE_COMMAND_WRITE_MUL_FUA48
:
10027 flags
|= ATA_CMD_FLAG_FUA
;
10030 case IDE_COMMAND_READ48
:
10031 case IDE_COMMAND_READ_DMA48
:
10032 case IDE_COMMAND_READ_DMA_Q48
:
10033 case IDE_COMMAND_READ_MUL48
:
10034 case IDE_COMMAND_READ_STREAM_DMA48
:
10035 case IDE_COMMAND_READ_STREAM48
:
10036 case IDE_COMMAND_WRITE48
:
10037 case IDE_COMMAND_WRITE_DMA48
:
10038 case IDE_COMMAND_WRITE_DMA_Q48
:
10039 case IDE_COMMAND_WRITE_MUL48
:
10040 case IDE_COMMAND_WRITE_STREAM_DMA48
:
10041 case IDE_COMMAND_WRITE_STREAM48
:
10042 case IDE_COMMAND_FLUSH_CACHE48
:
10043 case IDE_COMMAND_VERIFY48
:
10045 //KdPrint2((PRINT_PREFIX "48 "));
10046 flags
|= ATA_CMD_FLAG_48
;
10049 case IDE_COMMAND_READ
:
10050 case IDE_COMMAND_READ_MULTIPLE
:
10051 case IDE_COMMAND_READ_DMA
:
10052 case IDE_COMMAND_READ_DMA_Q
:
10053 case IDE_COMMAND_WRITE
:
10054 case IDE_COMMAND_WRITE_MULTIPLE
:
10055 case IDE_COMMAND_WRITE_DMA
:
10056 case IDE_COMMAND_WRITE_DMA_Q
:
10057 case IDE_COMMAND_FLUSH_CACHE
:
10058 case IDE_COMMAND_VERIFY
:
10060 //KdPrint2((PRINT_PREFIX "LBA "));
10061 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
10065 case IDE_COMMAND_READ_NATIVE_SIZE48
:
10066 case IDE_COMMAND_SET_NATIVE_SIZE48
:
10067 // we cannot set LBA flag for these commands to avoid BadBlock handling
10068 //flags |= ATA_CMD_FLAG_LBAIOsupp;
10069 flags
|= ATA_CMD_FLAG_48
;
10071 case IDE_COMMAND_READ_NATIVE_SIZE
:
10072 case IDE_COMMAND_SET_NATIVE_SIZE
:
10074 flags
|= ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_FUA
;
10077 flags
|= ATA_CMD_FLAG_48supp
;
10080 case IDE_COMMAND_READ
:
10081 command
= IDE_COMMAND_READ48
; break;
10082 case IDE_COMMAND_READ_MULTIPLE
:
10083 command
= IDE_COMMAND_READ_MUL48
; break;
10084 case IDE_COMMAND_READ_DMA
:
10085 command
= IDE_COMMAND_READ_DMA48
; break;
10086 case IDE_COMMAND_READ_DMA_Q
:
10087 command
= IDE_COMMAND_READ_DMA_Q48
; break;
10088 case IDE_COMMAND_WRITE
:
10089 command
= IDE_COMMAND_WRITE48
; break;
10090 case IDE_COMMAND_WRITE_MULTIPLE
:
10091 command
= IDE_COMMAND_WRITE_MUL48
; break;
10092 case IDE_COMMAND_WRITE_DMA
:
10093 command
= IDE_COMMAND_WRITE_DMA48
; break;
10094 case IDE_COMMAND_WRITE_DMA_Q
:
10095 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
10096 case IDE_COMMAND_FLUSH_CACHE
:
10097 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
10098 // case IDE_COMMAND_READ_NATIVE_SIZE:
10099 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
10100 case IDE_COMMAND_SET_NATIVE_SIZE
:
10101 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
10102 case IDE_COMMAND_VERIFY
:
10103 command
= IDE_COMMAND_VERIFY48
; break;
10105 //KdPrint2((PRINT_PREFIX "!28->48 "));
10106 flags
&= ~ATA_CMD_FLAG_48supp
;
10110 case IDE_COMMAND_READ
:
10111 case IDE_COMMAND_READ_MULTIPLE
:
10112 case IDE_COMMAND_READ_DMA48
:
10113 case IDE_COMMAND_READ_DMA_Q48
:
10114 case IDE_COMMAND_READ_STREAM_DMA48
:
10115 case IDE_COMMAND_READ_STREAM48
:
10116 case IDE_COMMAND_READ_DMA_Q
:
10117 case IDE_COMMAND_READ_DMA
:
10118 case IDE_COMMAND_READ_LOG_DMA48
:
10119 case IDE_COMMAND_TRUSTED_RCV_DMA
:
10120 case IDE_COMMAND_IDENTIFY
:
10121 case IDE_COMMAND_ATAPI_IDENTIFY
:
10122 //KdPrint2((PRINT_PREFIX "RD "));
10123 flags
|= ATA_CMD_FLAG_In
;
10125 case IDE_COMMAND_WRITE
:
10126 case IDE_COMMAND_WRITE_MULTIPLE
:
10127 case IDE_COMMAND_WRITE_DMA48
:
10128 case IDE_COMMAND_WRITE_DMA_Q48
:
10129 case IDE_COMMAND_WRITE_DMA
:
10130 case IDE_COMMAND_WRITE_DMA_Q
:
10131 case IDE_COMMAND_WRITE_STREAM_DMA48
:
10132 case IDE_COMMAND_WRITE_STREAM48
:
10133 case IDE_COMMAND_WRITE_FUA_DMA48
:
10134 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
10135 //KdPrint2((PRINT_PREFIX "WR "));
10136 flags
|= ATA_CMD_FLAG_Out
;
10140 //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
10141 AtaCommands48
[i
] = command
;
10142 AtaCommandFlags
[i
] = flags
;
10144 } // end UniataInitAtaCommands()
10148 Routine Description:
10150 Installable driver initialization entry point for system.
10158 Status from ScsiPortInitialize()
10165 IN PVOID DriverObject
,
10169 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
10170 ULONG adapterCount
;
10172 ULONG statusToReturn
, newStatus
;
10173 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
10174 BOOLEAN ReEnter
= FALSE
;
10176 #ifndef USE_REACTOS_DDK
10180 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
10181 BOOLEAN PrimaryClaimed
= FALSE
;
10182 BOOLEAN SecondaryClaimed
= FALSE
;
10184 LARGE_INTEGER t0
, t1
;
10186 Connect_DbgPrint();
10187 KdPrint2((PRINT_PREFIX
"%s", (PCCHAR
)ver_string
));
10188 //a = (WCHAR)strlen(ver_string);
10190 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
10191 if(g_opt_Verbose
) {
10192 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
10195 if(!SavedDriverObject
) {
10196 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
10197 #ifdef USE_REACTOS_DDK
10198 KdPrint(("UniATA Init: OS should be ReactOS\n"));
10203 // we are here for the 1st time
10204 // init CrossNT and get OS version
10205 if(!NT_SUCCESS(status
= CrNtInit(SavedDriverObject
, RegistryPath
))) {
10206 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status
));
10207 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
10210 #endif // USE_REACTOS_DDK
10211 KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion
, MinorVersion
, BuildNumber
, *KeNumberProcessors
));
10213 KeQuerySystemTime(&t0
);
10215 KeQuerySystemTime(&t1
);
10216 } while(t0
.QuadPart
== t1
.QuadPart
);
10220 KeQuerySystemTime(&t1
);
10222 } while(t0
.QuadPart
== t1
.QuadPart
);
10223 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
10224 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
10226 KdPrint(("UniATA Init: ReEnter\n"));
10230 // (re)read bad block list
10231 InitBadBlocks(NULL
);
10234 // init ATA command translation table
10235 UniataInitAtaCommands();
10236 // get registry path to settings
10237 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
10238 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
10239 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
10240 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
10241 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
10242 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
10245 if(WinVer_Id() >= WinVer_2k
) {
10246 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
10247 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
10248 WinVer_WDM_Model
= TRUE
;
10250 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
10251 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
10252 WinVer_WDM_Model
= TRUE
;
10256 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
10257 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
10259 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
10262 statusToReturn
= 0xffffffff;
10264 // Zero out structure.
10265 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
10267 // Set size of hwInitializationData.
10268 hwInitializationData
.comm
.HwInitializationDataSize
=
10269 sizeof(hwInitializationData
.comm
) +
10270 // sizeof(hwInitializationData.nt4) +
10271 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
10272 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
10274 // Set entry points.
10275 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
10276 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
10277 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
10278 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
10280 // Specify size of extensions.
10281 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
10282 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
10283 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
10285 // Indicate PIO device.
10286 hwInitializationData
.comm
.MapBuffers
= TRUE
;
10287 // Set PnP-specific API
10288 if(WinVer_Id() > WinVer_NT
) {
10289 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
10290 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
10291 KdPrint(("set AtapiAdapterControl() ptr\n"));
10292 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
10295 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE enum supported BusMaster Devices\n"));
10299 g_opt_VirtualMachine
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualMachineType", g_opt_VirtualMachine
);
10300 if(g_opt_VirtualMachine
> VM_MAX_KNOWN
) {
10301 g_opt_VirtualMachine
= 0;
10303 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualBox", (g_opt_VirtualMachine
== VM_VBOX
))) {
10304 g_opt_VirtualMachine
= VM_VBOX
;
10306 // Pre-scan PCI bus, also check if we are under VM
10307 UniataEnumBusMasterController(DriverObject
, Argument2
);
10309 switch(g_opt_VirtualMachine
) {
10311 KdPrint2((PRINT_PREFIX
"adjust options for VirtualBox\n"));
10312 // adjust options for VirtualBox
10313 g_opt_WaitBusyCount
= 20000;
10314 g_opt_WaitBusyDelay
= 150;
10315 g_opt_WaitDrqDelay
= 100;
10316 g_opt_WaitBusyLongCount
= 20000;
10317 g_opt_MaxIsrWait
= 200;
10318 g_opt_AtapiSendDisableIntr
= FALSE
;
10319 g_opt_AtapiDmaRawRead
= FALSE
;
10324 KdPrint2((PRINT_PREFIX
"old slow machine, adjust timings\n"));
10325 // old slow machine, adjust timings
10326 g_opt_WaitBusyCount
= 20000;
10327 g_opt_WaitBusyDelay
= 150;
10328 g_opt_WaitDrqDelay
= 100;
10329 g_opt_WaitBusyLongCount
= 20000;
10330 g_opt_MaxIsrWait
= 200;
10333 g_opt_WaitBusyCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyCount", g_opt_WaitBusyCount
); // 200 vs 20000
10334 g_opt_WaitBusyDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyDelay", g_opt_WaitBusyDelay
); // 10 vs 150
10335 g_opt_WaitDrqDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitDrqDelay", g_opt_WaitDrqDelay
); // 10 vs 100
10336 g_opt_WaitBusyLongCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongCount", g_opt_WaitBusyLongCount
); // 2000 vs 20000
10337 g_opt_WaitBusyLongDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongDelay", g_opt_WaitBusyLongDelay
); // 250 vs 250
10338 g_opt_AtapiSendDisableIntr
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr
) ? TRUE
: FALSE
; // 1 vs 0
10339 g_opt_AtapiDmaRawRead
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiDmaRawRead", g_opt_AtapiDmaRawRead
) ? TRUE
: FALSE
; // 1 vs 0
10340 g_opt_MaxIsrWait
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"MaxIsrWait", g_opt_MaxIsrWait
); // 40 vs xxx
10343 // Look for legacy ISA-bridged PCI IDE controller (onboard)
10344 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
10345 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
10346 for (i
=0; i
<BMListLen
; i
++) {
10348 if(!BMList
[i
].MasterDev
) {
10349 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
10352 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10356 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
10357 if(BMList
[i
].ChanInitOk
& 0x03) {
10358 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
10360 newStatus
= STATUS_SUCCESS
;
10364 //BMList[i].AltInitMasterDev = (UCHAR)0xff;
10366 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
10367 PrimaryClaimed
= TRUE
;
10368 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
10369 SecondaryClaimed
= TRUE
;
10371 if(!WinVer_WDM_Model
&& !PrimaryClaimed
&& !SecondaryClaimed
&&
10372 !(BMList
[i
].ChanInitOk
& 0x80)) {
10373 newStatus
= UniataClaimLegacyPCIIDE(i
);
10374 if(newStatus
!= STATUS_SUCCESS
) {
10375 KdPrint2((PRINT_PREFIX
"Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
10380 if(g_opt_Verbose
) {
10381 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
10385 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
10387 for(c
=0; c
<2; c
++) {
10389 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10393 if(PrimaryClaimed
) {
10394 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
10399 if(SecondaryClaimed
) {
10400 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
10405 if((WinVer_Id() < WinVer_2k
)) {
10406 // do not even try if already claimed
10408 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
10411 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
10414 if(!WinVer_WDM_Model
) {
10415 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10417 // in WDM model things are different....
10418 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
10419 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
10421 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10422 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10424 if(!WinVer_WDM_Model
) {
10425 BMList
[i
].channel
= (UCHAR
)c
;
10428 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
10429 newStatus
= ScsiPortInitialize(DriverObject
,
10431 &hwInitializationData
.comm
,
10432 (PVOID
)(i
| (alt
? 0x80000000 : 0)));
10433 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10434 if (newStatus
< statusToReturn
) {
10435 statusToReturn
= newStatus
;
10437 if (newStatus
== STATUS_SUCCESS
) {
10438 if(WinVer_Id() < WinVer_2k
) {
10439 // This should be done in HwInitialize under w2k+ to ensure that
10440 // channel is actually initialized
10441 BMList
[i
].ChanInitOk
|= 0x01 << c
;
10443 if(BMList
[i
].ChanInitOk
& (0x01 << c
)) {
10444 KdPrint2((PRINT_PREFIX
"HwInit passed\n"));
10448 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
10449 c = 1; // this will break our for()
10450 BMList[i].ChanInitOk |= 0x01 << c;
10455 /* if(WinVer_Id() >= WinVer_2k) {
10456 // the following didn't work under higher OSes,
10457 // until we move setting of FLAGS to HwInit
10458 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
10461 if(BMList
[i
].ChanInitOk
& 0x03) {
10462 // Under NT we receive status immediately, so
10463 // we can omit alternative init method if STATUS_SUCCESS returned.
10464 // Under w2k+ we relay on flags, set in HwInitialize.
10465 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
10468 if(WinVer_Id() >= WinVer_2k
) {
10469 // try AltInit if HwInit was not called immediately under w2k+
10470 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10472 // if (WinVer_Id() == WinVer_NT) and some error occured
10473 // try alternative init method
10474 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10477 if(g_opt_Verbose
) {
10478 if(BMList
[i
].ChanInitOk
& 0x03) {
10479 _PrintNtConsole(" OK\n");
10481 _PrintNtConsole(" failed\n");
10487 /* KeBugCheckEx(0xc000000e,
10488 (i << 16) | BMList[0].ChanInitOk,
10490 newStatus, statusToReturn);*/
10492 // Look for PCI IDE controller
10493 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
10494 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
10495 for (; i
<BMListLen
; i
++) {
10497 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", 0)) {
10500 /* if(BMList[i].MasterDev)
10502 if(g_opt_Verbose
) {
10503 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
10504 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
10505 BMList
[i
].busNumber
,
10506 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
10507 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
10510 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10511 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10512 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
10514 hwInitializationData
.comm
.VendorId
= (PVOID
)BMList
[i
].VendorId
;
10515 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
10516 hwInitializationData
.comm
.DeviceId
= (PVOID
)BMList
[i
].DeviceId
;
10517 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
10519 BMList
[i
].channel
= 0/*(UCHAR)c*/;
10521 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
10522 hwInitializationData
.comm
.VendorId
,
10523 hwInitializationData
.comm
.DeviceId
));
10524 newStatus
= ScsiPortInitialize(DriverObject
,
10526 &hwInitializationData
.comm
,
10528 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10529 if(newStatus
== (ULONG
)STATUS_DEVICE_DOES_NOT_EXIST
&& BMList
[i
].NeedAltInit
) {
10530 // Note: this is actually a BUG in scsiport.sys
10531 // It stops scanning PCI bus when reaches empty PCI Function inside Slot
10532 // However, this PCI Slot may have higher non-empty Functions
10533 // UniATA will perform all staff instead of ScsiPort under NT,
10534 // but for ReactOS it is better to patch ScsiPort.
10535 KdPrint2((PRINT_PREFIX
"STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
10536 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10537 newStatus
= ScsiPortInitialize(DriverObject
,
10539 &hwInitializationData
.comm
,
10540 (PVOID
)(i
| 0x80000000));
10541 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x (2)\n", newStatus
));
10543 if (newStatus
< statusToReturn
)
10544 statusToReturn
= newStatus
;
10546 if(g_opt_Verbose
) {
10547 if(newStatus
== STATUS_SUCCESS
) {
10548 _PrintNtConsole(" OK\n");
10550 _PrintNtConsole(" failed\n");
10556 /* KeBugCheckEx(0xc000000e,
10559 newStatus, statusToReturn);*/
10563 hwInitializationData
.comm
.VendorId
= 0;
10564 hwInitializationData
.comm
.VendorIdLength
= 0;
10565 hwInitializationData
.comm
.DeviceId
= 0;
10566 hwInitializationData
.comm
.DeviceIdLength
= 0;
10569 hwInitializationData
.comm
.SrbExtensionSize
= //FIELD_OFFSET(ATA_REQ, ata);
10571 KdPrint2((PRINT_PREFIX
"using AtaReq sz %x\n", hwInitializationData
.comm
.SrbExtensionSize
));
10574 // The adapter count is used by the find adapter routine to track how
10575 // which adapter addresses have been tested.
10577 // Indicate 2 access ranges and reset FindAdapter.
10578 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
10579 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindController
;
10581 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
10582 // Indicate ISA bustype.
10583 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10586 // Call initialization for ISA bustype.
10587 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
10588 newStatus
= ScsiPortInitialize(DriverObject
,
10590 &hwInitializationData
.comm
,
10592 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10593 if (newStatus
< statusToReturn
)
10594 statusToReturn
= newStatus
;
10596 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
10598 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
10599 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
10602 newStatus
= ScsiPortInitialize(DriverObject
,
10604 &hwInitializationData
.comm
,
10606 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10607 if (newStatus
< statusToReturn
)
10608 statusToReturn
= newStatus
;
10610 InDriverEntry
= FALSE
;
10612 KdPrint2((PRINT_PREFIX
"\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn
));
10614 return statusToReturn
;
10616 } // end DriverEntry()
10619 PSCSI_REQUEST_BLOCK
10621 BuildMechanismStatusSrb(
10622 IN PVOID HwDeviceExtension
,
10623 IN PSCSI_REQUEST_BLOCK Srb
10626 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10627 PSCSI_REQUEST_BLOCK srb
;
10629 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10631 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10633 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10635 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10636 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10637 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10638 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10640 // Set flags to disable synchronous negociation.
10641 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10643 // Set timeout to 4 seconds.
10644 srb
->TimeOutValue
= 4;
10646 srb
->CdbLength
= 6;
10647 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
10648 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10649 srb
->SrbExtension
= AtaReq
;
10651 // Set CDB operation code.
10652 cdb
= (PCDB
)srb
->Cdb
;
10653 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
10654 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10656 KdPrint2((PRINT_PREFIX
" MechanismStatusSrb %#x\n", srb
));
10659 } // end BuildMechanismStatusSrb()
10661 #endif //UNIATA_CORE
10663 PSCSI_REQUEST_BLOCK
10665 BuildRequestSenseSrb (
10666 IN PVOID HwDeviceExtension
,
10667 IN PSCSI_REQUEST_BLOCK Srb
10670 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10671 PSCSI_REQUEST_BLOCK srb
;
10673 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10675 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10677 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10679 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10680 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10681 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10682 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10684 // Set flags to disable synchronous negociation.
10685 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10687 // Set timeout to 2 seconds.
10688 srb
->TimeOutValue
= 4;
10690 srb
->CdbLength
= 6;
10691 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
10692 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
10693 srb
->SrbExtension
= AtaReq
;
10695 // Set CDB operation code.
10696 cdb
= (PCDB
)srb
->Cdb
;
10697 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
10698 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
10700 KdPrint2((PRINT_PREFIX
" RequestSenseSrb %#x\n", srb
));
10703 } // end BuildRequestSenseSrb()
10705 #ifndef UNIATA_CORE
10709 AtapiRegCheckDevLunValue(
10710 IN PVOID HwDeviceExtension
,
10711 IN PCWCH NamePrefix
,
10719 ULONG val
= Default
;
10721 val
= AtapiRegCheckParameterValue(
10722 HwDeviceExtension
, NamePrefix
, Name
, val
);
10724 if(chan
!= CHAN_NOT_SPECIFIED
) {
10725 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
10726 val
= AtapiRegCheckParameterValue(
10727 HwDeviceExtension
, namex
, Name
, val
);
10728 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
10729 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
10730 val
= AtapiRegCheckParameterValue(
10731 HwDeviceExtension
, namex
, Name
, val
);
10735 } // end AtapiRegCheckDevLunValue()
10748 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
10767 swprintf(Buffer
+j
, L
"%2.2x", a
);
10775 } // end EncodeVendorStr()
10779 AtapiRegCheckDevValue(
10780 IN PVOID HwDeviceExtension
,
10787 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10788 // WCHAR name0[11];
10789 // WCHAR name1[11+4+5];
10790 // WCHAR name2[11+4+4+10];
10791 // WCHAR name3[11+4+4+5+20];
10792 // WCHAR name3[11+4+4+5+20+1];
10801 IN ULONG SlotNumber
;
10803 ULONG val
= Default
;
10805 KdPrint(( " Parameter %ws\n", Name
));
10807 if(deviceExtension
) {
10808 VendorID
= deviceExtension
->DevID
& 0xffff;
10809 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
10810 SlotNumber
= deviceExtension
->slotNumber
;
10814 SlotNumber
= 0xffffffff;
10817 val
= AtapiRegCheckDevLunValue(
10818 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
10820 if(deviceExtension
) {
10821 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
10823 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
10824 swprintf(namex
, L
"Parameters%s", namev
);
10825 val
= AtapiRegCheckDevLunValue(
10826 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10829 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
10830 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
10831 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
10833 swprintf(namex
, L
"Parameters%s", namev
);
10834 val
= AtapiRegCheckDevLunValue(
10835 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10837 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
10838 val
= AtapiRegCheckDevLunValue(
10839 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10841 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
10842 val
= AtapiRegCheckDevLunValue(
10843 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10845 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
10847 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
10848 swprintf(namex
, L
"Parameters%s", namev
);
10849 val
= AtapiRegCheckDevLunValue(
10850 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10852 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
10853 swprintf(namex
, L
"Parameters%s", namev
);
10854 val
= AtapiRegCheckDevLunValue(
10855 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10858 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
10860 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
10861 swprintf(namex
, L
"Parameters%s", namev
);
10862 val
= AtapiRegCheckDevLunValue(
10863 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10865 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
10866 swprintf(namex
, L
"Parameters%s", namev
);
10867 val
= AtapiRegCheckDevLunValue(
10868 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10873 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
10876 } // end AtapiRegCheckDevValue()
10879 The user must specify that Xxx is to run on the platform
10880 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
10881 Services\UniATA\Xxx:REG_DWORD:Zzz.
10883 The user can override the global setting to enable or disable Xxx on a
10884 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
10885 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
10887 If this registry value does not exist or contains the value zero then
10888 the timer to check for media change does not run.
10892 RegistryPath - pointer to the unicode string inside
10893 ...\CurrentControlSet\Services\UniATA
10894 DeviceNumber - The number of the HBA device object
10896 Returns: Registry Key value
10900 AtapiRegCheckParameterValue(
10901 IN PVOID HwDeviceExtension
,
10902 IN PCWSTR PathSuffix
,
10907 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
10909 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10911 LONG zero
= Default
;
10913 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
10916 LONG doRun
= Default
;
10918 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
10920 UNICODE_STRING paramPath
;
10922 // <SavedRegPath>\<PathSuffix> -> <Name>
10923 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
10924 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
10926 paramPath
.Length
= 0;
10927 paramPath
.MaximumLength
= RegistryPath
->Length
+
10928 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
10929 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
10930 if(!paramPath
.Buffer
) {
10931 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
10935 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
10936 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
10937 RtlAppendUnicodeToString(¶mPath
, L
"\\");
10938 RtlAppendUnicodeToString(¶mPath
, REGRTL_STR_PTYPE PathSuffix
);
10940 // Check for the Xxx value.
10941 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
10943 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
10944 parameters
[0].Name
= REGRTL_STR_PTYPE Name
;
10945 parameters
[0].EntryContext
= &doRun
;
10946 parameters
[0].DefaultType
= REG_DWORD
;
10947 parameters
[0].DefaultData
= &zero
;
10948 parameters
[0].DefaultLength
= sizeof(ULONG
);
10950 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
10951 paramPath
.Buffer
, parameters
, NULL
, NULL
);
10952 if(NT_SUCCESS(status
)) {
10953 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix
, Name
, doRun
));
10956 ExFreePool(paramPath
.Buffer
);
10958 if(!NT_SUCCESS(status
)) {
10964 #undef ITEMS_TO_QUERY
10966 } // end AtapiRegCheckParameterValue()
10969 SCSI_ADAPTER_CONTROL_STATUS
10971 AtapiAdapterControl(
10972 IN PVOID HwDeviceExtension
,
10973 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
10974 IN PVOID Parameters
10977 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10978 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
10979 ULONG numberChannels
= deviceExtension
->NumberChannels
;
10983 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
10985 switch(ControlType
) {
10986 case ScsiQuerySupportedControlTypes
: {
10987 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
10988 TRUE
, // ScsiQuerySupportedControlTypes
10989 TRUE
, // ScsiStopAdapter
10990 TRUE
, // ScsiRestartAdapter
10991 FALSE
, // ScsiSetBootConfig
10992 FALSE
// ScsiSetRunningConfig
10995 ULONG lim
= ScsiAdapterControlMax
;
10998 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
11000 if(pControlTypeList
->MaxControlType
< lim
) {
11001 lim
= pControlTypeList
->MaxControlType
;
11004 for(i
= 0; i
< lim
; i
++) {
11005 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
11011 case ScsiStopAdapter
: {
11013 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
11014 // Shut down all interrupts on the adapter. They'll get re-enabled
11015 // by the initialization routines.
11016 for (c
= 0; c
< numberChannels
; c
++) {
11017 AtapiResetController(deviceExtension
, c
);
11018 AtapiDisableInterrupts(deviceExtension
, c
);
11020 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
11021 // we must never get here for non-PCI
11022 /*status =*/ UniataDisconnectIntr2(HwDeviceExtension
);
11023 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
11027 case ScsiRestartAdapter
: {
11029 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
11030 // Enable all the interrupts on the adapter while port driver call
11031 // for power up an HBA that was shut down for power management
11033 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
11034 status
= UniataConnectIntr2(HwDeviceExtension
);
11035 if(NT_SUCCESS(status
)) {
11036 for (c
= 0; c
< numberChannels
; c
++) {
11037 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
11038 FindDevices(HwDeviceExtension
, 0, c
);
11039 AtapiEnableInterrupts(deviceExtension
, c
);
11040 AtapiHwInitialize__(deviceExtension
, c
);
11042 if(deviceExtension
->Isr2DevObj
) {
11043 // we must never get here for non-PCI
11044 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
11052 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
11053 return ScsiAdapterControlUnsuccessful
;
11057 return ScsiAdapterControlSuccess
;
11058 } // end AtapiAdapterControl()
11060 #endif //UNIATA_CORE
11070 #define DEBUG_MSG_BUFFER_SIZE 512
11081 UCHAR dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
];
11082 // UNICODE_STRING msgBuff;
11084 va_start(ap
, DebugMessage
);
11086 /*len =*/ _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], DEBUG_MSG_BUFFER_SIZE
-1, DebugMessage
, ap
);
11088 dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
-1] = 0;
11090 //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro
11091 HalDisplayString(dbg_print_tmp_buff
);
11094 if(g_LogToDisplay
> 1) {
11095 AtapiStallExecution(g_LogToDisplay
*1000);
11101 } // end PrintNtConsole()