3 Copyright (c) 2002-2014 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
);
506 KdPrint2((PRINT_PREFIX
"AtapiSuckPort2: overrun detected (%#x words)\n", i
));
509 } // AtapiSuckPort2()
520 GetStatus(chan
, Status
);
521 for (i
=0; i
<g_opt_WaitBusyCount
; i
++) {
522 if (Status
& IDE_STATUS_BUSY
) {
523 AtapiStallExecution(g_opt_WaitBusyDelay
);
524 GetStatus(chan
, Status
);
531 } // end WaitOnBusy()
542 Status
= WaitOnBusy(chan
);
543 if(!(Status
& IDE_STATUS_BUSY
))
545 for (i
=0; i
<g_opt_WaitBusyLongCount
; i
++) {
546 GetStatus(chan
, Status
);
547 if (Status
& IDE_STATUS_BUSY
) {
548 AtapiStallExecution(g_opt_WaitBusyLongDelay
);
555 } // end WaitOnBusyLong()
564 UCHAR Status
= IDE_STATUS_WRONG
;
565 for (i
=0; i
<g_opt_WaitBusyCount
; i
++) {
566 GetBaseStatus(chan
, Status
);
567 if (Status
& IDE_STATUS_BUSY
) {
568 AtapiStallExecution(g_opt_WaitBusyDelay
);
575 } // end WaitOnBaseBusy()
586 Status
= WaitOnBaseBusy(chan
);
587 if(!(Status
& IDE_STATUS_BUSY
))
589 for (i
=0; i
<2000; i
++) {
590 GetBaseStatus(chan
, Status
);
591 if (Status
& IDE_STATUS_BUSY
) {
592 AtapiStallExecution(250);
599 } // end WaitOnBaseBusyLong()
604 IN
struct _HW_DEVICE_EXTENSION
* deviceExtension
,
610 if(Status
== IDE_STATUS_WRONG
) {
611 return IDE_STATUS_WRONG
;
613 if(Status
& IDE_STATUS_BUSY
) {
616 // if(deviceExtension->HwFlags & UNIATA_SATA) {
617 if(UniataIsSATARangeAvailable(deviceExtension
, 0)) {
618 if(Status
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
622 Status2
= Status
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
);
623 if ((Status
& IDE_STATUS_BUSY
) ||
624 (Status2
!= IDE_STATUS_IDLE
&& Status2
!= IDE_STATUS_DRDY
)) {
628 return IDE_STATUS_IDLE
;
629 } // end UniataIsIdle()
640 for (i
=0; i
<20000; i
++) {
641 GetStatus(chan
, Status
);
642 Status2
= UniataIsIdle(chan
->DeviceExtension
, Status
);
643 if(Status2
== IDE_STATUS_WRONG
) {
647 if(Status2
& IDE_STATUS_BUSY
) {
648 AtapiStallExecution(10);
655 } // end WaitForIdleLong()
665 for (i
=0; i
<1000; i
++) {
666 GetStatus(chan
, Status
);
667 if (Status
& IDE_STATUS_BUSY
) {
668 AtapiStallExecution(g_opt_WaitDrqDelay
);
669 } else if (Status
& IDE_STATUS_DRQ
) {
672 AtapiStallExecution(g_opt_WaitDrqDelay
*2);
676 } // end WaitForDrq()
686 for (i
=0; i
<2; i
++) {
687 GetStatus(chan
, Status
);
688 if (Status
& IDE_STATUS_BUSY
) {
689 AtapiStallExecution(g_opt_WaitDrqDelay
);
690 } else if (Status
& IDE_STATUS_DRQ
) {
693 AtapiStallExecution(g_opt_WaitDrqDelay
);
697 } // end WaitShortForDrq()
706 //ULONG c = chan->lChannel;
708 UCHAR dma_status
= 0;
709 KdPrint2((PRINT_PREFIX
"AtapiSoftReset:\n"));
712 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
713 UniataAhciSoftReset(chan
->DeviceExtension
, chan
->lChannel
, DeviceNumber
);
717 GetBaseStatus(chan
, statusByte2
);
718 KdPrint2((PRINT_PREFIX
" statusByte2 %x:\n", statusByte2
));
719 SelectDrive(chan
, DeviceNumber
);
720 if(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
722 AtapiStallExecution(10000);
723 for (i
= 0; i
< 1000; i
++) {
724 AtapiStallExecution(999);
727 AtapiStallExecution(500);
728 GetBaseStatus(chan
, statusByte2
);
729 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_RESET
);
731 // Do not wait for BUSY assertion if it was initially set, jump to
732 // BUSY release wait loop
733 if(!(statusByte2
& IDE_STATUS_BUSY
)) {
734 // Wait for BUSY assertion, in some cases delay may occure
735 // 100ms should be enough
737 while (!(AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
740 AtapiStallExecution(10);
745 // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
746 // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
747 // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
748 // implementation. (which is around 1 second)
749 while ((AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
752 AtapiStallExecution(30);
756 SelectDrive(chan
, DeviceNumber
);
758 GetBaseStatus(chan
, statusByte2
);
759 AtapiStallExecution(500);
761 GetBaseStatus(chan
, statusByte2
);
762 if(chan
&& chan
->DeviceExtension
) {
763 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
764 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
766 KdPrint2((PRINT_PREFIX
" can't get DMA status\n"));
768 if(dma_status
& BM_STATUS_INTR
) {
769 // bullshit, we have DMA interrupt, but had never initiate DMA operation
770 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr on ATAPI reset\n"));
771 AtapiDmaDone(chan
->DeviceExtension
, DeviceNumber
, chan
->lChannel
, NULL
);
772 GetBaseStatus(chan
, statusByte2
);
774 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
775 UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, DeviceNumber
);
776 /* if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
777 UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1);
782 } // end AtapiSoftReset()
785 Send command to device.
786 Translate to 48-Lba form if required
791 IN PHW_DEVICE_EXTENSION deviceExtension
,
792 IN ULONG DeviceNumber
,
801 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
806 KdPrint2((PRINT_PREFIX
"AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
807 deviceExtension
->DevIndex
, deviceExtension
->Channel
, DeviceNumber
, command
, lba
, count
, feature
));
809 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
810 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
812 KdPrint3((" (ahci)\n"));
814 statusByte
= UniataAhciSendPIOCommand(deviceExtension
, lChannel
, DeviceNumber
,
815 (PSCSI_REQUEST_BLOCK
)NULL
,
823 1000 /* timeout 1 sec */
829 SelectDrive(chan
, DeviceNumber
);
831 statusByte
= WaitOnBusy(chan
);
833 /* ready to issue command ? */
834 if (statusByte
& IDE_STATUS_BUSY
) {
835 KdPrint2((PRINT_PREFIX
" Returning BUSY status\n"));
838 // !!! We should not check ERROR condition here
839 // ERROR bit may be asserted durring previous operation
840 // and not cleared after SELECT
842 //>>>>>> NV: 2006/08/03
843 if(((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
|ATA_CMD_FLAG_FUA
)) == ATA_CMD_FLAG_LBAIOsupp
) &&
844 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
845 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
846 return IDE_STATUS_ERROR
;
847 //return SRB_STATUS_ERROR;
849 //<<<<<< NV: 2006/08/03
851 /* only use 48bit addressing if needed because of the overhead */
852 if (UniAta_need_lba48(command
, lba
, count
,
853 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
)) {
855 KdPrint2((PRINT_PREFIX
" dev %#x USE_LBA_48\n", DeviceNumber
));
856 /* translate command into 48bit version */
857 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
858 command
= AtaCommands48
[command
];
860 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
864 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
867 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)(feature
>>8));
868 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
869 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)(count
>>8));
870 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
871 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[3]));
872 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[0]));
873 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[4]));
874 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[1]));
875 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[5]));
876 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[2]));
878 //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber ));
879 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
) );
882 plba
= (PUCHAR
)&lba
; //ktp
883 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
886 // (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
887 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
889 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
890 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)plba
[0]);
891 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)plba
[1]);
892 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)plba
[2]);
893 if(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
894 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber ));
895 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
897 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber ));
898 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
902 // write command code to device
903 AtapiWritePort1(chan
, IDX_IO1_o_Command
, command
);
905 switch (wait_flags
) {
908 // caller requested wait for interrupt
911 statusByte
= WaitForDrq(chan
);
912 if (statusByte
& IDE_STATUS_DRQ
)
914 AtapiStallExecution(500);
915 KdPrint2((PRINT_PREFIX
" retry waiting DRQ, status %#x\n", statusByte
));
922 // caller requested wait for entering Wait state
923 for (i
=0; i
<30 * 1000; i
++) {
925 GetStatus(chan
, statusByte
);
926 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
927 if(statusByte
== IDE_STATUS_WRONG
) {
931 if(statusByte
& IDE_STATUS_ERROR
) {
934 if(statusByte
& IDE_STATUS_BUSY
) {
935 AtapiStallExecution(100);
938 if(statusByte
== IDE_STATUS_IDLE
) {
941 //if(deviceExtension->HwFlags & UNIATA_SATA) {
942 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
945 AtapiStallExecution(100);
948 //statusByte |= IDE_STATUS_BUSY;
952 statusByte
= WaitOnBusyLong(chan
);
954 case ATA_WAIT_BASE_READY
:
955 statusByte
= WaitOnBaseBusyLong(chan
);
958 GetStatus(chan
, statusByte
);
959 if (statusByte
& IDE_STATUS_ERROR
) {
960 KdPrint2((PRINT_PREFIX
" Warning: Immed Status %#x :(\n", statusByte
));
961 if(statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_ERROR
)) {
964 KdPrint2((PRINT_PREFIX
" try to continue\n"));
965 statusByte
&= ~IDE_STATUS_ERROR
;
967 UniataExpectChannelInterrupt(chan
, TRUE
);
969 InterlockedExchange(&(chan
->CheckIntr
),
975 KdPrint2((PRINT_PREFIX
" Status %#x\n", statusByte
));
978 } // end AtaCommand48()
981 Send command to device.
982 This is simply wrapper for AtaCommand48()
987 IN PHW_DEVICE_EXTENSION deviceExtension
,
988 IN ULONG DeviceNumber
,
999 if(!(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
1000 return AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1002 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
1003 count
, feature
, wait_flags
);
1005 return UniataAhciSendPIOCommand(deviceExtension
, lChannel
, DeviceNumber
,
1006 (PSCSI_REQUEST_BLOCK
)NULL
,
1010 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
1013 0 /* ahci flags */ ,
1015 1000 /* timeout 1 sec */
1019 } // end AtaCommand()
1023 AtaPio2Mode(LONG pio
)
1026 default: return ATA_PIO
;
1027 case 0: return ATA_PIO0
;
1028 case 1: return ATA_PIO1
;
1029 case 2: return ATA_PIO2
;
1030 case 3: return ATA_PIO3
;
1031 case 4: return ATA_PIO4
;
1032 case 5: return ATA_PIO5
;
1034 } // end AtaPio2Mode()
1038 AtaPioMode(PIDENTIFY_DATA2 ident
)
1040 if (ident
->PioTimingsValid
) {
1041 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_5
)
1043 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_4
)
1045 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_3
)
1048 if (ident
->PioCycleTimingMode
== 2)
1050 if (ident
->PioCycleTimingMode
== 1)
1052 if (ident
->PioCycleTimingMode
== 0)
1054 return IOMODE_NOT_SPECIFIED
;
1055 } // end AtaPioMode()
1059 AtaWmode(PIDENTIFY_DATA2 ident
)
1061 if (ident
->MultiWordDMASupport
& 0x04)
1063 if (ident
->MultiWordDMASupport
& 0x02)
1065 if (ident
->MultiWordDMASupport
& 0x01)
1067 return IOMODE_NOT_SPECIFIED
;
1072 AtaUmode(PIDENTIFY_DATA2 ident
)
1074 if (!ident
->UdmaModesValid
)
1075 return IOMODE_NOT_SPECIFIED
;
1076 if (ident
->UltraDMASupport
& 0x40)
1078 if (ident
->UltraDMASupport
& 0x20)
1080 if (ident
->UltraDMASupport
& 0x10)
1082 if (ident
->UltraDMASupport
& 0x08)
1084 if (ident
->UltraDMASupport
& 0x04)
1086 if (ident
->UltraDMASupport
& 0x02)
1088 if (ident
->UltraDMASupport
& 0x01)
1090 return IOMODE_NOT_SPECIFIED
;
1095 AtaSAmode(PIDENTIFY_DATA2 ident
) {
1096 if(!ident
->SataCapabilities
||
1097 ident
->SataCapabilities
== 0xffff) {
1098 return IOMODE_NOT_SPECIFIED
;
1100 if(ident
->SataCapabilities
& ATA_SATA_GEN3
) {
1103 if(ident
->SataCapabilities
& ATA_SATA_GEN2
) {
1106 if(ident
->SataCapabilities
& ATA_SATA_GEN1
) {
1109 return IOMODE_NOT_SPECIFIED
;
1110 } // end AtaSAmode()
1117 IN PVOID HwDeviceExtension
1120 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1121 PHW_TIMER HwScsiTimer
;
1123 ULONG MiniportTimerValue
;
1124 BOOLEAN recall
= FALSE
;
1128 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc:\n"));
1130 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1131 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1132 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no items\n"));
1135 chan
= &(deviceExtension
->chan
[lChannel
]);
1139 HwScsiTimer
= chan
->HwScsiTimer
;
1140 chan
->HwScsiTimer
= NULL
;
1142 deviceExtension
->FirstDpcChan
= chan
->NextDpcChan
;
1143 if(deviceExtension
->FirstDpcChan
!= CHAN_NOT_SPECIFIED
) {
1147 HwScsiTimer(HwDeviceExtension
);
1149 chan
->NextDpcChan
= CHAN_NOT_SPECIFIED
;
1151 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1152 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1153 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no more items\n"));
1154 deviceExtension
->FirstDpcChan
=
1155 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1159 KeQuerySystemTime(&time
);
1160 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1162 chan
= &deviceExtension
->chan
[lChannel
];
1163 if(time
.QuadPart
>= chan
->DpcTime
- 10) {
1165 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1166 (ULONG
)(chan
->DpcTime
>> 32), (ULONG
)(chan
->DpcTime
)));
1173 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1174 MiniportTimerValue
= (ULONG
)(time
.QuadPart
- chan
->DpcTime
)/10;
1175 if(!MiniportTimerValue
)
1176 MiniportTimerValue
= 1;
1178 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: recall AtapiTimerDpc\n"));
1179 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1186 } // end AtapiTimerDpc()
1189 Wrapper for ScsiPort, that implements smart Dpc
1190 queueing. We need it to allow parallel functioning
1191 of IDE channles with shared interrupt. Standard Dpc mechanism
1192 cancels previous Dpc request (if any), but we need Dpc queue.
1197 IN PVOID HwDeviceExtension
,
1199 IN PHW_TIMER HwScsiTimer
,
1200 IN ULONG MiniportTimerValue
1203 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1205 LARGE_INTEGER time2
;
1207 PHW_CHANNEL prev_chan
;
1209 // BOOLEAN UseRequestTimerCall = TRUE;
1211 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1212 KeQuerySystemTime(&time
);
1214 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1215 time
.QuadPart
+= MiniportTimerValue
*10;
1216 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1218 KdPrint2((PRINT_PREFIX
" ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension
->ActiveDpcChan
, deviceExtension
->FirstDpcChan
));
1220 i
= deviceExtension
->FirstDpcChan
;
1221 chan
= prev_chan
= NULL
;
1222 while(i
!= CHAN_NOT_SPECIFIED
) {
1224 chan
= &(deviceExtension
->chan
[i
]);
1225 if(chan
->DpcTime
> time
.QuadPart
) {
1228 i
= chan
->NextDpcChan
;
1230 chan
= &(deviceExtension
->chan
[lChannel
]);
1232 deviceExtension
->FirstDpcChan
= lChannel
;
1234 prev_chan
->NextDpcChan
= lChannel
;
1236 chan
->NextDpcChan
= i
;
1237 chan
->HwScsiTimer
= HwScsiTimer
;
1238 chan
->DpcTime
= time
.QuadPart
;
1240 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2
.HighPart
, time2
.LowPart
));
1241 if(time
.QuadPart
<= time2
.QuadPart
) {
1242 MiniportTimerValue
= 1;
1244 MiniportTimerValue
= (ULONG
)((time
.QuadPart
- time2
.QuadPart
) / 10);
1247 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1248 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1250 MiniportTimerValue
);
1252 } // end AtapiQueueTimerDpc()
1254 #endif //UNIATA_CORE
1264 UCHAR statusByteAlt
;
1266 GetStatus(chan
, statusByteAlt
);
1267 KdPrint2((PRINT_PREFIX
" AltStatus (%#x)\n", statusByteAlt
));
1269 for(j
=1; j
<IDX_IO1_SZ
; j
++) {
1270 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1271 KdPrint2((PRINT_PREFIX
1272 " Reg_%#x (%#x) = %#x\n",
1274 chan
->RegTranslation
[IDX_IO1
+j
].Addr
,
1277 for(j
=0; j
<IDX_BM_IO_SZ
-1; j
++) {
1278 statusByteAlt
= AtapiReadPort1(chan
, IDX_BM_IO
+j
);
1279 KdPrint2((PRINT_PREFIX
1280 " BM_%#x (%#x) = %#x\n",
1282 chan
->RegTranslation
[IDX_BM_IO
+j
].Addr
,
1286 } // end UniataDumpATARegs()
1292 IN PHW_CHANNEL chan
,
1293 IN ULONG DeviceNumber
,
1294 IN OUT PIDEREGS_EX regs
1297 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
1299 UniataAhciSnapAtaRegs(chan
, DeviceNumber
, regs
);
1301 // SATA/PATA, assume drive is selected
1303 UCHAR statusByteAlt
;
1305 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) {
1306 for(j
=IDX_IO1_i_Error
; j
<=IDX_IO1_i_Status
; j
++) {
1307 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1308 ((PUCHAR
)regs
)[j
-1] = statusByteAlt
;
1312 regs
->bDriveHeadReg
= AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
);
1313 for(j
=IDX_IO1_i_Error
; j
<IDX_IO1_i_DriveSelect
; j
++) {
1314 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1315 ((PUCHAR
)regs
)[j
-1] = statusByteAlt
;
1316 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1317 ((PUCHAR
)regs
)[j
+8-1] = statusByteAlt
;
1319 regs
->bCommandReg
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
1323 } // end UniataSnapAtaRegs()
1327 Routine Description:
1329 Issue IDENTIFY command to a device.
1333 HwDeviceExtension - HBA miniport driver's adapter data storage
1334 DeviceNumber - Indicates which device.
1335 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1339 TRUE if all goes well.
1345 IN PVOID HwDeviceExtension
,
1346 IN ULONG DeviceNumber
,
1352 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1353 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
1354 ULONG waitCount
= 50000;
1357 //UCHAR statusByte2;
1360 BOOLEAN atapiDev
= FALSE
;
1361 BOOLEAN use_ahci
= FALSE
;
1362 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
1364 use_ahci
= UniataIsSATARangeAvailable(deviceExtension
, lChannel
) &&
1365 (deviceExtension
->HwFlags
& UNIATA_AHCI
);
1367 if(chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) {
1368 if(chan
->PmLunMap
& (1 << DeviceNumber
)) {
1371 KdPrint2((PRINT_PREFIX
"IssueIdentify: PM empty port\n"));
1375 if(DeviceNumber
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
1376 KdPrint2((PRINT_PREFIX
"IssueIdentify: NO SLAVE\n"));
1379 if(LunExt
->DeviceFlags
& DFLAGS_HIDDEN
) {
1380 KdPrint2((PRINT_PREFIX
"IssueIdentify: HIDDEN\n"));
1385 statusByte
= WaitOnBusyLong(chan
);
1387 if(!chan
->AhciInternalAtaReq
) {
1388 KdPrint2((PRINT_PREFIX
"!AhciInternalAtaReq\n"));
1392 SelectDrive(chan
, DeviceNumber
);
1393 AtapiStallExecution(10);
1394 statusByte
= WaitOnBusyLong(chan
);
1395 // Check that the status register makes sense.
1396 GetBaseStatus(chan
, statusByte
);
1399 if (Command
== IDE_COMMAND_IDENTIFY
) {
1400 // Mask status byte ERROR bits.
1401 statusByte
= UniataIsIdle(deviceExtension
, statusByte
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
));
1402 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte
));
1403 // Check if register value is reasonable.
1405 if(statusByte
!= IDE_STATUS_IDLE
) {
1407 // No reset here !!!
1408 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1410 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1411 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1412 SelectDrive(chan
, DeviceNumber
);
1413 WaitOnBusyLong(chan
);
1415 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1416 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1418 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1419 signatureHigh
== ATAPI_MAGIC_MSB
) {
1421 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber
));
1425 // We really should wait up to 31 seconds
1426 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1427 // (30 seconds for device 1)
1429 // Wait for Busy to drop.
1430 AtapiStallExecution(100);
1431 GetStatus(chan
, statusByte
);
1432 if(statusByte
== IDE_STATUS_WRONG
) {
1433 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_WRONG (dev %d)\n", DeviceNumber
));
1437 } while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
--);
1438 GetBaseStatus(chan
, statusByte
);
1440 SelectDrive(chan
, DeviceNumber
);
1442 GetBaseStatus(chan
, statusByte
);
1444 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1446 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1447 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1449 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1450 signatureHigh
== ATAPI_MAGIC_MSB
) {
1451 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber
));
1456 statusByte
= UniataIsIdle(deviceExtension
, statusByte
) & ~IDE_STATUS_INDEX
;
1457 if (statusByte
!= IDE_STATUS_IDLE
) {
1459 KdPrint2((PRINT_PREFIX
"IssueIdentify: no dev (dev %d)\n", DeviceNumber
));
1464 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte
));
1465 if(statusByte
== IDE_STATUS_WRONG
) {
1468 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1469 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1470 statusByte
= WaitForIdleLong(chan
);
1471 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte
));
1476 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1478 statusByte
= UniataAhciSendPIOCommand(HwDeviceExtension
, lChannel
, DeviceNumber
,
1479 (PSCSI_REQUEST_BLOCK
)NULL
,
1480 (PUCHAR
)(&deviceExtension
->FullIdentifyData
),
1485 0 /* ahci flags */ ,
1487 1000 /* timeout 1 sec */
1489 j
= 9; // AHCI is rather different, skip loop at all
1491 if(LunExt
->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
1492 j
= 9; // don't send IDENTIFY, assume it is not supported
1493 KdPrint2((PRINT_PREFIX
"IssueIdentify: Manual CHS\n"));
1494 RtlZeroMemory(&(deviceExtension
->FullIdentifyData
), sizeof(deviceExtension
->FullIdentifyData
));
1495 RtlCopyMemory(&(deviceExtension
->FullIdentifyData
), &(LunExt
->IdentifyData
), sizeof(LunExt
->IdentifyData
));
1497 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1498 j
= 4; // skip old-style checks
1502 for (; j
< 4*2; j
++) {
1503 // Send IDENTIFY command.
1505 // Load CylinderHigh and CylinderLow with number bytes to transfer for old devices, use 0 for newer.
1507 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, Command
, (j
< 4) ? DEV_BSIZE
: 0 /* cyl */, 0, 0, 0, 0, ATA_WAIT_INTR
);
1510 if (statusByte
& IDE_STATUS_DRQ
) {
1511 // Read status to acknowledge any interrupts generated.
1512 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte
));
1513 GetBaseStatus(chan
, statusByte
);
1514 // One last check for Atapi.
1515 if (Command
== IDE_COMMAND_IDENTIFY
) {
1516 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1517 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1519 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1520 signatureHigh
== ATAPI_MAGIC_MSB
) {
1521 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber
));
1528 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte
));
1529 if (Command
== IDE_COMMAND_IDENTIFY
) {
1530 // Check the signature. If DRQ didn't come up it's likely Atapi.
1531 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1532 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1534 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1535 signatureHigh
== ATAPI_MAGIC_MSB
) {
1537 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber
));
1541 if(!(statusByte
& IDE_STATUS_ERROR
) && (statusByte
& IDE_STATUS_BUSY
)) {
1542 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n"));
1546 // Device didn't respond correctly. It will be given one more chance.
1547 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1548 statusByte
, AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
1549 GetBaseStatus(chan
, statusByte
);
1550 AtapiSoftReset(chan
,DeviceNumber
);
1552 AtapiDisableInterrupts(deviceExtension
, lChannel
);
1553 AtapiEnableInterrupts(deviceExtension
, lChannel
);
1555 GetBaseStatus(chan
, statusByte
);
1556 //GetStatus(chan, statusByte);
1557 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after soft reset (%#x)\n", statusByte
));
1560 // Check for error on really stupid master devices that assert random
1561 // patterns of bits in the status register at the slave address.
1562 if ((Command
== IDE_COMMAND_IDENTIFY
) && (statusByte
& IDE_STATUS_ERROR
)) {
1563 KdPrint2((PRINT_PREFIX
"IssueIdentify: Exit on error (%#x)\n", statusByte
));
1568 // everything should already be done by controller
1570 if(LunExt
->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
1571 j
= 9; // don't send IDENTIFY, assume it is not supported
1572 KdPrint2((PRINT_PREFIX
"IssueIdentify: Manual CHS (2)\n"));
1573 statusByte
= WaitForDrq(chan
);
1574 statusByte
= WaitOnBusyLong(chan
);
1575 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1576 GetBaseStatus(chan
, statusByte
);
1579 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status before read words %#x\n", statusByte
));
1580 // Suck out 256 words. After waiting for one model that asserts busy
1581 // after receiving the Packet Identify command.
1582 statusByte
= WaitForDrq(chan
);
1583 statusByte
= WaitOnBusyLong(chan
);
1584 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1586 if (!(statusByte
& IDE_STATUS_DRQ
)) {
1587 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte
));
1588 GetBaseStatus(chan
, statusByte
);
1591 GetBaseStatus(chan
, statusByte
);
1592 KdPrint2((PRINT_PREFIX
"IssueIdentify: BASE statusByte %#x\n", statusByte
));
1594 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
1596 KdPrint2((PRINT_PREFIX
" use 16bit IO\n"));
1598 // ATI/SII chipsets with memory-mapped IO hangs when
1599 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1600 // Unfortunately, I don't know yet how to workaround it except
1601 // spacifying manual delay in the way you see below.
1602 ReadBuffer(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256, PIO0_TIMING
);
1604 // Work around for some IDE and one model Atapi that will present more than
1605 // 256 bytes for the Identify data.
1606 KdPrint2((PRINT_PREFIX
"IssueIdentify: suck data port\n", statusByte
));
1607 statusByte
= AtapiSuckPort2(chan
);
1609 KdPrint2((PRINT_PREFIX
" use 32bit IO\n"));
1610 ReadBuffer2(chan
, (PULONG
)&deviceExtension
->FullIdentifyData
, 256/2, PIO0_TIMING
);
1613 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1614 statusByte
= WaitForDrq(chan
);
1615 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1616 GetBaseStatus(chan
, statusByte
);
1618 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after read words %#x\n", statusByte
));
1621 KdPrint2((PRINT_PREFIX
"IssueIdentify: no setup, exiting\n"));
1625 KdPrint2((PRINT_PREFIX
"Model: %20.20s\n", deviceExtension
->FullIdentifyData
.ModelNumber
));
1626 KdPrint2((PRINT_PREFIX
"FW: %4.4s\n", deviceExtension
->FullIdentifyData
.FirmwareRevision
));
1627 KdPrint2((PRINT_PREFIX
"S/N: %20.20s\n", deviceExtension
->FullIdentifyData
.SerialNumber
));
1628 KdPrint2((PRINT_PREFIX
"Pio: %x\n", deviceExtension
->FullIdentifyData
.PioCycleTimingMode
));
1629 if(deviceExtension
->FullIdentifyData
.PioTimingsValid
) {
1630 KdPrint2((PRINT_PREFIX
"APio: %x\n", deviceExtension
->FullIdentifyData
.AdvancedPIOModes
));
1632 KdPrint2((PRINT_PREFIX
"SWDMA: %x\n", deviceExtension
->FullIdentifyData
.SingleWordDMAActive
));
1633 KdPrint2((PRINT_PREFIX
"MWDMA: %x\n", deviceExtension
->FullIdentifyData
.MultiWordDMAActive
));
1634 if(deviceExtension
->FullIdentifyData
.UdmaModesValid
) {
1635 KdPrint2((PRINT_PREFIX
"UDMA: %x/%x\n", deviceExtension
->FullIdentifyData
.UltraDMAActive
, deviceExtension
->FullIdentifyData
.UltraDMASupport
));
1637 KdPrint2((PRINT_PREFIX
"SATA: %x\n", deviceExtension
->FullIdentifyData
.SataEnable
));
1638 KdPrint2((PRINT_PREFIX
"SATA support: %x, CAPs %#x\n",
1639 deviceExtension
->FullIdentifyData
.SataSupport
,
1640 deviceExtension
->FullIdentifyData
.SataCapabilities
));
1642 LunExt
->LimitedTransferMode
=
1643 LunExt
->OrigTransferMode
=
1644 (UCHAR
)ata_cur_mode_from_ident(&(deviceExtension
->FullIdentifyData
), IDENT_MODE_MAX
);
1645 LunExt
->TransferMode
=
1646 (UCHAR
)ata_cur_mode_from_ident(&(deviceExtension
->FullIdentifyData
), IDENT_MODE_ACTIVE
);
1648 KdPrint2((PRINT_PREFIX
"OrigTransferMode: %x, Active: %x\n", LunExt
->OrigTransferMode
, LunExt
->TransferMode
));
1649 KdPrint2((PRINT_PREFIX
"Accoustic %d, cur %d\n",
1650 deviceExtension
->FullIdentifyData
.VendorAcoustic
,
1651 deviceExtension
->FullIdentifyData
.CurrentAcoustic
1653 KdPrint2((PRINT_PREFIX
"AdvPowerMode %d, cur %d\n",
1654 deviceExtension
->FullIdentifyData
.CfAdvPowerMode
1657 // Check out a few capabilities / limitations of the device.
1658 if (deviceExtension
->FullIdentifyData
.RemovableStatus
& 1) {
1659 // Determine if this drive supports the MSN functions.
1660 KdPrint2((PRINT_PREFIX
"IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1662 deviceExtension
->FullIdentifyData
.RemovableStatus
));
1663 LunExt
->DeviceFlags
|= DFLAGS_REMOVABLE_DRIVE
;
1666 // AHCI doesn't recommend using PIO and multiblock
1667 LunExt
->MaximumBlockXfer
= 0;
1669 if (deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
) {
1670 // Determine max. block transfer for this device.
1671 LunExt
->MaximumBlockXfer
=
1672 (UCHAR
)(deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
& 0xFF);
1674 LunExt
->NumOfSectors
= 0;
1675 if (Command
== IDE_COMMAND_IDENTIFY
) {
1676 ULONGLONG NumOfSectors
=0;
1677 ULONGLONG NativeNumOfSectors
=0;
1678 ULONGLONG cylinders
=0;
1679 ULONGLONG tmp_cylinders
=0;
1681 KdPrint2((PRINT_PREFIX
"PhysLogSectorSize %#x, %#x, offset %#x\n",
1682 deviceExtension
->FullIdentifyData
.PhysLogSectorSize
,
1683 deviceExtension
->FullIdentifyData
.LargeSectorSize
,
1684 deviceExtension
->FullIdentifyData
.LogicalSectorOffset
1687 KdPrint2((PRINT_PREFIX
"NV PM_Sup %d, PM_En %d, En %d, PM ver %#x ver %#x\n",
1688 deviceExtension
->FullIdentifyData
.NVCache_PM_Supported
,
1689 deviceExtension
->FullIdentifyData
.NVCache_PM_Enabled
,
1690 deviceExtension
->FullIdentifyData
.NVCache_Enabled
,
1691 deviceExtension
->FullIdentifyData
.NVCache_PM_Version
,
1692 deviceExtension
->FullIdentifyData
.NVCache_Version
1695 KdPrint2((PRINT_PREFIX
"R-rate %#x\n",
1696 deviceExtension
->FullIdentifyData
.NominalMediaRotationRate
1699 // Read very-old-style drive geometry
1700 KdPrint2((PRINT_PREFIX
"CHS %#x:%#x:%#x\n",
1701 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1702 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1703 deviceExtension
->FullIdentifyData
.SectorsPerTrack
1705 NumOfSectors
= deviceExtension
->FullIdentifyData
.NumberOfCylinders
*
1706 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1707 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1708 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1709 // Check for HDDs > 8Gb
1710 if ((deviceExtension
->FullIdentifyData
.NumberOfCylinders
== 0x3fff) &&
1711 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1712 (NumOfSectors
< deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1713 KdPrint2((PRINT_PREFIX
"NumberOfCylinders == 0x3fff\n"));
1715 (deviceExtension
->FullIdentifyData
.UserAddressableSectors
/
1716 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1717 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1719 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1721 NumOfSectors
= cylinders
*
1722 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1723 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1725 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1729 // Check for LBA mode
1730 KdPrint2((PRINT_PREFIX
"SupportLba flag %#x\n", deviceExtension
->FullIdentifyData
.SupportLba
));
1731 KdPrint2((PRINT_PREFIX
"MajorRevision %#x\n", deviceExtension
->FullIdentifyData
.MajorRevision
));
1732 KdPrint2((PRINT_PREFIX
"UserAddressableSectors %#x\n", deviceExtension
->FullIdentifyData
.UserAddressableSectors
));
1733 if ( deviceExtension
->FullIdentifyData
.SupportLba
1735 (deviceExtension
->FullIdentifyData
.MajorRevision
&&
1736 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1737 deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1738 KdPrint2((PRINT_PREFIX
"LBA mode\n"));
1739 LunExt
->DeviceFlags
|= DFLAGS_LBA_ENABLED
;
1741 KdPrint2((PRINT_PREFIX
"Keep orig geometry\n"));
1742 LunExt
->DeviceFlags
|= DFLAGS_ORIG_GEOMETRY
;
1743 goto skip_lba_staff
;
1745 // Check for LBA48 support
1746 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1747 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
&&
1748 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Address48
&&
1749 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
> NumOfSectors
)
1751 KdPrint2((PRINT_PREFIX
"LBA48\n"));
1753 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
/
1754 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1755 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1757 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1759 NativeNumOfSectors
= cylinders
*
1760 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1761 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1763 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1765 if(NativeNumOfSectors
> NumOfSectors
) {
1766 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1767 NumOfSectors
= NativeNumOfSectors
;
1771 // Check drive capacity report for LBA48-capable drives.
1772 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
) {
1773 ULONG hNativeNumOfSectors
;
1774 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1776 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1777 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1779 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1781 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1783 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1784 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1785 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) ;
1787 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
1790 KdPrint2((PRINT_PREFIX
"Read high order bytes\n"));
1791 NativeNumOfSectors
|=
1792 (ULONG
)((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24 );
1793 hNativeNumOfSectors
=
1794 (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) |
1795 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 8) ;
1796 ((PULONG
)&NativeNumOfSectors
)[1] = hNativeNumOfSectors
;
1798 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1800 // Some drives report LBA48 capability while has capacity below 128Gb
1801 // Probably they support large block-counters.
1802 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
1803 // Here we check this
1804 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1805 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!!\n"));
1807 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1808 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1810 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1812 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1814 NativeNumOfSectors
= (ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1815 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24) |
1816 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8 ) |
1817 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 32) |
1818 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1819 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 40)
1824 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1825 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!! (2)\n"));
1826 NativeNumOfSectors
= 0;
1830 if(NumOfSectors
<= ATA_MAX_LBA28
&&
1831 NativeNumOfSectors
> NumOfSectors
) {
1833 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
1834 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1836 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1837 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1838 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1839 NumOfSectors
= NativeNumOfSectors
;
1845 if(NumOfSectors
< 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
1846 // check for native LBA size
1847 // some drives report ~32Gb in Identify Block
1848 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
1850 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_READ_NATIVE_SIZE
,
1851 0, IDE_USE_LBA
, 0, 0, 0, ATA_WAIT_READY
);
1853 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1855 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1857 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1858 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1859 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1860 (((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
) & 0xf) << 24);
1862 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1864 if(NativeNumOfSectors
> NumOfSectors
) {
1866 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
1867 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1869 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1870 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1871 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1872 NumOfSectors
= NativeNumOfSectors
;
1878 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
1880 // fill IdentifyData with bogus geometry
1881 KdPrint2((PRINT_PREFIX
"requested LunExt->GeomType=%x\n", LunExt
->opt_GeomType
));
1882 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*
1883 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
);
1884 KdPrint2((PRINT_PREFIX
"tmp_cylinders = %#I64x\n", tmp_cylinders
));
1885 if((tmp_cylinders
< 0xffff) || (LunExt
->opt_GeomType
== GEOM_ORIG
)) {
1886 // ok, we can keep original values
1887 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1888 LunExt
->opt_GeomType
= GEOM_ORIG
;
1891 tmp_cylinders
= NumOfSectors
/ (255*63);
1892 if(tmp_cylinders
< 0xffff) {
1893 // we can use generic values for H/S for generic geometry approach
1894 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1895 LunExt
->opt_GeomType
= GEOM_STD
;
1898 // we should use UNIATA geometry approach
1899 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1900 LunExt
->opt_GeomType
= GEOM_UNIATA
;
1905 if(LunExt
->opt_GeomType
== GEOM_STD
) {
1906 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
=
1907 deviceExtension
->FullIdentifyData
.SectorsPerTrack
= 63;
1909 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
=
1910 deviceExtension
->FullIdentifyData
.NumberOfHeads
= 255;
1912 cylinders
= NumOfSectors
/ (255*63);
1913 KdPrint2((PRINT_PREFIX
"Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders
, 255, 63));
1915 if(LunExt
->opt_GeomType
== GEOM_UNIATA
) {
1916 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x80)) {
1918 KdPrint2((PRINT_PREFIX
"cylinders /= 2\n"));
1919 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1920 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1922 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x80)) {
1924 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (2)\n"));
1925 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1926 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1928 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x8000)) {
1930 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (3)\n"));
1931 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1932 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1934 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x8000)) {
1936 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (4)\n"));
1937 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1938 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1940 KdPrint2((PRINT_PREFIX
"Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders
,
1941 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
,
1942 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
));
1945 KdPrint2((PRINT_PREFIX
"cylinders = tmp_cylinders (%x = %x)\n", cylinders
, tmp_cylinders
));
1946 cylinders
= tmp_cylinders
;
1948 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
=
1949 deviceExtension
->FullIdentifyData
.NumberOfCylinders
= (USHORT
)cylinders
;
1953 KdPrint2((PRINT_PREFIX
"Geometry: C %#x (%#x)\n",
1954 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1955 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
1957 KdPrint2((PRINT_PREFIX
"Geometry: H %#x (%#x)\n",
1958 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1959 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
1961 KdPrint2((PRINT_PREFIX
"Geometry: S %#x (%#x)\n",
1962 deviceExtension
->FullIdentifyData
.SectorsPerTrack
,
1963 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
1967 LunExt
->NumOfSectors
= NumOfSectors
;
1968 /* if(deviceExtension->FullIdentifyData.MajorRevision &&
1969 deviceExtension->FullIdentifyData.DoubleWordIo) {
1970 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
1974 ScsiPortMoveMemory(&LunExt
->IdentifyData
,
1975 &deviceExtension
->FullIdentifyData
,sizeof(IDENTIFY_DATA2
));
1977 InitBadBlocks(LunExt
);
1979 if ((LunExt
->IdentifyData
.DrqType
& ATAPI_DRQT_INTR
) &&
1980 (Command
!= IDE_COMMAND_IDENTIFY
)) {
1982 // This device interrupts with the assertion of DRQ after receiving
1983 // Atapi Packet Command
1984 LunExt
->DeviceFlags
|= DFLAGS_INT_DRQ
;
1985 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
1988 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
1991 if(Command
!= IDE_COMMAND_IDENTIFY
) {
1993 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_TAPE
) {
1995 LunExt
->DeviceFlags
|= DFLAGS_TAPE_DEVICE
;
1996 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is a tape drive.\n"));
1998 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
||
1999 LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_OPTICAL
) {
2000 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is CD/Optical drive.\n"));
2001 // set CD default costs
2002 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_CD
;
2003 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_CD
;
2004 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_CD
;
2005 statusByte
= WaitForDrq(chan
);
2007 KdPrint2((PRINT_PREFIX
"IssueIdentify: ATAPI drive type %#x.\n",
2008 LunExt
->IdentifyData
.DeviceType
));
2011 KdPrint2((PRINT_PREFIX
"IssueIdentify: hard drive.\n"));
2014 GetBaseStatus(chan
, statusByte
);
2015 KdPrint2((PRINT_PREFIX
"IssueIdentify: final Status on exit (%#x)\n", statusByte
));
2018 } // end IssueIdentify()
2023 Routine Description:
2024 Set drive parameters using the IDENTIFY data.
2027 HwDeviceExtension - HBA miniport driver's adapter data storage
2028 DeviceNumber - Indicates which device.
2031 TRUE if all goes well.
2037 IN PVOID HwDeviceExtension
,
2038 IN ULONG DeviceNumber
,
2042 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2043 PIDENTIFY_DATA2 identifyData
;
2044 PHW_LU_EXTENSION LunExt
;
2049 LunExt
= deviceExtension
->chan
[lChannel
].lun
[DeviceNumber
];
2050 identifyData
= &(LunExt
->IdentifyData
);
2052 if(LunExt
->DeviceFlags
&
2053 (DFLAGS_LBA_ENABLED
| DFLAGS_ORIG_GEOMETRY
))
2056 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Number of heads %#x\n", identifyData
->NumberOfHeads
));
2057 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Sectors per track %#x\n", identifyData
->SectorsPerTrack
));
2059 // Send SET PARAMETER command.
2060 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
2061 IDE_COMMAND_SET_DRIVE_PARAMETERS
, 0,
2062 (identifyData
->NumberOfHeads
- 1), 0,
2063 (UCHAR
)identifyData
->SectorsPerTrack
, 0, ATA_WAIT_IDLE
);
2065 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2066 if(statusByte
& IDE_STATUS_ERROR
) {
2067 errorByte
= AtapiReadPort1(&deviceExtension
->chan
[lChannel
], IDX_IO1_i_Error
);
2068 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Error bit set. Status %#x, error %#x\n",
2069 errorByte
, statusByte
));
2073 if(statusByte
== IDE_STATUS_IDLE
) {
2079 } // end SetDriveParameters()
2084 PHW_LU_EXTENSION LunExt
2087 // keep only DFLAGS_HIDDEN flag
2088 LunExt
->DeviceFlags
&= DFLAGS_HIDDEN
;
2089 LunExt
->AtapiReadyWaitDelay
= 0;
2090 } // end UniataForgetDevice()
2095 Routine Description:
2096 Reset IDE controller and/or Atapi device.
2100 HwDeviceExtension - HBA miniport driver's adapter data storage
2109 AtapiResetController(
2110 IN PVOID HwDeviceExtension
,
2114 KdPrint2((PRINT_PREFIX
"AtapiResetController(%x)\n", PathId
));
2115 return AtapiResetController__(HwDeviceExtension
, PathId
, RESET_COMPLETE_ALL
);
2116 } // end AtapiResetController()
2120 AtapiResetController__(
2121 IN PVOID HwDeviceExtension
,
2123 IN BOOLEAN CompleteType
2126 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2127 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2128 PHW_CHANNEL chan
= NULL
;
2132 PSCSI_REQUEST_BLOCK CurSrb
;
2133 ULONG ChannelCtrlFlags
;
2134 UCHAR dma_status
= 0;
2136 ULONG slotNumber
= deviceExtension
->slotNumber
;
2137 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
2138 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
2140 ULONG DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
2142 //ULONG RevID = deviceExtension->RevID;
2143 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
2147 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID
, DeviceID
, slotNumber
));
2148 KdPrint2((PRINT_PREFIX
"simplexOnly %d\n", deviceExtension
->simplexOnly
));
2150 if(!deviceExtension
->simplexOnly
&& (PathId
!= CHAN_NOT_SPECIFIED
)) {
2151 // we shall reset both channels on SimplexOnly devices,
2152 // It's not worth doing so on normal controllers
2154 numberChannels
= min(j
+1, deviceExtension
->NumberChannels
);
2157 numberChannels
= deviceExtension
->NumberChannels
;
2160 for (; j
< numberChannels
; j
++) {
2162 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset channel %d\n", j
));
2163 chan
= &(deviceExtension
->chan
[j
]);
2164 MaxLuns
= chan
->NumberLuns
;
2165 KdPrint2((PRINT_PREFIX
" CompleteType %#x, Luns %d, chan %#x, sptr %#x\n", CompleteType
, MaxLuns
, chan
, &chan
));
2166 //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
2167 if(CompleteType
!= RESET_COMPLETE_NONE
) {
2169 while((CurSrb
= UniataGetCurRequest(chan
))) {
2171 PATA_REQ AtaReq
= (PATA_REQ
)(CurSrb
->SrbExtension
);
2173 KdPrint2((PRINT_PREFIX
"AtapiResetController: pending SRB %#x, chan %#x\n", CurSrb
, chan
));
2174 // Check and see if we are processing an internal srb
2175 if (AtaReq
->OriginalSrb
) {
2176 KdPrint2((PRINT_PREFIX
" restore original SRB %#x\n", AtaReq
->OriginalSrb
));
2177 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
2178 CurSrb
->SrbExtension
= NULL
;
2179 AtaReq
->OriginalSrb
= NULL
;
2180 // NOTE: internal SRB doesn't get to SRB queue !!!
2181 CurSrb
= AtaReq
->Srb
;
2184 // Remove current request from queue
2185 UniataRemoveRequest(chan
, CurSrb
);
2187 // Check if request is in progress.
2188 ASSERT(AtaReq
->Srb
== CurSrb
);
2190 // Complete outstanding request with SRB_STATUS_BUS_RESET.
2191 UCHAR PathId
= CurSrb
->PathId
;
2192 UCHAR TargetId
= CurSrb
->TargetId
;
2193 UCHAR Lun
= CurSrb
->Lun
;
2195 CurSrb
->SrbStatus
= ((CompleteType
== RESET_COMPLETE_ALL
) ? SRB_STATUS_BUS_RESET
: SRB_STATUS_ABORTED
) | SRB_STATUS_AUTOSENSE_VALID
;
2196 CurSrb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2198 if (CurSrb
->SenseInfoBuffer
) {
2200 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)CurSrb
->SenseInfoBuffer
;
2201 KdPrint2((PRINT_PREFIX
" senseBuffer %#x, chan %#x\n", senseBuffer
, chan
));
2203 senseBuffer
->ErrorCode
= 0x70;
2204 senseBuffer
->Valid
= 1;
2205 senseBuffer
->AdditionalSenseLength
= 0xb;
2206 if(CompleteType
== RESET_COMPLETE_ALL
) {
2207 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
2208 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2209 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_BUS_RESET
;
2210 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_SCSI_BUS
;
2212 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
2213 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2214 senseBuffer
->AdditionalSenseCode
= 0;
2215 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2219 // Clear request tracking fields.
2220 AtaReq
->WordsLeft
= 0;
2221 AtaReq
->DataBuffer
= NULL
;
2222 AtaReq
->TransferLength
= 0;
2223 KdPrint2((PRINT_PREFIX
"chan %#x\n", chan
));
2225 ScsiPortNotification(RequestComplete
,
2229 // Indicate ready for next request.
2230 ScsiPortNotification(NextLuRequest
,
2236 if(CompleteType
!= RESET_COMPLETE_ALL
)
2239 #endif //UNIATA_CORE
2240 } // end if (!CompleteType != RESET_COMPLETE_NONE)
2242 // Save control flags
2243 ChannelCtrlFlags
= chan
->ChannelCtrlFlags
;
2244 // Clear expecting interrupt flag.
2245 UniataExpectChannelInterrupt(chan
, FALSE
);
2247 chan
->ChannelCtrlFlags
= 0;
2248 InterlockedExchange(&(chan
->CheckIntr
),
2251 for (i
= 0; i
< MaxLuns
; i
++) {
2252 chan
->lun
[i
]->PowerState
= 0;
2255 if(ChipFlags
& UNIATA_AHCI
) {
2256 KdPrint2((PRINT_PREFIX
" AHCI path\n"));
2257 if(UniataAhciChanImplemented(deviceExtension
, j
)) {
2259 UniataDumpAhciPortRegs(chan
);
2261 AtapiDisableInterrupts(deviceExtension
, j
);
2262 UniataAhciReset(HwDeviceExtension
, j
);
2264 KdPrint2((PRINT_PREFIX
" skip not implemented\n"));
2268 KdPrint2((PRINT_PREFIX
" ATA path, chan %#x\n", chan
));
2269 KdPrint2((PRINT_PREFIX
" disable intr (0)\n"));
2270 AtapiDisableInterrupts(deviceExtension
, j
);
2271 KdPrint2((PRINT_PREFIX
" done\n"));
2273 case ATA_INTEL_ID
: {
2277 if(!(ChipFlags
& UNIATA_SATA
)) {
2280 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2285 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2286 if(ChipFlags
& UNIATA_AHCI
) {
2289 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2290 GetPciConfig1(0x90, tmp8
);
2298 mask
= 1 << chan
->lun
[0]->SATA_lun_map
;
2300 mask
|= (1 << chan
->lun
[1]->SATA_lun_map
);
2303 ChangePciConfig2(0x92, a
& ~mask
);
2304 AtapiStallExecution(10);
2305 ChangePciConfig2(0x92, a
| mask
);
2308 /* Wait up to 1 sec for "connect well". */
2309 if (ChipFlags
& (I6CH
| I6CH2
)) {
2315 GetPciConfig2(0x92, tmp16
);
2316 if (((tmp16
>> pshift
) & mask
) == mask
) {
2317 GetBaseStatus(chan
, statusByte
);
2318 if(statusByte
!= IDE_STATUS_WRONG
) {
2322 AtapiStallExecution(10000);
2326 case ATA_NVIDIA_ID
: {
2327 KdPrint2((PRINT_PREFIX
" SIS/nVidia\n"));
2328 if(!(ChipFlags
& UNIATA_SATA
))
2331 case ATA_SILICON_IMAGE_ID
: {
2333 ULONG Channel
= deviceExtension
->Channel
+ j
;
2334 if(!(ChipFlags
& UNIATA_SATA
))
2336 offset
= ((Channel
& 1) << 7) + ((Channel
& 2) << 8);
2337 /* disable PHY state change interrupt */
2338 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x148 + offset
, 0);
2340 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2342 /* reset controller part for this channel */
2343 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2344 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) | (0xc0 >> Channel
));
2345 AtapiStallExecution(1000);
2346 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2347 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) & ~(0xc0 >> Channel
));
2351 case ATA_PROMISE_ID
: {
2354 if(ChipFlags
& UNIATA_SATA
) {
2355 KdPrint2((PRINT_PREFIX
" SATA generic reset\n"));
2356 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2359 KdPrint2((PRINT_PREFIX
" send reset\n"));
2360 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
|
2361 IDE_DC_RESET_CONTROLLER
);
2362 KdPrint2((PRINT_PREFIX
" wait a little\n"));
2363 AtapiStallExecution(10000);
2364 // Disable interrupts
2365 KdPrint2((PRINT_PREFIX
" disable intr\n"));
2366 AtapiDisableInterrupts(deviceExtension
, j
);
2367 AtapiStallExecution(100);
2368 KdPrint2((PRINT_PREFIX
" re-enable intr\n"));
2369 AtapiEnableInterrupts(deviceExtension
, j
);
2370 KdPrint2((PRINT_PREFIX
" wait a little (2)\n"));
2371 AtapiStallExecution(100000);
2372 KdPrint2((PRINT_PREFIX
" done\n"));
2377 //if(!(ChipFlags & UNIATA_SATA)) {}
2378 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2379 // Reset DMA engine if active
2380 KdPrint2((PRINT_PREFIX
" check DMA engine\n"));
2381 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
2382 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
2383 if((ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
2384 (dma_status
& BM_STATUS_INTR
)) {
2385 AtapiDmaDone(HwDeviceExtension
, 0, j
, NULL
);
2390 // all these shall be performed inside AtapiHwInitialize__() ?
2392 KdPrint2((PRINT_PREFIX
" process connected devices 0 - %d\n", MaxLuns
-1));
2393 // Do special processing for ATAPI and IDE disk devices.
2394 for (i
= 0; i
< MaxLuns
; i
++) {
2396 // Check if device present.
2397 KdPrint2((PRINT_PREFIX
" Chan %#x\n", chan
));
2398 KdPrint2((PRINT_PREFIX
" Lun %#x\n", i
));
2399 KdPrint2((PRINT_PREFIX
" Lun ptr %#x\n", chan
->lun
[i
]));
2400 if (!(chan
->lun
[i
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2401 if(ChipFlags
& UNIATA_AHCI
) {
2402 // everything is done in UniataAhciReset()
2403 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2409 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2410 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2413 if(!CheckDevice(HwDeviceExtension
, j
, i
, TRUE
)) {
2417 if(ChipFlags
& UNIATA_AHCI
) {
2418 // everything is done in UniataAhciReset()
2419 KdPrint2((PRINT_PREFIX
" found some device\n"));
2421 if(!IssueIdentify(HwDeviceExtension
,
2423 ATAPI_DEVICE(chan
, i
) ?
2424 IDE_COMMAND_ATAPI_IDENTIFY
: IDE_COMMAND_IDENTIFY
,
2426 KdPrint2((PRINT_PREFIX
" identify failed !\n"));
2427 UniataForgetDevice(chan
->lun
[i
]);
2431 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2432 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2433 UniataForgetDevice(chan
->lun
[i
]);
2438 SelectDrive(chan
, i
);
2439 AtapiStallExecution(10);
2440 statusByte
= WaitOnBusyLong(chan
);
2441 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2442 if(statusByte
== IDE_STATUS_WRONG
) {
2443 KdPrint2((PRINT_PREFIX
2444 "no drive, status %#x\n",
2446 UniataForgetDevice(chan
->lun
[i
]);
2448 // Check for ATAPI disk.
2449 if (ATAPI_DEVICE(chan
, i
)) {
2450 // Issue soft reset and issue identify.
2451 GetStatus(chan
, statusByte
);
2452 KdPrint2((PRINT_PREFIX
"AtapiResetController: Status before Atapi reset (%#x).\n",
2455 AtapiDisableInterrupts(deviceExtension
, j
);
2456 AtapiSoftReset(chan
, i
);
2457 AtapiEnableInterrupts(deviceExtension
, j
);
2459 GetStatus(chan
, statusByte
);
2461 if(statusByte
== IDE_STATUS_SUCCESS
) {
2463 IssueIdentify(HwDeviceExtension
,
2465 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
2468 KdPrint2((PRINT_PREFIX
2469 "AtapiResetController: Status after soft reset %#x\n",
2472 GetBaseStatus(chan
, statusByte
);
2475 // Issue identify and reinit after channel reset.
2477 if (statusByte
!= IDE_STATUS_IDLE
&&
2478 statusByte
!= IDE_STATUS_SUCCESS
&&
2479 statusByte
!= IDE_STATUS_DRDY
) {
2481 KdPrint2((PRINT_PREFIX
"AtapiResetController: IdeHardReset failed\n"));
2483 if(!IssueIdentify(HwDeviceExtension
,
2485 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2487 KdPrint2((PRINT_PREFIX
"AtapiResetController: IDE IssueIdentify failed\n"));
2489 // Set disk geometry parameters.
2490 if (!SetDriveParameters(HwDeviceExtension
, i
, j
)) {
2491 KdPrint2((PRINT_PREFIX
"AtapiResetController: SetDriveParameters failed\n"));
2493 GetBaseStatus(chan
, statusByte
);
2495 // force DMA mode reinit
2496 chan
->lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
2500 // Enable interrupts, note, we can have here recursive disable
2501 AtapiStallExecution(10);
2502 KdPrint2((PRINT_PREFIX
"AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2504 chan
->DisableIntr
));
2505 AtapiEnableInterrupts(deviceExtension
, j
);
2507 // Call the HwInitialize routine to setup multi-block.
2508 AtapiHwInitialize__(deviceExtension
, j
);
2510 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
2514 } // end AtapiResetController__()
2519 Routine Description:
2520 This routine maps ATAPI and IDE errors to specific SRB statuses.
2523 HwDeviceExtension - HBA miniport driver's adapter data storage
2524 Srb - IO request packet
2533 IN PVOID HwDeviceExtension
,
2534 IN PSCSI_REQUEST_BLOCK Srb
2537 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2538 ULONG lChannel
= GET_CHANNEL(Srb
);
2539 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2541 UCHAR errorByte
= 0;
2542 UCHAR srbStatus
= SRB_STATUS_SUCCESS
;
2544 ULONG DeviceNumber
= GET_CDEV(Srb
);
2545 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
2547 // Read the error register.
2549 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
2550 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2552 errorByte
= AtaReq
->ahci
.in_error
;
2556 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2558 KdPrint2((PRINT_PREFIX
2559 "MapError: Error register is %#x\n",
2562 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2564 switch (errorByte
>> 4) {
2565 case SCSI_SENSE_NO_SENSE
:
2567 KdPrint2((PRINT_PREFIX
2568 "ATAPI: No sense information\n"));
2569 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2570 srbStatus
= SRB_STATUS_ERROR
;
2573 case SCSI_SENSE_RECOVERED_ERROR
:
2575 KdPrint2((PRINT_PREFIX
2576 "ATAPI: Recovered error\n"));
2578 srbStatus
= SRB_STATUS_SUCCESS
;
2581 case SCSI_SENSE_NOT_READY
:
2583 KdPrint2((PRINT_PREFIX
2584 "ATAPI: Device not ready\n"));
2585 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2586 srbStatus
= SRB_STATUS_ERROR
;
2589 case SCSI_SENSE_MEDIUM_ERROR
:
2591 KdPrint2((PRINT_PREFIX
2592 "ATAPI: Media error\n"));
2593 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2594 srbStatus
= SRB_STATUS_ERROR
;
2597 case SCSI_SENSE_HARDWARE_ERROR
:
2599 KdPrint2((PRINT_PREFIX
2600 "ATAPI: Hardware error\n"));
2601 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2602 srbStatus
= SRB_STATUS_ERROR
;
2605 case SCSI_SENSE_ILLEGAL_REQUEST
:
2607 KdPrint2((PRINT_PREFIX
2608 "ATAPI: Illegal request\n"));
2609 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2610 srbStatus
= SRB_STATUS_ERROR
;
2613 case SCSI_SENSE_UNIT_ATTENTION
:
2615 KdPrint2((PRINT_PREFIX
2616 "ATAPI: Unit attention\n"));
2617 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2618 srbStatus
= SRB_STATUS_ERROR
;
2621 case SCSI_SENSE_DATA_PROTECT
:
2623 KdPrint2((PRINT_PREFIX
2624 "ATAPI: Data protect\n"));
2625 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2626 srbStatus
= SRB_STATUS_ERROR
;
2629 case SCSI_SENSE_BLANK_CHECK
:
2631 KdPrint2((PRINT_PREFIX
2632 "ATAPI: Blank check\n"));
2633 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2634 srbStatus
= SRB_STATUS_ERROR
;
2637 case SCSI_SENSE_ABORTED_COMMAND
:
2638 KdPrint2((PRINT_PREFIX
2639 "Atapi: Command Aborted\n"));
2640 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2641 srbStatus
= SRB_STATUS_ERROR
;
2646 KdPrint2((PRINT_PREFIX
2647 "ATAPI: Invalid sense information\n"));
2649 srbStatus
= SRB_STATUS_ERROR
;
2657 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
2658 chan
->ReturningMediaStatus
= errorByte
;
2660 if (errorByte
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
2661 KdPrint2((PRINT_PREFIX
2662 "IDE: Media change\n"));
2663 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2664 srbStatus
= SRB_STATUS_ERROR
;
2666 if (Srb
->SenseInfoBuffer
) {
2668 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2670 senseBuffer
->ErrorCode
= 0x70;
2671 senseBuffer
->Valid
= 1;
2672 senseBuffer
->AdditionalSenseLength
= 0xb;
2673 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2674 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2675 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2677 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2680 } else if (errorByte
& IDE_ERROR_COMMAND_ABORTED
) {
2681 KdPrint2((PRINT_PREFIX
2682 "IDE: Command abort\n"));
2683 srbStatus
= SRB_STATUS_ABORTED
;
2684 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2686 if (Srb
->SenseInfoBuffer
) {
2688 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2690 senseBuffer
->ErrorCode
= 0x70;
2691 senseBuffer
->Valid
= 1;
2692 senseBuffer
->AdditionalSenseLength
= 0xb;
2693 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2694 senseBuffer
->AdditionalSenseCode
= 0;
2695 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2697 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2700 LunExt
->ErrorCount
++;
2702 } else if (errorByte
& IDE_ERROR_END_OF_MEDIA
) {
2704 KdPrint2((PRINT_PREFIX
2705 "IDE: End of media\n"));
2706 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2707 srbStatus
= SRB_STATUS_ERROR
;
2709 if (Srb
->SenseInfoBuffer
) {
2711 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2713 senseBuffer
->ErrorCode
= 0x70;
2714 senseBuffer
->Valid
= 1;
2715 senseBuffer
->AdditionalSenseLength
= 0xb;
2716 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2717 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIA_STATE
;
2718 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_END_OF_MEDIUM
;
2719 senseBuffer
->EndOfMedia
= 1;
2721 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2724 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2725 LunExt
->ErrorCount
++;
2728 } else if (errorByte
& IDE_ERROR_ILLEGAL_LENGTH
) {
2730 KdPrint2((PRINT_PREFIX
2731 "IDE: Illegal length\n"));
2732 srbStatus
= SRB_STATUS_INVALID_REQUEST
;
2734 if (Srb
->SenseInfoBuffer
) {
2736 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2738 senseBuffer
->ErrorCode
= 0x70;
2739 senseBuffer
->Valid
= 1;
2740 senseBuffer
->AdditionalSenseLength
= 0xb;
2741 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
2742 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_VALUE
;
2743 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_PARAM_INVALID_VALUE
;
2744 senseBuffer
->IncorrectLength
= 1;
2746 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2749 } else if (errorByte
& IDE_ERROR_BAD_BLOCK
) {
2751 KdPrint2((PRINT_PREFIX
2752 "IDE: Bad block\n"));
2753 srbStatus
= SRB_STATUS_ERROR
;
2754 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2755 if (Srb
->SenseInfoBuffer
) {
2757 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2759 senseBuffer
->ErrorCode
= 0x70;
2760 senseBuffer
->Valid
= 1;
2761 senseBuffer
->AdditionalSenseLength
= 0xb;
2762 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2763 senseBuffer
->AdditionalSenseCode
= 0;
2764 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2766 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2769 } else if (errorByte
& IDE_ERROR_ID_NOT_FOUND
) {
2771 KdPrint2((PRINT_PREFIX
2772 "IDE: Id not found\n"));
2773 srbStatus
= SRB_STATUS_ERROR
;
2774 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2776 if (Srb
->SenseInfoBuffer
) {
2778 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2780 senseBuffer
->ErrorCode
= 0x70;
2781 senseBuffer
->Valid
= 1;
2782 senseBuffer
->AdditionalSenseLength
= 0xb;
2783 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2784 senseBuffer
->AdditionalSenseCode
= 0;
2785 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2787 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2790 LunExt
->ErrorCount
++;
2792 } else if (errorByte
& IDE_ERROR_MEDIA_CHANGE
) {
2794 KdPrint2((PRINT_PREFIX
2795 "IDE: Media change\n"));
2796 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2797 srbStatus
= SRB_STATUS_ERROR
;
2799 if (Srb
->SenseInfoBuffer
) {
2801 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2803 senseBuffer
->ErrorCode
= 0x70;
2804 senseBuffer
->Valid
= 1;
2805 senseBuffer
->AdditionalSenseLength
= 0xb;
2806 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2807 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2808 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2810 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2813 } else if (errorByte
& IDE_ERROR_DATA_ERROR
) {
2815 KdPrint2((PRINT_PREFIX
2816 "IDE: Data error\n"));
2817 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2818 srbStatus
= SRB_STATUS_ERROR
;
2820 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2821 LunExt
->ErrorCount
++;
2824 // Build sense buffer
2825 if (Srb
->SenseInfoBuffer
) {
2827 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2829 senseBuffer
->ErrorCode
= 0x70;
2830 senseBuffer
->Valid
= 1;
2831 senseBuffer
->AdditionalSenseLength
= 0xb;
2832 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2833 senseBuffer
->AdditionalSenseCode
= 0;
2834 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2836 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2840 if (LunExt
->ErrorCount
>= MAX_ERRORS
) {
2841 // deviceExtension->DWordIO = FALSE;
2843 KdPrint2((PRINT_PREFIX
2844 "MapError: ErrorCount >= MAX_ERRORS\n"));
2846 LunExt
->DeviceFlags
&= ~DFLAGS_DWORDIO_ENABLED
;
2847 LunExt
->MaximumBlockXfer
= 0;
2850 KdPrint2((PRINT_PREFIX
2851 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
2854 KdPrint2((PRINT_PREFIX
2855 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
2864 ScsiPortLogError( HwDeviceExtension
,
2872 // Reprogram to not use Multi-sector.
2875 if (LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
&&
2876 !(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
2878 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY
);
2880 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2881 // command was aborted.
2882 if (statusByte
& IDE_STATUS_ERROR
) {
2884 // Read the error register.
2885 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2887 KdPrint2((PRINT_PREFIX
"MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
2891 // Adjust the devExt. value, if necessary.
2892 LunExt
->MaximumBlockXfer
= 0;
2900 // Set SCSI status to indicate a check condition.
2901 Srb
->ScsiStatus
= scsiStatus
;
2910 Routine Description:
2913 HwDeviceExtension - HBA miniport driver's adapter data storage
2917 TRUE - if initialization successful.
2918 FALSE - if initialization unsuccessful.
2924 IN PVOID HwDeviceExtension
2927 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2928 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2931 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base)\n"));
2933 if(WinVer_WDM_Model
) {
2934 AtapiResetController__(HwDeviceExtension
, CHAN_NOT_SPECIFIED
, RESET_COMPLETE_ALL
);
2936 if(deviceExtension
->MasterDev
) {
2937 KdPrint2((PRINT_PREFIX
" mark chan %d of master controller [%x] as inited\n",
2938 deviceExtension
->Channel
, deviceExtension
->DevIndex
));
2939 BMList
[deviceExtension
->DevIndex
].ChanInitOk
|= 0x01 << deviceExtension
->Channel
;
2942 /* do extra chipset specific setups */
2943 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
2945 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
2946 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
2947 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
2950 for (c
= 0; c
< numberChannels
; c
++) {
2951 AtapiHwInitialize__(deviceExtension
, c
);
2953 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base) done\n"));
2955 } // end AtapiHwInitialize()
2959 AtapiHwInitialize__(
2960 IN PHW_DEVICE_EXTENSION deviceExtension
,
2965 UCHAR statusByte
, errorByte
;
2966 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2967 PHW_LU_EXTENSION LunExt
;
2969 ULONG PreferedMode
= 0xffffffff;
2971 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
2972 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
2976 AtapiChipInit(deviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
);
2977 FindDevices(deviceExtension
, 0, lChannel
);
2979 for (i
= 0; i
< chan
->NumberLuns
; i
++) {
2981 KdPrint3((PRINT_PREFIX
"AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel
, i
));
2983 LunExt
= chan
->lun
[i
];
2985 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2989 AtapiDisableInterrupts(deviceExtension
, lChannel
);
2990 AtapiStallExecution(1);
2992 if (!(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
2994 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: IDE branch\n"));
2995 // Enable media status notification
2996 IdeMediaStatus(TRUE
,deviceExtension
,lChannel
,(UCHAR
)i
);
2998 // If supported, setup Multi-block transfers.
2999 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3000 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
3001 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
3003 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
3004 // command was aborted.
3005 if (statusByte
& IDE_STATUS_ERROR
) {
3007 // Read the error register.
3008 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3010 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
3014 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3015 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
3016 0, 0, ATA_WAIT_BASE_READY
);
3018 if (statusByte
& IDE_STATUS_ERROR
) {
3019 // Read the error register.
3020 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3022 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
3026 // Adjust the devExt. value, if necessary.
3027 LunExt
->MaximumBlockXfer
= 0;
3030 KdPrint2((PRINT_PREFIX
3031 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
3033 LunExt
->MaximumBlockXfer
));
3036 if(LunExt
->IdentifyData
.MajorRevision
) {
3038 if(LunExt
->opt_ReadCacheEnable
) {
3039 KdPrint2((PRINT_PREFIX
" Try Enable Read Cache\n"));
3040 // If supported, setup read/write cacheing
3041 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3042 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3043 0, ATA_C_F_ENAB_RCACHE
, ATA_WAIT_BASE_READY
);
3045 // Check for errors.
3046 if (statusByte
& IDE_STATUS_ERROR
) {
3047 KdPrint2((PRINT_PREFIX
3048 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
3050 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3052 LunExt
->DeviceFlags
|= DFLAGS_RCACHE_ENABLED
;
3055 KdPrint2((PRINT_PREFIX
" Disable Read Cache\n"));
3056 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3057 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3058 0, ATA_C_F_DIS_RCACHE
, ATA_WAIT_BASE_READY
);
3059 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3061 if(LunExt
->opt_WriteCacheEnable
) {
3062 KdPrint2((PRINT_PREFIX
" Try Enable Write Cache\n"));
3063 // If supported & allowed, setup write cacheing
3064 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3065 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3066 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
3067 // Check for errors.
3068 if (statusByte
& IDE_STATUS_ERROR
) {
3069 KdPrint2((PRINT_PREFIX
3070 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
3072 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3074 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
3077 KdPrint2((PRINT_PREFIX
" Disable Write Cache\n"));
3078 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3079 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3080 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
3081 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3084 if(LunExt
->IdentifyData
.FeaturesSupport
.PowerMngt
||
3085 LunExt
->IdentifyData
.FeaturesSupport
.APM
) {
3087 if(LunExt
->opt_AdvPowerMode
) {
3088 KdPrint2((PRINT_PREFIX
" Try Enable Adv. Power Mgmt\n"));
3090 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3091 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3092 LunExt
->opt_AdvPowerMode
, ATA_C_F_ENAB_APM
, ATA_WAIT_BASE_READY
);
3093 // Check for errors.
3094 if (statusByte
& IDE_STATUS_ERROR
) {
3095 KdPrint2((PRINT_PREFIX
3096 "AtapiHwInitialize: Enable APM on Device %d failed\n",
3100 KdPrint2((PRINT_PREFIX
" Disable Adv. Power Mgmt\n"));
3101 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3102 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3103 0, ATA_C_F_DIS_APM
, ATA_WAIT_BASE_READY
);
3106 if(LunExt
->IdentifyData
.FeaturesSupport
.AutoAcoustic
) {
3107 if(LunExt
->opt_AcousticMode
) {
3108 KdPrint2((PRINT_PREFIX
" Try Enable Acoustic Mgmt\n"));
3109 // setup acoustic mgmt
3110 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3111 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3112 LunExt
->opt_AcousticMode
, ATA_C_F_ENAB_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3113 // Check for errors.
3114 if (statusByte
& IDE_STATUS_ERROR
) {
3115 KdPrint2((PRINT_PREFIX
3116 "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n",
3120 KdPrint2((PRINT_PREFIX
" Disable Acoustic Mgmt\n"));
3121 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3122 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3123 0, ATA_C_F_DIS_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3126 if(LunExt
->IdentifyData
.FeaturesSupport
.Standby
) {
3127 KdPrint2((PRINT_PREFIX
" Try init standby timer: %d\n"));
3128 // setup standby timer
3129 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3130 IDE_COMMAND_IDLE
, 0, 0, 0,
3131 LunExt
->opt_StandbyTimer
, 0, ATA_WAIT_BASE_READY
);
3132 // Check for errors.
3133 if (statusByte
& IDE_STATUS_ERROR
) {
3134 KdPrint2((PRINT_PREFIX
3135 "AtapiHwInitialize: standby timer on Device %d failed\n",
3141 } else if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)){
3144 //BOOLEAN isSanyo = FALSE;
3147 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: ATAPI/Changer branch\n"));
3149 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
3150 for (j
= 0; j
< 26; j
+= 2) {
3152 // Build a buffer based on the identify data.
3153 MOV_DW_SWP(vendorId
[j
], ((PUCHAR
)LunExt
->IdentifyData
.ModelNumber
)[j
]);
3156 if (!AtapiStringCmp (vendorId
, "CD-ROM CDR", 11)) {
3158 // Inquiry string for older model had a '-', newer is '_'
3159 if (vendorId
[12] == 'C') {
3161 // Torisan changer. Set the bit. This will be used in several places
3162 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
3163 LunExt
->DeviceFlags
|= (DFLAGS_CHANGER_INITED
| DFLAGS_SANYO_ATAPI_CHANGER
);
3164 LunExt
->DiscsPresent
= 3;
3170 PreferedMode
= LunExt
->opt_MaxTransferMode
;
3171 if((PreferedMode
== 0xffffffff) || (PreferedMode
> chan
->MaxTransferMode
)) {
3172 KdPrint2((PRINT_PREFIX
"MaxTransferMode (overriden): %#x\n", chan
->MaxTransferMode
));
3173 PreferedMode
= chan
->MaxTransferMode
;
3176 if(LunExt
->opt_PreferedTransferMode
!= 0xffffffff) {
3177 KdPrint2((PRINT_PREFIX
"PreferedTransferMode: %#x\n", PreferedMode
));
3178 PreferedMode
= min(LunExt
->opt_PreferedTransferMode
, PreferedMode
);
3181 KdPrint2((PRINT_PREFIX
" try mode %#x\n", PreferedMode
));
3182 LunExt
->LimitedTransferMode
=
3183 LunExt
->TransferMode
=
3186 AtapiDmaInit__(deviceExtension
, LunExt
);
3188 LunExt
->LimitedTransferMode
=
3189 LunExt
->TransferMode
;
3190 KdPrint2((PRINT_PREFIX
"Using %#x mode\n", LunExt
->TransferMode
));
3192 // We need to get our device ready for action before
3193 // returning from this function
3195 // According to the atapi spec 2.5 or 2.6, an atapi device
3196 // clears its status BSY bit when it is ready for atapi commands.
3197 // However, some devices (Panasonic SQ-TC500N) are still
3198 // not ready even when the status BSY is clear. They don't react
3199 // to atapi commands.
3201 // Since there is really no other indication that tells us
3202 // the drive is really ready for action. We are going to check BSY
3203 // is clear and then just wait for an arbitrary amount of time!
3205 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3208 // have to get out of the loop sometime!
3209 // 10000 * 100us = 1000,000us = 1000ms = 1s
3211 GetStatus(chan
, statusByte
);
3212 if(statusByte
== IDE_STATUS_WRONG
) {
3215 while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
) {
3217 KdPrint2((PRINT_PREFIX
"Wait for ATAPI (status %x)\n", statusByte
));
3218 // Wait for Busy to drop.
3219 AtapiStallExecution(100);
3220 GetStatus(chan
, statusByte
);
3224 // 5000 * 100us = 500,000us = 500ms = 0.5s
3225 if(statusByte
!= IDE_STATUS_WRONG
) {
3228 AtapiStallExecution(100);
3229 } while (waitCount
--);
3232 GetBaseStatus(chan
, statusByte
);
3233 AtapiEnableInterrupts(deviceExtension
, lChannel
);
3234 AtapiStallExecution(10);
3239 } // end AtapiHwInitialize__()
3246 AtapiHwInitializeChanger(
3247 IN PVOID HwDeviceExtension
,
3248 IN PSCSI_REQUEST_BLOCK Srb
,
3249 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus
)
3251 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3252 ULONG lChannel
= GET_CHANNEL(Srb
);
3253 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3254 ULONG DeviceNumber
= GET_CDEV(Srb
);
3255 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
3257 if (MechanismStatus
) {
3258 LunExt
->DiscsPresent
= MechanismStatus
->NumberAvailableSlots
;
3259 if (LunExt
->DiscsPresent
> 1) {
3260 LunExt
->DeviceFlags
|= DFLAGS_ATAPI_CHANGER
;
3264 } // end AtapiHwInitializeChanger()
3269 Routine Description:
3270 This routine will parse the string for a match on the keyword, then
3271 calculate the value for the keyword and return it to the caller.
3274 String - The ASCII string to parse.
3275 KeyWord - The keyword for the value desired.
3278 Zero if value not found
3279 Value converted from ASCII to binary.
3284 AtapiParseArgumentString(
3292 ULONG stringLength
= 0;
3293 ULONG keyWordLength
= 0;
3303 // Calculate the string length and lower case all characters.
3309 // Calculate the keyword length.
3315 if (keyWordLength
> stringLength
) {
3317 // Can't possibly have a match.
3321 // Now setup and start the compare.
3326 // The input string may start with white space. Skip it.
3327 while (*cptr
== ' ' || *cptr
== '\t') {
3331 if (*cptr
== '\0') {
3337 while ((*cptr
== *kptr
) ||
3338 (*cptr
>= 'A' && *cptr
<= 'Z' && *cptr
+ ('a' - 'A') == *kptr
) ||
3339 (*cptr
>= 'a' && *cptr
<= 'z' && *cptr
- ('a' - 'A') == *kptr
)) {
3343 if (*cptr
== '\0') {
3349 if (*kptr
== '\0') {
3351 // May have a match backup and check for blank or equals.
3352 while (*cptr
== ' ' || *cptr
== '\t') {
3356 // Found a match. Make sure there is an equals.
3359 // Not a match so move to the next semicolon.
3361 if (*cptr
++ == ';') {
3362 goto ContinueSearch
;
3367 // Skip the equals sign.
3370 // Skip white space.
3371 while ((*cptr
== ' ') || (*cptr
== '\t')) {
3375 if (*cptr
== '\0') {
3376 // Early end of string, return not found
3381 // This isn't it either.
3383 goto ContinueSearch
;
3387 if ((*cptr
== '0') && ((*(cptr
+ 1) == 'x') || (*(cptr
+ 1) == 'X'))) {
3388 // Value is in Hex. Skip the "0x"
3390 for (index
= 0; *(cptr
+ index
); index
++) {
3392 if (*(cptr
+ index
) == ' ' ||
3393 *(cptr
+ index
) == '\t' ||
3394 *(cptr
+ index
) == ';') {
3398 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3399 value
= (16 * value
) + (*(cptr
+ index
) - '0');
3401 if ((*(cptr
+ index
) >= 'a') && (*(cptr
+ index
) <= 'f')) {
3402 value
= (16 * value
) + (*(cptr
+ index
) - 'a' + 10);
3403 } else if ((*(cptr
+ index
) >= 'A') && (*(cptr
+ index
) <= 'F')) {
3404 value
= (16 * value
) + (*(cptr
+ index
) - 'A' + 10);
3406 // Syntax error, return not found.
3413 // Value is in Decimal.
3414 for (index
= 0; *(cptr
+ index
); index
++) {
3416 if (*(cptr
+ index
) == ' ' ||
3417 *(cptr
+ index
) == '\t' ||
3418 *(cptr
+ index
) == ';') {
3422 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3423 value
= (10 * value
) + (*(cptr
+ index
) - '0');
3426 // Syntax error return not found.
3435 // Not a match check for ';' to continue search.
3437 if (*cptr
++ == ';') {
3438 goto ContinueSearch
;
3444 } // end AtapiParseArgumentString()_
3452 IN PVOID HwDeviceExtension
,
3457 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3458 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3461 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3464 KdPrint2((PRINT_PREFIX
"AtapiCallBack:\n"));
3465 // If the last command was DSC restrictive, see if it's set. If so, the device is
3466 // ready for a new request. Otherwise, reset the timer and come back to here later.
3468 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3469 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3470 // we shall have no problem with interrupt handler.
3471 if (!srb
|| chan
->ExpectingInterrupt
) {
3472 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Calling ISR directly due to BUSY\n"));
3473 chan
->DpcState
= DPC_STATE_TIMER
;
3474 if(!AtapiInterrupt__(HwDeviceExtension
, lChannel
)) {
3475 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3476 KdPrint2((PRINT_PREFIX
"AtapiCallBack: What's fucking this ???\n"));
3478 goto ReturnCallback
;
3482 if (!IS_RDP((srb
->Cdb
[0]))) {
3483 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb
->Cdb
[0]));
3487 goto ReturnEnableIntr
;
3489 GetStatus(chan
, statusByte
);
3490 if (statusByte
& IDE_STATUS_DSC
) {
3492 UCHAR PathId
= srb
->PathId
;
3493 UCHAR TargetId
= srb
->TargetId
;
3494 UCHAR Lun
= srb
->Lun
;
3496 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Found DSC for RDP - %#x\n", srb
->Cdb
[0]));
3497 AtapiDmaDBSync(chan
, srb
);
3498 UniataRemoveRequest(chan
, srb
);
3499 ScsiPortNotification(RequestComplete
, deviceExtension
, srb
);
3500 // Clear current SRB.
3501 if(!deviceExtension
->simplexOnly
) {
3502 srb
= UniataGetCurRequest(chan
);
3508 // Ask for next request.
3509 ScsiPortNotification(NextLuRequest
,
3514 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
3517 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3521 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Requesting another timer for Op %#x\n",
3524 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3528 goto ReturnCallback
;
3533 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
3534 KdPrint2((PRINT_PREFIX
"AtapiCallBack: CallDisableInterrupts\n"));
3535 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3536 #ifdef UNIATA_USE_XXableInterrupts
3537 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
3538 // must be called on DISPATCH_LEVEL
3539 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
3540 AtapiEnableInterrupts__
);
3542 AtapiEnableInterrupts(HwDeviceExtension
, lChannel
);
3543 InterlockedExchange(&(chan
->CheckIntr
),
3545 // Will raise IRQL to DIRQL
3546 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3547 AtapiEnableInterrupts__
,
3549 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
3550 #endif // UNIATA_USE_XXableInterrupts
3552 //ASSERT(!deviceExtension->simplexOnly);
3557 // Check other channel
3558 // In simplex mode no interrupts must appear on other channels
3559 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3560 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3566 chan
= &(deviceExtension
->chan
[c
]);
3568 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
3569 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3570 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) == CHECK_INTR_DETECTED
)
3572 //ASSERT(!deviceExtension->simplexOnly);
3573 chan
->DpcState
= DPC_STATE_ISR
;
3574 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3575 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3579 KdPrint2((PRINT_PREFIX
"AtapiCallBack: return\n"));
3582 } // end AtapiCallBack__()
3587 IN PVOID HwDeviceExtension
3590 AtapiCallBack__(HwDeviceExtension
, (UCHAR
)((PHW_DEVICE_EXTENSION
)HwDeviceExtension
)->ActiveDpcChan
);
3591 } // end AtapiCallBack_X()
3593 #endif //UNIATA_CORE
3597 Routine Description:
3599 This is the interrupt service routine for ATAPI IDE miniport driver.
3603 HwDeviceExtension - HBA miniport driver's adapter data storage
3607 TRUE if expecting an interrupt.
3613 IN PVOID HwDeviceExtension
3616 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3618 BOOLEAN status
= FALSE
;
3622 //BOOLEAN checked[AHCI_MAX_PORT];
3626 KdPrint2((PRINT_PREFIX
"Intr: VendorID+DeviceID/Rev %#x/%#x (ex %d)\n",
3627 deviceExtension
->DevID
, deviceExtension
->RevID
, deviceExtension
->ExpectingInterrupt
));
3629 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3630 // AHCI may generate state change notification, never skip this check
3631 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
3632 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3636 // assume all non-interrupted ports to be already checked
3638 // assume all not implemented ports to be already checked
3639 checked
|= ~deviceExtension
->AHCI_PI
;
3641 checked
= 0; // assume all ports are not checked
3644 if(!deviceExtension
->ExpectingInterrupt
) {
3645 // if we do not expect interrupt, exit now,
3646 // but keep in mind that it can be unexpected one
3647 // Note: this is just a hint, not exact counter
3648 KdPrint2((PRINT_PREFIX
"unexpected, 1st chance\n"));
3649 //deviceExtension->ExpectingInterrupt++;
3652 // clear this flag now, it can be set again in sub-calls
3653 deviceExtension
->ExpectingInterrupt
=0;
3656 // for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
3657 // checked[_c] = (UCHAR)((hIS >> _c) & 0x01);
3661 for(pass
=0; pass
<2; pass
++) {
3662 //KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): pass %d\n", pass));
3663 if(status
&& pass
) {
3664 // we catched some expected interrupts now.
3665 // do not touch unexpected until next ISR call
3668 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3670 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3672 if((checked
>>c
) & 0x01)
3675 // check non-empty and expecting interrupt channels first
3676 if(!pass
&& !deviceExtension
->chan
[c
].ExpectingInterrupt
)
3679 checked
|= (ULONG
)1 << c
;
3681 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3683 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3684 // we get here on idle channels or when ISR is posted to DPC
3685 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): disabled INTR on ch %d\n", c
));
3688 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
3690 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): try lock\n"));
3691 // c_state = deviceExtension->chan[c].CheckIntr;
3692 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
3693 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
3696 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3697 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3698 CRNT_ILK_TYPE CHECK_INTR_DETECTED
);
3699 if(c_state
== CHECK_INTR_IDLE
) {
3700 // c_state = deviceExtension->chan[c].CheckIntr;
3701 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
3702 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
3705 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3706 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3707 CRNT_ILK_TYPE CHECK_INTR_IDLE
);
3709 } while(c_state
== CHECK_INTR_CHECK
);
3710 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): locked\n"));
3711 // check if already serviced
3712 if(c_state
== CHECK_INTR_ACTIVE
) {
3713 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
3717 if((c_state
== CHECK_INTR_DETECTED
) ||
3718 (i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3720 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
3721 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): Catch unexpected\n"));
3722 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3727 // disable interrupts on other channel of legacy mode
3728 // ISA-bridged onboard controller
3729 if(deviceExtension
->simplexOnly
/*||
3730 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3731 AtapiDisableInterrupts(deviceExtension
, !c
);
3734 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_ISR
;
3735 if(AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3736 deviceExtension
->LastInterruptedChannel
= (UCHAR
)c
;
3737 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): return status TRUE\n"));
3740 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
3741 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3744 // re-enable interrupts on other channel
3745 if(deviceExtension
->simplexOnly
/*||
3746 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3747 AtapiEnableInterrupts(deviceExtension
, !c
);
3751 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
3752 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3757 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): exit with status %#x\n", status
));
3759 deviceExtension
->FirstChannelToCheck
++;
3760 if(deviceExtension
->FirstChannelToCheck
>= deviceExtension
->NumberChannels
)
3761 deviceExtension
->FirstChannelToCheck
= 0;
3764 } // end AtapiInterrupt()
3772 IN PKINTERRUPT Interrupt
,
3773 IN PVOID Isr2HwDeviceExtension
3776 // This ISR is intended to catch interrupts when we are already in other ISR instance
3777 // for the same device. This may happen when we have multiple channels,
3778 // especially on SMP machines
3780 PISR2_DEVICE_EXTENSION Isr2DeviceExtension
= (PISR2_DEVICE_EXTENSION
)Isr2HwDeviceExtension
;
3781 PHW_DEVICE_EXTENSION deviceExtension
= Isr2DeviceExtension
->HwDeviceExtension
;
3783 BOOLEAN status
= FALSE
;
3789 // we should never get here for ISA/MCA
3790 if(!BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
3791 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3795 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3796 // AHCI may generate state change notification, never skip this check
3797 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
3798 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3802 // assume all non-interrupted ports to be already checked
3804 // assume all not implemented ports to be already checked
3805 checked
|= ~deviceExtension
->AHCI_PI
;
3808 checked
= 0; // assume all ports are not checked
3810 if(!deviceExtension
->ExpectingInterrupt
) {
3811 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !deviceExtension->ExpectingInterrupt\n"));
3812 deviceExtension
->ExpectingInterrupt
++;
3815 //deviceExtension->ExpectingInterrupt = 0;
3817 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3818 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3820 if((checked
>>c
) & 0x01)
3823 checked
|= (ULONG
)1 << c
;
3825 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3826 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: disabled INTR\n"));
3830 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3831 CRNT_ILK_TYPE CHECK_INTR_CHECK
,
3832 CRNT_ILK_TYPE CHECK_INTR_IDLE
) != CHECK_INTR_IDLE
)
3834 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
3835 // hunt on unexpected intr (Some devices generate double interrupts,
3836 // some controllers (at least CMD649) interrupt twice with small delay.
3837 // If interrupts are disabled, they queue interrupt and re-issue it later,
3838 // when we do not expect it.
3843 if((i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3845 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: intr\n"));
3846 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
3847 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: Catch unexpected\n"));
3848 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3853 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_DETECTED
);
3855 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3858 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: status %d, c_count %d\n", status
, c_count
));
3859 if(status
&& (c_count
!= deviceExtension
->NumberChannels
)) {
3860 // there is an active ISR/DPC for one channel, but
3861 // we have an interrupt from another one
3862 // Lets inform current ISR/DPC about new interrupt
3863 InterlockedExchange(&(deviceExtension
->ReCheckIntr
), CHECK_INTR_DETECTED
);
3867 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: return %d\n", status
));
3870 } // end AtapiInterrupt2()
3872 RETTYPE_XXableInterrupts
3875 IN PVOID HwDeviceExtension
3878 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3881 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3882 KdPrint2((PRINT_PREFIX
"AtapiInterruptDpc: %#x\n",c
));
3884 if(!(deviceExtension
->chan
[c
].ChannelCtrlFlags
& CTRFLAGS_DPC_REQ
)) {
3886 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3887 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3888 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
)
3894 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_DPC_REQ
;
3897 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
3898 AtapiDisableInterrupts(deviceExtension, lChannel);
3901 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_DPC
;
3902 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3903 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3906 return RETVAL_XXableInterrupts
;
3907 } // end AtapiInterruptDpc()
3910 RETTYPE_XXableInterrupts
3912 AtapiEnableInterrupts__(
3913 IN PVOID HwDeviceExtension
3916 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3917 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__():\n"));
3919 PHW_CHANNEL chan
= NULL
;
3921 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3922 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__(2): %#x\n",c
));
3923 chan
= &(deviceExtension
->chan
[c
]);
3925 if(chan
->ChannelCtrlFlags
& CTRFLAGS_ENABLE_INTR_REQ
) {
3926 // enable intrs on requested channel
3927 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_ENABLE_INTR_REQ
;
3928 AtapiEnableInterrupts(HwDeviceExtension
, c
);
3929 InterlockedExchange(&(chan
->CheckIntr
),
3932 // check if current or other channel(s) interrupted
3933 //AtapiInterrupt(HwDeviceExtension);
3935 if(deviceExtension
->simplexOnly
) {
3939 // check if other channel(s) interrupted
3940 // must do nothing in simplex mode
3941 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
3942 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3943 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
3946 //ASSERT(!deviceExtension->simplexOnly);
3947 chan
->DpcState
= DPC_STATE_ISR
;
3948 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3949 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3953 // In simplex mode next command must be sent to device here
3954 if(deviceExtension
->simplexOnly
&& chan
) {
3955 PSCSI_REQUEST_BLOCK srb
;
3956 chan
= UniataGetNextChannel(chan
);
3958 srb
= UniataGetCurRequest(chan
);
3963 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3967 return RETVAL_XXableInterrupts
;
3969 } // end AtapiEnableInterrupts__()
3971 #endif //UNIATA_CORE
3976 AtapiEnableInterrupts(
3977 IN PVOID HwDeviceExtension
,
3981 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3985 if(c
>= deviceExtension
->NumberChannels
) {
3986 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c
));
3989 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
3990 !UniataAhciChanImplemented(deviceExtension
, c
)) {
3991 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c
));
3995 chan
= &(deviceExtension
->chan
[c
]);
3996 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
3997 if(!InterlockedDecrement(&chan
->DisableIntr
)) {
3998 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3999 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
4000 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
4001 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_INF
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
4002 ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
: 0) |
4003 ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
| /* DEBUG */
4005 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
4006 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
)
4009 //SelectDrive(chan, 0);
4010 //GetBaseStatus(chan, statusByte);
4011 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4013 //if(chan->NumberLuns) {
4014 // SelectDrive(chan, 1);
4015 // GetBaseStatus(chan, statusByte);
4016 // AtapiWritePort1(chan, IDX_IO2_o_Control,
4018 // SelectDrive(chan, chan->cur_cdev);
4021 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_INTR_DISABLED
;
4023 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4024 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4027 } // end AtapiEnableInterrupts()
4031 AtapiDisableInterrupts(
4032 IN PVOID HwDeviceExtension
,
4036 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4038 if(c
>= deviceExtension
->NumberChannels
) {
4039 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c
));
4042 chan
= &(deviceExtension
->chan
[c
]);
4043 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
4044 // mark channel as busy
4045 if(InterlockedIncrement(&chan
->DisableIntr
)) {
4046 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4047 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
4049 //SelectDrive(chan, 0);
4050 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4051 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4052 //if(chan->NumberLuns) {
4053 // SelectDrive(chan, 1);
4054 // AtapiWritePort1(chan, IDX_IO2_o_Control,
4055 // IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4056 // SelectDrive(chan, chan->cur_cdev);
4059 chan
->ChannelCtrlFlags
|= CTRFLAGS_INTR_DISABLED
;
4063 } // end AtapiDisableInterrupts()
4066 UniataExpectChannelInterrupt(
4067 IN
struct _HW_CHANNEL
* chan
,
4068 IN BOOLEAN Expecting
4071 chan
->ExpectingInterrupt
= Expecting
;
4073 chan
->DeviceExtension
->ExpectingInterrupt
++;
4075 if(chan
->DeviceExtension
->ExpectingInterrupt
) {
4076 chan
->DeviceExtension
->ExpectingInterrupt
--;
4079 } // end UniataExpectChannelInterrupt()
4082 Check hardware for interrupt state
4086 AtapiCheckInterrupt__(
4087 IN PVOID HwDeviceExtension
,
4088 IN UCHAR c
// logical channel
4091 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4092 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4093 PHW_LU_EXTENSION LunExt
;
4095 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
4096 ULONG ChipType
= deviceExtension
->HwFlags
& CHIPTYPE_MASK
;
4099 ULONG pr_status
= 0;
4100 UCHAR dma_status
= 0;
4103 UCHAR statusByte
= 0;
4104 ULONG slotNumber
= deviceExtension
->slotNumber
;
4105 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
4106 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
4109 BOOLEAN DmaTransfer
= FALSE
;
4110 BOOLEAN OurInterrupt
= FALSE
;
4111 BOOLEAN StatusValid
= FALSE
;
4113 UCHAR interruptReason
;
4114 BOOLEAN EarlyIntr
= FALSE
;
4115 BOOLEAN SingleBlockIntr
= FALSE
;
4117 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__:\n"));
4120 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4121 LunExt
= chan
->lun
[chan
->cur_cdev
];
4123 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ chan %#x:\n", chan));
4124 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ (%d/%d):\n", Channel, chan->cur_cdev));
4126 if((ChipFlags
& UNIATA_AHCI
) &&
4127 UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4129 if(!UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
4130 return OurInterrupt
;
4133 OurInterrupt
= UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
4134 if((OurInterrupt
== INTERRUPT_REASON_UNEXPECTED
) &&
4135 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
4136 UniataAhciWaitCommandReady(chan
, 2 /* ms */ );
4137 statusByte
= (UCHAR
)UniataAhciWaitReady(chan
, 0 /* immediate */);
4138 if(!(statusByte
& (IDE_STATUS_BUSY
)) ) {
4139 KdPrint2((PRINT_PREFIX
"ATAPI special case READY\n"));
4140 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
4141 OurInterrupt
= INTERRUPT_REASON_OUR
;
4143 if((statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
)) == (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
) ) {
4144 KdPrint2((PRINT_PREFIX
"ATAPI special case pre ERR-READY\n"));
4145 OurInterrupt
= INTERRUPT_REASON_OUR
;
4147 if(statusByte
& IDE_STATUS_ERROR
) {
4148 KdPrint2((PRINT_PREFIX
"ATAPI special case ERR-READY\n"));
4149 OurInterrupt
= INTERRUPT_REASON_OUR
;
4151 KdPrint2((PRINT_PREFIX
"ATAPI special case ? %x\n", statusByte
));
4152 OurInterrupt
= INTERRUPT_REASON_OUR
;
4155 return OurInterrupt
;
4158 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4160 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension
->DevIndex
,
4161 deviceExtension
->Channel
+ c
, c
));
4163 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension
->DevIndex
,
4164 deviceExtension
->Channel
+ c
, c
));
4165 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4166 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
4169 // do controller-specific interrupt servicing staff
4170 if(deviceExtension
->UnknownDev
) {
4171 KdPrint2((PRINT_PREFIX
" UnknownDev\n"));
4176 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
4177 // Such behavior was observed with Intel ICH-xxx chips
4178 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
4182 case ATA_PROMISE_ID
: {
4186 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x1c);
4190 ((Channel
) ? 0x00004000 : 0x00000400))) {
4191 KdPrint2((PRINT_PREFIX
" Promise old/new unexpected\n"));
4192 return INTERRUPT_REASON_IGNORE
;
4196 AtapiWritePort1(chan
, IDX_BM_DeviceSpecific0
, 0x0b);
4197 status
= AtapiReadPort1(chan
, IDX_BM_DeviceSpecific1
);
4200 if(!(status
& 0x20)) {
4201 KdPrint2((PRINT_PREFIX
" Promise tx unexpected\n"));
4202 return INTERRUPT_REASON_IGNORE
;
4206 ULONG stat_reg
= (ChipFlags
& PRG2
) ? 0x60 : 0x6c;
4207 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x40);
4208 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x40, status
);
4210 if(status
& (1 << (Channel
+1))) {
4213 KdPrint2((PRINT_PREFIX
" Promise mio unexpected\n"));
4214 return INTERRUPT_REASON_IGNORE
;
4217 if(!(ChipFlags
& UNIATA_SATA
))
4220 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),stat_reg
);
4221 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),stat_reg
, (pr_status
& (0x11 << Channel
)));
4222 if(pr_status
& (0x11 << Channel
)) {
4223 // TODO: reset channel
4224 KdPrint2((PRINT_PREFIX
" Promise mio unexpected + reset req\n"));
4225 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, 0);
4227 if(!(status
& (0x01 << Channel
))) {
4229 KdPrint2((PRINT_PREFIX
" Promise mio unexpected attach\n"));
4230 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, 0);
4232 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4233 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4235 return INTERRUPT_REASON_IGNORE
;
4238 AtapiWritePort4(chan
, IDX_BM_DeviceSpecific0
, 0x00000001);
4242 case ATA_NVIDIA_ID
: {
4243 if(!(ChipFlags
& UNIATA_SATA
))
4246 KdPrint2((PRINT_PREFIX
"NVIDIA\n"));
4248 ULONG offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
4249 ULONG shift
= Channel
<< ((ChipFlags
& NVQ
) ? 4 : 2);
4251 /* get and clear interrupt status */
4252 if(ChipFlags
& NVQ
) {
4253 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4254 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0fUL
<< shift
) | 0x00f000f0);
4256 pr_status
= AtapiReadPortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4257 AtapiWritePortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0f << shift
));
4259 KdPrint2((PRINT_PREFIX
" pr_status %x\n", pr_status
));
4261 /* check for and handle connect events */
4262 if(((pr_status
& (0x0cUL
<< shift
)) == (0x04UL
<< shift
)) ) {
4263 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, 0);
4265 /* check for and handle disconnect events */
4266 if((pr_status
& (0x08UL
<< shift
)) &&
4267 !((pr_status
& (0x04UL
<< shift
) &&
4268 UniataSataReadPort4(chan
, IDX_SATA_SStatus
, 0))) ) {
4269 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, 0);
4271 /* do we have any device action ? */
4272 if(!(pr_status
& (0x01UL
<< shift
))) {
4273 KdPrint2((PRINT_PREFIX
" nVidia unexpected\n"));
4274 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4275 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4277 return INTERRUPT_REASON_IGNORE
;
4283 KdPrint2((PRINT_PREFIX
"ATI\n"));
4284 if(ChipType
== SIIMIO
) {
4289 case ATA_SILICON_IMAGE_ID
:
4291 if(ChipType
== SIIMIO
) {
4293 reg32
= AtapiReadPort4(chan
, IDX_BM_DeviceSpecific0
);
4294 KdPrint2((PRINT_PREFIX
" Sii DS0 %x\n", reg32
));
4295 if(reg32
== 0xffffffff) {
4296 KdPrint2((PRINT_PREFIX
" Sii mio unexpected\n"));
4297 return INTERRUPT_REASON_IGNORE
;
4299 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
))) {
4300 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (2)\n"));
4301 return INTERRUPT_REASON_IGNORE
;
4304 if(ChipFlags
& UNIATA_SATA
) {
4305 if(reg32
& (BM_DS0_SII_DMA_SATA_IRQ
| BM_DS0_SII_IRQ
)) {
4307 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
4308 * controllers continue to assert IRQ as long as
4309 * SError bits are pending. Clear SError immediately.
4311 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4312 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4319 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4320 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (3)\n"));
4321 return OurInterrupt
;
4323 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
& ~BM_STATUS_ERR
);
4324 goto skip_dma_stat_check
;
4327 if(!(deviceExtension
->HwFlags
& SIIINTR
))
4329 GetPciConfig1(0x71, reg8
);
4330 KdPrint2((PRINT_PREFIX
" 0x71 = %#x\n", reg8
));
4332 (Channel
? 0x08 : 0x04))) {
4333 return INTERRUPT_REASON_IGNORE
;
4336 KdPrint2((PRINT_PREFIX
" cmd our\n"));
4337 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4339 SetPciConfig1(0x71, (Channel
? 0x08 : 0x04));
4346 //dma_status = GetDmaStatus(deviceExtension, lChannel);
4347 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4348 KdPrint2((PRINT_PREFIX
" Acard unexpected\n"));
4349 return INTERRUPT_REASON_IGNORE
;
4351 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
| BM_STATUS_INTR
);
4352 AtapiStallExecution(1);
4353 AtapiWritePort1(chan
, IDX_BM_Command
,
4354 AtapiReadPort1(chan
, IDX_BM_Command
) & ~BM_COMMAND_START_STOP
);
4355 goto skip_dma_stat_check
;
4357 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4358 if(ChipFlags
& UNIATA_AHCI
) {
4361 if(ChipFlags
& UNIATA_SATA
) {
4362 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4363 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4365 if(!(chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
4366 if(UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, 1)) {
4367 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4374 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4375 if(ChipFlags
& UNIATA_AHCI
) {
4378 if(ChipFlags
& UNIATA_SATA
) {
4379 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4380 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4386 KdPrint2((PRINT_PREFIX
" perform generic check\n"));
4388 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4389 KdPrint2((PRINT_PREFIX
" DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status
));
4390 if(dma_status
& BM_STATUS_ERR
) {
4391 KdPrint2((PRINT_PREFIX
" DmaTransfer + BM_STATUS_ERR -> our\n"));
4392 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4394 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4395 GetStatus(chan
, statusByte
);
4397 KdPrint2((PRINT_PREFIX
" status %#x\n", statusByte
));
4398 if(statusByte
& IDE_STATUS_ERROR
) {
4399 KdPrint2((PRINT_PREFIX
" IDE_STATUS_ERROR -> our\n", statusByte
));
4400 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4402 if ((statusByte
& IDE_STATUS_DSC
) &&
4403 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
4404 (dma_status
== BM_STATUS_ACTIVE
)) {
4405 KdPrint2((PRINT_PREFIX
" special case DMA + ATAPI + IDE_STATUS_DSC -> our\n", statusByte
));
4406 // some devices interrupts on each block transfer even in DMA mode
4407 if(LunExt
->TransferMode
>= ATA_SDMA
&& LunExt
->TransferMode
<= ATA_WDMA2
) {
4408 KdPrint2((PRINT_PREFIX
" wait for completion\n"));
4409 ///* clear interrupt and get status */
4410 //GetBaseStatus(chan, statusByte);
4411 //return INTERRUPT_REASON_IGNORE;
4412 SingleBlockIntr
= TRUE
;
4415 return INTERRUPT_REASON_IGNORE
;
4420 if(dma_status
& BM_STATUS_INTR
) {
4421 // bullshit, we have DMA interrupt, but had never initiate DMA operation
4422 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr\n"));
4423 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4425 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4428 skip_dma_stat_check
:
4429 if(!(ChipFlags
& UNIATA_SATA
) && chan
->ExpectingInterrupt
) {
4430 AtapiStallExecution(1);
4433 /* if drive is busy it didn't interrupt */
4434 /* the exception is DCS + BSY state of ATAPI devices */
4436 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4437 GetStatus(chan
, statusByte
);
4439 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4440 KdPrint3((PRINT_PREFIX
" ATAPI status %#x\n", statusByte
));
4442 KdPrint2((PRINT_PREFIX
" IDE status %#x\n", statusByte
));
4444 if (statusByte
== IDE_STATUS_WRONG
) {
4445 // interrupt from empty controller ?
4447 if (statusByte
& IDE_STATUS_BUSY
) {
4448 if(!chan
->ExpectingInterrupt
) {
4449 KdPrint3((PRINT_PREFIX
" unexpected intr + BUSY\n"));
4450 return OurInterrupt
;
4453 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4454 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4456 KdPrint2((PRINT_PREFIX
" expecting intr + BUSY (3), non ATAPI\n"));
4457 return INTERRUPT_REASON_IGNORE
;
4459 if((statusByte
& ~IDE_STATUS_DRQ
) != (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
| IDE_STATUS_DSC
)) {
4460 KdPrint3((PRINT_PREFIX
" unexpected status, seems it is not our\n"));
4461 return INTERRUPT_REASON_IGNORE
;
4463 if(!(LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
) && (statusByte
& IDE_STATUS_DRQ
)) {
4464 KdPrint3((PRINT_PREFIX
" unexpected DRQ, seems it is not our\n"));
4465 return INTERRUPT_REASON_IGNORE
;
4470 if(dma_status
& BM_STATUS_INTR
) {
4471 KdPrint3((PRINT_PREFIX
" our interrupt with BSY set, try wait in ISR or post to DPC\n"));
4472 /* clear interrupt and get status */
4473 GetBaseStatus(chan
, statusByte
);
4474 if(!(dma_status
& BM_STATUS_ACTIVE
)) {
4475 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4477 KdPrint3((PRINT_PREFIX
" base status %#x (+BM_STATUS_INTR)\n", statusByte
));
4478 return INTERRUPT_REASON_OUR
;
4481 if(g_WaitBusyInISR
) {
4482 GetStatus(chan
, statusByte
);
4483 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4484 reg8
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4485 KdPrint2((PRINT_PREFIX
" Error reg (%#x)\n", reg8
));
4486 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4487 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4489 if (statusByte
& IDE_STATUS_BUSY
) {
4490 KdPrint2((PRINT_PREFIX
" still BUSY, seems it is not our\n"));
4491 return INTERRUPT_REASON_IGNORE
;
4497 /* clear interrupt and get status */
4498 GetBaseStatus(chan
, statusByte
);
4499 KdPrint2((PRINT_PREFIX
" base status %#x\n", statusByte
));
4500 if (statusByte
== IDE_STATUS_WRONG
) {
4501 // interrupt from empty controller ?
4503 if(!(statusByte
& (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
))) {
4504 KdPrint2((PRINT_PREFIX
" no DRQ/DRDY set\n"));
4505 return OurInterrupt
;
4508 #ifndef UNIATA_PIO_ONLY
4510 if(!SingleBlockIntr
&& (!EarlyIntr
|| g_WaitBusyInISR
)) {
4511 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4513 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4514 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4518 if(SingleBlockIntr
) {
4519 KdPrint2((PRINT_PREFIX
" set REQ_STATE_ATAPI_EXPECTING_DATA_INTR2.\n"));
4521 KdPrint2((PRINT_PREFIX
" set REQ_STATE_EARLY_INTR.\n"));
4524 AtaReq
->ReqState
= SingleBlockIntr
? REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
: REQ_STATE_EARLY_INTR
;
4530 if (!(chan
->ExpectingInterrupt
)) {
4532 KdPrint2((PRINT_PREFIX
" Unexpected interrupt.\n"));
4534 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4535 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4537 KdPrint2((PRINT_PREFIX
" OurInterrupt = %d\n", OurInterrupt
));
4538 return OurInterrupt
;
4540 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
4541 KdPrint3((PRINT_PREFIX
"AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason
));
4542 return OurInterrupt
;
4544 //ASSERT(!chan->queue_depth || chan->cur_req);
4546 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__: exit with TRUE\n"));
4547 return INTERRUPT_REASON_OUR
;
4549 } // end AtapiCheckInterrupt__()
4555 IN PVOID HwDeviceExtension
,
4559 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4560 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4562 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4563 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4565 ULONG wordCount
= 0, wordsThisInterrupt
= DEV_BSIZE
/2;
4566 ULONG status
= SRB_STATUS_SUCCESS
;
4567 UCHAR dma_status
= 0;
4570 UCHAR statusByte
= 0,interruptReason
;
4572 BOOLEAN atapiDev
= FALSE
;
4579 BOOLEAN DmaTransfer
= FALSE
;
4581 ULONG TimerValue
= 1000;
4582 ULONG TotalTimerValue
= 0;
4583 #ifdef UNIATA_USE_XXableInterrupts
4584 BOOLEAN InDpc
= (KeGetCurrentIrql() == DISPATCH_LEVEL
);
4586 BOOLEAN InDpc
= (chan
->DpcState
!= DPC_STATE_ISR
);
4587 #endif // UNIATA_USE_XXableInterrupts
4588 BOOLEAN UseDpc
= deviceExtension
->UseDpc
;
4589 // BOOLEAN RestoreUseDpc = FALSE;
4590 BOOLEAN DataOverrun
= FALSE
;
4591 BOOLEAN NoStartIo
= TRUE
;
4592 BOOLEAN NoRetry
= FALSE
;
4594 KdPrint2((PRINT_PREFIX
"AtapiInterrupt:\n"));
4596 KdPrint2((PRINT_PREFIX
" InDpc = TRUE\n"));
4597 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
4603 UCHAR OldReqState
= REQ_STATE_NONE
;
4605 PHW_LU_EXTENSION LunExt
;
4610 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4612 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension
->DevIndex
, Channel
, KeGetCurrentIrql(), c
));
4615 if((chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
4616 (AtaReq
&& (AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
)) ||
4617 (deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
4619 KdPrint2((PRINT_PREFIX
" DmaTransfer = TRUE\n"));
4623 PathId
= srb
->PathId
;
4624 TargetId
= srb
->TargetId
;
4630 goto enqueue_next_req
;
4633 //ldev = GET_LDEV2(PathId, TargetId, Lun);
4634 DeviceNumber
= (UCHAR
)(TargetId
);
4635 LunExt
= chan
->lun
[DeviceNumber
];
4636 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
4637 KdPrint2((PRINT_PREFIX
" dev_type %s\n", atapiDev
? "ATAPI" : "IDE"));
4639 // check if we are in ISR DPC
4641 KdPrint2((PRINT_PREFIX
" InDpc -> CTRFLAGS_INTR_DISABLED\n"));
4642 goto ServiceInterrupt
;
4646 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4649 if (!(chan
->ExpectingInterrupt
)) {
4651 KdPrint2((PRINT_PREFIX
" Unexpected interrupt for this channel.\n"));
4655 // change request state
4657 OldReqState
= AtaReq
->ReqState
;
4658 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4659 KdPrint2((PRINT_PREFIX
" OldReqState = %x\n", OldReqState
));
4662 // We don't want using DPC for fast operations, like
4663 // DMA completion, sending CDB, short ATAPI transfers, etc.
4665 // We MUST use DPC, because of interprocessor synchronization
4666 // on multiprocessor platforms
4669 goto ServiceInterrupt
;
4671 switch(OldReqState
) {
4672 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR
:
4673 KdPrint3((PRINT_PREFIX
" EXPECTING_CMD_INTR\n"));
4674 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR
:
4675 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
:
4676 case REQ_STATE_DPC_WAIT_BUSY0
:
4677 case REQ_STATE_DPC_WAIT_BUSY1
:
4678 KdPrint2((PRINT_PREFIX
" continue service interrupt\n"));
4679 goto ServiceInterrupt
;
4680 case REQ_STATE_ATAPI_DO_NOTHING_INTR
:
4681 KdPrint2((PRINT_PREFIX
" do nothing on interrupt\n"));
4685 if(!DmaTransfer
&& !atapiDev
) {
4686 KdPrint2((PRINT_PREFIX
" service PIO HDD\n"));
4693 goto ServiceInterrupt
;
4695 #ifdef UNIATA_USE_XXableInterrupts
4697 KdPrint2((PRINT_PREFIX
" Unexpected InDpc\n"));
4699 // shall never get here
4704 KdPrint2((PRINT_PREFIX
" this is direct DPC call on DRQL\n"));
4706 AtaReq
->ReqState
= REQ_STATE_DPC_INTR_REQ
;
4707 KdPrint2((PRINT_PREFIX
" ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
4709 KdPrint2((PRINT_PREFIX
" DPC without AtaReq!!!\n"));
4712 KdPrint2((PRINT_PREFIX
"call service interrupt\n"));
4713 goto ServiceInterrupt
;
4714 #endif // UNIATA_USE_XXableInterrupts
4719 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
4720 // We always get here when are called from timer callback, which is invoked on DRQL.
4721 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
4723 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: start DPC init...\n"));
4724 // disable interrupts for this channel,
4725 // but avoid recursion and double-disable
4726 if(OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4727 UniataExpectChannelInterrupt(chan
, FALSE
);
4728 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4731 chan
->ChannelCtrlFlags
|= CTRFLAGS_DPC_REQ
;
4733 #ifdef UNIATA_USE_XXableInterrupts
4734 // Will lower IRQL to DISPATCH_LEVEL
4735 ScsiPortNotification(CallEnableInterrupts
, HwDeviceExtension
,
4736 /*c ?*/ AtapiInterruptDpc
/*_1 : AtapiInterruptDpc_0*/);
4737 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DPC inited\n"));
4739 // Will raise IRQL to DIRQL
4740 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4743 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
4744 #endif // UNIATA_USE_XXableInterrupts
4749 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4751 if(!InDpc
&& OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4752 // we must block interrupts from this channel
4753 // If device generate new interrupt before we get to DPC,
4754 // ISR will assume, that it is NOT our interrupt
4755 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4756 // We should not clean ExpectingInterrupt flag on channel, since it is used in DPC
4758 // Will raise IRQL to DIRQL
4759 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4763 #endif //UNIATA_CORE
4767 if(AtaReq
&& InDpc
) {
4768 switch(AtaReq
->ReqState
) {
4769 case REQ_STATE_DPC_WAIT_DRQ0
:
4771 case REQ_STATE_DPC_WAIT_BUSY
:
4773 case REQ_STATE_DPC_WAIT_DRQ
:
4775 case REQ_STATE_DPC_WAIT_DRQ_ERR
:
4777 case REQ_STATE_DPC_WAIT_BUSY0
:
4778 case REQ_STATE_DPC_WAIT_BUSY1
:
4779 // continue normal execution
4785 #endif //UNIATA_CORE
4787 // make additional delay for old devices (if we are not in DPC)
4788 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
4792 !(deviceExtension->HwFlags & UNIATA_SATA)
4794 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
4795 AtapiStallExecution(10);
4799 /* clear interrupt and get status */
4800 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4801 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, srb
);
4802 statusByte
= (UCHAR
)(AtaReq
->ahci
.in_status
& IDE_STATUS_MASK
);
4804 if(chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
)) {
4805 KdPrint3((PRINT_PREFIX
"Err intr (%#x), SE (%#x)\n",
4806 chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
),
4807 chan
->AhciLastSError
));
4808 if(chan
->AhciLastIS
& ~ATA_AHCI_P_IX_OF
) {
4809 //KdPrint3((PRINT_PREFIX "Err mask (%#x)\n", chan->AhciLastIS & ~ATA_AHCI_P_IX_OF));
4810 // We have some other error except Overflow
4811 // Just signal ERROR, operation will be aborted in ERROR branch.
4812 statusByte
|= IDE_STATUS_ERROR
;
4813 AtaReq
->ahci
.in_serror
= chan
->AhciLastSError
;
4814 if(chan
->AhciLastSError
& (ATA_SE_HANDSHAKE_ERR
| ATA_SE_LINKSEQ_ERR
| ATA_SE_TRANSPORT_ERR
| ATA_SE_UNKNOWN_FIS
)) {
4815 KdPrint2((PRINT_PREFIX
"Unrecoverable\n"));
4819 // We have only Overflow. Abort operation and continue
4821 UniataDumpAhciPortRegs(chan
);
4823 if(!UniataAhciAbortOperation(chan
)) {
4824 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
4827 UniataDumpAhciPortRegs(chan
);
4829 UniataAhciWaitCommandReady(chan
, 10);
4834 GetBaseStatus(chan
, statusByte
);
4837 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte
));
4839 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Entered with status (%#x)\n", statusByte
));
4843 KdPrint2((PRINT_PREFIX
" operate like in DPC\n"));
4849 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4850 KdPrint3((PRINT_PREFIX
" AHCI branch (IDE)\n"));
4852 if (statusByte
& IDE_STATUS_BUSY
) {
4853 if (deviceExtension
->DriverMustPoll
) {
4854 // Crashdump is polling and we got caught with busy asserted.
4855 // Just go away, and we will be polled again shortly.
4856 KdPrint2((PRINT_PREFIX
" Hit BUSY while polling during crashdump.\n"));
4857 goto ReturnEnableIntr
;
4860 // Ensure BUSY is non-asserted.
4861 // make a very small idle before falling to DPC
4862 k
= (InDpc
&& UseDpc
) ? 1000 : 2;
4864 for (i
= 0; i
< k
; i
++) {
4866 GetBaseStatus(chan
, statusByte
);
4867 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4870 AtapiStallExecution(10);
4873 if (!InDpc
&& UseDpc
&& i
== 2) {
4875 KdPrint2((PRINT_PREFIX
" BUSY on entry. Status %#x, Base IO %#x\n", statusByte
));
4878 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4883 AtapiStallExecution(TimerValue
);
4884 goto ServiceInterrupt
;
4885 #endif //UNIATA_CORE
4887 if (InDpc
&& i
== k
) {
4888 // reset the controller.
4889 KdPrint2((PRINT_PREFIX
4890 " Resetting due to BUSY on entry - %#x.\n",
4892 goto IntrPrepareResetController
;
4897 if(!LunExt
->IdentifyData
.MajorRevision
&&
4900 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
4902 //KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n"));
4903 //AtapiStallExecution(10);
4905 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4906 KdPrint3((PRINT_PREFIX
" AHCI branch (ATAPI)\n"));
4908 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
4909 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
4912 if (statusByte
& IDE_STATUS_BUSY
) {
4913 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
4916 // This is just workaround
4917 // We should DISABLE interrupts before entering WAIT state
4918 UniataExpectChannelInterrupt(chan, TRUE);
4919 #endif //UNIATA_CORE
4921 KdPrint3((PRINT_PREFIX
" BUSY on ATAPI device, waiting %d us\n", LunExt
->AtapiReadyWaitDelay
));
4923 if(LunExt
->AtapiReadyWaitDelay
&& (LunExt
->AtapiReadyWaitDelay
> g_opt_MaxIsrWait
) && !InDpc
&& UseDpc
) {
4924 TimerValue
= LunExt
->AtapiReadyWaitDelay
;
4925 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC (0)\n"));
4926 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4929 #endif //UNIATA_CORE
4932 GetBaseStatus(chan
, statusByte
);
4933 KdPrint3((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4934 KdPrint3((PRINT_PREFIX
" Error reg (%#x)\n",
4935 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Error
)));
4936 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4937 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4940 TotalTimerValue
+= TimerValue
;
4942 KdPrint3((PRINT_PREFIX
" too long wait -> DPC\n"));
4944 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC\n"));
4946 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4948 KdPrint2((PRINT_PREFIX
" too long wait: DPC -> DPC\n"));
4950 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY1
;
4954 if(!LunExt
->AtapiReadyWaitDelay
) {
4955 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
4959 #endif //UNIATA_CORE
4962 AtapiStallExecution(TimerValue
);
4965 if(!LunExt
->AtapiReadyWaitDelay
) {
4966 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
4967 KdPrint2((PRINT_PREFIX
" store AtapiReadyWaitDelay: %d\n", LunExt
->AtapiReadyWaitDelay
));
4969 if (statusByte
& IDE_STATUS_BUSY
) {
4970 KdPrint3((PRINT_PREFIX
" expecting intr + BUSY (2), try DPC wait\n"));
4976 if(AtaReq
&& DmaTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
4977 switch(OldReqState
) {
4978 case REQ_STATE_EARLY_INTR
:
4979 case REQ_STATE_DPC_WAIT_BUSY0
:
4981 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4982 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DMA still active\n"));
4983 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4990 // Check for error conditions.
4991 if ((statusByte
& IDE_STATUS_ERROR
) ||
4992 (dma_status
& BM_STATUS_ERR
)) {
4994 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4995 error
= AtaReq
->ahci
.in_error
;
4998 UniataDumpAhciPortRegs(chan
);
5000 if(!UniataAhciAbortOperation(chan
)) {
5001 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
5003 // clear interrupts again
5004 UniataAhciWaitCommandReady(chan
, 10);
5006 UniataDumpAhciPortRegs(chan
);
5008 UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
5010 AtaReq
->retry
+= MAX_RETRIES
;
5011 if(!error
&& (statusByte
& IDE_STATUS_ERROR
)) {
5012 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: force error status\n"));
5013 error
|= IDE_STATUS_ERROR
;
5017 UniataDumpAhciPortRegs(chan
);
5020 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5022 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error %#x\n", error
));
5024 if(error & IDE_STATUS_CORRECTED_ERROR) {
5025 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
5026 statusByte &= ~IDE_STATUS_ERROR;
5031 KdPrint2((PRINT_PREFIX
" Bad Lba %#I64x\n", AtaReq
->lba
));
5033 KdPrint2((PRINT_PREFIX
" Bad Lba unknown\n"));
5036 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5037 KdPrint2((PRINT_PREFIX
" no wait ready after error\n"));
5040 KdPrint2((PRINT_PREFIX
" wait 100 ready after IDE error\n"));
5041 AtapiStallExecution(100);
5043 KdPrint2((PRINT_PREFIX
" wait 10 ready after ATAPI error\n"));
5044 AtapiStallExecution(10);
5048 KdPrint3((PRINT_PREFIX
" Intr on DRQ %x\n",
5049 LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
));
5051 for (k
= atapiDev
? 0 : 200; k
; k
--) {
5052 GetBaseStatus(chan
, statusByte
);
5053 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5054 AtapiStallExecution(50);
5061 /* if this is a UDMA CRC error, reinject request */
5064 if(AtaReq
->retry
< MAX_RETRIES
) {
5065 #ifdef IO_STATISTICS
5066 chan
->lun
[DeviceNumber
]->ModeErrorCount
[AtaReq
->retry
]++;
5067 #endif //IO_STATISTICS
5069 (error & IDE_ERROR_ICRC)*/) {
5070 KdPrint2((PRINT_PREFIX
"Errors in DMA mode\n"));
5071 if(AtaReq
->retry
< MAX_RETRIES
) {
5073 if(!(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
5074 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5075 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5076 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5078 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5082 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5085 KdPrint2((PRINT_PREFIX
"Errors in PIO mode\n"));
5089 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5090 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason
));
5092 if(DmaTransfer
&& (chan
->lun
[DeviceNumber
]->TransferMode
> ATA_UDMA2
) &&
5093 ((error
>> 4) == SCSI_SENSE_HARDWARE_ERROR
)) {
5094 if(AtaReq
->retry
< MAX_RETRIES
) {
5096 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5097 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5098 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5099 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5103 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5106 KdPrint3((PRINT_PREFIX
"Errors in PIO mode\n"));
5110 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error\n"));
5111 if (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
5112 // Fail this request.
5113 status
= SRB_STATUS_ERROR
;
5114 goto CompleteRequest
;
5116 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n"));
5119 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE_LBA48
) {
5120 KdPrint2((PRINT_PREFIX
"DMA doesn't work right with LBA48\n"));
5121 deviceExtension
->HbaCtrlFlags
|= HBAFLAGS_DMA_DISABLED_LBA48
;
5123 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
) {
5124 #ifdef IO_STATISTICS
5125 KdPrint2((PRINT_PREFIX
"Some higher mode doesn't work right :((\n"));
5126 KdPrint2((PRINT_PREFIX
"Recovery stats[%d]: %d vs %d\n",
5128 LunExt
->RecoverCount
[AtaReq
->retry
],
5129 LunExt
->BlockIoCount
5131 LunExt
->RecoverCount
[AtaReq
->retry
]++;
5132 if(LunExt
->RecoverCount
[AtaReq
->retry
] >= chan
->lun
[DeviceNumber
]->BlockIoCount
/3 ||
5133 (deviceExtension
->HwFlags
& UNIATA_NO80CHK
)
5136 if(deviceExtension
->HwFlags
& UNIATA_NO80CHK
) {
5137 #endif //IO_STATISTICS
5138 KdPrint2((PRINT_PREFIX
"Limit transfer rate to %x\n", LunExt
->TransferMode
));
5139 LunExt
->LimitedTransferMode
=
5140 LunExt
->TransferMode
;
5143 #ifdef IO_STATISTICS
5144 if(AtaReq
->bcount
) {
5145 // we need stats for Read/Write operations
5146 LunExt
->BlockIoCount
++;
5149 #endif //IO_STATISTICS
5153 // check reason for this interrupt.
5156 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI branch\n"));
5159 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5160 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
5162 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5164 wordsThisInterrupt
= DEV_BSIZE
/2;
5172 // simulate DRQ for DMA transfers
5173 statusByte
|= IDE_STATUS_DRQ
;
5175 if (statusByte
& IDE_STATUS_DRQ
) {
5178 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5180 if (LunExt
->MaximumBlockXfer
) {
5181 wordsThisInterrupt
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5184 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5186 interruptReason
= ATAPI_IR_IO_toHost
;
5188 } else if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5189 interruptReason
= ATAPI_IR_IO_toDev
;
5192 status
= SRB_STATUS_ERROR
;
5193 goto CompleteRequest
;
5196 } else if (statusByte
& IDE_STATUS_BUSY
) {
5198 //AtapiEnableInterrupts(deviceExtension, lChannel);
5199 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
5204 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: !DRQ, !BUSY, WordsLeft %#x\n", AtaReq
->WordsLeft
));
5205 if (AtaReq
->WordsLeft
) {
5207 // Funky behaviour seen with PCI IDE (not all, just one).
5209 // The ISR hits with DRQ low, but comes up later.
5210 for (k
= 0; k
< 5000; k
++) {
5211 GetBaseStatus(chan
, statusByte
);
5212 if (statusByte
& IDE_STATUS_DRQ
) {
5217 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ0
;
5219 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq0)\n"));
5223 AtapiStallExecution(TimerValue
);
5224 goto ServiceInterrupt
;
5225 #endif //UNIATA_CORE
5227 AtapiStallExecution(100);
5230 // reset the controller.
5231 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
5233 IntrPrepareResetController
:
5234 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
);
5235 goto ReturnEnableIntr
;
5238 interruptReason
= (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? ATAPI_IR_IO_toHost
: ATAPI_IR_IO_toDev
;
5242 // Command complete - verify, write, or the SMART enable/disable.
5243 // Also get_media_status
5244 interruptReason
= ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
;
5249 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason
, statusByte
));
5250 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5251 KdPrint2((PRINT_PREFIX
" AHCI path, WordsTransfered %x, WordsLeft %x\n", AtaReq
->WordsTransfered
, AtaReq
->WordsLeft
));
5252 /* if(chan->AhciLastIS & ATA_AHCI_P_IX_OF) {
5253 //status = SRB_STATUS_DATA_OVERRUN;
5256 status = SRB_STATUS_SUCCESS;
5258 if(AtaReq
->WordsTransfered
>= AtaReq
->WordsLeft
) {
5259 AtaReq
->WordsLeft
= 0;
5261 AtaReq
->WordsLeft
-= AtaReq
->WordsTransfered
;
5263 //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
5264 // status = SRB_STATUS_DATA_OVERRUN;
5266 status
= SRB_STATUS_SUCCESS
;
5267 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5268 goto CompleteRequest
;
5270 if (interruptReason
== ATAPI_IR_COD_Cmd
&& (statusByte
& IDE_STATUS_DRQ
)) {
5271 // Write the packet.
5272 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Writing Atapi packet.\n"));
5273 // Send CDB to device.
5274 WriteBuffer(chan
, (PUSHORT
)srb
->Cdb
,
5275 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
5277 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5279 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
5280 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: AtapiDmaStart().\n"));
5281 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, srb
);
5284 goto ReturnEnableIntr
;
5286 } else if (interruptReason
== ATAPI_IR_IO_toDev
&& (statusByte
& IDE_STATUS_DRQ
)) {
5291 // Pick up bytes to transfer and convert to words.
5293 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
5296 (USHORT
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
5298 // Covert bytes to words.
5300 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get W wordCount %#x\n", wordCount
));
5302 if (wordCount
!= AtaReq
->WordsLeft
) {
5303 KdPrint2((PRINT_PREFIX
5304 "AtapiInterrupt: %d words requested; %d words xferred\n",
5309 // Verify this makes sense.
5310 if (wordCount
> AtaReq
->WordsLeft
) {
5311 wordCount
= AtaReq
->WordsLeft
;
5312 KdPrint2((PRINT_PREFIX
5313 "AtapiInterrupt: Write underrun\n"));
5319 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
5320 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5321 // Transfer only words requested.
5322 wordCount
= AtaReq
->WordsLeft
;
5324 // Transfer next block.
5325 wordCount
= wordsThisInterrupt
;
5330 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5331 //ASSERT(AtaReq->WordsLeft == wordCount);
5332 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5333 KdPrint2((PRINT_PREFIX
5334 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5335 if(AtaReq
->WordsLeft
> wordCount
) {
5336 AtaReq
->WordsLeft
-= wordCount
;
5337 AtaReq
->WordsTransfered
+= wordCount
;
5338 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5339 goto ReturnEnableIntr
;
5341 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5343 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5344 AtaReq
->WordsLeft
= 0;
5345 status
= SRB_STATUS_SUCCESS
;
5346 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5347 goto CompleteRequest
;
5350 // Ensure that this is a write command.
5351 if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5353 KdPrint2((PRINT_PREFIX
5354 "AtapiInterrupt: Write interrupt\n"));
5356 statusByte
= WaitOnBusy(chan
);
5358 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
5363 UniataGetPioTiming(LunExt
));
5367 (PULONG
)(AtaReq
->DataBuffer
),
5369 UniataGetPioTiming(LunExt
));
5373 KdPrint3((PRINT_PREFIX
5374 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5378 // Fail this request.
5379 status
= SRB_STATUS_ERROR
;
5380 goto CompleteRequest
;
5382 // Advance data buffer pointer and bytes left.
5383 AtaReq
->DataBuffer
+= wordCount
;
5384 AtaReq
->WordsLeft
-= wordCount
;
5385 AtaReq
->WordsTransfered
+= wordCount
;
5388 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5391 goto ReturnEnableIntr
;
5393 } else if (interruptReason
== ATAPI_IR_IO_toHost
&& (statusByte
& IDE_STATUS_DRQ
)) {
5398 // Pick up bytes to transfer and convert to words.
5400 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
) |
5401 (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8);
5403 // Convert bytes to words.
5405 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get R wordCount %#x\n", wordCount
));
5407 if (wordCount
!= AtaReq
->WordsLeft
) {
5408 KdPrint2((PRINT_PREFIX
5409 "AtapiInterrupt: %d words requested; %d words xferred\n",
5414 // Verify this makes sense.
5415 if (wordCount
> AtaReq
->WordsLeft
) {
5416 wordCount
= AtaReq
->WordsLeft
;
5422 // Check if words left is at least 256.
5423 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5424 // Transfer only words requested.
5425 wordCount
= AtaReq
->WordsLeft
;
5427 // Transfer next block.
5428 wordCount
= wordsThisInterrupt
;
5433 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5434 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5435 KdPrint2((PRINT_PREFIX
5436 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5437 if(AtaReq
->WordsLeft
> wordCount
) {
5438 AtaReq
->WordsLeft
-= wordCount
;
5439 AtaReq
->WordsTransfered
+= wordCount
;
5440 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5441 goto ReturnEnableIntr
;
5443 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5445 //ASSERT(AtaReq->WordsLeft == wordCount);
5446 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5447 AtaReq
->WordsLeft
= 0;
5448 status
= SRB_STATUS_SUCCESS
;
5449 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5450 goto CompleteRequest
;
5452 // Ensure that this is a read command.
5453 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5456 "AtapiInterrupt: Read interrupt\n"));*/
5458 statusByte
= WaitOnBusy(chan
);
5460 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
5461 KdPrint2((PRINT_PREFIX
5462 "IdeIntr: Read %#x words\n", wordCount
));
5467 UniataGetPioTiming(LunExt
));
5468 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)-1) ));
5469 //KdDump(AtaReq->DataBuffer, wordCount*2);
5470 if(srb
&& atapiDev
&& srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
5471 KdDump(AtaReq
->DataBuffer
, wordCount
*2);
5474 GetBaseStatus(chan
, statusByte
);
5475 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
5478 KdPrint2((PRINT_PREFIX
" DataOverrun\n"));
5479 AtapiSuckPort2(chan
);
5480 GetBaseStatus(chan
, statusByte
);
5483 if(statusByte
& IDE_STATUS_BUSY
) {
5484 for (i
= 0; i
< 2; i
++) {
5485 AtapiStallExecution(10);
5486 GetBaseStatus(chan
, statusByte
);
5487 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5494 KdPrint2((PRINT_PREFIX
5495 "IdeIntr: Read %#x Dwords\n", wordCount
/2));
5498 (PULONG
)(AtaReq
->DataBuffer
),
5500 UniataGetPioTiming(LunExt
));
5504 KdPrint3((PRINT_PREFIX
5505 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5509 // Fail this request.
5510 status
= SRB_STATUS_ERROR
;
5511 goto CompleteRequest
;
5514 // Advance data buffer pointer and bytes left.
5515 AtaReq
->DataBuffer
+= wordCount
;
5516 AtaReq
->WordsLeft
-= wordCount
;
5517 AtaReq
->WordsTransfered
+= wordCount
;
5519 // Check for read command complete.
5520 if (AtaReq
->WordsLeft
== 0) {
5522 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
5525 // Work around to make many atapi devices return correct sector size
5526 // of 2048. Also certain devices will have sector count == 0x00, check
5528 if ((srb
->Cdb
[0] == SCSIOP_READ_CAPACITY
) &&
5529 (LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
)) {
5531 AtaReq
->DataBuffer
-= wordCount
;
5532 if (AtaReq
->DataBuffer
[0] == 0x00) {
5534 *((ULONG
*) &(AtaReq
->DataBuffer
[0])) = 0xFFFFFF7F;
5538 *((ULONG
*) &(AtaReq
->DataBuffer
[2])) = 0x00080000;
5539 AtaReq
->DataBuffer
+= wordCount
;
5542 GetStatus(chan
, statusByte
);
5543 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5544 // Assume command is completed if BUSY is cleared
5545 // and all data read
5546 // Optionally, we may receive COMPLETE interrupt later and
5547 // treat it as unexpected
5548 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete ? status %x\n", statusByte
));
5550 status
= SRB_STATUS_SUCCESS
;
5551 goto CompleteRequest
;
5557 // Completion for IDE drives.
5558 if (AtaReq->WordsLeft) {
5559 status = SRB_STATUS_DATA_OVERRUN;
5561 status = SRB_STATUS_SUCCESS;
5564 goto CompleteRequest;
5566 status
= SRB_STATUS_SUCCESS
;
5567 goto CompleteRequest
;
5572 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5573 GetStatus(chan
, statusByte
);
5574 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5575 // Assume command is completed if BUSY is cleared
5576 // even if NOT all data read
5577 // Optionally, we may receive COMPLETE interrupt later and
5578 // treat it as unexpected
5579 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete + underrun ? status %x\n", statusByte
));
5581 status
= SRB_STATUS_SUCCESS
;
5582 goto CompleteRequest
;
5587 goto ReturnEnableIntr
;
5589 } else if (interruptReason
== (ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
) && !(statusByte
& IDE_STATUS_DRQ
)) {
5591 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: interruptReason = CompleteRequest\n"));
5592 // Command complete. We exactly know this because of IReason.
5595 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
5596 AtaReq
->WordsTransfered
+= AtaReq
->WordsLeft
;
5597 AtaReq
->WordsLeft
= 0;
5599 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was PIO\n"));
5601 wordCount
= AtaReq
->WordsLeft
;
5602 // Advance data buffer pointer and bytes left.
5603 AtaReq
->DataBuffer
+= wordCount
;
5604 AtaReq
->WordsLeft
-= wordCount
;
5605 AtaReq
->WordsTransfered
+= wordCount
;
5607 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: wordCount %#x, WordsTransfered %#x\n", wordCount
, AtaReq
->WordsTransfered
));
5610 //if (AtaReq->WordsLeft) {
5611 // status = SRB_STATUS_DATA_OVERRUN;
5613 status
= SRB_STATUS_SUCCESS
;
5616 #ifdef UNIATA_DUMP_ATAPI
5618 srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5622 PCHAR ModeSelectData
;
5624 PSCSI_REQUEST_BLOCK Srb
= srb
;
5626 Cdb
= (PCDB
)(Srb
->Cdb
);
5627 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
5628 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
5629 CdbDataLen
= Srb
->DataTransferLength
;
5631 if(CdbDataLen
> 0x1000) {
5632 CdbDataLen
= 0x1000;
5636 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
5637 KdPrint2(("P:T:D=%d:%d:%d\n",
5641 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand
));
5644 if(ScsiCommand
== SCSIOP_MODE_SENSE
) {
5645 KdPrint(("ModeSense 6\n"));
5646 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5647 ModeSelectData
= CdbData
+4;
5648 KdDump(CdbData
, CdbDataLen
);
5650 if(ScsiCommand
== SCSIOP_MODE_SENSE10
) {
5651 KdPrint(("ModeSense 10\n"));
5652 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5653 ModeSelectData
= CdbData
+8;
5654 KdDump(CdbData
, CdbDataLen
);
5656 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5657 KdPrint(("Read buffer from device:\n"));
5658 KdDump(CdbData
, CdbDataLen
);
5663 #endif //UNIATA_DUMP_ATAPI
5667 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, srbstatus %x\n", status
));
5668 // Check and see if we are processing our secret (mechanism status/request sense) srb
5670 if(AtaReq
->WordsLeft
&& (status
== SRB_STATUS_SUCCESS
)) {
5671 KdPrint2((PRINT_PREFIX
"WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq
->WordsLeft
));
5672 status
= SRB_STATUS_DATA_OVERRUN
;
5675 if (AtaReq
->OriginalSrb
) {
5679 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: OriginalSrb != NULL\n"));
5680 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
5682 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
5683 if (status
== SRB_STATUS_SUCCESS
) {
5685 AtapiHwInitializeChanger (HwDeviceExtension
,
5687 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
5689 // Get ready to issue the original srb
5690 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5691 AtaReq
->OriginalSrb
= NULL
;
5694 // failed! Get the sense key and maybe try again
5695 srb
= AtaReq
->Srb
= BuildRequestSenseSrb (
5697 AtaReq
->OriginalSrb
);
5700 // do not enable interrupts in DPC, do not waste time, do it now!
5701 if(UseDpc && chan->DisableIntr) {
5702 AtapiEnableInterrupts(HwDeviceExtension, c);
5704 RestoreUseDpc = TRUE;
5707 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
5709 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
5711 if (srbStatus
== SRB_STATUS_PENDING
) {
5712 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
5713 goto ReturnEnableIntr
;
5717 // restore state on error
5719 AtapiDisableInterrupts(HwDeviceExtension, c);
5723 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
5725 PSENSE_DATA senseData
= (PSENSE_DATA
) srb
->DataBuffer
;
5727 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI command status %#x\n", status
));
5728 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5729 // Check to see if we at least get mininum number of bytes
5730 if ((srb
->DataTransferLength
- AtaReq
->WordsLeft
) >
5731 (FIELD_OFFSET (SENSE_DATA
, AdditionalSenseLength
) + sizeof(senseData
->AdditionalSenseLength
))) {
5732 status
= SRB_STATUS_SUCCESS
;
5736 if (status
== SRB_STATUS_SUCCESS
) {
5738 if ((senseData
->SenseKey
!= SCSI_SENSE_ILLEGAL_REQUEST
) &&
5739 chan
->MechStatusRetryCount
) {
5741 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: MechStatusRetryCount %#x\n", chan
->MechStatusRetryCount
));
5742 // The sense key doesn't say the last request is illegal, so try again
5743 chan
->MechStatusRetryCount
--;
5744 srb
= AtaReq
->Srb
= BuildMechanismStatusSrb (
5746 AtaReq
->OriginalSrb
);
5749 // last request was illegal. No point trying again.
5750 // Do-nothing call ?
5751 AtapiHwInitializeChanger (HwDeviceExtension
,
5753 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
5755 // Get ready to issue the original srb
5756 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5757 AtaReq
->OriginalSrb
= NULL
;
5759 #endif //UNIATA_CORE
5761 // do not enable interrupts in DPC, do not waste time, do it now!
5762 if(UseDpc && chan->DisableIntr) {
5763 AtapiEnableInterrupts(HwDeviceExtension, c);
5765 RestoreUseDpc = TRUE;
5768 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
5770 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan
->ExpectingInterrupt
));
5772 if (srbStatus
== SRB_STATUS_PENDING
) {
5773 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
5774 goto ReturnEnableIntr
;
5778 // restore state on error
5780 AtapiDisableInterrupts(HwDeviceExtension, c);
5786 // If we get here, it means AtapiSendCommand() has failed
5787 // Can't recover. Pretend the original srb has failed and complete it.
5789 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. complete OriginalSrb\n"));
5791 if (AtaReq
->OriginalSrb
) {
5792 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
5793 // Do-nothing call ?
5794 AtapiHwInitializeChanger (HwDeviceExtension
,
5796 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
5797 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5798 AtaReq
->OriginalSrb
= NULL
;
5801 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan
->ExpectingInterrupt
));
5803 // fake an error and read no data
5804 status
= SRB_STATUS_ERROR
;
5805 srb
->ScsiStatus
= 0;
5806 AtaReq
->DataBuffer
= (PUSHORT
)(srb
->DataBuffer
);
5807 AtaReq
->WordsLeft
= srb
->DataTransferLength
;
5810 } else if (status
== SRB_STATUS_ERROR
) {
5812 // Map error to specific SRB status and handle request sense.
5813 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. Begin mapping...\n"));
5814 status
= MapError(deviceExtension
,
5819 } else if(!DmaTransfer
) {
5821 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion\n"));
5822 // Command complete.
5824 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion, wait BUSY\n"));
5825 // Wait for busy to drop.
5826 for (i
= 0; i
< 5*30; i
++) {
5827 GetBaseStatus(chan
, statusByte
);
5828 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5833 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY
;
5835 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (busy)\n"));
5839 AtapiStallExecution(TimerValue
);
5840 goto ServiceInterrupt
;
5841 #endif //UNIATA_CORE
5843 AtapiStallExecution(100);
5848 // reset the controller.
5849 KdPrint2((PRINT_PREFIX
5850 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
5852 goto IntrPrepareResetController
;
5854 // Check to see if DRQ is still up.
5855 if(statusByte
& IDE_STATUS_DRQ
) {
5856 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DRQ...\n"));
5858 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5859 KdPrint2((PRINT_PREFIX
"srb %x data in\n", srb
));
5861 KdPrint2((PRINT_PREFIX
"srb %x data out\n", srb
));
5864 KdPrint2((PRINT_PREFIX
"srb NULL\n"));
5867 KdPrint2((PRINT_PREFIX
"AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq
, AtaReq
->WordsLeft
));
5869 KdPrint2((PRINT_PREFIX
"AtaReq NULL\n"));
5871 if(AtaReq
&& AtaReq
->WordsLeft
/*&&
5872 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
5873 KdPrint2((PRINT_PREFIX
"DRQ+AtaReq->WordsLeft -> next portion\n"));
5877 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
5878 //if ((statusByte & IDE_STATUS_DRQ)) {}
5879 if((statusByte
& IDE_STATUS_DRQ
) &&
5880 (LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_TAPE_DEVICE
| DFLAGS_LBA_ENABLED
)) ) {
5883 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO_wait_DRQ\n"));
5884 for (i
= 0; i
< 200; i
++) {
5885 GetBaseStatus(chan
, statusByte
);
5886 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5891 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq)\n"));
5892 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ
;
5897 AtapiStallExecution(TimerValue
);
5898 goto ServiceInterrupt
;
5899 #endif //UNIATA_CORE
5901 AtapiStallExecution(100);
5905 // reset the controller.
5906 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
5908 goto IntrPrepareResetController
;
5912 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
5913 AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)(-1)), srb
->DataTransferLength
));
5914 //KdDump(srb->DataBuffer, srb->DataTransferLength);
5916 if(!AtapiDmaPioSync(HwDeviceExtension
, srb
, (PUCHAR
)(srb
->DataBuffer
), srb
->DataTransferLength
)) {
5917 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
5921 // Clear interrupt expecting flag.
5922 UniataExpectChannelInterrupt(chan
, FALSE
);
5923 // clear this flag now, it can be set again in sub-calls
5924 InterlockedExchange(&(chan
->CheckIntr
),
5927 // Sanity check that there is a current request.
5929 // Set status in SRB.
5930 srb
->SrbStatus
= (UCHAR
)status
;
5932 // Check for underflow.
5933 if(AtaReq
->WordsLeft
) {
5935 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq
->WordsLeft
));
5936 // Subtract out residual words and update if filemark hit,
5937 // setmark hit , end of data, end of media...
5938 if (!(LunExt
->DeviceFlags
& DFLAGS_TAPE_DEVICE
)) {
5939 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5940 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5942 srb
->DataTransferLength
= 0;
5945 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5948 if(status
== SRB_STATUS_SUCCESS
) {
5949 //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) {
5950 // // This should be set in UniataAhciEndTransaction() for AHCI
5951 // AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
5954 AtaReq
->WordsTransfered
*2 < AtaReq
->TransferLength
) {
5955 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
5956 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5957 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5958 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_NEXT
;
5961 KdPrint2((PRINT_PREFIX
" Transfered %x, full size %x\n",
5962 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5966 if (srb
->Function
!= SRB_FUNCTION_IO_CONTROL
) {
5969 // Indicate command complete.
5971 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete\n"));
5974 if (status
== SRB_STATUS_SUCCESS
&&
5975 srb
->SenseInfoBuffer
&&
5976 srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
5978 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)srb
->SenseInfoBuffer
;
5980 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: set AutoSense\n"));
5981 senseBuffer
->ErrorCode
= 0;
5982 senseBuffer
->Valid
= 1;
5983 senseBuffer
->AdditionalSenseLength
= 0xb;
5984 senseBuffer
->SenseKey
= 0;
5985 senseBuffer
->AdditionalSenseCode
= 0;
5986 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
5988 srb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
5990 AtapiDmaDBSync(chan
, srb
);
5991 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove srb %#x, status %x\n", srb
, status
));
5992 UniataRemoveRequest(chan
, srb
);
5993 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete, srb %#x\n", srb
));
5994 ScsiPortNotification(RequestComplete
,
6000 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: IOCTL completion\n"));
6002 if (status
!= SRB_STATUS_SUCCESS
) {
6003 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6004 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: error %#x\n", error
));
6007 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
6009 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6010 // Build the SMART status block depending upon the completion status.
6011 cmdOutParameters
->cBufferSize
= wordCount
;
6012 cmdOutParameters
->DriverStatus
.bDriverError
= (error
) ? SMART_IDE_ERROR
: 0;
6013 cmdOutParameters
->DriverStatus
.bIDEError
= error
;
6015 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
6017 if (chan
->SmartCommand
== RETURN_SMART_STATUS
) {
6018 PIDEREGS_EX regs
= (PIDEREGS_EX
)&(cmdOutParameters
->bBuffer
);
6021 UniataSnapAtaRegs(chan
, 0, regs
);
6023 regs
->bCommandReg
= SMART_CMD
;
6024 regs
->bFeaturesReg
= RETURN_SMART_STATUS
;
6026 cmdOutParameters
->cBufferSize
= 8;
6028 chan
->SmartCommand
= 0; // cleanup after execution
6030 // Indicate command complete.
6031 goto IntrCompleteReq
;
6036 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: No SRB!\n"));
6041 for (i
= 0; i
< 5; i
++) {
6042 GetBaseStatus(chan
, statusByte
);
6043 if(!(statusByte
& IDE_STATUS_BUSY
)) {
6044 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RDP + cleared BUSY\n"));
6048 if (statusByte
& IDE_STATUS_DSC
) {
6049 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Clear RDP\n"));
6053 AtapiStallExecution(50);
6056 // RDP can be cleared since previous check
6058 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestTimerCall 2000\n"));
6064 AtapiStallExecution(TimerValue
);
6065 goto ServiceInterrupt
;
6066 #endif //UNIATA_CORE
6069 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
6072 srb
= UniataGetCurRequest(chan
);
6077 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: NextRequest, srb=%#x\n",srb
));
6079 ScsiPortNotification(NextRequest
,
6083 ScsiPortNotification(NextLuRequest
,
6088 // in simplex mode next command must NOT be sent here
6089 if(!deviceExtension
->simplexOnly
) {
6090 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6093 // Try to get SRB fron any non-empty queue (later)
6094 if(deviceExtension
->simplexOnly
) {
6097 #endif //UNIATA_CORE
6099 goto ReturnEnableIntr
;
6103 // Unexpected int. Catch it
6104 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
6108 if(OldReqState
== REQ_STATE_DPC_WAIT_BUSY0
&&
6109 AtaReq
->WordsLeft
== 0) {
6110 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: pending WAIT_BUSY0. Complete.\n"));
6111 status
= SRB_STATUS_SUCCESS
;
6112 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6113 goto CompleteRequest
;
6119 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ReturnEnableIntr\n",srb
));
6120 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6121 deviceExtension
->ExpectingInterrupt
= TRUE
;
6123 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
6124 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
6125 #ifdef UNIATA_USE_XXableInterrupts
6126 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
6127 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
6128 // must be called on DISPATCH_LEVEL
6129 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
6130 AtapiEnableInterrupts__
);
6132 AtapiEnableInterrupts(HwDeviceExtension
, c
);
6133 InterlockedExchange(&(chan
->CheckIntr
),
6135 // Will raise IRQL to DIRQL
6137 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
6138 AtapiEnableInterrupts__
,
6140 #endif // UNIATA_CORE
6141 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
6142 #endif // UNIATA_USE_XXableInterrupts
6146 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
6147 // in simplex mode next command must be sent here if
6149 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc
, NoStartIo
));
6152 if(!UseDpc
&& /*deviceExtension->simplexOnly &&*/ !NoStartIo
) {
6153 chan
= UniataGetNextChannel(chan
);
6155 srb
= UniataGetCurRequest(chan
);
6159 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: run srb %x\n", srb
));
6161 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6164 #endif //UNIATA_CORE
6167 } // end AtapiInterrupt__()
6173 Routine Description:
6175 This routine handles SMART enable, disable, read attributes and threshold commands.
6179 HwDeviceExtension - HBA miniport driver's adapter data storage
6180 Srb - IO request packet
6189 IdeSendSmartCommand(
6190 IN PVOID HwDeviceExtension
,
6191 IN PSCSI_REQUEST_BLOCK Srb
,
6192 IN ULONG targetId
// assume it is always valid
6195 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6196 ULONG c
; // = GET_CHANNEL(Srb); may be invalid
6197 PHW_CHANNEL chan
; // = &(deviceExtension->chan[c]);
6198 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6199 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6200 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6201 PIDEREGS regs
= &cmdInParameters
.irDriveRegs
;
6206 if (regs
->bCommandReg
!= SMART_CMD
) {
6207 KdPrint2((PRINT_PREFIX
6208 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
6209 return SRB_STATUS_INVALID_REQUEST
;
6212 c
= targetId
/ deviceExtension
->NumberLuns
;
6213 DeviceNumber
= targetId
% deviceExtension
->NumberLuns
;
6214 KdPrint2((PRINT_PREFIX
" c %d, dev %d\n", c
, DeviceNumber
));
6216 chan
= &(deviceExtension
->chan
[c
]);
6218 chan
->SmartCommand
= regs
->bFeaturesReg
;
6220 // Determine which of the commands to carry out.
6221 switch(regs
->bFeaturesReg
) {
6222 case READ_ATTRIBUTES
:
6223 case READ_THRESHOLDS
:
6224 case READ_LOG_SECTOR
:
6225 case WRITE_LOG_SECTOR
:
6227 if(Srb
->DataTransferLength
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1) {
6228 KdPrint2((PRINT_PREFIX
6229 "IdeSendSmartCommand: wrong buffer size\n"));
6230 return SRB_STATUS_DATA_OVERRUN
;
6233 statusByte
= WaitOnBusy(chan
);
6235 if (statusByte
& IDE_STATUS_BUSY
) {
6236 KdPrint2((PRINT_PREFIX
6237 "IdeSendSmartCommand: Returning BUSY status\n"));
6238 return SRB_STATUS_BUSY
;
6241 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6242 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1);
6244 // Set data buffer pointer and words left.
6245 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6246 AtaReq
->WordsLeft
= READ_ATTRIBUTE_BUFFER_SIZE
/ 2;
6248 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6250 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6252 regs
->bSectorNumberReg
,
6253 regs
->bSectorCountReg
,
6257 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6258 // Wait for interrupt.
6259 return SRB_STATUS_PENDING
;
6261 return SRB_STATUS_ERROR
;
6265 case RETURN_SMART_STATUS
:
6266 case ENABLE_DISABLE_AUTOSAVE
:
6267 case EXECUTE_OFFLINE_DIAGS
:
6268 case SAVE_ATTRIBUTE_VALUES
:
6271 statusByte
= WaitOnBusy(chan
);
6273 if (statusByte
& IDE_STATUS_BUSY
) {
6274 KdPrint2((PRINT_PREFIX
6275 "IdeSendSmartCommand: Returning BUSY status\n"));
6276 return SRB_STATUS_BUSY
;
6279 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6280 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) - 1);
6282 // Set data buffer pointer and indicate no data transfer.
6283 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6284 AtaReq
->WordsLeft
= 0;
6286 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6288 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6290 regs
->bSectorNumberReg
,
6291 regs
->bSectorCountReg
,
6295 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6296 // Wait for interrupt.
6297 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6298 return SRB_STATUS_PENDING
;
6300 return SRB_STATUS_ERROR
;
6301 } // end switch(regs->bFeaturesReg)
6303 return SRB_STATUS_INVALID_REQUEST
;
6305 } // end IdeSendSmartCommand()
6307 #endif //UNIATA_CORE
6311 UniAtaCalculateLBARegs(
6312 PHW_LU_EXTENSION LunExt
,
6313 ULONGLONG startingSector
,
6317 UCHAR drvSelect
,sectorNumber
;
6321 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6322 if(LunExt
->LimitedTransferMode
>= ATA_DMA
) {
6323 if(LunExt
->DeviceExtension
) {
6324 (*max_bcount
) = LunExt
->DeviceExtension
->MaximumDmaTransferLength
/ DEV_BSIZE
;
6327 return startingSector
;
6329 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6330 LunExt
->IdentifyData
.NumberOfHeads
;
6332 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
6336 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
;
6338 cylinder
= (USHORT
)(startingSector
/ tmp
);
6339 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
6340 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
6341 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
- sectorNumber
+ 1;
6342 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
6343 cylinder
, drvSelect
, sectorNumber
, (*max_bcount
)));
6347 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
6348 } // end UniAtaCalculateLBARegs()
6352 UniAtaCalculateLBARegsBack(
6353 PHW_LU_EXTENSION LunExt
,
6357 ULONG drvSelect
,sectorNumber
;
6361 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6364 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6365 LunExt
->IdentifyData
.NumberOfHeads
;
6367 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
6368 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
6369 sectorNumber
= (UCHAR
)(lba
& 0xff);
6371 lba
= sectorNumber
-1 +
6372 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
6376 } // end UniAtaCalculateLBARegsBack()
6381 Routine Description:
6383 This routine handles IDE read and writes.
6387 HwDeviceExtension - HBA miniport driver's adapter data storage
6388 Srb - IO request packet
6398 IN PVOID HwDeviceExtension
,
6399 IN PSCSI_REQUEST_BLOCK Srb
,
6403 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6404 UCHAR lChannel
= GET_CHANNEL(Srb
);
6405 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6406 PHW_LU_EXTENSION LunExt
;
6407 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6408 //ULONG ldev = GET_LDEV(Srb);
6409 UCHAR DeviceNumber
= GET_CDEV(Srb
);;
6410 ULONGLONG startingSector
=0;
6412 ULONG wordCount
= 0;
6413 UCHAR statusByte
,statusByte2
;
6416 BOOLEAN use_dma
= FALSE
;
6419 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6420 LunExt
= chan
->lun
[DeviceNumber
];
6422 if((CmdAction
& CMD_ACTION_PREPARE
) &&
6423 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
6425 if(LunExt
->opt_ReadOnly
&&
6426 (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) {
6427 if(LunExt
->opt_ReadOnly
== 1) {
6428 KdPrint2((PRINT_PREFIX
"Abort WRITE (Soft R/O)\n"));
6429 return SRB_STATUS_ERROR
;
6431 KdPrint2((PRINT_PREFIX
"Ignore WRITE (Soft R/O)\n"));
6432 return SRB_STATUS_SUCCESS
;
6436 // Set data buffer pointer and words left.
6437 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6439 if(AtaReq
->WordsTransfered
) {
6440 AtaReq
->DataBuffer
= ((PUSHORT
)(Srb
->DataBuffer
)) + AtaReq
->WordsTransfered
;
6441 startingSector
= (UniAtaCalculateLBARegsBack(LunExt
, AtaReq
->lba
)) /* latest lba */ + AtaReq
->bcount
/* previous bcount */;
6442 AtaReq
->bcount
= (AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2 + DEV_BSIZE
-1) / DEV_BSIZE
;
6443 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Chained REQ): Starting sector %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
6445 AtaReq
->TransferLength
/2,
6446 AtaReq
->WordsTransfered
,
6449 AtaReq
->DataBuffer
= (PUSHORT
)(Srb
->DataBuffer
);
6450 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
6451 // Set up 1st block.
6452 switch(Srb
->Cdb
[0]) {
6455 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6456 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6459 case SCSIOP_WRITE12
:
6460 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
6461 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6464 case SCSIOP_WRITE16
:
6465 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6466 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6469 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Orig REQ): Starting sector %I64x, OrigWordsRequested %#x, DevSize %#x\n",
6471 AtaReq
->TransferLength
/2,
6474 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6477 AtaReq
->bcount
= min(AtaReq
->bcount
, max_bcount
);
6479 AtaReq
->WordsLeft
= min(AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2,
6480 AtaReq
->bcount
* DEV_BSIZE
) / 2;
6482 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n",
6489 // assume best case here
6490 // we cannot reinit Dma until previous request is completed
6491 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6492 UniataAhciSetupCmdPtr(AtaReq
);
6493 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6494 (PUCHAR
)(AtaReq
->DataBuffer
),
6495 AtaReq
->bcount
* DEV_BSIZE
)) {
6496 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !DMA\n"));
6497 return SRB_STATUS_ERROR
;
6500 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
6502 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6503 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6504 (PUCHAR
)(AtaReq
->DataBuffer
),
6505 AtaReq
->bcount
* DEV_BSIZE
)) {
6510 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6511 KdPrint2((PRINT_PREFIX
"IdeReadWrite: setup AHCI FIS\n"));
6512 RtlZeroMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
), sizeof(AtaReq
->ahci_cmd0
.cfis
));
6514 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
6515 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
6516 (AtaReq
->Flags
& REQ_FLAG_READ
) ? IDE_COMMAND_READ_DMA
: IDE_COMMAND_WRITE_DMA
,
6518 (USHORT
)(AtaReq
->bcount
),
6520 /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/
6524 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !FIS\n"));
6525 return SRB_STATUS_ERROR
;
6528 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0, (AtaReq
->Flags
& REQ_FLAG_READ
) ? 0 : ATA_AHCI_CMD_WRITE
, fis_size
, DeviceNumber
);
6529 KdPrint2((PRINT_PREFIX
"IdeReadWrite ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
6532 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
6534 } else { // exec_only
6535 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
6538 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6542 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
6544 return SRB_STATUS_PENDING
;
6547 // if this is queued request, reinit DMA and check
6548 // if DMA mode is still available
6549 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
6550 if (/*EnableDma &&*/
6551 (LunExt
->TransferMode
>= ATA_DMA
)) {
6554 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6558 // Check if write request.
6559 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6561 // Prepare read command.
6563 cmd
= IDE_COMMAND_READ_DMA
;
6565 if(LunExt
->MaximumBlockXfer
) {
6566 cmd
= IDE_COMMAND_READ_MULTIPLE
;
6568 cmd
= IDE_COMMAND_READ
;
6572 // Prepare write command.
6574 wordCount
= AtaReq
->bcount
*DEV_BSIZE
/2;
6575 cmd
= IDE_COMMAND_WRITE_DMA
;
6577 if (LunExt
->MaximumBlockXfer
) {
6578 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
6580 if (AtaReq
->WordsLeft
< wordCount
) {
6581 // Transfer only words requested.
6582 wordCount
= AtaReq
->WordsLeft
;
6584 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
6587 wordCount
= DEV_BSIZE
/2;
6588 cmd
= IDE_COMMAND_WRITE
;
6593 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
6594 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
6596 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
6598 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6601 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6602 // AHCI doesn't distinguish DMA and PIO
6603 //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
6604 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
6605 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6606 InterlockedExchange(&(chan
->CheckIntr
),
6608 return SRB_STATUS_PENDING
;
6611 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
6613 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
6615 (USHORT
)(AtaReq
->bcount
),
6616 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6618 if(statusByte2
!= IDE_STATUS_WRONG
) {
6619 GetStatus(chan
, statusByte2
);
6621 if(statusByte2
& IDE_STATUS_ERROR
) {
6622 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6623 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
6624 return SRB_STATUS_ERROR
;
6627 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
6629 return SRB_STATUS_PENDING
;
6632 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
6634 (USHORT
)(AtaReq
->bcount
),
6635 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6638 if (!(statusByte
& IDE_STATUS_DRQ
) ||
6639 statusByte
== IDE_STATUS_WRONG
) {
6641 if(statusByte
== IDE_STATUS_WRONG
) {
6642 KdPrint2((PRINT_PREFIX
6643 "IdeReadWrite: error sending command (%#x)\n",
6646 KdPrint2((PRINT_PREFIX
6647 "IdeReadWrite: DRQ never asserted (%#x)\n",
6651 AtaReq
->WordsLeft
= 0;
6653 // Clear interrupt expecting flag.
6654 UniataExpectChannelInterrupt(chan
, FALSE
);
6655 InterlockedExchange(&(chan
->CheckIntr
),
6658 // Clear current SRB.
6659 UniataRemoveRequest(chan
, Srb
);
6661 return (statusByte
== IDE_STATUS_WRONG
) ? SRB_STATUS_ERROR
: SRB_STATUS_TIMEOUT
;
6664 UniataExpectChannelInterrupt(chan
, TRUE
);
6665 InterlockedExchange(&(chan
->CheckIntr
),
6668 // Write next DEV_BSIZE/2*N words.
6669 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
)) {
6670 KdPrint2((PRINT_PREFIX
6671 "IdeReadWrite: Write %#x words\n", wordCount
));
6676 UniataGetPioTiming(LunExt
));
6680 KdPrint2((PRINT_PREFIX
6681 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
6684 (PULONG
)(AtaReq
->DataBuffer
),
6686 UniataGetPioTiming(LunExt
));
6689 // Adjust buffer address and words left count.
6690 AtaReq
->WordsLeft
-= wordCount
;
6691 AtaReq
->DataBuffer
+= wordCount
;
6693 // Wait for interrupt.
6694 return SRB_STATUS_PENDING
;
6696 } // end IdeReadWrite()
6702 Routine Description:
6703 This routine handles IDE Verify.
6706 HwDeviceExtension - HBA miniport driver's adapter data storage
6707 Srb - IO request packet
6716 IN PVOID HwDeviceExtension
,
6717 IN PSCSI_REQUEST_BLOCK Srb
6720 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6721 UCHAR lChannel
= GET_CHANNEL(Srb
);
6722 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6723 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6724 PHW_LU_EXTENSION LunExt
;
6725 //ULONG ldev = GET_LDEV(Srb);
6726 ULONG DeviceNumber
= GET_CDEV(Srb
);
6728 ULONGLONG startingSector
=0;
6731 ULONGLONG endSector
;
6732 ULONG sectorCount
=0;
6735 LunExt
= chan
->lun
[DeviceNumber
];
6736 // Drive has these number sectors.
6737 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
6738 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
6739 LunExt
->IdentifyData
.NumberOfHeads
*
6740 LunExt
->IdentifyData
.NumberOfCylinders
;
6743 KdPrint2((PRINT_PREFIX
6744 "IdeVerify: Total sectors %#x\n",
6747 // Get starting sector number from CDB.
6748 switch(Srb
->Cdb
[0]) {
6750 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6751 MOV_SWP_DW2DD(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6753 case SCSIOP_VERIFY12
:
6754 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
6755 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6757 case SCSIOP_VERIFY16
:
6758 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6759 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6763 KdPrint2((PRINT_PREFIX
6764 "IdeVerify: Starting sector %#I64x. Number of blocks %#x\n",
6768 endSector
= startingSector
+ sectorCount
;
6770 KdPrint2((PRINT_PREFIX
6771 "IdeVerify: Ending sector %#I64x\n",
6774 if (endSector
> sectors
) {
6776 // Too big, round down.
6777 KdPrint2((PRINT_PREFIX
6778 "IdeVerify: Truncating request to %#x blocks\n",
6779 sectors
- startingSector
- 1));
6781 sectorCount
= (ULONG
)(sectors
- startingSector
- 1);
6785 // Set up sector count register. Round up to next block.
6786 if (sectorCount
> 0xFF) {
6787 sectorCount
= (USHORT
)0xFF;
6791 // Set data buffer pointer and words left.
6792 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
6793 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
6795 // Indicate expecting an interrupt.
6796 InterlockedExchange(&(chan
->CheckIntr
),
6799 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6801 statusByte
= AtaCommand48(deviceExtension
, LunExt
->Lun
, GET_CHANNEL(Srb
),
6802 IDE_COMMAND_VERIFY
, lba
,
6803 (USHORT
)sectorCount
,
6806 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6807 // Wait for interrupt.
6808 return SRB_STATUS_PENDING
;
6810 return SRB_STATUS_ERROR
;
6812 } // end IdeVerify()
6814 #endif //UNIATA_CORE
6818 Routine Description:
6819 Send ATAPI packet command to device.
6822 HwDeviceExtension - HBA miniport driver's adapter data storage
6823 Srb - IO request packet
6831 IN PVOID HwDeviceExtension
,
6832 IN PSCSI_REQUEST_BLOCK Srb
,
6836 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6837 UCHAR lChannel
= GET_CHANNEL(Srb
);
6838 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6839 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6840 PHW_LU_EXTENSION LunExt
;
6841 //ULONG ldev = GET_LDEV(Srb);
6842 ULONG DeviceNumber
= GET_CDEV(Srb
);
6844 UCHAR statusByte
,statusByte0
,byteCountLow
,byteCountHigh
;
6845 BOOLEAN use_dma
= FALSE
;
6846 BOOLEAN dma_reinited
= FALSE
;
6847 BOOLEAN retried
= FALSE
;
6851 LunExt
= chan
->lun
[DeviceNumber
];
6853 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: req state %#x, Action %x\n", AtaReq
->ReqState
, CmdAction
));
6854 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
6855 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
6858 #ifdef UNIATA_DUMP_ATAPI
6859 if(CmdAction
& CMD_ACTION_PREPARE
) {
6863 PCHAR ModeSelectData
;
6866 Cdb
= (PCDB
)(Srb
->Cdb
);
6867 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
6868 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
6869 CdbDataLen
= Srb
->DataTransferLength
;
6871 if(CdbDataLen
> 0x1000) {
6872 CdbDataLen
= 0x1000;
6876 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
6877 KdPrint2(("P:T:D=%d:%d:%d\n",
6881 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
6884 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
6885 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
6886 Cdb
->WRITE_CD
.LBA
[0],
6887 Cdb
->WRITE_CD
.LBA
[1],
6888 Cdb
->WRITE_CD
.LBA
[2],
6889 Cdb
->WRITE_CD
.LBA
[3]
6892 if(ScsiCommand
== SCSIOP_WRITE12
) {
6893 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
6894 Cdb
->CDB12READWRITE
.LBA
[0],
6895 Cdb
->CDB12READWRITE
.LBA
[1],
6896 Cdb
->CDB12READWRITE
.LBA
[2],
6897 Cdb
->CDB12READWRITE
.LBA
[3]
6900 if(ScsiCommand
== SCSIOP_WRITE16
) {
6901 KdPrint(("Write16, LBA %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
6902 Cdb
->CDB16READWRITE
.LBA
[0],
6903 Cdb
->CDB16READWRITE
.LBA
[1],
6904 Cdb
->CDB16READWRITE
.LBA
[2],
6905 Cdb
->CDB16READWRITE
.LBA
[3],
6906 Cdb
->CDB16READWRITE
.LBA
[4],
6907 Cdb
->CDB16READWRITE
.LBA
[5],
6908 Cdb
->CDB16READWRITE
.LBA
[6],
6909 Cdb
->CDB16READWRITE
.LBA
[7]
6912 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
6913 KdPrint(("ModeSelect 6\n"));
6914 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6915 ModeSelectData
= CdbData
+4;
6916 KdDump(CdbData
, CdbDataLen
);
6918 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
6919 KdPrint(("ModeSelect 10\n"));
6920 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6921 ModeSelectData
= CdbData
+8;
6922 KdDump(CdbData
, CdbDataLen
);
6924 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
6925 KdPrint(("Send buffer to device:\n"));
6926 KdDump(CdbData
, CdbDataLen
);
6931 #endif //UNIATA_DUMP_ATAPI
6934 if(CmdAction
== CMD_ACTION_PREPARE
) {
6935 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb
->Cdb
)));
6937 switch (Srb
->Cdb
[0]) {
6938 case SCSIOP_RECEIVE
:
6943 case SCSIOP_WRITE12
:
6945 case SCSIOP_WRITE16
:
6948 case SCSIOP_READ_CD
:
6949 case SCSIOP_READ_CD_MSF
:
6950 if(deviceExtension
->opt_AtapiDmaRawRead
) {
6956 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
6957 return SRB_STATUS_BUSY
;
6960 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6961 !AtaReq
->OriginalSrb
) {
6962 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
6963 return SRB_STATUS_BUSY
;
6968 // We need to know how many platters our atapi cd-rom device might have.
6969 // Before anyone tries to send a srb to our target for the first time,
6970 // we must "secretly" send down a separate mechanism status srb in order to
6971 // initialize our device extension changer data. That's how we know how
6972 // many platters our target has.
6974 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6975 !AtaReq
->OriginalSrb
) {
6979 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
6980 // Set this flag now. If the device hangs on the mech. status
6981 // command, we will not have the chance to set it.
6982 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
6984 chan
->MechStatusRetryCount
= 3;
6985 AtaReq
->OriginalSrb
= Srb
;
6986 AtaReq
->Srb
= BuildMechanismStatusSrb (
6990 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
6991 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
6992 if (srbStatus
== SRB_STATUS_PENDING
) {
6993 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
6997 // failed! Get the sense key and maybe try again
6998 AtaReq
->Srb
= BuildRequestSenseSrb ( HwDeviceExtension
,
6999 AtaReq
->OriginalSrb
);
7001 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
7003 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
7005 if (srbStatus
== SRB_STATUS_PENDING
) {
7006 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n"));
7010 // failed again ? should not get here
7012 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
7013 AtaReq
->OriginalSrb
= NULL
;
7015 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiHwInitializeChanger()\n"));
7016 // Do-nothing call ?
7017 AtapiHwInitializeChanger (HwDeviceExtension
, Srb
,
7018 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
7022 #endif //UNIATA_CORE
7024 if((CmdAction
& CMD_ACTION_PREPARE
) &&
7025 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
7027 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb
->Cdb
[0], &(Srb
->Cdb
)));
7029 if(!LunExt
->IdentifyData
.AtapiCmdSize
&&
7030 (Srb
->CdbLength
> 12)) {
7031 KdPrint2((PRINT_PREFIX
"Cdb16 not supported\n"));
7032 return SRB_STATUS_INVALID_REQUEST
;
7035 // Set data buffer pointer and words left.
7036 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
7037 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
7038 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
7039 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7040 // reset this to force PRD init. May be already setup by recursive SRB
7041 AtaReq
->dma_entries
= 0;
7043 // check if reorderable
7044 switch(Srb
->Cdb
[0]) {
7046 case SCSIOP_WRITE16
:
7048 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
7049 MOV_QD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
7053 case SCSIOP_WRITE12
:
7055 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
7061 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
7063 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
7065 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
7066 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7067 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
7068 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
7069 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ?
7070 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
7073 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7074 if(!AtaReq
->TransferLength
) {
7075 KdPrint((" assume 0-transfer\n"));
7077 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
7078 KdPrint((" assume OUT\n"));
7079 AtaReq
->Flags
|= REQ_FLAG_WRITE
;
7081 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7082 KdPrint((" assume IN\n"));
7083 AtaReq
->Flags
|= REQ_FLAG_READ
;
7088 // check if DMA read/write
7089 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7090 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: force use dma (ahci)\n"));
7094 /* if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) {
7095 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n"));
7099 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
7100 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
7102 if(AtaReq
->TransferLength
) {
7104 switch(Srb
->Cdb
[0]) {
7106 case SCSIOP_WRITE12
:
7107 case SCSIOP_WRITE16
:
7109 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
7112 case SCSIOP_RECEIVE
:
7117 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
7119 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7120 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7123 if(AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7124 (PUCHAR
)(AtaReq
->DataBuffer
),
7125 Srb
->DataTransferLength
7126 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
7128 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7133 case SCSIOP_READ_CD
:
7134 case SCSIOP_READ_CD_MSF
:
7135 if(deviceExtension
->opt_AtapiDmaRawRead
)
7136 goto call_dma_setup
;
7140 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
7141 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7146 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
7147 KdPrint2((PRINT_PREFIX
"dma RO\n"));
7159 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7160 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7163 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7164 (PUCHAR
)(AtaReq
->DataBuffer
),
7165 Srb
->DataTransferLength
)) {
7166 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
7169 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7173 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer, no DMA setup\n"));
7177 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7179 UniataAhciSetupCmdPtr(AtaReq
);
7181 if(!Srb
->DataTransferLength
) {
7182 KdPrint2((PRINT_PREFIX
"zero-transfer\n"));
7185 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7186 (PUCHAR
)(AtaReq
->DataBuffer
),
7187 Srb
->DataTransferLength
)) {
7188 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no AHCI dma!\n"));
7189 return SRB_STATUS_ERROR
;
7192 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7194 FeatureReg
|= ATA_F_DMA
;
7195 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7196 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7197 FeatureReg
|= ATA_F_DMAREAD
;
7201 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: setup AHCI FIS\n"));
7202 // this is done in UniataAhciSetupFIS_H2D()
7203 //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
7204 RtlCopyMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), Srb
->Cdb
, Srb
->CdbLength
);
7206 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
7207 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
7208 IDE_COMMAND_ATAPI_PACKET
/* command */,
7210 (Srb
->DataTransferLength
>= 0x10000) ? (USHORT
)(0xffff) : (USHORT
)(Srb
->DataTransferLength
),
7211 FeatureReg
/* feature */
7215 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AHCI !FIS\n"));
7216 return SRB_STATUS_ERROR
;
7219 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0,
7220 ((Srb
->DataTransferLength
&& (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) ? ATA_AHCI_CMD_WRITE
: 0) |
7221 (ATA_AHCI_CMD_ATAPI
| ATA_AHCI_CMD_PREFETCH
),
7222 fis_size
, DeviceNumber
);
7224 KdPrint2((PRINT_PREFIX
"AtapiSendCommand ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
7228 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7229 // if this is queued request, reinit DMA and check
7230 // if DMA mode is still available
7231 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
7232 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7233 if (/*EnableDma &&*/
7234 (LunExt
->TransferMode
>= ATA_DMA
)) {
7235 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
7238 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7239 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
7242 dma_reinited
= TRUE
;
7246 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
7247 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
7248 return SRB_STATUS_PENDING
;
7250 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma
, Srb
->Cdb
[0]));
7251 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7252 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7255 if((Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) && !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7256 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
7258 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7259 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7260 } if(AtaReq
->TransferLength
) {
7262 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
7263 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7264 if (/*EnableDma &&*/
7265 (LunExt
->TransferMode
>= ATA_DMA
)) {
7268 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7273 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
7275 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7276 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7277 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
7278 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7281 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
7282 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7283 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7286 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
7288 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
7289 &(Srb
->Cdb
), Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
7291 // Make sure command is to ATAPI device.
7292 flags
= LunExt
->DeviceFlags
;
7293 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7294 if((Srb
->Lun
) > (LunExt
->DiscsPresent
- 1)) {
7296 // Indicate no device found at this address.
7297 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7298 return SRB_STATUS_SELECTION_TIMEOUT
;
7300 } else if(Srb
->Lun
> 0) {
7301 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7302 return SRB_STATUS_SELECTION_TIMEOUT
;
7305 if(!(flags
& DFLAGS_ATAPI_DEVICE
)) {
7306 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7307 return SRB_STATUS_SELECTION_TIMEOUT
;
7310 // Select device 0 or 1. Or more for PM
7311 SelectDrive(chan
, DeviceNumber
);
7313 // Verify that controller is ready for next command.
7314 GetStatus(chan
, statusByte
);
7315 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
7317 if(statusByte
== IDE_STATUS_WRONG
) {
7318 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
7321 if(statusByte
& IDE_STATUS_BUSY
) {
7322 if(statusByte
& IDE_STATUS_DSC
) {
7323 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
7325 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
7326 // We have to make reset here, since we are expecting device to be available
7327 //return SRB_STATUS_BUSY; // this cause queue freeze
7331 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7333 // Check if command list is free
7334 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
7336 // controller is busy, however we expect it to be free
7337 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI
));
7341 if(statusByte
& IDE_STATUS_ERROR
) {
7342 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
7344 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
7345 // Read the error reg. to clear it and fail this request.
7346 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7347 return MapError(deviceExtension
, Srb
);
7349 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
7352 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
7353 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
7354 if((!(statusByte
& IDE_STATUS_DSC
)) &&
7355 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
7357 AtapiStallExecution(200);
7358 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
7359 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7360 return SRB_STATUS_PENDING
;
7363 if(IS_RDP(Srb
->Cdb
[0])) {
7365 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
7369 if(statusByte
& IDE_STATUS_DRQ
) {
7371 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
7373 // Try to drain the data that one preliminary device thinks that it has
7374 // to transfer. Hopefully this random assertion of DRQ will not be present
7375 // in production devices.
7376 statusByte
= AtapiSuckPort2(chan
);
7378 for (i = 0; i < 0x10000; i++) {
7379 GetStatus(chan, statusByte);
7380 if(statusByte & IDE_STATUS_DRQ) {
7381 AtapiReadPort2(chan, IDX_IO1_i_Data);
7387 if (statusByte
& IDE_STATUS_DRQ
) {
7389 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte
));
7391 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7393 AtapiSoftReset(chan
, DeviceNumber
);
7395 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
7396 // Re-initialize Atapi device.
7397 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), DeviceNumber
, TRUE
);
7399 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
7400 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
7402 // Inform the port driver that the bus has been reset.
7403 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
7404 // Clean up device extension fields that AtapiStartIo won't.
7405 UniataExpectChannelInterrupt(chan
, FALSE
);
7407 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
7410 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7412 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7413 return SRB_STATUS_BUS_RESET;
7416 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
7420 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
7421 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7422 return SRB_STATUS_SELECTION_TIMEOUT
;
7426 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7427 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
7428 Srb
->Cdb
[1] &= ~0xE0;
7429 if((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
7430 // Torisan changer. TUR's are overloaded to be platter switches.
7431 Srb
->Cdb
[7] = Srb
->Lun
;
7438 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
7440 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
7443 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7444 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AHCI, begin transaction\n"));
7445 //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
7446 UniataExpectChannelInterrupt(chan
, TRUE
);
7447 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
7448 return SRB_STATUS_PENDING
;
7451 statusByte
= WaitOnBusy(chan
);
7452 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
7456 FeatureReg
|= ATA_F_DMA
;
7457 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7458 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7459 FeatureReg
|= ATA_F_DMAREAD
;
7463 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, FeatureReg
);
7465 // Write transfer byte count to registers.
7466 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
7467 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
7469 if (Srb
->DataTransferLength
>= 0x10000) {
7470 byteCountLow
= byteCountHigh
= 0xFF;
7473 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
7474 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
7476 if (flags
& DFLAGS_INT_DRQ
) {
7478 // This device interrupts when ready to receive the packet.
7480 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
7483 UniataExpectChannelInterrupt(chan
, TRUE
);
7484 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
7485 InterlockedExchange(&(chan
->CheckIntr
),
7488 // Write ATAPI packet command.
7489 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7491 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
7492 return SRB_STATUS_PENDING
;
7496 // This device quickly sets DRQ when ready to receive the packet.
7498 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
7501 UniataExpectChannelInterrupt(chan
, TRUE
);
7502 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
7503 InterlockedExchange(&(chan
->CheckIntr
),
7506 if(g_opt_AtapiSendDisableIntr
) {
7507 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7509 // remember status. Later we may check if error appeared after cmd packet
7510 statusByte0
= statusByte
;
7512 // Write ATAPI packet command.
7513 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7517 statusByte
= WaitForDrq(chan
);
7519 // Need to read status register and clear interrupt (if any)
7520 GetBaseStatus(chan
, statusByte
);
7522 if (!(statusByte
& IDE_STATUS_DRQ
)) {
7524 if(g_opt_AtapiSendDisableIntr
) {
7525 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7527 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte
));
7528 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7529 return SRB_STATUS_ERROR
;
7532 GetStatus(chan
, statusByte
);
7533 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
7535 // Send CDB to device.
7536 statusByte
= WaitOnBaseBusy(chan
);
7538 // Indicate expecting an interrupt and wait for it.
7539 UniataExpectChannelInterrupt(chan
, TRUE
);
7540 InterlockedExchange(&(chan
->CheckIntr
),
7542 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
7544 GetBaseStatus(chan
, statusByte
);
7546 if(g_opt_AtapiSendDisableIntr
) {
7547 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7552 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
7555 GetStatus(chan
, statusByte
);
7556 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: cmd status (%#x)\n", statusByte
));
7558 // When we operate in DMA mode, we should not start transfer when there is an error on entry
7559 // Interrupt may never come in such case.
7560 if(statusByte
& IDE_STATUS_ERROR
) {
7561 UCHAR interruptReason
;
7563 GetBaseStatus(chan
, statusByte
);
7564 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on cmd: (%#x)\n", statusByte
));
7566 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
7567 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: iReason %x\n", interruptReason
));
7569 // TODO: we should check interruptReason and decide what to do now
7571 // Read the error reg. to clear it and fail this request.
7572 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7573 return MapError(deviceExtension
, Srb
);
7575 /* if(statusByte & IDE_STATUS_DSC) {
7576 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DSC on cmd: (%#x)\n", statusByte));
7577 // Read the error reg. to clear it and fail this request.
7578 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7579 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte));
7580 if(statusByte >> 4) {
7581 GetBaseStatus(chan, statusByte);
7582 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7583 return MapError(deviceExtension, Srb);
7587 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
7588 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
7591 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
7593 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
7594 return SRB_STATUS_PENDING
;
7596 } // end AtapiSendCommand()
7603 Routine Description:
7604 Program ATA registers for IDE disk transfer.
7607 HwDeviceExtension - ATAPI driver storage.
7608 Srb - System request block.
7611 SRB status (pending if all goes well).
7616 ULONG check_point
= 0;
7617 #define SetCheckPoint(cp) { check_point = (cp) ; }
7619 #define SetCheckPoint(cp)
7625 IN PVOID HwDeviceExtension
,
7626 IN PSCSI_REQUEST_BLOCK Srb
,
7631 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
7634 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7639 PHW_LU_EXTENSION LunExt
;
7643 UCHAR statusByte
,errorByte
;
7644 ULONG status
= SRB_STATUS_INVALID_REQUEST
;
7647 PMODE_PARAMETER_HEADER modeData
;
7654 //ULONG __ebp__ = 0;
7656 SetCheckPoint(0x20);
7657 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
7662 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
7663 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
7664 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
7665 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
7666 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
7668 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
7669 Srb->SrbExtension));
7670 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
7673 SetCheckPoint(0x30);
7674 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7676 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
7678 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
7680 KdPrint2((PRINT_PREFIX
"** --- **\n"));
7682 lChannel
= GET_CHANNEL(Srb
);
7683 chan
= &(deviceExtension
->chan
[lChannel
]);
7684 //ldev = GET_LDEV(Srb);
7685 DeviceNumber
= GET_CDEV(Srb
);
7686 LunExt
= chan
->lun
[DeviceNumber
];
7688 SetCheckPoint(0x40);
7689 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
7690 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
7692 cdb
= (PCDB
)(Srb
->Cdb
);
7694 if(CmdAction
== CMD_ACTION_PREPARE
) {
7695 switch (Srb
->Cdb
[0]) {
7696 case SCSIOP_SERVICE_ACTION16
:
7697 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
7700 goto default_no_prep
;
7703 case SCSIOP_INQUIRY
: // now it requires device access
7705 case SCSIOP_READ_CAPACITY
:
7709 case SCSIOP_WRITE12
:
7711 case SCSIOP_WRITE16
:
7712 case SCSIOP_REQUEST_SENSE
:
7714 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
7720 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
7721 return SRB_STATUS_BUSY
;
7725 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
7726 switch (Srb
->Cdb
[0]) {
7727 case SCSIOP_INQUIRY
:
7729 KdPrint2((PRINT_PREFIX
7730 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
7731 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7732 // Filter out wrong TIDs.
7733 if ((Srb
->Lun
!= 0) ||
7734 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
7735 (Srb
->TargetId
>= deviceExtension
->NumberLuns
)) {
7737 KdPrint2((PRINT_PREFIX
7738 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
7739 // Indicate no device found at this address.
7740 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7745 KdPrint2((PRINT_PREFIX
7746 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
7747 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
7748 PIDENTIFY_DATA2 identifyData
= &(LunExt
->IdentifyData
);
7750 if (!(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7752 if(!CheckDevice(HwDeviceExtension
, lChannel
, DeviceNumber
, FALSE
)) {
7753 KdPrint2((PRINT_PREFIX
7754 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
7755 // Indicate no device found at this address.
7757 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7761 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, DeviceNumber
)) {
7762 KdPrint2((PRINT_PREFIX
7763 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
7764 // Indicate no device found at this address.
7765 UniataForgetDevice(chan
->lun
[DeviceNumber
]);
7767 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7772 // Zero INQUIRY data structure.
7773 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
7775 // Standard IDE interface only supports disks.
7776 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
7778 // Set the removable bit, if applicable.
7779 if (LunExt
->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
7780 KdPrint2((PRINT_PREFIX
7781 "RemovableMedia\n"));
7782 inquiryData
->RemovableMedia
= 1;
7784 // Set the Relative Addressing (LBA) bit, if applicable.
7785 if (LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
7786 inquiryData
->RelativeAddressing
= 1;
7787 KdPrint2((PRINT_PREFIX
7788 "RelativeAddressing\n"));
7790 // Set the CommandQueue bit
7791 inquiryData
->CommandQueue
= 1;
7793 // Fill in vendor identification fields.
7794 for (i
= 0; i
< 24; i
+= 2) {
7795 MOV_DW_SWP(inquiryData
->DeviceIdentificationString
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
7798 // Initialize unused portion of product id.
7799 for (i = 0; i < 4; i++) {
7800 inquiryData->ProductId[12+i] = ' ';
7803 // Move firmware revision from IDENTIFY data to
7804 // product revision in INQUIRY data.
7805 for (i
= 0; i
< 4; i
+= 2) {
7806 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
7809 status
= SRB_STATUS_SUCCESS
;
7814 case SCSIOP_REPORT_LUNS
: {
7817 PREPORT_LUNS_INFO_HDR LunInfo
;
7819 KdPrint2((PRINT_PREFIX
7820 "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
7821 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7823 MOV_DD_SWP(alen
, cdb
->REPORT_LUNS
.AllocationLength
);
7830 LunInfo
= (PREPORT_LUNS_INFO_HDR
)(Srb
->DataBuffer
);
7831 RtlZeroMemory(LunInfo
, 16);
7833 MOV_DD_SWP( LunInfo
->ListLength
, alen
);
7834 Srb
->DataTransferLength
= 16;
7835 status
= SRB_STATUS_SUCCESS
;
7839 case SCSIOP_MODE_SENSE
:
7841 KdPrint2((PRINT_PREFIX
7842 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
7843 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7845 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_POWER_CONDITION
) {
7846 PMODE_POWER_CONDITION_PAGE modeData
;
7848 KdPrint2((PRINT_PREFIX
"MODE_PAGE_POWER_CONDITION\n"));
7849 modeData
= (PMODE_POWER_CONDITION_PAGE
)(Srb
->DataBuffer
);
7850 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_POWER_CONDITION_PAGE
)) {
7851 status
= SRB_STATUS_DATA_OVERRUN
;
7853 RtlZeroMemory(modeData
, sizeof(MODE_POWER_CONDITION_PAGE
));
7854 modeData
->PageCode
= MODE_PAGE_POWER_CONDITION
;
7855 modeData
->PageLength
= sizeof(MODE_POWER_CONDITION_PAGE
)-sizeof(MODE_PARAMETER_HEADER
);
7856 modeData
->Byte3
.Fields
.Idle
= LunExt
->PowerState
<= StartStop_Power_Idle
;
7857 modeData
->Byte3
.Fields
.Standby
= LunExt
->PowerState
== StartStop_Power_Standby
;
7858 Srb
->DataTransferLength
= sizeof(MODE_POWER_CONDITION_PAGE
);
7859 status
= SRB_STATUS_SUCCESS
;
7862 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_CACHING
) {
7863 PMODE_CACHING_PAGE modeData
;
7865 KdPrint2((PRINT_PREFIX
"MODE_PAGE_CACHING\n"));
7866 modeData
= (PMODE_CACHING_PAGE
)(Srb
->DataBuffer
);
7867 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_CACHING_PAGE
)) {
7868 status
= SRB_STATUS_DATA_OVERRUN
;
7870 RtlZeroMemory(modeData
, sizeof(MODE_CACHING_PAGE
));
7871 modeData
->PageCode
= MODE_PAGE_CACHING
;
7872 modeData
->PageLength
= sizeof(MODE_CACHING_PAGE
)-sizeof(MODE_PARAMETER_HEADER
);
7873 modeData
->ReadDisableCache
= (LunExt
->DeviceFlags
& DFLAGS_RCACHE_ENABLED
) ? 0 : 1;
7874 modeData
->WriteCacheEnable
= (LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) ? 1 : 0;
7875 Srb
->DataTransferLength
= sizeof(MODE_CACHING_PAGE
);
7876 status
= SRB_STATUS_SUCCESS
;
7879 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
7881 // This is used to determine if the media is write-protected.
7882 // Since IDE does not support mode sense then we will modify just the portion we need
7883 // so the higher level driver can determine if media is protected.
7885 //SelectDrive(chan, DeviceNumber);
7886 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7887 //statusByte = WaitOnBusy(chan);
7888 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
7890 if (!(statusByte
& IDE_STATUS_ERROR
)) {
7892 // no error occured return success, media is not protected
7893 UniataExpectChannelInterrupt(chan
, FALSE
);
7894 InterlockedExchange(&(chan
->CheckIntr
),
7896 status
= SRB_STATUS_SUCCESS
;
7900 // error occured, handle it locally, clear interrupt
7901 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7903 GetBaseStatus(chan
, statusByte
);
7904 UniataExpectChannelInterrupt(chan
, FALSE
);
7905 InterlockedExchange(&(chan
->CheckIntr
),
7907 status
= SRB_STATUS_SUCCESS
;
7909 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
7911 //media is write-protected, set bit in mode sense buffer
7912 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
7914 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
7915 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
7918 status
= SRB_STATUS_SUCCESS
;
7920 status
= SRB_STATUS_INVALID_REQUEST
;
7924 case SCSIOP_TEST_UNIT_READY
:
7926 KdPrint2((PRINT_PREFIX
7927 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
7928 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7929 if (chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
7931 // Select device 0 or 1.
7932 //SelectDrive(chan, DeviceNumber);
7933 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7934 // Wait for busy. If media has not changed, return success
7935 //statusByte = WaitOnBusy(chan);
7936 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
7938 if (!(statusByte
& IDE_STATUS_ERROR
)){
7939 UniataExpectChannelInterrupt(chan
, FALSE
);
7940 InterlockedExchange(&(chan
->CheckIntr
),
7942 status
= SRB_STATUS_SUCCESS
;
7944 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7945 if (errorByte
== IDE_ERROR_DATA_ERROR
){
7947 // Special case: If current media is write-protected,
7948 // the 0xDA command will always fail since the write-protect bit
7949 // is sticky,so we can ignore this error
7950 GetBaseStatus(chan
, statusByte
);
7951 UniataExpectChannelInterrupt(chan
, FALSE
);
7952 InterlockedExchange(&(chan
->CheckIntr
),
7954 status
= SRB_STATUS_SUCCESS
;
7958 // Request sense buffer to be build
7959 UniataExpectChannelInterrupt(chan
, TRUE
);
7960 InterlockedExchange(&(chan
->CheckIntr
),
7962 status
= SRB_STATUS_PENDING
;
7966 status
= SRB_STATUS_SUCCESS
;
7971 case SCSIOP_READ_CAPACITY
:
7973 KdPrint2((PRINT_PREFIX
7974 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7975 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7976 // Claim 512 byte blocks (big-endian).
7977 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7979 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY_DATA
));
7980 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
7982 // Calculate last sector.
7983 if(!(i
= (ULONG
)LunExt
->NumOfSectors
)) {
7984 i
= LunExt
->IdentifyData
.SectorsPerTrack
*
7985 LunExt
->IdentifyData
.NumberOfHeads
*
7986 LunExt
->IdentifyData
.NumberOfCylinders
;
7990 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
7991 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
7992 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
7994 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
7996 KdPrint2((PRINT_PREFIX
7997 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
7999 LunExt
->IdentifyData
.SectorsPerTrack
,
8000 LunExt
->IdentifyData
.NumberOfHeads
,
8001 LunExt
->IdentifyData
.NumberOfCylinders
));
8004 status
= SRB_STATUS_SUCCESS
;
8007 case SCSIOP_SERVICE_ACTION16
:
8009 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
8010 KdPrint2((PRINT_PREFIX
8011 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
8012 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8013 // Claim 512 byte blocks (big-endian).
8014 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
8016 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY16_DATA
));
8017 MOV_DD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
8019 // Calculate last sector.
8020 if(!(lba
= LunExt
->NumOfSectors
)) {
8021 lba
= LunExt
->IdentifyData
.SectorsPerTrack
*
8022 LunExt
->IdentifyData
.NumberOfHeads
*
8023 LunExt
->IdentifyData
.NumberOfCylinders
;
8026 MOV_QD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, lba
);
8028 KdPrint2((PRINT_PREFIX
8029 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n",
8031 LunExt
->IdentifyData
.SectorsPerTrack
,
8032 LunExt
->IdentifyData
.NumberOfHeads
,
8033 LunExt
->IdentifyData
.NumberOfCylinders
));
8035 status
= SRB_STATUS_SUCCESS
;
8042 case SCSIOP_VERIFY12
:
8043 case SCSIOP_VERIFY16
:
8045 KdPrint2((PRINT_PREFIX
8046 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
8047 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8048 status
= IdeVerify(HwDeviceExtension
,Srb
);
8055 case SCSIOP_WRITE12
:
8057 case SCSIOP_WRITE16
:
8059 KdPrint2((PRINT_PREFIX
8060 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
8061 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
8062 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8063 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
8064 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
8065 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
8066 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
8067 status
= IdeReadWrite(HwDeviceExtension
,
8071 case SCSIOP_START_STOP_UNIT
:
8073 KdPrint2((PRINT_PREFIX
8074 "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
8075 cdb
->START_STOP
.Immediate
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8076 //Determine what type of operation we should perform
8080 if(cdb
->START_STOP
.FL
||
8081 cdb
->START_STOP
.FormatLayerNumber
||
8082 cdb
->START_STOP
.Reserved2
||
8083 cdb
->START_STOP
.Reserved2_2
||
8084 cdb
->START_STOP
.Reserved3
||
8089 if (cdb
->START_STOP
.PowerConditions
) {
8090 KdPrint2((PRINT_PREFIX
"START_STOP Power %d\n", cdb
->START_STOP
.PowerConditions
));
8091 switch(cdb
->START_STOP
.PowerConditions
) {
8092 case StartStop_Power_Idle
:
8093 command
= IDE_COMMAND_IDLE_IMMED
;
8095 case StartStop_Power_Standby
:
8096 command
= IDE_COMMAND_STANDBY_IMMED
;
8098 case StartStop_Power_Sleep
:
8099 // TODO: we should save power state in order to know
8100 // that RESET sould be issued to revert device into
8103 command
= IDE_COMMAND_SLEEP
;
8108 LunExt
->PowerState
= cdb
->START_STOP
.PowerConditions
;
8110 if (cdb
->START_STOP
.LoadEject
== 1) {
8111 KdPrint2((PRINT_PREFIX
"START_STOP eject\n"));
8113 // first select device 0 or 1.
8114 //SelectDrive(chan, DeviceNumber);
8115 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
8116 command
= IDE_COMMAND_MEDIA_EJECT
;
8118 if (cdb
->START_STOP
.Start
== 0) {
8119 KdPrint2((PRINT_PREFIX
"START_STOP standby\n"));
8120 command
= IDE_COMMAND_STANDBY_IMMED
;
8122 // TODO: we may need to perform hard reset (after sleep) or
8123 // issue IDE_COMMAND_IDLE_IMMED in order to activate device
8124 KdPrint2((PRINT_PREFIX
"START_STOP activate\n"));
8126 if(LunExt
->PowerState
== StartStop_Power_Sleep
) {
8127 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
8128 status
= SRB_STATUS_SUCCESS
;
8131 if(LunExt
->PowerState
> StartStop_Power_Idle
) {
8132 KdPrint2((PRINT_PREFIX
" issue IDLE\n"));
8133 command
= IDE_COMMAND_IDLE_IMMED
;
8135 KdPrint2((PRINT_PREFIX
" do nothing\n"));
8136 status
= SRB_STATUS_SUCCESS
;
8141 statusByte
= WaitOnBaseBusy(chan
);
8142 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, command
, 0, 0, 0, 0, 0,
8143 cdb
->START_STOP
.Immediate
? ATA_IMMEDIATE
: ATA_WAIT_READY
);
8144 status
= (statusByte
& IDE_STATUS_ERROR
) ? SRB_STATUS_ERROR
: SRB_STATUS_SUCCESS
;
8145 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
8149 KdPrint2((PRINT_PREFIX
"START_STOP invalid\n"));
8150 if (Srb
->SenseInfoBuffer
) {
8152 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8154 senseBuffer
->ErrorCode
= 0x70;
8155 senseBuffer
->Valid
= 1;
8156 senseBuffer
->AdditionalSenseLength
= 0xb;
8157 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
8158 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_CDB
;
8159 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8161 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8162 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8164 status
= SRB_STATUS_ERROR
;
8168 case SCSIOP_MEDIUM_REMOVAL
:
8170 cdb
= (PCDB
)Srb
->Cdb
;
8172 if(LunExt
->IdentifyData
.Removable
) {
8173 statusByte
= WaitOnBaseBusy(chan
);
8175 //SelectDrive(chan, DeviceNumber);
8176 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
8177 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
8178 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_LOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8180 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
8181 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_UNLOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8183 status
= SRB_STATUS_SUCCESS
;
8185 status
= SRB_STATUS_INVALID_REQUEST
;
8190 // Note: I don't implement this, because NTFS driver too often issues this command
8191 // It causes awful performance degrade. However, if somebody wants, I will implement
8192 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
8193 case SCSIOP_FLUSH_BUFFER
:
8194 case SCSIOP_SYNCHRONIZE_CACHE
:
8196 SelectDrive(chan
, DeviceNumber
);
8197 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
8198 status
= SRB_STATUS_SUCCESS
;
8199 // status = SRB_STATUS_PENDING;
8200 statusByte
= WaitOnBusy(chan
);
8204 case SCSIOP_REQUEST_SENSE
:
8205 // this function makes sense buffers to report the results
8206 // of the original GET_MEDIA_STATUS command
8208 KdPrint2((PRINT_PREFIX
8209 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8210 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8211 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8212 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
8215 status
= SRB_STATUS_INVALID_REQUEST
;
8219 case SCSIOP_ATA_PASSTHROUGH
:
8222 BOOLEAN use_dma
= FALSE
;
8225 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
8227 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
8228 //lChannel = Srb->TargetId >> 1;
8230 DeviceNumber
= max(DeviceNumber
, 1);
8231 regs
->bDriveHeadReg
&= 0x0f;
8232 regs
->bDriveHeadReg
|= (UCHAR
) (((DeviceNumber
& 0x1) << 4) | 0xA0);
8235 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
8237 KdPrint2((PRINT_PREFIX
8238 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
8239 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8241 if((regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) == UNIATA_SPTI_EX_SPEC_TO
) {
8242 to_lim
= Srb
->TimeOutValue
;
8244 if(Srb
->TimeOutValue
<= 2) {
8245 to_lim
= Srb
->TimeOutValue
*900;
8247 to_lim
= (Srb
->TimeOutValue
*999) - 500;
8251 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8253 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
8255 statusByte
= UniataAhciSendPIOCommandDirect(
8264 if(statusByte
== IDE_STATUS_WRONG
) {
8265 goto passthrough_err
;
8267 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8268 UniataAhciAbortOperation(chan
);
8269 goto passthrough_err
;
8271 goto passthrough_done
;
8275 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
8276 if((chan
->lun
[DeviceNumber
]->LimitedTransferMode
>= ATA_DMA
)) {
8278 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
8279 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
8280 (PUCHAR
)(Srb
->DataBuffer
),
8281 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
8287 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
8288 AtapiStallExecution(10);
8290 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
8291 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8292 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8293 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8294 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8295 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8297 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
8298 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8299 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
8300 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8301 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
8302 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8303 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
8304 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8305 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
8306 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8308 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
8311 GetBaseStatus(chan
, statusByte
);
8312 if(statusByte
& IDE_STATUS_ERROR
) {
8313 goto passthrough_err
;
8315 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
8318 ScsiPortStallExecution(1); // wait for busy to be set
8320 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
8321 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
8322 GetBaseStatus(chan
, statusByte
);
8323 if(statusByte
& IDE_STATUS_ERROR
) {
8326 if(!(statusByte
& IDE_STATUS_BUSY
)) {
8331 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
8333 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8334 goto passthrough_err
;
8338 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
8340 AtapiDmaDone(deviceExtension
, DeviceNumber
, lChannel
, NULL
);
8341 GetBaseStatus(chan
, statusByte
);
8343 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8344 AtapiSuckPort2(chan
);
8346 if (Srb
->SenseInfoBuffer
) {
8348 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8350 senseBuffer
->ErrorCode
= 0x70;
8351 senseBuffer
->Valid
= 1;
8352 senseBuffer
->AdditionalSenseLength
= 0xb;
8353 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
8354 senseBuffer
->AdditionalSenseCode
= 0;
8355 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8357 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8358 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8360 status
= SRB_STATUS_ERROR
;
8364 if (statusByte
& IDE_STATUS_DRQ
) {
8365 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
8367 (PUSHORT
) Srb
->DataBuffer
,
8368 Srb
->DataTransferLength
/ 2,
8370 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
8372 (PUSHORT
) Srb
->DataBuffer
,
8373 Srb
->DataTransferLength
/ 2,
8378 status
= SRB_STATUS_SUCCESS
;
8381 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8383 } else { // read task register
8386 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
8388 KdPrint2((PRINT_PREFIX
8389 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
8390 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8392 if((Srb
->DataTransferLength
>= sizeof(IDEREGS_EX
)) &&
8393 (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
)) {
8396 if(Srb
->DataTransferLength
>= sizeof(IDEREGS
)) {
8399 KdPrint2((PRINT_PREFIX
" buffer too small \n"));
8400 status
= SRB_STATUS_DATA_OVERRUN
;
8403 RtlZeroMemory(regs
, use48
? sizeof(IDEREGS_EX
) : sizeof(IDEREGS
));
8404 regs
->bOpFlags
= use48
? ATA_FLAGS_48BIT_COMMAND
: 0;
8405 UniataSnapAtaRegs(chan
, 0, regs
);
8407 status
= SRB_STATUS_SUCCESS
;
8414 KdPrint2((PRINT_PREFIX
8415 "IdeSendCommand: Unsupported command %#x\n",
8418 status
= SRB_STATUS_INVALID_REQUEST
;
8422 if(status
== SRB_STATUS_PENDING
) {
8423 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
8424 if(CmdAction
& CMD_ACTION_EXEC
) {
8425 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
8426 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
8429 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
8430 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8435 } // end IdeSendCommand()
8440 Routine Description:
8441 Enables disables media status notification
8444 HwDeviceExtension - ATAPI driver storage.
8451 IN PVOID HwDeviceExtension
,
8453 IN ULONG DeviceNumber
8456 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8458 UCHAR statusByte
,errorByte
;
8460 chan
= &(deviceExtension
->chan
[lChannel
]);
8461 SelectDrive(chan
, DeviceNumber
);
8463 if (EnableMSN
== TRUE
){
8465 // If supported enable Media Status Notification support
8466 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
8469 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8470 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8471 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8473 if (statusByte
& IDE_STATUS_ERROR
) {
8474 // Read the error register.
8475 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8477 KdPrint2((PRINT_PREFIX
8478 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
8482 chan
->lun
[DeviceNumber
]->DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
8483 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
8484 chan
->ReturningMediaStatus
= 0;
8489 } else { // end if EnableMSN == TRUE
8491 // disable if previously enabled
8492 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
8494 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8495 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8496 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8497 chan
->lun
[DeviceNumber
]->DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
8504 } // end IdeMediaStatus()
8509 Routine Description:
8511 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
8512 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
8515 HwDeviceExtension - ATAPI driver storage.
8516 Srb - System request block.
8520 SRB status (ALWAYS SUCCESS).
8525 IdeBuildSenseBuffer(
8526 IN PVOID HwDeviceExtension
,
8527 IN PSCSI_REQUEST_BLOCK Srb
8530 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8532 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
8533 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
8537 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
8539 senseBuffer
->ErrorCode
= 0x70;
8540 senseBuffer
->Valid
= 1;
8541 senseBuffer
->AdditionalSenseLength
= 0xb;
8542 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8543 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8544 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8545 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
8547 senseBuffer
->ErrorCode
= 0x70;
8548 senseBuffer
->Valid
= 1;
8549 senseBuffer
->AdditionalSenseLength
= 0xb;
8550 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8551 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8552 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8553 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
8555 senseBuffer
->ErrorCode
= 0x70;
8556 senseBuffer
->Valid
= 1;
8557 senseBuffer
->AdditionalSenseLength
= 0xb;
8558 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
8559 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
8560 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8561 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
8563 senseBuffer
->ErrorCode
= 0x70;
8564 senseBuffer
->Valid
= 1;
8565 senseBuffer
->AdditionalSenseLength
= 0xb;
8566 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
8567 senseBuffer
->AdditionalSenseCode
= 0;
8568 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8570 return SRB_STATUS_SUCCESS
;
8572 return SRB_STATUS_ERROR
;
8574 }// End of IdeBuildSenseBuffer
8578 UniataUserDeviceReset(
8579 PHW_DEVICE_EXTENSION deviceExtension
,
8580 PHW_LU_EXTENSION LunExt
,
8585 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8586 if ((LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
8587 (LunExt
->PowerState
!= StartStop_Power_Sleep
)) {
8588 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
8589 AtapiSoftReset(&(deviceExtension
->chan
[lChannel
]), LunExt
->Lun
);
8591 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
8592 AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8593 for(i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
8594 deviceExtension
->chan
[lChannel
].lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
8597 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
8598 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8600 } // end UniataUserDeviceReset()
8605 PHW_DEVICE_EXTENSION deviceExtension
,
8610 BOOLEAN PostReq
= FALSE
;
8612 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
8613 if(chan
->queue_depth
> 0) {
8616 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
8617 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
8618 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
8620 status
= SRB_STATUS_BUSY
;
8629 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
8633 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
8636 } // end UniataNeedQueueing()
8640 Routine Description:
8642 This routine is called from the SCSI port driver synchronized
8643 with the kernel to start an IO request.
8648 HwDeviceExtension - HBA miniport driver's adapter data storage
8649 Srb - IO request packet
8659 IN PVOID HwDeviceExtension
,
8660 IN PSCSI_REQUEST_BLOCK Srb
8663 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
8664 } // end AtapiStartIo()
8669 IN PVOID HwDeviceExtension
,
8670 IN PSCSI_REQUEST_BLOCK Srb
,
8674 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8677 PHW_LU_EXTENSION LunExt
;
8685 PSCSI_REQUEST_BLOCK tmpSrb
;
8686 BOOLEAN PostReq
= FALSE
;
8688 BOOLEAN commPort
= FALSE
;
8690 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
8691 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
8692 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
8693 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
8695 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
8697 /* KeBugCheckEx(0xc000000e,
8698 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8700 TopLevel, 0x80000001);
8702 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
8703 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
8704 //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
8705 UniAtaClearAtaReq(Srb
->SrbExtension
);
8708 do { // fetch all queued commands for the channel (if valid)
8710 lChannel
= GET_CHANNEL(Srb
);
8711 //ldev = GET_LDEV(Srb);
8714 DeviceNumber
= GET_CDEV(Srb
);
8717 //ASSERT(deviceExtension);
8720 KdPrint2((PRINT_PREFIX
8721 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8722 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8723 KdPrint2((PRINT_PREFIX
" VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
8725 if(lChannel
== deviceExtension
->NumberChannels
&&
8726 !Srb
->Lun
&& !Srb
->TargetId
&&
8727 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
8728 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
8730 // This is our virtual device
8731 KdPrint2((PRINT_PREFIX
8732 "AtapiStartIo: Communication port\n"));
8733 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
8735 if(Srb
->DataTransferLength
< sizeof(PINQUIRYDATA
)) {
8736 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", Srb
->DataTransferLength
,
8737 sizeof(PINQUIRYDATA
) ));
8739 status
= SRB_STATUS_DATA_OVERRUN
;
8743 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
8745 KdPrint2((PRINT_PREFIX
8747 // Zero INQUIRY data structure.
8748 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
8750 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
8752 // Fill in vendor identification fields.
8753 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
8755 status
= SRB_STATUS_SUCCESS
;
8759 /* Pass IOCTL request down */
8761 if(lChannel
>= deviceExtension
->NumberChannels
||
8762 Srb
->TargetId
/*DeviceNumber*/ >= deviceExtension
->NumberLuns
||
8765 if(lChannel
>= deviceExtension
->NumberChannels
) {
8770 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8771 KdPrint3((PRINT_PREFIX
8772 "AtapiStartIo: SRB rejected\n"));
8773 // Indicate no device found at this address.
8774 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
8775 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8779 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
8780 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
8785 chan
= &(deviceExtension
->chan
[lChannel
]);
8786 LunExt
= chan
->lun
[DeviceNumber
];
8790 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
8796 if(!commPort
&& !LunExt
) {
8798 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
8801 deviceExtension
->NumberChannels
);
8802 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
8803 lChannel
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
8804 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8805 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
8809 for(i=0; i<1000; i++) {
8810 AtapiStallExecution(3*1000);
8817 // Determine which function.
8818 switch (Srb
->Function
) {
8820 case SRB_FUNCTION_EXECUTE_SCSI
:
8822 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8823 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
8824 // let passthrough go
8826 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
8830 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8831 KdPrint2((PRINT_PREFIX
8832 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
8833 // Indicate no device found at this address.
8834 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
8835 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8840 KdPrint2((PRINT_PREFIX
8841 " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb
, &(Srb
->Cdb
), Srb
->SrbExtension
, Srb
->Cdb
[0]));
8845 if(Srb->DataTransferLength) {
8847 a = ((PUCHAR)(Srb->DataBuffer))[0];
8850 } __except(EXCEPTION_EXECUTE_HANDLER) {
8851 KdPrint3((PRINT_PREFIX
8852 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
8853 // Indicate no device found at this address.
8854 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
8855 status = SRB_STATUS_ERROR;
8856 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
8861 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
8865 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
8867 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
8868 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
8870 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
8872 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
8873 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
8875 /*KeBugCheckEx(0xc000000e,
8876 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8878 status, 0x80000001);*/
8879 if(status
== SRB_STATUS_BUSY
)
8880 status
= SRB_STATUS_PENDING
;
8881 // Insert requests AFTER they have been initialized on
8882 // CMD_ACTION_PREPARE stage
8883 // we should not check TopLevel here (it is always TRUE)
8884 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8885 UniataQueueRequest(chan
, Srb
);
8887 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
8891 // Send command to device.
8892 KdPrint2((PRINT_PREFIX
"Send to device %x\n", Srb
->Cdb
[0]));
8894 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
8895 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8896 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
8897 //ASSERT(!AtaReq->Flags);
8898 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8899 UniataQueueRequest(chan
, Srb
);
8900 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
8901 //ASSERT(!AtaReq->Flags);
8902 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
8903 //ASSERT(!AtaReq->Flags);
8907 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8911 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
8912 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, DeviceNumber
)) {
8913 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, DeviceNumber
, TRUE
)) {
8917 if(!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8921 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
8930 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)/* &&
8931 (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
8932 KdPrint3((PRINT_PREFIX
"Try ATAPI send %x\n", Srb
->Cdb
[0]));
8933 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
8935 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
8940 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
8947 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
8949 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
8951 /* KeBugCheckEx(0xc000000e,
8952 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8954 status, 0x80000002);*/
8962 case SRB_FUNCTION_ABORT_COMMAND
:
8964 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
8966 // Verify that SRB to abort is still outstanding.
8967 if((tmpSrb
!= Srb
->NextSrb
) ||
8968 !chan
->queue_depth
) {
8970 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
8972 // Complete abort SRB.
8973 status
= SRB_STATUS_ABORT_FAILED
;
8977 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
8978 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
8979 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
8980 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
8981 // Log reset failure.
8982 KdPrint3((PRINT_PREFIX
8983 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
8984 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
8986 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
8987 status
= SRB_STATUS_ERROR
;
8990 status
= SRB_STATUS_SUCCESS
;
8993 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
8994 if (tmpSrb
->SenseInfoBuffer
&&
8995 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
8997 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
8999 senseBuffer
->ErrorCode
= 0;
9000 senseBuffer
->Valid
= 1;
9001 senseBuffer
->AdditionalSenseLength
= 0xb;
9002 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
9003 senseBuffer
->AdditionalSenseCode
= 0;
9004 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
9006 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
9008 AtapiDmaDBSync(chan
, tmpSrb
);
9009 UniataRemoveRequest(chan
, tmpSrb
);
9010 // Indicate command complete.
9011 ScsiPortNotification(RequestComplete
,
9014 status
= SRB_STATUS_SUCCESS
;
9018 // Abort function indicates that a request timed out.
9019 // Call reset routine. Card will only be reset if
9020 // status indicates something is wrong.
9021 // Fall through to reset code.
9023 case SRB_FUNCTION_RESET_DEVICE
:
9024 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
9026 // Reset single device.
9027 // For now we support only Lun=0
9029 // Note: reset is immediate command, it cannot be queued since it is usually used to
9030 // revert not-responding device to operational state
9031 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
9032 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
9033 status
= SRB_STATUS_SUCCESS
;
9036 case SRB_FUNCTION_RESET_BUS
:
9038 // Reset Atapi and SCSI bus.
9040 // Note: reset is immediate command, it cannot be queued since it is usually used to
9041 // revert not- responding device to operational state
9042 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
9043 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
9044 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
9045 // Log reset failure.
9046 KdPrint3((PRINT_PREFIX
9047 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
9048 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
9050 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
9051 status
= SRB_STATUS_ERROR
;
9054 status
= SRB_STATUS_SUCCESS
;
9059 case SRB_FUNCTION_SHUTDOWN
:
9061 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
9062 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9063 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
9066 // FLUSH ATAPI device - do nothing
9067 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
9069 // FLUSH IDE/ATA device
9070 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
9071 AtapiDisableInterrupts(deviceExtension
, lChannel
);
9072 status
= AtaCommand(deviceExtension
, DeviceNumber
, GET_CHANNEL(Srb
),
9073 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
9074 // If supported & allowed, reset write cacheing
9075 if(LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
9077 // Disable write cache
9078 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9079 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9080 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
9081 // Check for errors.
9082 if (status
& IDE_STATUS_ERROR
) {
9083 KdPrint2((PRINT_PREFIX
9084 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
9087 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9089 // Re-enable write cache
9090 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9091 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9092 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
9093 // Check for errors.
9094 if (status
& IDE_STATUS_ERROR
) {
9095 KdPrint2((PRINT_PREFIX
9096 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
9098 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9100 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
9104 AtapiEnableInterrupts(deviceExtension
, lChannel
);
9106 status
= SRB_STATUS_SUCCESS
;
9110 case SRB_FUNCTION_FLUSH
:
9112 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
9113 status
= SRB_STATUS_SUCCESS
;
9116 case SRB_FUNCTION_IO_CONTROL
: {
9120 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
9122 len
= Srb
->DataTransferLength
;
9124 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
9126 ULONG targetId
= (ULONG
)(-1);
9128 if(len
< sizeof(SRB_IO_CONTROL
)) {
9129 goto wrong_buffer_size
;
9132 // extract bogus bus address
9133 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9134 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9135 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9137 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(GETVERSIONINPARAMS
)) {
9138 goto wrong_buffer_size
;
9141 targetId
= versionParameters
->bIDEDeviceMap
;
9142 KdPrint2((PRINT_PREFIX
"targetId (smart ver) %d\n", targetId
));
9144 case IOCTL_SCSI_MINIPORT_IDENTIFY
:
9145 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
9146 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
9147 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
9148 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
9149 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
9150 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
9151 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
9152 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
9153 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE
:
9154 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG
:
9155 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG
:
9157 PSENDCMDINPARAMS cmdInParameters
= (PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9159 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDINPARAMS
) - 1) {
9160 goto wrong_buffer_size
;
9163 targetId
= cmdInParameters
->bDriveNumber
;
9164 KdPrint2((PRINT_PREFIX
"targetId (smart/ident) %d\n", targetId
));
9168 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9169 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
9170 status
= SRB_STATUS_INVALID_REQUEST
;
9174 // adjust (if necessary) bus address
9175 if(targetId
!= (ULONG
)(-1)) {
9177 // This is done because of how the IOCTL_SCSI_MINIPORT
9178 // determines 'targetid's'. Disk.sys places the real target id value
9179 // in the DeviceMap field. Once we do some parameter checking, the value passed
9180 // back to the application will be determined.
9182 if (deviceExtension
->NumberChannels
== 1) {
9183 // do this for legacy controllers and legacy callers
9184 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call\n"));
9185 DeviceNumber
= (targetId
& 0x01);
9189 // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
9190 // due to DISK.SYS design bug, we have invalid SCSI address in SRB
9191 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call (2)\n"));
9192 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
9193 lChannel
= (UCHAR
)targetId
/ 2;
9196 lChannel
= (UCHAR
)(targetId
/ 2);
9197 DeviceNumber
= targetId
& 0x01;
9200 // otherwise assume lChannel and DeviceNumber from Srb are ok
9202 if(lChannel
>= deviceExtension
->NumberChannels
||
9203 DeviceNumber
>= deviceExtension
->NumberLuns
) {
9204 KdPrint2((PRINT_PREFIX
9205 "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
9207 // Indicate no device found at this address.
9210 targetId
= lChannel
*deviceExtension
->NumberLuns
+DeviceNumber
;
9211 chan
= &(deviceExtension
->chan
[lChannel
]);
9212 LunExt
= chan
->lun
[DeviceNumber
];
9216 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
9218 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9223 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9224 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9226 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9227 UCHAR deviceNumberMap
;
9229 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
9231 // Version and revision per SMART 1.03
9233 versionParameters
->bVersion
= 1;
9234 versionParameters
->bRevision
= 1;
9235 versionParameters
->bReserved
= 0;
9237 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
9238 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
9241 goto invalid_request
;
9244 // NOTE: This will only set the bit
9245 // corresponding to this drive's target id.
9246 // The bit mask is as follows:
9252 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
9253 deviceNumberMap
= 1 << lChannel
;
9256 if (deviceExtension
->NumberChannels
== 1) {
9257 if (chan
->PrimaryAddress
) {
9258 deviceNumberMap
= 1 << DeviceNumber
;
9260 deviceNumberMap
= 4 << DeviceNumber
;
9263 deviceNumberMap
= 1 << (DeviceNumber
+lChannel
*2);
9266 versionParameters
->bIDEDeviceMap
= deviceNumberMap
;
9268 status
= SRB_STATUS_SUCCESS
;
9272 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
9274 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9275 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9277 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
9278 // Extract the target.
9279 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
9281 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
9284 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
9285 goto invalid_request
;
9291 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
9292 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
9293 goto invalid_request
;
9296 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
9297 // Zero the output buffer
9298 RtlZeroMemory(cmdOutParameters
, len
);
9299 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
9300 ((PUCHAR)cmdOutParameters)[i] = 0;
9303 // Build status block.
9304 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
9305 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
9306 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
9308 // Extract the identify data from the device extension.
9309 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &(LunExt
->IdentifyData
),
9310 cmdOutParameters
->cBufferSize
);
9312 if((cmdOutParameters
->cBufferSize
== IDENTIFY_BUFFER_SIZE
) &&
9313 (LunExt
->IdentifyData
.ChecksumValid
== ATA_ChecksumValid
)) {
9314 // adjust checksum if it is possible
9318 for(i
=0; i
< IDENTIFY_BUFFER_SIZE
-1; i
++) {
9319 csum
+= (CHAR
)(cmdOutParameters
->bBuffer
[i
]);
9321 cmdOutParameters
->bBuffer
[i
] = -csum
;
9322 KdPrint2((PRINT_PREFIX
"AtapiStartIo: adjust checksum %d\n"));
9324 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
9326 status
= SRB_STATUS_SUCCESS
;
9330 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
9331 cmdInParameters
.irDriveRegs
.bCommandReg
));
9332 status
= SRB_STATUS_INVALID_REQUEST
;
9338 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9339 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9340 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9341 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9342 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9343 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9344 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9345 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9348 // *all* IOCTLs here are SMART
9350 KdPrint2((PRINT_PREFIX
9351 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
9354 goto invalid_request
;
9357 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9359 if(PostReq
|| TopLevel
) {
9360 UniataQueueRequest(chan
, Srb
);
9361 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9362 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9367 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
9368 status
= SRB_STATUS_PENDING
;
9370 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9373 status
= IdeSendSmartCommand(HwDeviceExtension
, Srb
, targetId
);
9377 // we should not get here, checked above
9379 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9380 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9381 status = SRB_STATUS_INVALID_REQUEST;
9386 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
9388 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
9389 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
9390 ULONG DeviceNumber
= AtaCtl
->addr
.TargetId
;
9394 pos
= FIELD_OFFSET(UNIATA_CTL
, RawData
);
9395 //chan = &(deviceExtension->chan[lChannel]);
9397 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9398 FIELD_OFFSET(UNIATA_CTL
, RawData
) ));
9399 goto wrong_buffer_size
;
9402 if(AtaCtl
->addr
.Lun
||
9403 AtaCtl
->addr
.TargetId
>= deviceExtension
->NumberLuns
||
9404 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
9412 lChannel
= AtaCtl
->addr
.PathId
;
9413 chan
= &(deviceExtension
->chan
[lChannel
]);
9414 LunExt
= chan
->lun
[DeviceNumber
];
9417 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl
->hdr
.ControlCode
, DeviceNumber
));
9419 /* check for valid LUN */
9420 switch (AtaCtl
->hdr
.ControlCode
) {
9421 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9422 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
9423 // this would be BUS reset
9425 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
9426 AtaCtl
->addr
.TargetId
!= 0xff ||
9427 AtaCtl
->addr
.Lun
!= 0
9429 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
9430 DeviceNumber
< deviceExtension
->NumberLuns
) { // AtaCtl->addr.TargetId != 0xff
9431 lChannel
= AtaCtl
->addr
.PathId
;
9432 chan
= &(deviceExtension
->chan
[lChannel
]);
9433 LunExt
= chan
->lun
[DeviceNumber
];
9436 goto handle_bad_ldev
;
9439 lChannel
= AtaCtl
->addr
.PathId
;
9440 chan
= &(deviceExtension
->chan
[lChannel
]);
9443 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
9444 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9445 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
9446 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9447 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
9450 KdPrint2((PRINT_PREFIX
9451 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
9452 // Indicate no device found at this address.
9457 /* check if queueing is necessary */
9458 switch (AtaCtl
->hdr
.ControlCode
) {
9459 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9460 if(!LunExt
->nBadBlocks
) {
9463 goto uata_ctl_queue
;
9464 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9465 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9466 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9467 pos
+sizeof(AtaCtl
->SetMode
) ));
9468 goto wrong_buffer_size
;
9470 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
9473 goto uata_ctl_queue
;
9474 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9475 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
9477 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
9478 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9480 if(PostReq
|| TopLevel
) {
9481 UniataQueueRequest(chan
, Srb
);
9482 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9483 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9486 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
9487 status
= SRB_STATUS_PENDING
;
9489 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9492 } // end switch (AtaCtl->hdr.ControlCode)
9494 /* process request */
9495 switch (AtaCtl
->hdr
.ControlCode
) {
9496 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9498 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
9500 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9501 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9502 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9503 goto wrong_buffer_size
;
9505 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
9506 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
9507 if(AtaCtl
->addr
.TargetId
!= 0xff) {
9508 LunExt
->DeviceFlags
&= ~DFLAGS_HIDDEN
;
9513 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9514 AtapiStallExecution(1000 * 1000);
9517 FindDevices(HwDeviceExtension
,
9518 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
9519 ? UNIATA_FIND_DEV_UNHIDE
: 0,
9520 AtaCtl
->addr
.PathId
);
9521 status
= SRB_STATUS_SUCCESS
;
9525 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
9527 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
9529 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9530 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9531 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9532 goto wrong_buffer_size
;
9534 LunExt
->DeviceFlags
= 0;
9535 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
9536 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
9537 //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
9538 UniataForgetDevice(LunExt
);
9541 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9542 AtapiStallExecution(1000 * 1000);
9545 status
= SRB_STATUS_SUCCESS
;
9548 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
9550 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
9552 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9553 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9554 pos
+sizeof(AtaCtl
->SetMode
) ));
9555 goto wrong_buffer_size
;
9557 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
9558 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
9560 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
9561 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
9562 if(LunExt
->LimitedTransferMode
>
9563 LunExt
->OrigTransferMode
) {
9564 // check for incorrect value
9565 LunExt
->LimitedTransferMode
=
9566 LunExt
->OrigTransferMode
;
9569 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
9571 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
9572 if(AtaCtl
->SetMode
.ApplyImmediately
) {
9573 AtapiDmaInit__(deviceExtension
, LunExt
);
9575 /* LunExt->TransferMode =
9576 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
9577 status
= SRB_STATUS_SUCCESS
;
9580 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
9582 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
9584 if(len
< pos
+sizeof(AtaCtl
->GetMode
)) {
9585 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9586 pos
+sizeof(AtaCtl
->GetMode
) ));
9587 goto wrong_buffer_size
;
9589 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
9590 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
9591 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
9592 AtaCtl
->GetMode
.PhyMode
= LunExt
->PhyTransferMode
;
9594 status
= SRB_STATUS_SUCCESS
;
9597 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION
: {
9599 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get version\n"));
9601 if(len
< pos
+sizeof(AtaCtl
->Version
)) {
9602 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9603 pos
+sizeof(AtaCtl
->Version
) ));
9604 goto wrong_buffer_size
;
9606 AtaCtl
->Version
.Length
= sizeof(GETDRVVERSION
);
9607 AtaCtl
->Version
.VersionMj
= UNIATA_VER_MJ
;
9608 AtaCtl
->Version
.VersionMn
= UNIATA_VER_MN
;
9609 AtaCtl
->Version
.SubVerMj
= UNIATA_VER_SUB_MJ
;
9610 AtaCtl
->Version
.SubVerMn
= UNIATA_VER_SUB_MN
;
9612 status
= SRB_STATUS_SUCCESS
;
9615 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
9617 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
9619 if(len
< pos
+sizeof(AtaCtl
->AdapterInfo
)) {
9620 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9621 pos
+sizeof(AtaCtl
->AdapterInfo
) ));
9622 goto wrong_buffer_size
;
9624 AtaCtl
->AdapterInfo
.HeaderLength
= sizeof(ADAPTERINFO
);
9626 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
9627 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
9628 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
9629 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
9630 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
9631 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
9632 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
9633 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
9634 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
9635 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
9636 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
9637 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
9638 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
9639 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
9640 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
9641 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
9642 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
9643 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
9644 AtaCtl
->AdapterInfo
.NumberLuns
= (UCHAR
)deviceExtension
->NumberLuns
;
9645 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
9646 if(deviceExtension
->FullDevName
) {
9647 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
9649 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
9650 AtaCtl
->AdapterInfo
.LunInfoValid
= FALSE
;
9651 AtaCtl
->AdapterInfo
.ChanHeaderLengthValid
= TRUE
;
9653 pos
+= AtaCtl
->AdapterInfo
.HeaderLength
;
9656 RtlZeroMemory(((PCHAR
)AtaCtl
)+pos
,
9659 if(len
>= pos
+AtaCtl
->AdapterInfo
.NumberChannels
*sizeof(CHANINFO
)) {
9660 PCHANINFO ChanInfo
= (PCHANINFO
)( ((PCHAR
)AtaCtl
)+pos
);
9661 PHW_CHANNEL cur_chan
;
9662 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Fill channel info\n"));
9663 for(i
=0;i
<AtaCtl
->AdapterInfo
.NumberChannels
;i
++) {
9664 KdPrint2((PRINT_PREFIX
"chan[%d] %x\n", i
, cur_chan
));
9665 cur_chan
= &(deviceExtension
->chan
[i
]);
9666 ChanInfo
->MaxTransferMode
= cur_chan
->MaxTransferMode
;
9667 ChanInfo
->ChannelCtrlFlags
= cur_chan
->ChannelCtrlFlags
;
9668 RtlCopyMemory(&(ChanInfo
->QueueStat
), &(cur_chan
->QueueStat
), sizeof(ChanInfo
->QueueStat
));
9669 ChanInfo
->ReorderCount
= cur_chan
->ReorderCount
;
9670 ChanInfo
->IntersectCount
= cur_chan
->IntersectCount
;
9671 ChanInfo
->TryReorderCount
= cur_chan
->TryReorderCount
;
9672 ChanInfo
->TryReorderHeadCount
= cur_chan
->TryReorderHeadCount
;
9673 ChanInfo
->TryReorderTailCount
= cur_chan
->TryReorderTailCount
;
9674 //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
9677 AtaCtl
->AdapterInfo
.ChanInfoValid
= TRUE
;
9678 AtaCtl
->AdapterInfo
.ChanHeaderLength
= sizeof(*ChanInfo
);
9681 status
= SRB_STATUS_SUCCESS
;
9684 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
9686 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
9688 ForgetBadBlocks(LunExt
);
9690 status
= SRB_STATUS_SUCCESS
;
9693 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
9695 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
9700 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
);
9703 status
= SRB_STATUS_SUCCESS
;
9707 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
9708 AtaCtl
->hdr
.ControlCode
));
9709 status
= SRB_STATUS_INVALID_REQUEST
;
9714 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
9715 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
9716 "SCSIDISK", "-UNIATA-"));
9718 status
= SRB_STATUS_INVALID_REQUEST
;
9723 } // end SRB_FUNCTION_IO_CONTROL
9726 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
9727 // Indicate unsupported command.
9728 status
= SRB_STATUS_INVALID_REQUEST
;
9736 PathId
= Srb
->PathId
;
9737 TargetId
= Srb
->TargetId
;
9740 if (status
!= SRB_STATUS_PENDING
) {
9742 KdPrint2((PRINT_PREFIX
9743 "AtapiStartIo: Srb %#x complete with status %#x\n",
9747 // Set status in SRB.
9748 Srb
->SrbStatus
= (UCHAR
)status
;
9751 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan
, Srb
));
9752 AtapiDmaDBSync(chan
, Srb
);
9754 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan
, Srb
));
9755 UniataRemoveRequest(chan
, Srb
);
9756 // Indicate command complete.
9757 KdPrint2((PRINT_PREFIX
"AtapiStartIo: ScsiPortNotification\n"));
9758 ScsiPortNotification(RequestComplete
,
9762 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataGetCurRequest\n"));
9763 // Remove current Srb & get next one
9764 if((Srb
= UniataGetCurRequest(chan
))) {
9765 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9766 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
9767 // current request is under precessing, thus
9768 // we should do nothing here
9772 KdPrint2((PRINT_PREFIX
"AtapiStartIo: chan %x, Src %x\n", chan
, Srb
));
9777 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
9779 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
9781 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
9782 // Indicate ready for next request.
9783 ScsiPortNotification(NextRequest
,
9787 ScsiPortNotification(NextLuRequest
,
9795 } // end AtapiStartIo__()
9800 UniataInitAtaCommands()
9806 KdPrint2((PRINT_PREFIX
"UniataInitAtaCommands:\n"));
9808 for(i
=0; i
<256; i
++) {
9813 //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
9816 case IDE_COMMAND_READ_DMA48
:
9817 case IDE_COMMAND_READ_DMA_Q48
:
9818 case IDE_COMMAND_READ_STREAM_DMA48
:
9819 case IDE_COMMAND_READ_STREAM48
:
9820 case IDE_COMMAND_WRITE_DMA48
:
9821 case IDE_COMMAND_WRITE_DMA_Q48
:
9822 case IDE_COMMAND_READ_DMA_Q
:
9823 case IDE_COMMAND_READ_DMA
:
9824 case IDE_COMMAND_WRITE_DMA
:
9825 case IDE_COMMAND_WRITE_DMA_Q
:
9826 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9827 case IDE_COMMAND_WRITE_STREAM48
:
9828 case IDE_COMMAND_WRITE_FUA_DMA48
:
9829 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9830 case IDE_COMMAND_READ_LOG_DMA48
:
9831 case IDE_COMMAND_WRITE_LOG_DMA48
:
9832 case IDE_COMMAND_TRUSTED_RCV_DMA
:
9833 case IDE_COMMAND_TRUSTED_SEND_DMA
:
9834 case IDE_COMMAND_DATA_SET_MGMT
:
9835 //KdPrint2((PRINT_PREFIX "DMA "));
9836 flags
|= ATA_CMD_FLAG_DMA
;
9840 case IDE_COMMAND_WRITE_FUA_DMA48
:
9841 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9842 case IDE_COMMAND_WRITE_MUL_FUA48
:
9844 flags
|= ATA_CMD_FLAG_FUA
;
9847 case IDE_COMMAND_READ48
:
9848 case IDE_COMMAND_READ_DMA48
:
9849 case IDE_COMMAND_READ_DMA_Q48
:
9850 case IDE_COMMAND_READ_MUL48
:
9851 case IDE_COMMAND_READ_STREAM_DMA48
:
9852 case IDE_COMMAND_READ_STREAM48
:
9853 case IDE_COMMAND_WRITE48
:
9854 case IDE_COMMAND_WRITE_DMA48
:
9855 case IDE_COMMAND_WRITE_DMA_Q48
:
9856 case IDE_COMMAND_WRITE_MUL48
:
9857 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9858 case IDE_COMMAND_WRITE_STREAM48
:
9859 case IDE_COMMAND_FLUSH_CACHE48
:
9860 case IDE_COMMAND_VERIFY48
:
9862 //KdPrint2((PRINT_PREFIX "48 "));
9863 flags
|= ATA_CMD_FLAG_48
;
9866 case IDE_COMMAND_READ
:
9867 case IDE_COMMAND_READ_MULTIPLE
:
9868 case IDE_COMMAND_READ_DMA
:
9869 case IDE_COMMAND_READ_DMA_Q
:
9870 case IDE_COMMAND_WRITE
:
9871 case IDE_COMMAND_WRITE_MULTIPLE
:
9872 case IDE_COMMAND_WRITE_DMA
:
9873 case IDE_COMMAND_WRITE_DMA_Q
:
9874 case IDE_COMMAND_FLUSH_CACHE
:
9875 case IDE_COMMAND_VERIFY
:
9877 //KdPrint2((PRINT_PREFIX "LBA "));
9878 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
9882 case IDE_COMMAND_READ_NATIVE_SIZE48
:
9883 case IDE_COMMAND_SET_NATIVE_SIZE48
:
9884 // we cannot set LBA flag for these commands to avoid BadBlock handling
9885 //flags |= ATA_CMD_FLAG_LBAIOsupp;
9886 flags
|= ATA_CMD_FLAG_48
;
9888 case IDE_COMMAND_READ_NATIVE_SIZE
:
9889 case IDE_COMMAND_SET_NATIVE_SIZE
:
9891 flags
|= ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_FUA
;
9894 flags
|= ATA_CMD_FLAG_48supp
;
9897 case IDE_COMMAND_READ
:
9898 command
= IDE_COMMAND_READ48
; break;
9899 case IDE_COMMAND_READ_MULTIPLE
:
9900 command
= IDE_COMMAND_READ_MUL48
; break;
9901 case IDE_COMMAND_READ_DMA
:
9902 command
= IDE_COMMAND_READ_DMA48
; break;
9903 case IDE_COMMAND_READ_DMA_Q
:
9904 command
= IDE_COMMAND_READ_DMA_Q48
; break;
9905 case IDE_COMMAND_WRITE
:
9906 command
= IDE_COMMAND_WRITE48
; break;
9907 case IDE_COMMAND_WRITE_MULTIPLE
:
9908 command
= IDE_COMMAND_WRITE_MUL48
; break;
9909 case IDE_COMMAND_WRITE_DMA
:
9910 command
= IDE_COMMAND_WRITE_DMA48
; break;
9911 case IDE_COMMAND_WRITE_DMA_Q
:
9912 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
9913 case IDE_COMMAND_FLUSH_CACHE
:
9914 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
9915 // case IDE_COMMAND_READ_NATIVE_SIZE:
9916 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
9917 case IDE_COMMAND_SET_NATIVE_SIZE
:
9918 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
9919 case IDE_COMMAND_VERIFY
:
9920 command
= IDE_COMMAND_VERIFY48
; break;
9922 //KdPrint2((PRINT_PREFIX "!28->48 "));
9923 flags
&= ~ATA_CMD_FLAG_48supp
;
9927 case IDE_COMMAND_READ
:
9928 case IDE_COMMAND_READ_MULTIPLE
:
9929 case IDE_COMMAND_READ_DMA48
:
9930 case IDE_COMMAND_READ_DMA_Q48
:
9931 case IDE_COMMAND_READ_STREAM_DMA48
:
9932 case IDE_COMMAND_READ_STREAM48
:
9933 case IDE_COMMAND_READ_DMA_Q
:
9934 case IDE_COMMAND_READ_DMA
:
9935 case IDE_COMMAND_READ_LOG_DMA48
:
9936 case IDE_COMMAND_TRUSTED_RCV_DMA
:
9937 case IDE_COMMAND_IDENTIFY
:
9938 case IDE_COMMAND_ATAPI_IDENTIFY
:
9939 //KdPrint2((PRINT_PREFIX "RD "));
9940 flags
|= ATA_CMD_FLAG_In
;
9942 case IDE_COMMAND_WRITE
:
9943 case IDE_COMMAND_WRITE_MULTIPLE
:
9944 case IDE_COMMAND_WRITE_DMA48
:
9945 case IDE_COMMAND_WRITE_DMA_Q48
:
9946 case IDE_COMMAND_WRITE_DMA
:
9947 case IDE_COMMAND_WRITE_DMA_Q
:
9948 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9949 case IDE_COMMAND_WRITE_STREAM48
:
9950 case IDE_COMMAND_WRITE_FUA_DMA48
:
9951 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9952 //KdPrint2((PRINT_PREFIX "WR "));
9953 flags
|= ATA_CMD_FLAG_Out
;
9957 //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
9958 AtaCommands48
[i
] = command
;
9959 AtaCommandFlags
[i
] = flags
;
9961 } // end UniataInitAtaCommands()
9965 Routine Description:
9967 Installable driver initialization entry point for system.
9975 Status from ScsiPortInitialize()
9982 IN PVOID DriverObject
,
9986 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
9989 ULONG statusToReturn
, newStatus
;
9990 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
9991 BOOLEAN ReEnter
= FALSE
;
9993 #ifndef USE_REACTOS_DDK
9997 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
9998 BOOLEAN PrimaryClaimed
= FALSE
;
9999 BOOLEAN SecondaryClaimed
= FALSE
;
10001 LARGE_INTEGER t0
, t1
;
10003 Connect_DbgPrint();
10004 KdPrint2((PRINT_PREFIX
"%s", (PCCHAR
)ver_string
));
10005 //a = (WCHAR)strlen(ver_string);
10007 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
10008 if(g_opt_Verbose
) {
10009 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
10012 if(!SavedDriverObject
) {
10013 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
10014 #ifdef USE_REACTOS_DDK
10015 KdPrint(("UniATA Init: OS should be ReactOS\n"));
10020 // we are here for the 1st time
10021 // init CrossNT and get OS version
10022 if(!NT_SUCCESS(status
= CrNtInit(SavedDriverObject
, RegistryPath
))) {
10023 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status
));
10024 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
10027 #endif // USE_REACTOS_DDK
10028 KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion
, MinorVersion
, BuildNumber
, KeNumberProcessors
));
10030 KeQuerySystemTime(&t0
);
10032 KeQuerySystemTime(&t1
);
10033 } while(t0
.QuadPart
== t1
.QuadPart
);
10037 KeQuerySystemTime(&t1
);
10039 } while(t0
.QuadPart
== t1
.QuadPart
);
10040 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
10041 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
10043 KdPrint(("UniATA Init: ReEnter\n"));
10047 // (re)read bad block list
10048 InitBadBlocks(NULL
);
10051 // init ATA command translation table
10052 UniataInitAtaCommands();
10053 // get registry path to settings
10054 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
10055 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
10056 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
10057 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
10058 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
10059 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
10062 if(WinVer_Id() >= WinVer_2k
) {
10063 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
10064 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
10065 WinVer_WDM_Model
= TRUE
;
10067 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
10068 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
10069 WinVer_WDM_Model
= TRUE
;
10073 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
10074 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
10076 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
10079 statusToReturn
= 0xffffffff;
10081 // Zero out structure.
10082 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
10084 // Set size of hwInitializationData.
10085 hwInitializationData
.comm
.HwInitializationDataSize
=
10086 sizeof(hwInitializationData
.comm
) +
10087 // sizeof(hwInitializationData.nt4) +
10088 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
10089 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
10091 // Set entry points.
10092 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
10093 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
10094 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
10095 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
10097 // Specify size of extensions.
10098 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
10099 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
10100 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
10102 // Indicate PIO device.
10103 hwInitializationData
.comm
.MapBuffers
= TRUE
;
10104 // Set PnP-specific API
10105 if(WinVer_Id() > WinVer_NT
) {
10106 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
10107 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
10108 KdPrint(("set AtapiAdapterControl() ptr\n"));
10109 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
10112 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE enum supported BusMaster Devices\n"));
10116 g_opt_VirtualMachine
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualMachineType", g_opt_VirtualMachine
);
10117 if(g_opt_VirtualMachine
> VM_MAX_KNOWN
) {
10118 g_opt_VirtualMachine
= 0;
10120 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualBox", (g_opt_VirtualMachine
== VM_VBOX
))) {
10121 g_opt_VirtualMachine
= VM_VBOX
;
10123 // Pre-scan PCI bus, also check if we are under VM
10124 UniataEnumBusMasterController(DriverObject
, Argument2
);
10126 switch(g_opt_VirtualMachine
) {
10128 KdPrint2((PRINT_PREFIX
"adjust options for VirtualBox\n"));
10129 // adjust options for VirtualBox
10130 g_opt_WaitBusyCount
= 20000;
10131 g_opt_WaitBusyDelay
= 150;
10132 g_opt_WaitDrqDelay
= 100;
10133 g_opt_WaitBusyLongCount
= 20000;
10134 g_opt_MaxIsrWait
= 200;
10135 g_opt_AtapiSendDisableIntr
= 0;
10136 g_opt_AtapiDmaRawRead
= FALSE
;
10141 KdPrint2((PRINT_PREFIX
"old slow machine, adjust timings\n"));
10142 // old slow machine, adjust timings
10143 g_opt_WaitBusyCount
= 20000;
10144 g_opt_WaitBusyDelay
= 150;
10145 g_opt_WaitDrqDelay
= 100;
10146 g_opt_WaitBusyLongCount
= 20000;
10147 g_opt_MaxIsrWait
= 200;
10150 g_opt_WaitBusyCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyCount", g_opt_WaitBusyCount
); // 200 vs 20000
10151 g_opt_WaitBusyDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyDelay", g_opt_WaitBusyDelay
); // 10 vs 150
10152 g_opt_WaitDrqDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitDrqDelay", g_opt_WaitDrqDelay
); // 10 vs 100
10153 g_opt_WaitBusyLongCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongCount", g_opt_WaitBusyLongCount
); // 2000 vs 20000
10154 g_opt_WaitBusyLongDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongDelay", g_opt_WaitBusyLongDelay
); // 250 vs 250
10155 g_opt_AtapiSendDisableIntr
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr
); // 1 vs 0
10156 g_opt_AtapiDmaRawRead
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiDmaRawRead", g_opt_AtapiDmaRawRead
); // 1 vs 0
10157 g_opt_MaxIsrWait
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"MaxIsrWait", g_opt_MaxIsrWait
); // 40 vs xxx
10160 // Look for legacy ISA-bridged PCI IDE controller (onboard)
10161 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
10162 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
10163 for (i
=0; i
<BMListLen
; i
++) {
10165 if(!BMList
[i
].MasterDev
) {
10166 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
10169 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10173 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
10174 if(BMList
[i
].ChanInitOk
& 0x03) {
10175 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
10177 newStatus
= STATUS_SUCCESS
;
10181 //BMList[i].AltInitMasterDev = (UCHAR)0xff;
10183 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
10184 PrimaryClaimed
= TRUE
;
10185 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
10186 SecondaryClaimed
= TRUE
;
10188 if(!WinVer_WDM_Model
&& !PrimaryClaimed
&& !SecondaryClaimed
&&
10189 !(BMList
[i
].ChanInitOk
& 0x80)) {
10190 newStatus
= UniataClaimLegacyPCIIDE(i
);
10191 if(newStatus
!= STATUS_SUCCESS
) {
10192 KdPrint2((PRINT_PREFIX
"Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
10197 if(g_opt_Verbose
) {
10198 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
10202 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
10204 for(c
=0; c
<2; c
++) {
10206 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10210 if(PrimaryClaimed
) {
10211 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
10216 if(SecondaryClaimed
) {
10217 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
10222 if((WinVer_Id() < WinVer_2k
)) {
10223 // do not even try if already claimed
10225 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
10228 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
10231 if(!WinVer_WDM_Model
) {
10232 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10234 // in WDM model things are different....
10235 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
10236 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
10238 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10239 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10241 if(!WinVer_WDM_Model
) {
10242 BMList
[i
].channel
= (UCHAR
)c
;
10245 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
10246 newStatus
= ScsiPortInitialize(DriverObject
,
10248 &hwInitializationData
.comm
,
10249 (PVOID
)(i
| (alt
? 0x80000000 : 0)));
10250 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10251 if (newStatus
< statusToReturn
) {
10252 statusToReturn
= newStatus
;
10254 if (newStatus
== STATUS_SUCCESS
) {
10255 if(WinVer_Id() < WinVer_2k
) {
10256 // This should be done in HwInitialize under w2k+ to ensure that
10257 // channel is actually initialized
10258 BMList
[i
].ChanInitOk
|= 0x01 << c
;
10260 if(BMList
[i
].ChanInitOk
& (0x01 << c
)) {
10261 KdPrint2((PRINT_PREFIX
"HwInit passed\n"));
10265 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
10266 c = 1; // this will break our for()
10267 BMList[i].ChanInitOk |= 0x01 << c;
10272 /* if(WinVer_Id() >= WinVer_2k) {
10273 // the following didn't work under higher OSes,
10274 // until we move setting of FLAGS to HwInit
10275 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
10278 if(BMList
[i
].ChanInitOk
& 0x03) {
10279 // Under NT we receive status immediately, so
10280 // we can omit alternative init method if STATUS_SUCCESS returned.
10281 // Under w2k+ we relay on flags, set in HwInitialize.
10282 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
10285 if(WinVer_Id() >= WinVer_2k
) {
10286 // try AltInit if HwInit was not called immediately under w2k+
10287 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10289 // if (WinVer_Id() == WinVer_NT) and some error occured
10290 // try alternative init method
10291 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10294 if(g_opt_Verbose
) {
10295 if(BMList
[i
].ChanInitOk
& 0x03) {
10296 _PrintNtConsole(" OK\n");
10298 _PrintNtConsole(" failed\n");
10304 /* KeBugCheckEx(0xc000000e,
10305 (i << 16) | BMList[0].ChanInitOk,
10307 newStatus, statusToReturn);*/
10309 // Look for PCI IDE controller
10310 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
10311 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
10312 for (; i
<BMListLen
; i
++) {
10314 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", 0)) {
10317 /* if(BMList[i].MasterDev)
10319 if(g_opt_Verbose
) {
10320 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
10321 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
10322 BMList
[i
].busNumber
,
10323 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
10324 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
10327 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10328 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10329 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
10331 hwInitializationData
.comm
.VendorId
= (PVOID
)BMList
[i
].VendorId
;
10332 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
10333 hwInitializationData
.comm
.DeviceId
= (PVOID
)BMList
[i
].DeviceId
;
10334 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
10336 BMList
[i
].channel
= 0/*(UCHAR)c*/;
10338 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
10339 hwInitializationData
.comm
.VendorId
,
10340 hwInitializationData
.comm
.DeviceId
));
10341 newStatus
= ScsiPortInitialize(DriverObject
,
10343 &hwInitializationData
.comm
,
10345 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10346 if(newStatus
== (ULONG
)STATUS_DEVICE_DOES_NOT_EXIST
&& BMList
[i
].NeedAltInit
) {
10347 // Note: this is actually a BUG in scsiport.sys
10348 // It stops scanning PCI bus when reaches empty PCI Function inside Slot
10349 // However, this PCI Slot may have higher non-empty Functions
10350 // UniATA will perform all staff instead of ScsiPort under NT,
10351 // but for ReactOS it is better to patch ScsiPort.
10352 KdPrint2((PRINT_PREFIX
"STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
10353 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10354 newStatus
= ScsiPortInitialize(DriverObject
,
10356 &hwInitializationData
.comm
,
10357 (PVOID
)(i
| 0x80000000));
10358 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x (2)\n", newStatus
));
10360 if (newStatus
< statusToReturn
)
10361 statusToReturn
= newStatus
;
10363 if(g_opt_Verbose
) {
10364 if(newStatus
== STATUS_SUCCESS
) {
10365 _PrintNtConsole(" OK\n");
10367 _PrintNtConsole(" failed\n");
10373 /* KeBugCheckEx(0xc000000e,
10376 newStatus, statusToReturn);*/
10380 hwInitializationData
.comm
.VendorId
= 0;
10381 hwInitializationData
.comm
.VendorIdLength
= 0;
10382 hwInitializationData
.comm
.DeviceId
= 0;
10383 hwInitializationData
.comm
.DeviceIdLength
= 0;
10386 hwInitializationData
.comm
.SrbExtensionSize
= //FIELD_OFFSET(ATA_REQ, ata);
10388 KdPrint2((PRINT_PREFIX
"using AtaReq sz %x\n", hwInitializationData
.comm
.SrbExtensionSize
));
10391 // The adapter count is used by the find adapter routine to track how
10392 // which adapter addresses have been tested.
10394 // Indicate 2 access ranges and reset FindAdapter.
10395 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
10396 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindController
;
10398 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
10399 // Indicate ISA bustype.
10400 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10403 // Call initialization for ISA bustype.
10404 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
10405 newStatus
= ScsiPortInitialize(DriverObject
,
10407 &hwInitializationData
.comm
,
10409 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10410 if (newStatus
< statusToReturn
)
10411 statusToReturn
= newStatus
;
10413 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
10415 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
10416 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
10419 newStatus
= ScsiPortInitialize(DriverObject
,
10421 &hwInitializationData
.comm
,
10423 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10424 if (newStatus
< statusToReturn
)
10425 statusToReturn
= newStatus
;
10427 InDriverEntry
= FALSE
;
10429 KdPrint2((PRINT_PREFIX
"\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn
));
10431 return statusToReturn
;
10433 } // end DriverEntry()
10436 PSCSI_REQUEST_BLOCK
10438 BuildMechanismStatusSrb(
10439 IN PVOID HwDeviceExtension
,
10440 IN PSCSI_REQUEST_BLOCK Srb
10443 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10444 PSCSI_REQUEST_BLOCK srb
;
10446 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10448 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10450 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10452 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10453 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10454 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10455 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10457 // Set flags to disable synchronous negociation.
10458 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10460 // Set timeout to 4 seconds.
10461 srb
->TimeOutValue
= 4;
10463 srb
->CdbLength
= 6;
10464 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
10465 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10466 srb
->SrbExtension
= AtaReq
;
10468 // Set CDB operation code.
10469 cdb
= (PCDB
)srb
->Cdb
;
10470 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
10471 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10473 KdPrint2((PRINT_PREFIX
" MechanismStatusSrb %#x\n", srb
));
10476 } // end BuildMechanismStatusSrb()
10478 #endif //UNIATA_CORE
10480 PSCSI_REQUEST_BLOCK
10482 BuildRequestSenseSrb (
10483 IN PVOID HwDeviceExtension
,
10484 IN PSCSI_REQUEST_BLOCK Srb
10487 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10488 PSCSI_REQUEST_BLOCK srb
;
10490 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10492 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10494 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10496 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10497 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10498 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10499 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10501 // Set flags to disable synchronous negociation.
10502 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10504 // Set timeout to 2 seconds.
10505 srb
->TimeOutValue
= 4;
10507 srb
->CdbLength
= 6;
10508 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
10509 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
10510 srb
->SrbExtension
= AtaReq
;
10512 // Set CDB operation code.
10513 cdb
= (PCDB
)srb
->Cdb
;
10514 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
10515 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
10517 KdPrint2((PRINT_PREFIX
" RequestSenseSrb %#x\n", srb
));
10520 } // end BuildRequestSenseSrb()
10522 #ifndef UNIATA_CORE
10526 AtapiRegCheckDevLunValue(
10527 IN PVOID HwDeviceExtension
,
10528 IN PCWCH NamePrefix
,
10536 ULONG val
= Default
;
10538 val
= AtapiRegCheckParameterValue(
10539 HwDeviceExtension
, NamePrefix
, Name
, val
);
10541 if(chan
!= CHAN_NOT_SPECIFIED
) {
10542 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
10543 val
= AtapiRegCheckParameterValue(
10544 HwDeviceExtension
, namex
, Name
, val
);
10545 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
10546 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
10547 val
= AtapiRegCheckParameterValue(
10548 HwDeviceExtension
, namex
, Name
, val
);
10552 } // end AtapiRegCheckDevLunValue()
10565 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
10584 swprintf(Buffer
+j
, L
"%2.2x", a
);
10592 } // end EncodeVendorStr()
10596 AtapiRegCheckDevValue(
10597 IN PVOID HwDeviceExtension
,
10604 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10605 // WCHAR name0[11];
10606 // WCHAR name1[11+4+5];
10607 // WCHAR name2[11+4+4+10];
10608 // WCHAR name3[11+4+4+5+20];
10609 // WCHAR name3[11+4+4+5+20+1];
10618 IN ULONG SlotNumber
;
10620 ULONG val
= Default
;
10622 KdPrint(( " Parameter %ws\n", Name
));
10624 if(deviceExtension
) {
10625 VendorID
= deviceExtension
->DevID
& 0xffff;
10626 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
10627 SlotNumber
= deviceExtension
->slotNumber
;
10631 SlotNumber
= 0xffffffff;
10634 val
= AtapiRegCheckDevLunValue(
10635 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
10637 if(deviceExtension
) {
10638 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
10640 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
10641 swprintf(namex
, L
"Parameters%s", namev
);
10642 val
= AtapiRegCheckDevLunValue(
10643 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10646 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
10647 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
10648 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
10650 swprintf(namex
, L
"Parameters%s", namev
);
10651 val
= AtapiRegCheckDevLunValue(
10652 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10654 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
10655 val
= AtapiRegCheckDevLunValue(
10656 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10658 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
10659 val
= AtapiRegCheckDevLunValue(
10660 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10662 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
10664 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
10665 swprintf(namex
, L
"Parameters%s", namev
);
10666 val
= AtapiRegCheckDevLunValue(
10667 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10669 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
10670 swprintf(namex
, L
"Parameters%s", namev
);
10671 val
= AtapiRegCheckDevLunValue(
10672 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10675 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
10677 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
10678 swprintf(namex
, L
"Parameters%s", namev
);
10679 val
= AtapiRegCheckDevLunValue(
10680 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10682 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
10683 swprintf(namex
, L
"Parameters%s", namev
);
10684 val
= AtapiRegCheckDevLunValue(
10685 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10690 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
10693 } // end AtapiRegCheckDevValue()
10696 The user must specify that Xxx is to run on the platform
10697 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
10698 Services\UniATA\Xxx:REG_DWORD:Zzz.
10700 The user can override the global setting to enable or disable Xxx on a
10701 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
10702 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
10704 If this registry value does not exist or contains the value zero then
10705 the timer to check for media change does not run.
10709 RegistryPath - pointer to the unicode string inside
10710 ...\CurrentControlSet\Services\UniATA
10711 DeviceNumber - The number of the HBA device object
10713 Returns: Registry Key value
10717 AtapiRegCheckParameterValue(
10718 IN PVOID HwDeviceExtension
,
10719 IN PCWSTR PathSuffix
,
10724 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
10726 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10728 LONG zero
= Default
;
10730 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
10733 LONG doRun
= Default
;
10735 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
10737 UNICODE_STRING paramPath
;
10739 // <SavedRegPath>\<PathSuffix> -> <Name>
10740 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
10741 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
10743 paramPath
.Length
= 0;
10744 paramPath
.MaximumLength
= RegistryPath
->Length
+
10745 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
10746 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
10747 if(!paramPath
.Buffer
) {
10748 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
10752 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
10753 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
10754 RtlAppendUnicodeToString(¶mPath
, L
"\\");
10755 RtlAppendUnicodeToString(¶mPath
, REGRTL_STR_PTYPE PathSuffix
);
10757 // Check for the Xxx value.
10758 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
10760 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
10761 parameters
[0].Name
= REGRTL_STR_PTYPE Name
;
10762 parameters
[0].EntryContext
= &doRun
;
10763 parameters
[0].DefaultType
= REG_DWORD
;
10764 parameters
[0].DefaultData
= &zero
;
10765 parameters
[0].DefaultLength
= sizeof(ULONG
);
10767 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
10768 paramPath
.Buffer
, parameters
, NULL
, NULL
);
10769 if(NT_SUCCESS(status
)) {
10770 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix
, Name
, doRun
));
10773 ExFreePool(paramPath
.Buffer
);
10775 if(!NT_SUCCESS(status
)) {
10781 #undef ITEMS_TO_QUERY
10783 } // end AtapiRegCheckParameterValue()
10786 SCSI_ADAPTER_CONTROL_STATUS
10788 AtapiAdapterControl(
10789 IN PVOID HwDeviceExtension
,
10790 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
10791 IN PVOID Parameters
10794 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10795 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
10796 ULONG numberChannels
= deviceExtension
->NumberChannels
;
10800 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
10802 switch(ControlType
) {
10803 case ScsiQuerySupportedControlTypes
: {
10804 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
10805 TRUE
, // ScsiQuerySupportedControlTypes
10806 TRUE
, // ScsiStopAdapter
10807 TRUE
, // ScsiRestartAdapter
10808 FALSE
, // ScsiSetBootConfig
10809 FALSE
// ScsiSetRunningConfig
10812 ULONG lim
= ScsiAdapterControlMax
;
10815 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
10817 if(pControlTypeList
->MaxControlType
< lim
) {
10818 lim
= pControlTypeList
->MaxControlType
;
10821 for(i
= 0; i
< lim
; i
++) {
10822 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
10828 case ScsiStopAdapter
: {
10830 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
10831 // Shut down all interrupts on the adapter. They'll get re-enabled
10832 // by the initialization routines.
10833 for (c
= 0; c
< numberChannels
; c
++) {
10834 AtapiResetController(deviceExtension
, c
);
10835 AtapiDisableInterrupts(deviceExtension
, c
);
10837 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
10838 // we must never get here for non-PCI
10839 /*status =*/ UniataDisconnectIntr2(HwDeviceExtension
);
10840 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
10844 case ScsiRestartAdapter
: {
10846 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
10847 // Enable all the interrupts on the adapter while port driver call
10848 // for power up an HBA that was shut down for power management
10850 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
10851 status
= UniataConnectIntr2(HwDeviceExtension
);
10852 if(NT_SUCCESS(status
)) {
10853 for (c
= 0; c
< numberChannels
; c
++) {
10854 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
10855 FindDevices(HwDeviceExtension
, 0, c
);
10856 AtapiEnableInterrupts(deviceExtension
, c
);
10857 AtapiHwInitialize__(deviceExtension
, c
);
10859 if(deviceExtension
->Isr2DevObj
) {
10860 // we must never get here for non-PCI
10861 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
10869 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
10870 return ScsiAdapterControlUnsuccessful
;
10874 return ScsiAdapterControlSuccess
;
10875 } // end AtapiAdapterControl()
10877 #endif //UNIATA_CORE
10887 #define DEBUG_MSG_BUFFER_SIZE 512
10898 UCHAR dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
];
10899 // UNICODE_STRING msgBuff;
10901 va_start(ap
, DebugMessage
);
10903 /*len =*/ _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], DEBUG_MSG_BUFFER_SIZE
-1, DebugMessage
, ap
);
10905 dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
-1] = 0;
10907 //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro
10908 HalDisplayString(dbg_print_tmp_buff
);
10911 if(g_LogToDisplay
> 1) {
10912 AtapiStallExecution(g_LogToDisplay
*1000);
10918 } // end PrintNtConsole()