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;
1680 // Read very-old-style drive geometry
1681 KdPrint2((PRINT_PREFIX
"CHS %#x:%#x:%#x\n",
1682 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1683 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1684 deviceExtension
->FullIdentifyData
.SectorsPerTrack
1686 NumOfSectors
= deviceExtension
->FullIdentifyData
.NumberOfCylinders
*
1687 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1688 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1689 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1690 // Check for HDDs > 8Gb
1691 if ((deviceExtension
->FullIdentifyData
.NumberOfCylinders
== 0x3fff) &&
1692 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1693 (NumOfSectors
< deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1694 KdPrint2((PRINT_PREFIX
"NumberOfCylinders == 0x3fff\n"));
1696 (deviceExtension
->FullIdentifyData
.UserAddressableSectors
/
1697 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1698 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1700 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1702 NumOfSectors
= cylinders
*
1703 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1704 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1706 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1710 // Check for LBA mode
1711 KdPrint2((PRINT_PREFIX
"SupportLba flag %#x\n", deviceExtension
->FullIdentifyData
.SupportLba
));
1712 KdPrint2((PRINT_PREFIX
"MajorRevision %#x\n", deviceExtension
->FullIdentifyData
.MajorRevision
));
1713 KdPrint2((PRINT_PREFIX
"UserAddressableSectors %#x\n", deviceExtension
->FullIdentifyData
.UserAddressableSectors
));
1714 if ( deviceExtension
->FullIdentifyData
.SupportLba
1716 (deviceExtension
->FullIdentifyData
.MajorRevision
&&
1717 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1718 deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1719 KdPrint2((PRINT_PREFIX
"LBA mode\n"));
1720 LunExt
->DeviceFlags
|= DFLAGS_LBA_ENABLED
;
1722 KdPrint2((PRINT_PREFIX
"Keep orig geometry\n"));
1723 LunExt
->DeviceFlags
|= DFLAGS_ORIG_GEOMETRY
;
1724 goto skip_lba_staff
;
1726 // Check for LBA48 support
1727 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1728 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
&&
1729 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Address48
&&
1730 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
> NumOfSectors
)
1732 KdPrint2((PRINT_PREFIX
"LBA48\n"));
1734 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
/
1735 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1736 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1738 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1740 NativeNumOfSectors
= cylinders
*
1741 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1742 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1744 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1746 if(NativeNumOfSectors
> NumOfSectors
) {
1747 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1748 NumOfSectors
= NativeNumOfSectors
;
1752 // Check drive capacity report for LBA48-capable drives.
1753 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
) {
1754 ULONG hNativeNumOfSectors
;
1755 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1757 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1758 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1760 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1762 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1764 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1765 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1766 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) ;
1768 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
1771 KdPrint2((PRINT_PREFIX
"Read high order bytes\n"));
1772 NativeNumOfSectors
|=
1773 (ULONG
)((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24 );
1774 hNativeNumOfSectors
=
1775 (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) |
1776 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 8) ;
1777 ((PULONG
)&NativeNumOfSectors
)[1] = hNativeNumOfSectors
;
1779 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1781 // Some drives report LBA48 capability while has capacity below 128Gb
1782 // Probably they support large block-counters.
1783 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
1784 // Here we check this
1785 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1786 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!!\n"));
1788 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1789 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1791 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1793 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1795 NativeNumOfSectors
= (ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1796 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24) |
1797 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8 ) |
1798 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 32) |
1799 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1800 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 40)
1805 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1806 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!! (2)\n"));
1807 NativeNumOfSectors
= 0;
1811 if(NumOfSectors
<= ATA_MAX_LBA28
&&
1812 NativeNumOfSectors
> NumOfSectors
) {
1814 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
1815 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1817 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1818 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1819 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1820 NumOfSectors
= NativeNumOfSectors
;
1826 if(NumOfSectors
< 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
1827 // check for native LBA size
1828 // some drives report ~32Gb in Identify Block
1829 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
1831 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_READ_NATIVE_SIZE
,
1832 0, IDE_USE_LBA
, 0, 0, 0, ATA_WAIT_READY
);
1834 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1836 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1838 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1839 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1840 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1841 (((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
) & 0xf) << 24);
1843 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1845 if(NativeNumOfSectors
> NumOfSectors
) {
1847 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
1848 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1850 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1851 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1852 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1853 NumOfSectors
= NativeNumOfSectors
;
1859 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
1861 // fill IdentifyData with bogus geometry
1862 KdPrint2((PRINT_PREFIX
"requested LunExt->GeomType=%x\n", LunExt
->opt_GeomType
));
1863 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*
1864 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
);
1865 KdPrint2((PRINT_PREFIX
"tmp_cylinders = %#I64x\n", tmp_cylinders
));
1866 if((tmp_cylinders
< 0xffff) || (LunExt
->opt_GeomType
== GEOM_ORIG
)) {
1867 // ok, we can keep original values
1868 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1869 LunExt
->opt_GeomType
= GEOM_ORIG
;
1872 tmp_cylinders
= NumOfSectors
/ (255*63);
1873 if(tmp_cylinders
< 0xffff) {
1874 // we can use generic values for H/S for generic geometry approach
1875 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1876 LunExt
->opt_GeomType
= GEOM_STD
;
1879 // we should use UNIATA geometry approach
1880 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1881 LunExt
->opt_GeomType
= GEOM_UNIATA
;
1886 if(LunExt
->opt_GeomType
== GEOM_STD
) {
1887 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
=
1888 deviceExtension
->FullIdentifyData
.SectorsPerTrack
= 63;
1890 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
=
1891 deviceExtension
->FullIdentifyData
.NumberOfHeads
= 255;
1893 cylinders
= NumOfSectors
/ (255*63);
1894 KdPrint2((PRINT_PREFIX
"Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders
, 255, 63));
1896 if(LunExt
->opt_GeomType
== GEOM_UNIATA
) {
1897 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x80)) {
1899 KdPrint2((PRINT_PREFIX
"cylinders /= 2\n"));
1900 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1901 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1903 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x80)) {
1905 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (2)\n"));
1906 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1907 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1909 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x8000)) {
1911 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (3)\n"));
1912 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1913 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1915 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x8000)) {
1917 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (4)\n"));
1918 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1919 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1921 KdPrint2((PRINT_PREFIX
"Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders
,
1922 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
,
1923 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
));
1926 KdPrint2((PRINT_PREFIX
"cylinders = tmp_cylinders (%x = %x)\n", cylinders
, tmp_cylinders
));
1927 cylinders
= tmp_cylinders
;
1929 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
=
1930 deviceExtension
->FullIdentifyData
.NumberOfCylinders
= (USHORT
)cylinders
;
1934 KdPrint2((PRINT_PREFIX
"Geometry: C %#x (%#x)\n",
1935 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1936 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
1938 KdPrint2((PRINT_PREFIX
"Geometry: H %#x (%#x)\n",
1939 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1940 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
1942 KdPrint2((PRINT_PREFIX
"Geometry: S %#x (%#x)\n",
1943 deviceExtension
->FullIdentifyData
.SectorsPerTrack
,
1944 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
1948 LunExt
->NumOfSectors
= NumOfSectors
;
1949 /* if(deviceExtension->FullIdentifyData.MajorRevision &&
1950 deviceExtension->FullIdentifyData.DoubleWordIo) {
1951 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
1955 ScsiPortMoveMemory(&LunExt
->IdentifyData
,
1956 &deviceExtension
->FullIdentifyData
,sizeof(IDENTIFY_DATA2
));
1958 InitBadBlocks(LunExt
);
1960 if ((LunExt
->IdentifyData
.DrqType
& ATAPI_DRQT_INTR
) &&
1961 (Command
!= IDE_COMMAND_IDENTIFY
)) {
1963 // This device interrupts with the assertion of DRQ after receiving
1964 // Atapi Packet Command
1965 LunExt
->DeviceFlags
|= DFLAGS_INT_DRQ
;
1966 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
1969 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
1972 if(Command
!= IDE_COMMAND_IDENTIFY
) {
1974 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_TAPE
) {
1976 LunExt
->DeviceFlags
|= DFLAGS_TAPE_DEVICE
;
1977 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is a tape drive.\n"));
1979 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
||
1980 LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_OPTICAL
) {
1981 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is CD/Optical drive.\n"));
1982 // set CD default costs
1983 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_CD
;
1984 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_CD
;
1985 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_CD
;
1986 statusByte
= WaitForDrq(chan
);
1988 KdPrint2((PRINT_PREFIX
"IssueIdentify: ATAPI drive type %#x.\n",
1989 LunExt
->IdentifyData
.DeviceType
));
1992 KdPrint2((PRINT_PREFIX
"IssueIdentify: hard drive.\n"));
1995 GetBaseStatus(chan
, statusByte
);
1996 KdPrint2((PRINT_PREFIX
"IssueIdentify: final Status on exit (%#x)\n", statusByte
));
1999 } // end IssueIdentify()
2004 Routine Description:
2005 Set drive parameters using the IDENTIFY data.
2008 HwDeviceExtension - HBA miniport driver's adapter data storage
2009 DeviceNumber - Indicates which device.
2012 TRUE if all goes well.
2018 IN PVOID HwDeviceExtension
,
2019 IN ULONG DeviceNumber
,
2023 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2024 PIDENTIFY_DATA2 identifyData
;
2025 PHW_LU_EXTENSION LunExt
;
2030 LunExt
= deviceExtension
->chan
[lChannel
].lun
[DeviceNumber
];
2031 identifyData
= &(LunExt
->IdentifyData
);
2033 if(LunExt
->DeviceFlags
&
2034 (DFLAGS_LBA_ENABLED
| DFLAGS_ORIG_GEOMETRY
))
2037 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Number of heads %#x\n", identifyData
->NumberOfHeads
));
2038 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Sectors per track %#x\n", identifyData
->SectorsPerTrack
));
2040 // Send SET PARAMETER command.
2041 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
2042 IDE_COMMAND_SET_DRIVE_PARAMETERS
, 0,
2043 (identifyData
->NumberOfHeads
- 1), 0,
2044 (UCHAR
)identifyData
->SectorsPerTrack
, 0, ATA_WAIT_IDLE
);
2046 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2047 if(statusByte
& IDE_STATUS_ERROR
) {
2048 errorByte
= AtapiReadPort1(&deviceExtension
->chan
[lChannel
], IDX_IO1_i_Error
);
2049 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Error bit set. Status %#x, error %#x\n",
2050 errorByte
, statusByte
));
2054 if(statusByte
== IDE_STATUS_IDLE
) {
2060 } // end SetDriveParameters()
2065 PHW_LU_EXTENSION LunExt
2068 // keep only DFLAGS_HIDDEN flag
2069 LunExt
->DeviceFlags
&= DFLAGS_HIDDEN
;
2070 LunExt
->AtapiReadyWaitDelay
= 0;
2071 } // end UniataForgetDevice()
2076 Routine Description:
2077 Reset IDE controller and/or Atapi device.
2081 HwDeviceExtension - HBA miniport driver's adapter data storage
2090 AtapiResetController(
2091 IN PVOID HwDeviceExtension
,
2095 KdPrint2((PRINT_PREFIX
"AtapiResetController(%x)\n", PathId
));
2096 return AtapiResetController__(HwDeviceExtension
, PathId
, RESET_COMPLETE_ALL
);
2097 } // end AtapiResetController()
2101 AtapiResetController__(
2102 IN PVOID HwDeviceExtension
,
2104 IN BOOLEAN CompleteType
2107 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2108 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2109 PHW_CHANNEL chan
= NULL
;
2113 PSCSI_REQUEST_BLOCK CurSrb
;
2114 ULONG ChannelCtrlFlags
;
2115 UCHAR dma_status
= 0;
2117 ULONG slotNumber
= deviceExtension
->slotNumber
;
2118 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
2119 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
2121 ULONG DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
2123 //ULONG RevID = deviceExtension->RevID;
2124 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
2128 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID
, DeviceID
, slotNumber
));
2129 KdPrint2((PRINT_PREFIX
"simplexOnly %d\n", deviceExtension
->simplexOnly
));
2131 if(!deviceExtension
->simplexOnly
&& (PathId
!= CHAN_NOT_SPECIFIED
)) {
2132 // we shall reset both channels on SimplexOnly devices,
2133 // It's not worth doing so on normal controllers
2135 numberChannels
= min(j
+1, deviceExtension
->NumberChannels
);
2138 numberChannels
= deviceExtension
->NumberChannels
;
2141 for (; j
< numberChannels
; j
++) {
2143 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset channel %d\n", j
));
2144 chan
= &(deviceExtension
->chan
[j
]);
2145 MaxLuns
= chan
->NumberLuns
;
2146 KdPrint2((PRINT_PREFIX
" CompleteType %#x, Luns %d, chan %#x, sptr %#x\n", CompleteType
, MaxLuns
, chan
, &chan
));
2147 //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
2148 if(CompleteType
!= RESET_COMPLETE_NONE
) {
2150 while((CurSrb
= UniataGetCurRequest(chan
))) {
2152 PATA_REQ AtaReq
= (PATA_REQ
)(CurSrb
->SrbExtension
);
2154 KdPrint2((PRINT_PREFIX
"AtapiResetController: pending SRB %#x, chan %#x\n", CurSrb
, chan
));
2155 // Check and see if we are processing an internal srb
2156 if (AtaReq
->OriginalSrb
) {
2157 KdPrint2((PRINT_PREFIX
" restore original SRB %#x\n", AtaReq
->OriginalSrb
));
2158 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
2159 CurSrb
->SrbExtension
= NULL
;
2160 AtaReq
->OriginalSrb
= NULL
;
2161 // NOTE: internal SRB doesn't get to SRB queue !!!
2162 CurSrb
= AtaReq
->Srb
;
2165 // Remove current request from queue
2166 UniataRemoveRequest(chan
, CurSrb
);
2168 // Check if request is in progress.
2169 ASSERT(AtaReq
->Srb
== CurSrb
);
2171 // Complete outstanding request with SRB_STATUS_BUS_RESET.
2172 UCHAR PathId
= CurSrb
->PathId
;
2173 UCHAR TargetId
= CurSrb
->TargetId
;
2174 UCHAR Lun
= CurSrb
->Lun
;
2176 CurSrb
->SrbStatus
= ((CompleteType
== RESET_COMPLETE_ALL
) ? SRB_STATUS_BUS_RESET
: SRB_STATUS_ABORTED
) | SRB_STATUS_AUTOSENSE_VALID
;
2177 CurSrb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2179 if (CurSrb
->SenseInfoBuffer
) {
2181 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)CurSrb
->SenseInfoBuffer
;
2182 KdPrint2((PRINT_PREFIX
" senseBuffer %#x, chan %#x\n", senseBuffer
, chan
));
2184 senseBuffer
->ErrorCode
= 0x70;
2185 senseBuffer
->Valid
= 1;
2186 senseBuffer
->AdditionalSenseLength
= 0xb;
2187 if(CompleteType
== RESET_COMPLETE_ALL
) {
2188 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
2189 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2190 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_BUS_RESET
;
2191 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_SCSI_BUS
;
2193 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
2194 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2195 senseBuffer
->AdditionalSenseCode
= 0;
2196 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2200 // Clear request tracking fields.
2201 AtaReq
->WordsLeft
= 0;
2202 AtaReq
->DataBuffer
= NULL
;
2203 AtaReq
->TransferLength
= 0;
2204 KdPrint2((PRINT_PREFIX
"chan %#x\n", chan
));
2206 ScsiPortNotification(RequestComplete
,
2210 // Indicate ready for next request.
2211 ScsiPortNotification(NextLuRequest
,
2217 if(CompleteType
!= RESET_COMPLETE_ALL
)
2220 #endif //UNIATA_CORE
2221 } // end if (!CompleteType != RESET_COMPLETE_NONE)
2223 // Save control flags
2224 ChannelCtrlFlags
= chan
->ChannelCtrlFlags
;
2225 // Clear expecting interrupt flag.
2226 UniataExpectChannelInterrupt(chan
, FALSE
);
2228 chan
->ChannelCtrlFlags
= 0;
2229 InterlockedExchange(&(chan
->CheckIntr
),
2232 for (i
= 0; i
< MaxLuns
; i
++) {
2233 chan
->lun
[i
]->PowerState
= 0;
2236 if(ChipFlags
& UNIATA_AHCI
) {
2237 KdPrint2((PRINT_PREFIX
" AHCI path\n"));
2238 if(UniataAhciChanImplemented(deviceExtension
, j
)) {
2240 UniataDumpAhciPortRegs(chan
);
2242 AtapiDisableInterrupts(deviceExtension
, j
);
2243 UniataAhciReset(HwDeviceExtension
, j
);
2245 KdPrint2((PRINT_PREFIX
" skip not implemented\n"));
2248 KdPrint2((PRINT_PREFIX
" ATA path, chan %#x\n", chan
));
2249 KdPrint2((PRINT_PREFIX
" disable intr (0)\n"));
2250 AtapiDisableInterrupts(deviceExtension
, j
);
2251 KdPrint2((PRINT_PREFIX
" done\n"));
2253 case ATA_INTEL_ID
: {
2257 if(!(ChipFlags
& UNIATA_SATA
)) {
2260 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2265 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2266 if(ChipFlags
& UNIATA_AHCI
) {
2269 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2270 GetPciConfig1(0x90, tmp8
);
2278 mask
= 1 << chan
->lun
[0]->SATA_lun_map
;
2280 mask
|= (1 << chan
->lun
[1]->SATA_lun_map
);
2283 ChangePciConfig2(0x92, a
& ~mask
);
2284 AtapiStallExecution(10);
2285 ChangePciConfig2(0x92, a
| mask
);
2288 /* Wait up to 1 sec for "connect well". */
2289 if (ChipFlags
& (I6CH
| I6CH2
)) {
2295 GetPciConfig2(0x92, tmp16
);
2296 if (((tmp16
>> pshift
) & mask
) == mask
) {
2297 GetBaseStatus(chan
, statusByte
);
2298 if(statusByte
!= IDE_STATUS_WRONG
) {
2302 AtapiStallExecution(10000);
2306 case ATA_NVIDIA_ID
: {
2307 KdPrint2((PRINT_PREFIX
" SIS/nVidia\n"));
2308 if(!(ChipFlags
& UNIATA_SATA
))
2311 case ATA_SILICON_IMAGE_ID
: {
2313 ULONG Channel
= deviceExtension
->Channel
+ j
;
2314 if(!(ChipFlags
& UNIATA_SATA
))
2316 offset
= ((Channel
& 1) << 7) + ((Channel
& 2) << 8);
2317 /* disable PHY state change interrupt */
2318 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x148 + offset
, 0);
2320 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2322 /* reset controller part for this channel */
2323 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2324 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) | (0xc0 >> Channel
));
2325 AtapiStallExecution(1000);
2326 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2327 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) & ~(0xc0 >> Channel
));
2331 case ATA_PROMISE_ID
: {
2334 if(ChipFlags
& UNIATA_SATA
) {
2335 KdPrint2((PRINT_PREFIX
" SATA generic reset\n"));
2336 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2339 KdPrint2((PRINT_PREFIX
" send reset\n"));
2340 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
|
2341 IDE_DC_RESET_CONTROLLER
);
2342 KdPrint2((PRINT_PREFIX
" wait a little\n"));
2343 AtapiStallExecution(10000);
2344 // Disable interrupts
2345 KdPrint2((PRINT_PREFIX
" disable intr\n"));
2346 AtapiDisableInterrupts(deviceExtension
, j
);
2347 AtapiStallExecution(100);
2348 KdPrint2((PRINT_PREFIX
" re-enable intr\n"));
2349 AtapiEnableInterrupts(deviceExtension
, j
);
2350 KdPrint2((PRINT_PREFIX
" wait a little (2)\n"));
2351 AtapiStallExecution(100000);
2352 KdPrint2((PRINT_PREFIX
" done\n"));
2357 //if(!(ChipFlags & UNIATA_SATA)) {}
2358 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2359 // Reset DMA engine if active
2360 KdPrint2((PRINT_PREFIX
" check DMA engine\n"));
2361 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
2362 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
2363 if((ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
2364 (dma_status
& BM_STATUS_INTR
)) {
2365 AtapiDmaDone(HwDeviceExtension
, 0, j
, NULL
);
2370 // all these shall be performed inside AtapiHwInitialize__() ?
2372 KdPrint2((PRINT_PREFIX
" process connected devices 0 - %d\n", MaxLuns
-1));
2373 // Do special processing for ATAPI and IDE disk devices.
2374 for (i
= 0; i
< MaxLuns
; i
++) {
2376 // Check if device present.
2377 KdPrint2((PRINT_PREFIX
" Chan %#x\n", chan
));
2378 KdPrint2((PRINT_PREFIX
" Lun %#x\n", i
));
2379 KdPrint2((PRINT_PREFIX
" Lun ptr %#x\n", chan
->lun
[i
]));
2380 if (!(chan
->lun
[i
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2381 if(ChipFlags
& UNIATA_AHCI
) {
2382 // everything is done in UniataAhciReset()
2383 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2389 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2390 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2393 if(!CheckDevice(HwDeviceExtension
, j
, i
, TRUE
)) {
2397 if(ChipFlags
& UNIATA_AHCI
) {
2398 // everything is done in UniataAhciReset()
2399 KdPrint2((PRINT_PREFIX
" found some device\n"));
2401 if(!IssueIdentify(HwDeviceExtension
,
2403 ATAPI_DEVICE(chan
, i
) ?
2404 IDE_COMMAND_ATAPI_IDENTIFY
: IDE_COMMAND_IDENTIFY
,
2406 KdPrint2((PRINT_PREFIX
" identify failed !\n"));
2407 UniataForgetDevice(chan
->lun
[i
]);
2411 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2412 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2413 UniataForgetDevice(chan
->lun
[i
]);
2418 SelectDrive(chan
, i
);
2419 AtapiStallExecution(10);
2420 statusByte
= WaitOnBusyLong(chan
);
2421 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2422 if(statusByte
== IDE_STATUS_WRONG
) {
2423 KdPrint2((PRINT_PREFIX
2424 "no drive, status %#x\n",
2426 UniataForgetDevice(chan
->lun
[i
]);
2428 // Check for ATAPI disk.
2429 if (ATAPI_DEVICE(chan
, i
)) {
2430 // Issue soft reset and issue identify.
2431 GetStatus(chan
, statusByte
);
2432 KdPrint2((PRINT_PREFIX
"AtapiResetController: Status before Atapi reset (%#x).\n",
2435 AtapiDisableInterrupts(deviceExtension
, j
);
2436 AtapiSoftReset(chan
, i
);
2437 AtapiEnableInterrupts(deviceExtension
, j
);
2439 GetStatus(chan
, statusByte
);
2441 if(statusByte
== IDE_STATUS_SUCCESS
) {
2443 IssueIdentify(HwDeviceExtension
,
2445 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
2448 KdPrint2((PRINT_PREFIX
2449 "AtapiResetController: Status after soft reset %#x\n",
2452 GetBaseStatus(chan
, statusByte
);
2455 // Issue identify and reinit after channel reset.
2457 if (statusByte
!= IDE_STATUS_IDLE
&&
2458 statusByte
!= IDE_STATUS_SUCCESS
&&
2459 statusByte
!= IDE_STATUS_DRDY
) {
2461 KdPrint2((PRINT_PREFIX
"AtapiResetController: IdeHardReset failed\n"));
2463 if(!IssueIdentify(HwDeviceExtension
,
2465 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2467 KdPrint2((PRINT_PREFIX
"AtapiResetController: IDE IssueIdentify failed\n"));
2469 // Set disk geometry parameters.
2470 if (!SetDriveParameters(HwDeviceExtension
, i
, j
)) {
2471 KdPrint2((PRINT_PREFIX
"AtapiResetController: SetDriveParameters failed\n"));
2473 GetBaseStatus(chan
, statusByte
);
2475 // force DMA mode reinit
2476 chan
->lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
2480 // Enable interrupts, note, we can have here recursive disable
2481 AtapiStallExecution(10);
2482 KdPrint2((PRINT_PREFIX
"AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2484 chan
->DisableIntr
));
2485 AtapiEnableInterrupts(deviceExtension
, j
);
2487 // Call the HwInitialize routine to setup multi-block.
2488 AtapiHwInitialize__(deviceExtension
, j
);
2490 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
2494 } // end AtapiResetController__()
2499 Routine Description:
2500 This routine maps ATAPI and IDE errors to specific SRB statuses.
2503 HwDeviceExtension - HBA miniport driver's adapter data storage
2504 Srb - IO request packet
2513 IN PVOID HwDeviceExtension
,
2514 IN PSCSI_REQUEST_BLOCK Srb
2517 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2518 ULONG lChannel
= GET_CHANNEL(Srb
);
2519 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2521 UCHAR errorByte
= 0;
2522 UCHAR srbStatus
= SRB_STATUS_SUCCESS
;
2524 ULONG DeviceNumber
= GET_CDEV(Srb
);
2525 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
2527 // Read the error register.
2529 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
2530 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2532 errorByte
= AtaReq
->ahci
.in_error
;
2536 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2538 KdPrint2((PRINT_PREFIX
2539 "MapError: Error register is %#x\n",
2542 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2544 switch (errorByte
>> 4) {
2545 case SCSI_SENSE_NO_SENSE
:
2547 KdPrint2((PRINT_PREFIX
2548 "ATAPI: No sense information\n"));
2549 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2550 srbStatus
= SRB_STATUS_ERROR
;
2553 case SCSI_SENSE_RECOVERED_ERROR
:
2555 KdPrint2((PRINT_PREFIX
2556 "ATAPI: Recovered error\n"));
2558 srbStatus
= SRB_STATUS_SUCCESS
;
2561 case SCSI_SENSE_NOT_READY
:
2563 KdPrint2((PRINT_PREFIX
2564 "ATAPI: Device not ready\n"));
2565 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2566 srbStatus
= SRB_STATUS_ERROR
;
2569 case SCSI_SENSE_MEDIUM_ERROR
:
2571 KdPrint2((PRINT_PREFIX
2572 "ATAPI: Media error\n"));
2573 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2574 srbStatus
= SRB_STATUS_ERROR
;
2577 case SCSI_SENSE_HARDWARE_ERROR
:
2579 KdPrint2((PRINT_PREFIX
2580 "ATAPI: Hardware error\n"));
2581 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2582 srbStatus
= SRB_STATUS_ERROR
;
2585 case SCSI_SENSE_ILLEGAL_REQUEST
:
2587 KdPrint2((PRINT_PREFIX
2588 "ATAPI: Illegal request\n"));
2589 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2590 srbStatus
= SRB_STATUS_ERROR
;
2593 case SCSI_SENSE_UNIT_ATTENTION
:
2595 KdPrint2((PRINT_PREFIX
2596 "ATAPI: Unit attention\n"));
2597 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2598 srbStatus
= SRB_STATUS_ERROR
;
2601 case SCSI_SENSE_DATA_PROTECT
:
2603 KdPrint2((PRINT_PREFIX
2604 "ATAPI: Data protect\n"));
2605 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2606 srbStatus
= SRB_STATUS_ERROR
;
2609 case SCSI_SENSE_BLANK_CHECK
:
2611 KdPrint2((PRINT_PREFIX
2612 "ATAPI: Blank check\n"));
2613 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2614 srbStatus
= SRB_STATUS_ERROR
;
2617 case SCSI_SENSE_ABORTED_COMMAND
:
2618 KdPrint2((PRINT_PREFIX
2619 "Atapi: Command Aborted\n"));
2620 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2621 srbStatus
= SRB_STATUS_ERROR
;
2626 KdPrint2((PRINT_PREFIX
2627 "ATAPI: Invalid sense information\n"));
2629 srbStatus
= SRB_STATUS_ERROR
;
2637 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
2638 chan
->ReturningMediaStatus
= errorByte
;
2640 if (errorByte
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
2641 KdPrint2((PRINT_PREFIX
2642 "IDE: Media change\n"));
2643 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2644 srbStatus
= SRB_STATUS_ERROR
;
2646 if (Srb
->SenseInfoBuffer
) {
2648 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2650 senseBuffer
->ErrorCode
= 0x70;
2651 senseBuffer
->Valid
= 1;
2652 senseBuffer
->AdditionalSenseLength
= 0xb;
2653 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2654 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2655 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2657 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2660 } else if (errorByte
& IDE_ERROR_COMMAND_ABORTED
) {
2661 KdPrint2((PRINT_PREFIX
2662 "IDE: Command abort\n"));
2663 srbStatus
= SRB_STATUS_ABORTED
;
2664 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
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_ABORTED_COMMAND
;
2674 senseBuffer
->AdditionalSenseCode
= 0;
2675 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2677 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2680 LunExt
->ErrorCount
++;
2682 } else if (errorByte
& IDE_ERROR_END_OF_MEDIA
) {
2684 KdPrint2((PRINT_PREFIX
2685 "IDE: End of media\n"));
2686 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2687 srbStatus
= SRB_STATUS_ERROR
;
2689 if (Srb
->SenseInfoBuffer
) {
2691 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2693 senseBuffer
->ErrorCode
= 0x70;
2694 senseBuffer
->Valid
= 1;
2695 senseBuffer
->AdditionalSenseLength
= 0xb;
2696 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2697 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIA_STATE
;
2698 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_END_OF_MEDIUM
;
2699 senseBuffer
->EndOfMedia
= 1;
2701 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2704 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2705 LunExt
->ErrorCount
++;
2708 } else if (errorByte
& IDE_ERROR_ILLEGAL_LENGTH
) {
2710 KdPrint2((PRINT_PREFIX
2711 "IDE: Illegal length\n"));
2712 srbStatus
= SRB_STATUS_INVALID_REQUEST
;
2714 if (Srb
->SenseInfoBuffer
) {
2716 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2718 senseBuffer
->ErrorCode
= 0x70;
2719 senseBuffer
->Valid
= 1;
2720 senseBuffer
->AdditionalSenseLength
= 0xb;
2721 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
2722 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_VALUE
;
2723 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_PARAM_INVALID_VALUE
;
2724 senseBuffer
->IncorrectLength
= 1;
2726 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2729 } else if (errorByte
& IDE_ERROR_BAD_BLOCK
) {
2731 KdPrint2((PRINT_PREFIX
2732 "IDE: Bad block\n"));
2733 srbStatus
= SRB_STATUS_ERROR
;
2734 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2735 if (Srb
->SenseInfoBuffer
) {
2737 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2739 senseBuffer
->ErrorCode
= 0x70;
2740 senseBuffer
->Valid
= 1;
2741 senseBuffer
->AdditionalSenseLength
= 0xb;
2742 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2743 senseBuffer
->AdditionalSenseCode
= 0;
2744 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2746 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2749 } else if (errorByte
& IDE_ERROR_ID_NOT_FOUND
) {
2751 KdPrint2((PRINT_PREFIX
2752 "IDE: Id not found\n"));
2753 srbStatus
= SRB_STATUS_ERROR
;
2754 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2756 if (Srb
->SenseInfoBuffer
) {
2758 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2760 senseBuffer
->ErrorCode
= 0x70;
2761 senseBuffer
->Valid
= 1;
2762 senseBuffer
->AdditionalSenseLength
= 0xb;
2763 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2764 senseBuffer
->AdditionalSenseCode
= 0;
2765 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2767 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2770 LunExt
->ErrorCount
++;
2772 } else if (errorByte
& IDE_ERROR_MEDIA_CHANGE
) {
2774 KdPrint2((PRINT_PREFIX
2775 "IDE: Media change\n"));
2776 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2777 srbStatus
= SRB_STATUS_ERROR
;
2779 if (Srb
->SenseInfoBuffer
) {
2781 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2783 senseBuffer
->ErrorCode
= 0x70;
2784 senseBuffer
->Valid
= 1;
2785 senseBuffer
->AdditionalSenseLength
= 0xb;
2786 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2787 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2788 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2790 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2793 } else if (errorByte
& IDE_ERROR_DATA_ERROR
) {
2795 KdPrint2((PRINT_PREFIX
2796 "IDE: Data error\n"));
2797 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2798 srbStatus
= SRB_STATUS_ERROR
;
2800 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2801 LunExt
->ErrorCount
++;
2804 // Build sense buffer
2805 if (Srb
->SenseInfoBuffer
) {
2807 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2809 senseBuffer
->ErrorCode
= 0x70;
2810 senseBuffer
->Valid
= 1;
2811 senseBuffer
->AdditionalSenseLength
= 0xb;
2812 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2813 senseBuffer
->AdditionalSenseCode
= 0;
2814 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2816 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2820 if (LunExt
->ErrorCount
>= MAX_ERRORS
) {
2821 // deviceExtension->DWordIO = FALSE;
2823 KdPrint2((PRINT_PREFIX
2824 "MapError: ErrorCount >= MAX_ERRORS\n"));
2826 LunExt
->DeviceFlags
&= ~DFLAGS_DWORDIO_ENABLED
;
2827 LunExt
->MaximumBlockXfer
= 0;
2830 KdPrint2((PRINT_PREFIX
2831 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
2834 KdPrint2((PRINT_PREFIX
2835 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
2844 ScsiPortLogError( HwDeviceExtension
,
2852 // Reprogram to not use Multi-sector.
2855 if (LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
&&
2856 !(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
2858 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY
);
2860 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2861 // command was aborted.
2862 if (statusByte
& IDE_STATUS_ERROR
) {
2864 // Read the error register.
2865 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2867 KdPrint2((PRINT_PREFIX
"MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
2871 // Adjust the devExt. value, if necessary.
2872 LunExt
->MaximumBlockXfer
= 0;
2880 // Set SCSI status to indicate a check condition.
2881 Srb
->ScsiStatus
= scsiStatus
;
2890 Routine Description:
2893 HwDeviceExtension - HBA miniport driver's adapter data storage
2897 TRUE - if initialization successful.
2898 FALSE - if initialization unsuccessful.
2904 IN PVOID HwDeviceExtension
2907 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2908 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2911 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base)\n"));
2913 if(WinVer_WDM_Model
) {
2914 AtapiResetController__(HwDeviceExtension
, CHAN_NOT_SPECIFIED
, RESET_COMPLETE_ALL
);
2916 if(deviceExtension
->MasterDev
) {
2917 KdPrint2((PRINT_PREFIX
" mark chan %d of master controller [%x] as inited\n",
2918 deviceExtension
->Channel
, deviceExtension
->DevIndex
));
2919 BMList
[deviceExtension
->DevIndex
].ChanInitOk
|= 0x01 << deviceExtension
->Channel
;
2922 /* do extra chipset specific setups */
2923 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
2925 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
2926 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
2927 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
2930 for (c
= 0; c
< numberChannels
; c
++) {
2931 AtapiHwInitialize__(deviceExtension
, c
);
2933 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base) done\n"));
2935 } // end AtapiHwInitialize()
2939 AtapiHwInitialize__(
2940 IN PHW_DEVICE_EXTENSION deviceExtension
,
2945 UCHAR statusByte
, errorByte
;
2946 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2947 PHW_LU_EXTENSION LunExt
;
2949 ULONG PreferedMode
= 0xffffffff;
2951 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
2952 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
2956 AtapiChipInit(deviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
);
2957 FindDevices(deviceExtension
, 0, lChannel
);
2959 for (i
= 0; i
< chan
->NumberLuns
; i
++) {
2961 KdPrint3((PRINT_PREFIX
"AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel
, i
));
2963 LunExt
= chan
->lun
[i
];
2965 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2969 AtapiDisableInterrupts(deviceExtension
, lChannel
);
2970 AtapiStallExecution(1);
2972 if (!(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
2974 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: IDE branch\n"));
2975 // Enable media status notification
2976 IdeMediaStatus(TRUE
,deviceExtension
,lChannel
,(UCHAR
)i
);
2978 // If supported, setup Multi-block transfers.
2979 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
2980 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2981 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2983 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2984 // command was aborted.
2985 if (statusByte
& IDE_STATUS_ERROR
) {
2987 // Read the error register.
2988 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2990 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
2994 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
2995 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2996 0, 0, ATA_WAIT_BASE_READY
);
2998 if (statusByte
& IDE_STATUS_ERROR
) {
2999 // Read the error register.
3000 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3002 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
3006 // Adjust the devExt. value, if necessary.
3007 LunExt
->MaximumBlockXfer
= 0;
3010 KdPrint2((PRINT_PREFIX
3011 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
3013 LunExt
->MaximumBlockXfer
));
3016 if(LunExt
->IdentifyData
.MajorRevision
) {
3018 if(LunExt
->opt_ReadCacheEnable
) {
3019 KdPrint2((PRINT_PREFIX
" Try Enable Read Cache\n"));
3020 // If supported, setup read/write cacheing
3021 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3022 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3023 0, ATA_C_F_ENAB_RCACHE
, ATA_WAIT_BASE_READY
);
3025 // Check for errors.
3026 if (statusByte
& IDE_STATUS_ERROR
) {
3027 KdPrint2((PRINT_PREFIX
3028 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
3030 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3032 LunExt
->DeviceFlags
|= DFLAGS_RCACHE_ENABLED
;
3035 KdPrint2((PRINT_PREFIX
" Disable Read Cache\n"));
3036 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3037 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3038 0, ATA_C_F_DIS_RCACHE
, ATA_WAIT_BASE_READY
);
3039 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3041 if(LunExt
->opt_WriteCacheEnable
) {
3042 KdPrint2((PRINT_PREFIX
" Try Enable Write Cache\n"));
3043 // If supported & allowed, setup write cacheing
3044 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3045 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3046 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
3047 // Check for errors.
3048 if (statusByte
& IDE_STATUS_ERROR
) {
3049 KdPrint2((PRINT_PREFIX
3050 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
3052 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3054 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
3057 KdPrint2((PRINT_PREFIX
" Disable Write Cache\n"));
3058 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3059 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3060 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
3061 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3064 if(LunExt
->IdentifyData
.FeaturesSupport
.PowerMngt
||
3065 LunExt
->IdentifyData
.FeaturesSupport
.APM
) {
3067 if(LunExt
->opt_AdvPowerMode
) {
3068 KdPrint2((PRINT_PREFIX
" Try Enable Adv. Power Mgmt\n"));
3070 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3071 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3072 LunExt
->opt_AdvPowerMode
, ATA_C_F_ENAB_APM
, ATA_WAIT_BASE_READY
);
3073 // Check for errors.
3074 if (statusByte
& IDE_STATUS_ERROR
) {
3075 KdPrint2((PRINT_PREFIX
3076 "AtapiHwInitialize: Enable APM on Device %d failed\n",
3080 KdPrint2((PRINT_PREFIX
" Disable Adv. Power Mgmt\n"));
3081 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3082 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3083 0, ATA_C_F_DIS_APM
, ATA_WAIT_BASE_READY
);
3086 if(LunExt
->IdentifyData
.FeaturesSupport
.AutoAcoustic
) {
3087 if(LunExt
->opt_AcousticMode
) {
3088 KdPrint2((PRINT_PREFIX
" Try Enable Acoustic Mgmt\n"));
3089 // setup acoustic mgmt
3090 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3091 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3092 LunExt
->opt_AcousticMode
, ATA_C_F_ENAB_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3093 // Check for errors.
3094 if (statusByte
& IDE_STATUS_ERROR
) {
3095 KdPrint2((PRINT_PREFIX
3096 "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n",
3100 KdPrint2((PRINT_PREFIX
" Disable Acoustic Mgmt\n"));
3101 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3102 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3103 0, ATA_C_F_DIS_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3106 if(LunExt
->IdentifyData
.FeaturesSupport
.Standby
) {
3107 KdPrint2((PRINT_PREFIX
" Try init standby timer: %d\n"));
3108 // setup standby timer
3109 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3110 IDE_COMMAND_IDLE
, 0, 0, 0,
3111 LunExt
->opt_StandbyTimer
, 0, ATA_WAIT_BASE_READY
);
3112 // Check for errors.
3113 if (statusByte
& IDE_STATUS_ERROR
) {
3114 KdPrint2((PRINT_PREFIX
3115 "AtapiHwInitialize: standby timer on Device %d failed\n",
3121 } else if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)){
3124 //BOOLEAN isSanyo = FALSE;
3127 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: ATAPI/Changer branch\n"));
3129 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
3130 for (j
= 0; j
< 26; j
+= 2) {
3132 // Build a buffer based on the identify data.
3133 MOV_DW_SWP(vendorId
[j
], ((PUCHAR
)LunExt
->IdentifyData
.ModelNumber
)[j
]);
3136 if (!AtapiStringCmp (vendorId
, "CD-ROM CDR", 11)) {
3138 // Inquiry string for older model had a '-', newer is '_'
3139 if (vendorId
[12] == 'C') {
3141 // Torisan changer. Set the bit. This will be used in several places
3142 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
3143 LunExt
->DeviceFlags
|= (DFLAGS_CHANGER_INITED
| DFLAGS_SANYO_ATAPI_CHANGER
);
3144 LunExt
->DiscsPresent
= 3;
3150 PreferedMode
= LunExt
->opt_MaxTransferMode
;
3151 if((PreferedMode
== 0xffffffff) || (PreferedMode
> chan
->MaxTransferMode
)) {
3152 KdPrint2((PRINT_PREFIX
"MaxTransferMode (overriden): %#x\n", chan
->MaxTransferMode
));
3153 PreferedMode
= chan
->MaxTransferMode
;
3156 if(LunExt
->opt_PreferedTransferMode
!= 0xffffffff) {
3157 KdPrint2((PRINT_PREFIX
"PreferedTransferMode: %#x\n", PreferedMode
));
3158 PreferedMode
= min(LunExt
->opt_PreferedTransferMode
, PreferedMode
);
3161 KdPrint2((PRINT_PREFIX
" try mode %#x\n", PreferedMode
));
3162 LunExt
->LimitedTransferMode
=
3163 LunExt
->TransferMode
=
3166 AtapiDmaInit__(deviceExtension
, LunExt
);
3168 LunExt
->LimitedTransferMode
=
3169 LunExt
->TransferMode
;
3170 KdPrint2((PRINT_PREFIX
"Using %#x mode\n", LunExt
->TransferMode
));
3172 // We need to get our device ready for action before
3173 // returning from this function
3175 // According to the atapi spec 2.5 or 2.6, an atapi device
3176 // clears its status BSY bit when it is ready for atapi commands.
3177 // However, some devices (Panasonic SQ-TC500N) are still
3178 // not ready even when the status BSY is clear. They don't react
3179 // to atapi commands.
3181 // Since there is really no other indication that tells us
3182 // the drive is really ready for action. We are going to check BSY
3183 // is clear and then just wait for an arbitrary amount of time!
3185 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3188 // have to get out of the loop sometime!
3189 // 10000 * 100us = 1000,000us = 1000ms = 1s
3191 GetStatus(chan
, statusByte
);
3192 if(statusByte
== IDE_STATUS_WRONG
) {
3195 while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
) {
3197 KdPrint2((PRINT_PREFIX
"Wait for ATAPI (status %x)\n", statusByte
));
3198 // Wait for Busy to drop.
3199 AtapiStallExecution(100);
3200 GetStatus(chan
, statusByte
);
3204 // 5000 * 100us = 500,000us = 500ms = 0.5s
3205 if(statusByte
!= IDE_STATUS_WRONG
) {
3208 AtapiStallExecution(100);
3209 } while (waitCount
--);
3212 GetBaseStatus(chan
, statusByte
);
3213 AtapiEnableInterrupts(deviceExtension
, lChannel
);
3214 AtapiStallExecution(10);
3219 } // end AtapiHwInitialize__()
3226 AtapiHwInitializeChanger(
3227 IN PVOID HwDeviceExtension
,
3228 IN PSCSI_REQUEST_BLOCK Srb
,
3229 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus
)
3231 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3232 ULONG lChannel
= GET_CHANNEL(Srb
);
3233 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3234 ULONG DeviceNumber
= GET_CDEV(Srb
);
3235 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
3237 if (MechanismStatus
) {
3238 LunExt
->DiscsPresent
= MechanismStatus
->NumberAvailableSlots
;
3239 if (LunExt
->DiscsPresent
> 1) {
3240 LunExt
->DeviceFlags
|= DFLAGS_ATAPI_CHANGER
;
3244 } // end AtapiHwInitializeChanger()
3249 Routine Description:
3250 This routine will parse the string for a match on the keyword, then
3251 calculate the value for the keyword and return it to the caller.
3254 String - The ASCII string to parse.
3255 KeyWord - The keyword for the value desired.
3258 Zero if value not found
3259 Value converted from ASCII to binary.
3264 AtapiParseArgumentString(
3272 ULONG stringLength
= 0;
3273 ULONG keyWordLength
= 0;
3283 // Calculate the string length and lower case all characters.
3289 // Calculate the keyword length.
3295 if (keyWordLength
> stringLength
) {
3297 // Can't possibly have a match.
3301 // Now setup and start the compare.
3306 // The input string may start with white space. Skip it.
3307 while (*cptr
== ' ' || *cptr
== '\t') {
3311 if (*cptr
== '\0') {
3317 while ((*cptr
== *kptr
) ||
3318 (*cptr
>= 'A' && *cptr
<= 'Z' && *cptr
+ ('a' - 'A') == *kptr
) ||
3319 (*cptr
>= 'a' && *cptr
<= 'z' && *cptr
- ('a' - 'A') == *kptr
)) {
3323 if (*cptr
== '\0') {
3329 if (*kptr
== '\0') {
3331 // May have a match backup and check for blank or equals.
3332 while (*cptr
== ' ' || *cptr
== '\t') {
3336 // Found a match. Make sure there is an equals.
3339 // Not a match so move to the next semicolon.
3341 if (*cptr
++ == ';') {
3342 goto ContinueSearch
;
3347 // Skip the equals sign.
3350 // Skip white space.
3351 while ((*cptr
== ' ') || (*cptr
== '\t')) {
3355 if (*cptr
== '\0') {
3356 // Early end of string, return not found
3361 // This isn't it either.
3363 goto ContinueSearch
;
3367 if ((*cptr
== '0') && ((*(cptr
+ 1) == 'x') || (*(cptr
+ 1) == 'X'))) {
3368 // Value is in Hex. Skip the "0x"
3370 for (index
= 0; *(cptr
+ index
); index
++) {
3372 if (*(cptr
+ index
) == ' ' ||
3373 *(cptr
+ index
) == '\t' ||
3374 *(cptr
+ index
) == ';') {
3378 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3379 value
= (16 * value
) + (*(cptr
+ index
) - '0');
3381 if ((*(cptr
+ index
) >= 'a') && (*(cptr
+ index
) <= 'f')) {
3382 value
= (16 * value
) + (*(cptr
+ index
) - 'a' + 10);
3383 } else if ((*(cptr
+ index
) >= 'A') && (*(cptr
+ index
) <= 'F')) {
3384 value
= (16 * value
) + (*(cptr
+ index
) - 'A' + 10);
3386 // Syntax error, return not found.
3393 // Value is in Decimal.
3394 for (index
= 0; *(cptr
+ index
); index
++) {
3396 if (*(cptr
+ index
) == ' ' ||
3397 *(cptr
+ index
) == '\t' ||
3398 *(cptr
+ index
) == ';') {
3402 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3403 value
= (10 * value
) + (*(cptr
+ index
) - '0');
3406 // Syntax error return not found.
3415 // Not a match check for ';' to continue search.
3417 if (*cptr
++ == ';') {
3418 goto ContinueSearch
;
3424 } // end AtapiParseArgumentString()_
3432 IN PVOID HwDeviceExtension
,
3437 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3438 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3441 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3444 KdPrint2((PRINT_PREFIX
"AtapiCallBack:\n"));
3445 // If the last command was DSC restrictive, see if it's set. If so, the device is
3446 // ready for a new request. Otherwise, reset the timer and come back to here later.
3448 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3449 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3450 // we shall have no problem with interrupt handler.
3451 if (!srb
|| chan
->ExpectingInterrupt
) {
3452 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Calling ISR directly due to BUSY\n"));
3453 chan
->DpcState
= DPC_STATE_TIMER
;
3454 if(!AtapiInterrupt__(HwDeviceExtension
, lChannel
)) {
3455 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3456 KdPrint2((PRINT_PREFIX
"AtapiCallBack: What's fucking this ???\n"));
3458 goto ReturnCallback
;
3462 if (!IS_RDP((srb
->Cdb
[0]))) {
3463 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb
->Cdb
[0]));
3467 goto ReturnEnableIntr
;
3469 GetStatus(chan
, statusByte
);
3470 if (statusByte
& IDE_STATUS_DSC
) {
3472 UCHAR PathId
= srb
->PathId
;
3473 UCHAR TargetId
= srb
->TargetId
;
3474 UCHAR Lun
= srb
->Lun
;
3476 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Found DSC for RDP - %#x\n", srb
->Cdb
[0]));
3477 AtapiDmaDBSync(chan
, srb
);
3478 UniataRemoveRequest(chan
, srb
);
3479 ScsiPortNotification(RequestComplete
, deviceExtension
, srb
);
3480 // Clear current SRB.
3481 if(!deviceExtension
->simplexOnly
) {
3482 srb
= UniataGetCurRequest(chan
);
3488 // Ask for next request.
3489 ScsiPortNotification(NextLuRequest
,
3494 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
3497 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3501 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Requesting another timer for Op %#x\n",
3504 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3508 goto ReturnCallback
;
3513 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
3514 KdPrint2((PRINT_PREFIX
"AtapiCallBack: CallDisableInterrupts\n"));
3515 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3516 #ifdef UNIATA_USE_XXableInterrupts
3517 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
3518 // must be called on DISPATCH_LEVEL
3519 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
3520 AtapiEnableInterrupts__
);
3522 AtapiEnableInterrupts(HwDeviceExtension
, lChannel
);
3523 InterlockedExchange(&(chan
->CheckIntr
),
3525 // Will raise IRQL to DIRQL
3526 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3527 AtapiEnableInterrupts__
,
3529 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
3530 #endif // UNIATA_USE_XXableInterrupts
3532 //ASSERT(!deviceExtension->simplexOnly);
3537 // Check other channel
3538 // In simplex mode no interrupts must appear on other channels
3539 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3540 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3546 chan
= &(deviceExtension
->chan
[c
]);
3548 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
3549 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3550 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) == CHECK_INTR_DETECTED
)
3552 //ASSERT(!deviceExtension->simplexOnly);
3553 chan
->DpcState
= DPC_STATE_ISR
;
3554 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3555 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3559 KdPrint2((PRINT_PREFIX
"AtapiCallBack: return\n"));
3562 } // end AtapiCallBack__()
3567 IN PVOID HwDeviceExtension
3570 AtapiCallBack__(HwDeviceExtension
, (UCHAR
)((PHW_DEVICE_EXTENSION
)HwDeviceExtension
)->ActiveDpcChan
);
3571 } // end AtapiCallBack_X()
3573 #endif //UNIATA_CORE
3577 Routine Description:
3579 This is the interrupt service routine for ATAPI IDE miniport driver.
3583 HwDeviceExtension - HBA miniport driver's adapter data storage
3587 TRUE if expecting an interrupt.
3593 IN PVOID HwDeviceExtension
3596 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3598 BOOLEAN status
= FALSE
;
3602 //BOOLEAN checked[AHCI_MAX_PORT];
3606 KdPrint2((PRINT_PREFIX
"Intr: VendorID+DeviceID/Rev %#x/%#x (ex %d)\n",
3607 deviceExtension
->DevID
, deviceExtension
->RevID
, deviceExtension
->ExpectingInterrupt
));
3609 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3610 // AHCI may generate state change notification, never skip this check
3611 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
3612 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3616 // assume all non-interrupted ports to be already checked
3618 // assume all not implemented ports to be already checked
3619 checked
|= ~deviceExtension
->AHCI_PI
;
3621 checked
= 0; // assume all ports are not checked
3624 if(!deviceExtension
->ExpectingInterrupt
) {
3625 // if we do not expect interrupt, exit now,
3626 // but keep in mind that it can be unexpected one
3627 // Note: this is just a hint, not exact counter
3628 KdPrint2((PRINT_PREFIX
"unexpected, 1st chance\n"));
3629 //deviceExtension->ExpectingInterrupt++;
3632 // clear this flag now, it can be set again in sub-calls
3633 deviceExtension
->ExpectingInterrupt
=0;
3636 // for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
3637 // checked[_c] = (UCHAR)((hIS >> _c) & 0x01);
3641 for(pass
=0; pass
<2; pass
++) {
3642 //KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): pass %d\n", pass));
3643 if(status
&& pass
) {
3644 // we catched some expected interrupts now.
3645 // do not touch unexpected until next ISR call
3648 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3650 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3652 if((checked
>>c
) & 0x01)
3655 // check non-empty and expecting interrupt channels first
3656 if(!pass
&& !deviceExtension
->chan
[c
].ExpectingInterrupt
)
3659 checked
|= (ULONG
)1 << c
;
3661 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3663 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3664 // we get here on idle channels or when ISR is posted to DPC
3665 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): disabled INTR on ch %d\n", c
));
3668 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
3670 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): try lock\n"));
3671 // c_state = deviceExtension->chan[c].CheckIntr;
3672 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
3673 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
3676 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3677 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3678 CRNT_ILK_TYPE CHECK_INTR_DETECTED
);
3679 if(c_state
== CHECK_INTR_IDLE
) {
3680 // c_state = deviceExtension->chan[c].CheckIntr;
3681 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
3682 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
3685 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3686 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3687 CRNT_ILK_TYPE CHECK_INTR_IDLE
);
3689 } while(c_state
== CHECK_INTR_CHECK
);
3690 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): locked\n"));
3691 // check if already serviced
3692 if(c_state
== CHECK_INTR_ACTIVE
) {
3693 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
3697 if((c_state
== CHECK_INTR_DETECTED
) ||
3698 (i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3700 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
3701 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): Catch unexpected\n"));
3702 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3707 // disable interrupts on other channel of legacy mode
3708 // ISA-bridged onboard controller
3709 if(deviceExtension
->simplexOnly
/*||
3710 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3711 AtapiDisableInterrupts(deviceExtension
, !c
);
3714 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_ISR
;
3715 if(AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3716 deviceExtension
->LastInterruptedChannel
= (UCHAR
)c
;
3717 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): return status TRUE\n"));
3720 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
3721 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3724 // re-enable interrupts on other channel
3725 if(deviceExtension
->simplexOnly
/*||
3726 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3727 AtapiEnableInterrupts(deviceExtension
, !c
);
3731 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
3732 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3737 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): exit with status %#x\n", status
));
3739 deviceExtension
->FirstChannelToCheck
++;
3740 if(deviceExtension
->FirstChannelToCheck
>= deviceExtension
->NumberChannels
)
3741 deviceExtension
->FirstChannelToCheck
= 0;
3744 } // end AtapiInterrupt()
3752 IN PKINTERRUPT Interrupt
,
3753 IN PVOID Isr2HwDeviceExtension
3756 // This ISR is intended to catch interrupts when we are already in other ISR instance
3757 // for the same device. This may happen when we have multiple channels,
3758 // especially on SMP machines
3760 PISR2_DEVICE_EXTENSION Isr2DeviceExtension
= (PISR2_DEVICE_EXTENSION
)Isr2HwDeviceExtension
;
3761 PHW_DEVICE_EXTENSION deviceExtension
= Isr2DeviceExtension
->HwDeviceExtension
;
3763 BOOLEAN status
= FALSE
;
3769 // we should never get here for ISA/MCA
3770 if(!BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
3771 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3775 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3776 // AHCI may generate state change notification, never skip this check
3777 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
3778 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3782 // assume all non-interrupted ports to be already checked
3784 // assume all not implemented ports to be already checked
3785 checked
|= ~deviceExtension
->AHCI_PI
;
3788 checked
= 0; // assume all ports are not checked
3790 if(!deviceExtension
->ExpectingInterrupt
) {
3791 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !deviceExtension->ExpectingInterrupt\n"));
3792 deviceExtension
->ExpectingInterrupt
++;
3795 //deviceExtension->ExpectingInterrupt = 0;
3797 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3798 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3800 if((checked
>>c
) & 0x01)
3803 checked
|= (ULONG
)1 << c
;
3805 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3806 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: disabled INTR\n"));
3810 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3811 CRNT_ILK_TYPE CHECK_INTR_CHECK
,
3812 CRNT_ILK_TYPE CHECK_INTR_IDLE
) != CHECK_INTR_IDLE
)
3814 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
3815 // hunt on unexpected intr (Some devices generate double interrupts,
3816 // some controllers (at least CMD649) interrupt twice with small delay.
3817 // If interrupts are disabled, they queue interrupt and re-issue it later,
3818 // when we do not expect it.
3823 if((i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3825 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: intr\n"));
3826 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
3827 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: Catch unexpected\n"));
3828 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3833 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_DETECTED
);
3835 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3838 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: status %d, c_count %d\n", status
, c_count
));
3839 if(status
&& (c_count
!= deviceExtension
->NumberChannels
)) {
3840 // there is an active ISR/DPC for one channel, but
3841 // we have an interrupt from another one
3842 // Lets inform current ISR/DPC about new interrupt
3843 InterlockedExchange(&(deviceExtension
->ReCheckIntr
), CHECK_INTR_DETECTED
);
3847 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: return %d\n", status
));
3850 } // end AtapiInterrupt2()
3852 RETTYPE_XXableInterrupts
3855 IN PVOID HwDeviceExtension
3858 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3861 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3862 KdPrint2((PRINT_PREFIX
"AtapiInterruptDpc: %#x\n",c
));
3864 if(!(deviceExtension
->chan
[c
].ChannelCtrlFlags
& CTRFLAGS_DPC_REQ
)) {
3866 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3867 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3868 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
)
3874 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_DPC_REQ
;
3877 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
3878 AtapiDisableInterrupts(deviceExtension, lChannel);
3881 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_DPC
;
3882 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3883 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3886 return RETVAL_XXableInterrupts
;
3887 } // end AtapiInterruptDpc()
3890 RETTYPE_XXableInterrupts
3892 AtapiEnableInterrupts__(
3893 IN PVOID HwDeviceExtension
3896 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3897 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__():\n"));
3899 PHW_CHANNEL chan
= NULL
;
3901 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3902 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__(2): %#x\n",c
));
3903 chan
= &(deviceExtension
->chan
[c
]);
3905 if(chan
->ChannelCtrlFlags
& CTRFLAGS_ENABLE_INTR_REQ
) {
3906 // enable intrs on requested channel
3907 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_ENABLE_INTR_REQ
;
3908 AtapiEnableInterrupts(HwDeviceExtension
, c
);
3909 InterlockedExchange(&(chan
->CheckIntr
),
3912 // check if current or other channel(s) interrupted
3913 //AtapiInterrupt(HwDeviceExtension);
3915 if(deviceExtension
->simplexOnly
) {
3919 // check if other channel(s) interrupted
3920 // must do nothing in simplex mode
3921 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
3922 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3923 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
3926 //ASSERT(!deviceExtension->simplexOnly);
3927 chan
->DpcState
= DPC_STATE_ISR
;
3928 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3929 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3933 // In simplex mode next command must be sent to device here
3934 if(deviceExtension
->simplexOnly
&& chan
) {
3935 PSCSI_REQUEST_BLOCK srb
;
3936 chan
= UniataGetNextChannel(chan
);
3938 srb
= UniataGetCurRequest(chan
);
3943 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3947 return RETVAL_XXableInterrupts
;
3949 } // end AtapiEnableInterrupts__()
3951 #endif //UNIATA_CORE
3956 AtapiEnableInterrupts(
3957 IN PVOID HwDeviceExtension
,
3961 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3965 if(c
>= deviceExtension
->NumberChannels
) {
3966 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c
));
3969 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
3970 !UniataAhciChanImplemented(deviceExtension
, c
)) {
3971 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c
));
3975 chan
= &(deviceExtension
->chan
[c
]);
3976 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
3977 if(!InterlockedDecrement(&chan
->DisableIntr
)) {
3978 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3979 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
3980 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
3981 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_INF
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
3982 ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
: 0) |
3983 ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
| /* DEBUG */
3985 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
3986 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
)
3989 //SelectDrive(chan, 0);
3990 //GetBaseStatus(chan, statusByte);
3991 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
3993 //if(chan->NumberLuns) {
3994 // SelectDrive(chan, 1);
3995 // GetBaseStatus(chan, statusByte);
3996 // AtapiWritePort1(chan, IDX_IO2_o_Control,
3998 // SelectDrive(chan, chan->cur_cdev);
4001 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_INTR_DISABLED
;
4003 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4004 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4007 } // end AtapiEnableInterrupts()
4011 AtapiDisableInterrupts(
4012 IN PVOID HwDeviceExtension
,
4016 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4018 if(c
>= deviceExtension
->NumberChannels
) {
4019 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c
));
4022 chan
= &(deviceExtension
->chan
[c
]);
4023 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
4024 // mark channel as busy
4025 if(InterlockedIncrement(&chan
->DisableIntr
)) {
4026 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4027 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
4029 //SelectDrive(chan, 0);
4030 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4031 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4032 //if(chan->NumberLuns) {
4033 // SelectDrive(chan, 1);
4034 // AtapiWritePort1(chan, IDX_IO2_o_Control,
4035 // IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4036 // SelectDrive(chan, chan->cur_cdev);
4039 chan
->ChannelCtrlFlags
|= CTRFLAGS_INTR_DISABLED
;
4043 } // end AtapiDisableInterrupts()
4046 UniataExpectChannelInterrupt(
4047 IN
struct _HW_CHANNEL
* chan
,
4048 IN BOOLEAN Expecting
4051 chan
->ExpectingInterrupt
= Expecting
;
4053 chan
->DeviceExtension
->ExpectingInterrupt
++;
4055 if(chan
->DeviceExtension
->ExpectingInterrupt
) {
4056 chan
->DeviceExtension
->ExpectingInterrupt
--;
4059 } // end UniataExpectChannelInterrupt()
4062 Check hardware for interrupt state
4066 AtapiCheckInterrupt__(
4067 IN PVOID HwDeviceExtension
,
4068 IN UCHAR c
// logical channel
4071 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4072 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4073 PHW_LU_EXTENSION LunExt
;
4075 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
4076 ULONG ChipType
= deviceExtension
->HwFlags
& CHIPTYPE_MASK
;
4079 ULONG pr_status
= 0;
4080 UCHAR dma_status
= 0;
4083 UCHAR statusByte
= 0;
4084 ULONG slotNumber
= deviceExtension
->slotNumber
;
4085 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
4086 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
4089 BOOLEAN DmaTransfer
= FALSE
;
4090 BOOLEAN OurInterrupt
= FALSE
;
4091 BOOLEAN StatusValid
= FALSE
;
4093 UCHAR interruptReason
;
4094 BOOLEAN EarlyIntr
= FALSE
;
4095 BOOLEAN SingleBlockIntr
= FALSE
;
4097 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__:\n"));
4100 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4101 LunExt
= chan
->lun
[chan
->cur_cdev
];
4103 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ chan %#x:\n", chan));
4104 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ (%d/%d):\n", Channel, chan->cur_cdev));
4106 if((ChipFlags
& UNIATA_AHCI
) &&
4107 UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4109 if(!UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
4110 return OurInterrupt
;
4113 OurInterrupt
= UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
4114 if((OurInterrupt
== INTERRUPT_REASON_UNEXPECTED
) &&
4115 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
4116 UniataAhciWaitCommandReady(chan
, 2 /* ms */ );
4117 statusByte
= (UCHAR
)UniataAhciWaitReady(chan
, 0 /* immediate */);
4118 if(!(statusByte
& (IDE_STATUS_BUSY
)) ) {
4119 KdPrint2((PRINT_PREFIX
"ATAPI special case READY\n"));
4120 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
4121 OurInterrupt
= INTERRUPT_REASON_OUR
;
4123 if((statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
)) == (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
) ) {
4124 KdPrint2((PRINT_PREFIX
"ATAPI special case pre ERR-READY\n"));
4125 OurInterrupt
= INTERRUPT_REASON_OUR
;
4127 if(statusByte
& IDE_STATUS_ERROR
) {
4128 KdPrint2((PRINT_PREFIX
"ATAPI special case ERR-READY\n"));
4129 OurInterrupt
= INTERRUPT_REASON_OUR
;
4131 KdPrint2((PRINT_PREFIX
"ATAPI special case ? %x\n", statusByte
));
4132 OurInterrupt
= INTERRUPT_REASON_OUR
;
4135 return OurInterrupt
;
4138 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4140 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension
->DevIndex
,
4141 deviceExtension
->Channel
+ c
, c
));
4143 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension
->DevIndex
,
4144 deviceExtension
->Channel
+ c
, c
));
4145 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4146 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
4149 // do controller-specific interrupt servicing staff
4150 if(deviceExtension
->UnknownDev
) {
4151 KdPrint2((PRINT_PREFIX
" UnknownDev\n"));
4156 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
4157 // Such behavior was observed with Intel ICH-xxx chips
4158 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
4162 case ATA_PROMISE_ID
: {
4166 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x1c);
4170 ((Channel
) ? 0x00004000 : 0x00000400))) {
4171 KdPrint2((PRINT_PREFIX
" Promise old/new unexpected\n"));
4172 return INTERRUPT_REASON_IGNORE
;
4176 AtapiWritePort1(chan
, IDX_BM_DeviceSpecific0
, 0x0b);
4177 status
= AtapiReadPort1(chan
, IDX_BM_DeviceSpecific1
);
4180 if(!(status
& 0x20)) {
4181 KdPrint2((PRINT_PREFIX
" Promise tx unexpected\n"));
4182 return INTERRUPT_REASON_IGNORE
;
4186 ULONG stat_reg
= (ChipFlags
& PRG2
) ? 0x60 : 0x6c;
4187 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x40);
4188 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x40, status
);
4190 if(status
& (1 << (Channel
+1))) {
4193 KdPrint2((PRINT_PREFIX
" Promise mio unexpected\n"));
4194 return INTERRUPT_REASON_IGNORE
;
4197 if(!(ChipFlags
& UNIATA_SATA
))
4200 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),stat_reg
);
4201 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),stat_reg
, (pr_status
& (0x11 << Channel
)));
4202 if(pr_status
& (0x11 << Channel
)) {
4203 // TODO: reset channel
4204 KdPrint2((PRINT_PREFIX
" Promise mio unexpected + reset req\n"));
4205 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, 0);
4207 if(!(status
& (0x01 << Channel
))) {
4209 KdPrint2((PRINT_PREFIX
" Promise mio unexpected attach\n"));
4210 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, 0);
4212 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4213 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4215 return INTERRUPT_REASON_IGNORE
;
4218 AtapiWritePort4(chan
, IDX_BM_DeviceSpecific0
, 0x00000001);
4222 case ATA_NVIDIA_ID
: {
4223 if(!(ChipFlags
& UNIATA_SATA
))
4226 KdPrint2((PRINT_PREFIX
"NVIDIA\n"));
4228 ULONG offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
4229 ULONG shift
= Channel
<< ((ChipFlags
& NVQ
) ? 4 : 2);
4231 /* get and clear interrupt status */
4232 if(ChipFlags
& NVQ
) {
4233 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4234 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0fUL
<< shift
) | 0x00f000f0);
4236 pr_status
= AtapiReadPortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4237 AtapiWritePortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0f << shift
));
4239 KdPrint2((PRINT_PREFIX
" pr_status %x\n", pr_status
));
4241 /* check for and handle connect events */
4242 if(((pr_status
& (0x0cUL
<< shift
)) == (0x04UL
<< shift
)) ) {
4243 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, 0);
4245 /* check for and handle disconnect events */
4246 if((pr_status
& (0x08UL
<< shift
)) &&
4247 !((pr_status
& (0x04UL
<< shift
) &&
4248 UniataSataReadPort4(chan
, IDX_SATA_SStatus
, 0))) ) {
4249 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, 0);
4251 /* do we have any device action ? */
4252 if(!(pr_status
& (0x01UL
<< shift
))) {
4253 KdPrint2((PRINT_PREFIX
" nVidia unexpected\n"));
4254 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4255 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4257 return INTERRUPT_REASON_IGNORE
;
4263 KdPrint2((PRINT_PREFIX
"ATI\n"));
4264 if(ChipType
== SIIMIO
) {
4269 case ATA_SILICON_IMAGE_ID
:
4271 if(ChipType
== SIIMIO
) {
4273 reg32
= AtapiReadPort4(chan
, IDX_BM_DeviceSpecific0
);
4274 KdPrint2((PRINT_PREFIX
" Sii DS0 %x\n", reg32
));
4275 if(reg32
== 0xffffffff) {
4276 KdPrint2((PRINT_PREFIX
" Sii mio unexpected\n"));
4277 return INTERRUPT_REASON_IGNORE
;
4279 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
))) {
4280 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (2)\n"));
4281 return INTERRUPT_REASON_IGNORE
;
4284 if(ChipFlags
& UNIATA_SATA
) {
4285 if(reg32
& (BM_DS0_SII_DMA_SATA_IRQ
| BM_DS0_SII_IRQ
)) {
4287 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
4288 * controllers continue to assert IRQ as long as
4289 * SError bits are pending. Clear SError immediately.
4291 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4292 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4299 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4300 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (3)\n"));
4301 return OurInterrupt
;
4303 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
& ~BM_STATUS_ERR
);
4304 goto skip_dma_stat_check
;
4307 if(!(deviceExtension
->HwFlags
& SIIINTR
))
4309 GetPciConfig1(0x71, reg8
);
4310 KdPrint2((PRINT_PREFIX
" 0x71 = %#x\n", reg8
));
4312 (Channel
? 0x08 : 0x04))) {
4313 return INTERRUPT_REASON_IGNORE
;
4316 KdPrint2((PRINT_PREFIX
" cmd our\n"));
4317 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4319 SetPciConfig1(0x71, (Channel
? 0x08 : 0x04));
4326 //dma_status = GetDmaStatus(deviceExtension, lChannel);
4327 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4328 KdPrint2((PRINT_PREFIX
" Acard unexpected\n"));
4329 return INTERRUPT_REASON_IGNORE
;
4331 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
| BM_STATUS_INTR
);
4332 AtapiStallExecution(1);
4333 AtapiWritePort1(chan
, IDX_BM_Command
,
4334 AtapiReadPort1(chan
, IDX_BM_Command
) & ~BM_COMMAND_START_STOP
);
4335 goto skip_dma_stat_check
;
4337 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4338 if(ChipFlags
& UNIATA_AHCI
) {
4341 if(ChipFlags
& UNIATA_SATA
) {
4342 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4343 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4345 if(!(chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
4346 if(UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, 1)) {
4347 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4354 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4355 if(ChipFlags
& UNIATA_AHCI
) {
4358 if(ChipFlags
& UNIATA_SATA
) {
4359 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4360 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4366 KdPrint2((PRINT_PREFIX
" perform generic check\n"));
4368 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4369 KdPrint2((PRINT_PREFIX
" DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status
));
4370 if(dma_status
& BM_STATUS_ERR
) {
4371 KdPrint2((PRINT_PREFIX
" DmaTransfer + BM_STATUS_ERR -> our\n"));
4372 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4374 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4375 GetStatus(chan
, statusByte
);
4377 KdPrint2((PRINT_PREFIX
" status %#x\n", statusByte
));
4378 if(statusByte
& IDE_STATUS_ERROR
) {
4379 KdPrint2((PRINT_PREFIX
" IDE_STATUS_ERROR -> our\n", statusByte
));
4380 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4382 if ((statusByte
& IDE_STATUS_DSC
) &&
4383 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
4384 (dma_status
== BM_STATUS_ACTIVE
)) {
4385 KdPrint2((PRINT_PREFIX
" special case DMA + ATAPI + IDE_STATUS_DSC -> our\n", statusByte
));
4386 // some devices interrupts on each block transfer even in DMA mode
4387 if(LunExt
->TransferMode
>= ATA_SDMA
&& LunExt
->TransferMode
<= ATA_WDMA2
) {
4388 KdPrint2((PRINT_PREFIX
" wait for completion\n"));
4389 ///* clear interrupt and get status */
4390 //GetBaseStatus(chan, statusByte);
4391 //return INTERRUPT_REASON_IGNORE;
4392 SingleBlockIntr
= TRUE
;
4395 return INTERRUPT_REASON_IGNORE
;
4400 if(dma_status
& BM_STATUS_INTR
) {
4401 // bullshit, we have DMA interrupt, but had never initiate DMA operation
4402 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr\n"));
4403 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4405 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4408 skip_dma_stat_check
:
4409 if(!(ChipFlags
& UNIATA_SATA
) && chan
->ExpectingInterrupt
) {
4410 AtapiStallExecution(1);
4413 /* if drive is busy it didn't interrupt */
4414 /* the exception is DCS + BSY state of ATAPI devices */
4416 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4417 GetStatus(chan
, statusByte
);
4419 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4420 KdPrint3((PRINT_PREFIX
" ATAPI status %#x\n", statusByte
));
4422 KdPrint2((PRINT_PREFIX
" IDE status %#x\n", statusByte
));
4424 if (statusByte
== IDE_STATUS_WRONG
) {
4425 // interrupt from empty controller ?
4427 if (statusByte
& IDE_STATUS_BUSY
) {
4428 if(!chan
->ExpectingInterrupt
) {
4429 KdPrint3((PRINT_PREFIX
" unexpected intr + BUSY\n"));
4430 return OurInterrupt
;
4433 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4434 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4436 KdPrint2((PRINT_PREFIX
" expecting intr + BUSY (3), non ATAPI\n"));
4437 return INTERRUPT_REASON_IGNORE
;
4439 if((statusByte
& ~IDE_STATUS_DRQ
) != (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
| IDE_STATUS_DSC
)) {
4440 KdPrint3((PRINT_PREFIX
" unexpected status, seems it is not our\n"));
4441 return INTERRUPT_REASON_IGNORE
;
4443 if(!(LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
) && (statusByte
& IDE_STATUS_DRQ
)) {
4444 KdPrint3((PRINT_PREFIX
" unexpected DRQ, seems it is not our\n"));
4445 return INTERRUPT_REASON_IGNORE
;
4450 if(dma_status
& BM_STATUS_INTR
) {
4451 KdPrint3((PRINT_PREFIX
" our interrupt with BSY set, try wait in ISR or post to DPC\n"));
4452 /* clear interrupt and get status */
4453 GetBaseStatus(chan
, statusByte
);
4454 if(!(dma_status
& BM_STATUS_ACTIVE
)) {
4455 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4457 KdPrint3((PRINT_PREFIX
" base status %#x (+BM_STATUS_INTR)\n", statusByte
));
4458 return INTERRUPT_REASON_OUR
;
4461 if(g_WaitBusyInISR
) {
4462 GetStatus(chan
, statusByte
);
4463 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4464 reg8
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4465 KdPrint2((PRINT_PREFIX
" Error reg (%#x)\n", reg8
));
4466 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4467 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4469 if (statusByte
& IDE_STATUS_BUSY
) {
4470 KdPrint2((PRINT_PREFIX
" still BUSY, seems it is not our\n"));
4471 return INTERRUPT_REASON_IGNORE
;
4477 /* clear interrupt and get status */
4478 GetBaseStatus(chan
, statusByte
);
4479 KdPrint2((PRINT_PREFIX
" base status %#x\n", statusByte
));
4480 if (statusByte
== IDE_STATUS_WRONG
) {
4481 // interrupt from empty controller ?
4483 if(!(statusByte
& (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
))) {
4484 KdPrint2((PRINT_PREFIX
" no DRQ/DRDY set\n"));
4485 return OurInterrupt
;
4488 #ifndef UNIATA_PIO_ONLY
4490 if(!SingleBlockIntr
&& (!EarlyIntr
|| g_WaitBusyInISR
)) {
4491 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4493 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4494 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4498 if(SingleBlockIntr
) {
4499 KdPrint2((PRINT_PREFIX
" set REQ_STATE_ATAPI_EXPECTING_DATA_INTR2.\n"));
4501 KdPrint2((PRINT_PREFIX
" set REQ_STATE_EARLY_INTR.\n"));
4504 AtaReq
->ReqState
= SingleBlockIntr
? REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
: REQ_STATE_EARLY_INTR
;
4510 if (!(chan
->ExpectingInterrupt
)) {
4512 KdPrint2((PRINT_PREFIX
" Unexpected interrupt.\n"));
4514 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4515 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4517 KdPrint2((PRINT_PREFIX
" OurInterrupt = %d\n", OurInterrupt
));
4518 return OurInterrupt
;
4520 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
4521 KdPrint3((PRINT_PREFIX
"AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason
));
4522 return OurInterrupt
;
4524 //ASSERT(!chan->queue_depth || chan->cur_req);
4526 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__: exit with TRUE\n"));
4527 return INTERRUPT_REASON_OUR
;
4529 } // end AtapiCheckInterrupt__()
4535 IN PVOID HwDeviceExtension
,
4539 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4540 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4542 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4543 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4545 ULONG wordCount
= 0, wordsThisInterrupt
= DEV_BSIZE
/2;
4546 ULONG status
= SRB_STATUS_SUCCESS
;
4547 UCHAR dma_status
= 0;
4550 UCHAR statusByte
= 0,interruptReason
;
4552 BOOLEAN atapiDev
= FALSE
;
4559 BOOLEAN DmaTransfer
= FALSE
;
4561 ULONG TimerValue
= 1000;
4562 ULONG TotalTimerValue
= 0;
4563 #ifdef UNIATA_USE_XXableInterrupts
4564 BOOLEAN InDpc
= (KeGetCurrentIrql() == DISPATCH_LEVEL
);
4566 BOOLEAN InDpc
= (chan
->DpcState
!= DPC_STATE_ISR
);
4567 #endif // UNIATA_USE_XXableInterrupts
4568 BOOLEAN UseDpc
= deviceExtension
->UseDpc
;
4569 // BOOLEAN RestoreUseDpc = FALSE;
4570 BOOLEAN DataOverrun
= FALSE
;
4571 BOOLEAN NoStartIo
= TRUE
;
4572 BOOLEAN NoRetry
= FALSE
;
4574 KdPrint2((PRINT_PREFIX
"AtapiInterrupt:\n"));
4576 KdPrint2((PRINT_PREFIX
" InDpc = TRUE\n"));
4577 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
4583 UCHAR OldReqState
= REQ_STATE_NONE
;
4585 PHW_LU_EXTENSION LunExt
;
4590 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4592 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension
->DevIndex
, Channel
, KeGetCurrentIrql(), c
));
4595 if((chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
4596 (AtaReq
&& (AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
)) ||
4597 (deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
4599 KdPrint2((PRINT_PREFIX
" DmaTransfer = TRUE\n"));
4603 PathId
= srb
->PathId
;
4604 TargetId
= srb
->TargetId
;
4610 goto enqueue_next_req
;
4613 //ldev = GET_LDEV2(PathId, TargetId, Lun);
4614 DeviceNumber
= (UCHAR
)(TargetId
);
4615 LunExt
= chan
->lun
[DeviceNumber
];
4616 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
4617 KdPrint2((PRINT_PREFIX
" dev_type %s\n", atapiDev
? "ATAPI" : "IDE"));
4619 // check if we are in ISR DPC
4621 KdPrint2((PRINT_PREFIX
" InDpc -> CTRFLAGS_INTR_DISABLED\n"));
4622 goto ServiceInterrupt
;
4626 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4629 if (!(chan
->ExpectingInterrupt
)) {
4631 KdPrint2((PRINT_PREFIX
" Unexpected interrupt for this channel.\n"));
4635 // change request state
4637 OldReqState
= AtaReq
->ReqState
;
4638 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4639 KdPrint2((PRINT_PREFIX
" OldReqState = %x\n", OldReqState
));
4642 // We don't want using DPC for fast operations, like
4643 // DMA completion, sending CDB, short ATAPI transfers, etc.
4645 // We MUST use DPC, because of interprocessor synchronization
4646 // on multiprocessor platforms
4649 goto ServiceInterrupt
;
4651 switch(OldReqState
) {
4652 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR
:
4653 KdPrint3((PRINT_PREFIX
" EXPECTING_CMD_INTR\n"));
4654 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR
:
4655 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
:
4656 case REQ_STATE_DPC_WAIT_BUSY0
:
4657 case REQ_STATE_DPC_WAIT_BUSY1
:
4658 KdPrint2((PRINT_PREFIX
" continue service interrupt\n"));
4659 goto ServiceInterrupt
;
4660 case REQ_STATE_ATAPI_DO_NOTHING_INTR
:
4661 KdPrint2((PRINT_PREFIX
" do nothing on interrupt\n"));
4665 if(!DmaTransfer
&& !atapiDev
) {
4666 KdPrint2((PRINT_PREFIX
" service PIO HDD\n"));
4673 goto ServiceInterrupt
;
4675 #ifdef UNIATA_USE_XXableInterrupts
4677 KdPrint2((PRINT_PREFIX
" Unexpected InDpc\n"));
4679 // shall never get here
4684 KdPrint2((PRINT_PREFIX
" this is direct DPC call on DRQL\n"));
4686 AtaReq
->ReqState
= REQ_STATE_DPC_INTR_REQ
;
4687 KdPrint2((PRINT_PREFIX
" ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
4689 KdPrint2((PRINT_PREFIX
" DPC without AtaReq!!!\n"));
4692 KdPrint2((PRINT_PREFIX
"call service interrupt\n"));
4693 goto ServiceInterrupt
;
4694 #endif // UNIATA_USE_XXableInterrupts
4699 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
4700 // We always get here when are called from timer callback, which is invoked on DRQL.
4701 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
4703 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: start DPC init...\n"));
4704 // disable interrupts for this channel,
4705 // but avoid recursion and double-disable
4706 if(OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4707 UniataExpectChannelInterrupt(chan
, FALSE
);
4708 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4711 chan
->ChannelCtrlFlags
|= CTRFLAGS_DPC_REQ
;
4713 #ifdef UNIATA_USE_XXableInterrupts
4714 // Will lower IRQL to DISPATCH_LEVEL
4715 ScsiPortNotification(CallEnableInterrupts
, HwDeviceExtension
,
4716 /*c ?*/ AtapiInterruptDpc
/*_1 : AtapiInterruptDpc_0*/);
4717 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DPC inited\n"));
4719 // Will raise IRQL to DIRQL
4720 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4723 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
4724 #endif // UNIATA_USE_XXableInterrupts
4729 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4731 if(!InDpc
&& OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4732 // we must block interrupts from this channel
4733 // If device generate new interrupt before we get to DPC,
4734 // ISR will assume, that it is NOT our interrupt
4735 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4736 // We should not clean ExpectingInterrupt flag on channel, since it is used in DPC
4738 // Will raise IRQL to DIRQL
4739 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4743 #endif //UNIATA_CORE
4747 if(AtaReq
&& InDpc
) {
4748 switch(AtaReq
->ReqState
) {
4749 case REQ_STATE_DPC_WAIT_DRQ0
:
4751 case REQ_STATE_DPC_WAIT_BUSY
:
4753 case REQ_STATE_DPC_WAIT_DRQ
:
4755 case REQ_STATE_DPC_WAIT_DRQ_ERR
:
4757 case REQ_STATE_DPC_WAIT_BUSY0
:
4758 case REQ_STATE_DPC_WAIT_BUSY1
:
4759 // continue normal execution
4765 #endif //UNIATA_CORE
4767 // make additional delay for old devices (if we are not in DPC)
4768 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
4772 !(deviceExtension->HwFlags & UNIATA_SATA)
4774 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
4775 AtapiStallExecution(10);
4779 /* clear interrupt and get status */
4780 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4781 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, srb
);
4782 statusByte
= (UCHAR
)(AtaReq
->ahci
.in_status
& IDE_STATUS_MASK
);
4784 if(chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
)) {
4785 KdPrint3((PRINT_PREFIX
"Err intr (%#x), SE (%#x)\n",
4786 chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
),
4787 chan
->AhciLastSError
));
4788 if(chan
->AhciLastIS
& ~ATA_AHCI_P_IX_OF
) {
4789 //KdPrint3((PRINT_PREFIX "Err mask (%#x)\n", chan->AhciLastIS & ~ATA_AHCI_P_IX_OF));
4790 // We have some other error except Overflow
4791 // Just signal ERROR, operation will be aborted in ERROR branch.
4792 statusByte
|= IDE_STATUS_ERROR
;
4793 AtaReq
->ahci
.in_serror
= chan
->AhciLastSError
;
4794 if(chan
->AhciLastSError
& (ATA_SE_HANDSHAKE_ERR
| ATA_SE_LINKSEQ_ERR
| ATA_SE_TRANSPORT_ERR
| ATA_SE_UNKNOWN_FIS
)) {
4795 KdPrint2((PRINT_PREFIX
"Unrecoverable\n"));
4799 // We have only Overflow. Abort operation and continue
4801 UniataDumpAhciPortRegs(chan
);
4803 if(!UniataAhciAbortOperation(chan
)) {
4804 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
4807 UniataDumpAhciPortRegs(chan
);
4809 UniataAhciWaitCommandReady(chan
, 10);
4814 GetBaseStatus(chan
, statusByte
);
4817 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte
));
4819 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Entered with status (%#x)\n", statusByte
));
4823 KdPrint2((PRINT_PREFIX
" operate like in DPC\n"));
4829 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4830 KdPrint3((PRINT_PREFIX
" AHCI branch (IDE)\n"));
4832 if (statusByte
& IDE_STATUS_BUSY
) {
4833 if (deviceExtension
->DriverMustPoll
) {
4834 // Crashdump is polling and we got caught with busy asserted.
4835 // Just go away, and we will be polled again shortly.
4836 KdPrint2((PRINT_PREFIX
" Hit BUSY while polling during crashdump.\n"));
4837 goto ReturnEnableIntr
;
4840 // Ensure BUSY is non-asserted.
4841 // make a very small idle before falling to DPC
4842 k
= (InDpc
&& UseDpc
) ? 1000 : 2;
4844 for (i
= 0; i
< k
; i
++) {
4846 GetBaseStatus(chan
, statusByte
);
4847 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4850 AtapiStallExecution(10);
4853 if (!InDpc
&& UseDpc
&& i
== 2) {
4855 KdPrint2((PRINT_PREFIX
" BUSY on entry. Status %#x, Base IO %#x\n", statusByte
));
4858 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4863 AtapiStallExecution(TimerValue
);
4864 goto ServiceInterrupt
;
4865 #endif //UNIATA_CORE
4867 if (InDpc
&& i
== k
) {
4868 // reset the controller.
4869 KdPrint2((PRINT_PREFIX
4870 " Resetting due to BUSY on entry - %#x.\n",
4872 goto IntrPrepareResetController
;
4877 if(!LunExt
->IdentifyData
.MajorRevision
&&
4880 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
4882 //KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n"));
4883 //AtapiStallExecution(10);
4885 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4886 KdPrint3((PRINT_PREFIX
" AHCI branch (ATAPI)\n"));
4888 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
4889 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
4892 if (statusByte
& IDE_STATUS_BUSY
) {
4893 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
4896 // This is just workaround
4897 // We should DISABLE interrupts before entering WAIT state
4898 UniataExpectChannelInterrupt(chan, TRUE);
4899 #endif //UNIATA_CORE
4901 KdPrint3((PRINT_PREFIX
" BUSY on ATAPI device, waiting %d us\n", LunExt
->AtapiReadyWaitDelay
));
4903 if(LunExt
->AtapiReadyWaitDelay
&& (LunExt
->AtapiReadyWaitDelay
> g_opt_MaxIsrWait
) && !InDpc
&& UseDpc
) {
4904 TimerValue
= LunExt
->AtapiReadyWaitDelay
;
4905 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC (0)\n"));
4906 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4909 #endif //UNIATA_CORE
4912 GetBaseStatus(chan
, statusByte
);
4913 KdPrint3((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4914 KdPrint3((PRINT_PREFIX
" Error reg (%#x)\n",
4915 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Error
)));
4916 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4917 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4920 TotalTimerValue
+= TimerValue
;
4922 KdPrint3((PRINT_PREFIX
" too long wait -> DPC\n"));
4924 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC\n"));
4926 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4928 KdPrint2((PRINT_PREFIX
" too long wait: DPC -> DPC\n"));
4930 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY1
;
4934 if(!LunExt
->AtapiReadyWaitDelay
) {
4935 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
4939 #endif //UNIATA_CORE
4942 AtapiStallExecution(TimerValue
);
4945 if(!LunExt
->AtapiReadyWaitDelay
) {
4946 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
4947 KdPrint2((PRINT_PREFIX
" store AtapiReadyWaitDelay: %d\n", LunExt
->AtapiReadyWaitDelay
));
4949 if (statusByte
& IDE_STATUS_BUSY
) {
4950 KdPrint3((PRINT_PREFIX
" expecting intr + BUSY (2), try DPC wait\n"));
4956 if(AtaReq
&& DmaTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
4957 switch(OldReqState
) {
4958 case REQ_STATE_EARLY_INTR
:
4959 case REQ_STATE_DPC_WAIT_BUSY0
:
4961 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4962 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DMA still active\n"));
4963 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4970 // Check for error conditions.
4971 if ((statusByte
& IDE_STATUS_ERROR
) ||
4972 (dma_status
& BM_STATUS_ERR
)) {
4974 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4975 error
= AtaReq
->ahci
.in_error
;
4978 UniataDumpAhciPortRegs(chan
);
4980 if(!UniataAhciAbortOperation(chan
)) {
4981 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
4983 // clear interrupts again
4984 UniataAhciWaitCommandReady(chan
, 10);
4986 UniataDumpAhciPortRegs(chan
);
4988 UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
4990 AtaReq
->retry
+= MAX_RETRIES
;
4991 if(!error
&& (statusByte
& IDE_STATUS_ERROR
)) {
4992 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: force error status\n"));
4993 error
|= IDE_STATUS_ERROR
;
4997 UniataDumpAhciPortRegs(chan
);
5000 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5002 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error %#x\n", error
));
5004 if(error & IDE_STATUS_CORRECTED_ERROR) {
5005 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
5006 statusByte &= ~IDE_STATUS_ERROR;
5011 KdPrint2((PRINT_PREFIX
" Bad Lba %#I64x\n", AtaReq
->lba
));
5013 KdPrint2((PRINT_PREFIX
" Bad Lba unknown\n"));
5016 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5017 KdPrint2((PRINT_PREFIX
" no wait ready after error\n"));
5020 KdPrint2((PRINT_PREFIX
" wait 100 ready after IDE error\n"));
5021 AtapiStallExecution(100);
5023 KdPrint2((PRINT_PREFIX
" wait 10 ready after ATAPI error\n"));
5024 AtapiStallExecution(10);
5028 KdPrint3((PRINT_PREFIX
" Intr on DRQ %x\n",
5029 LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
));
5031 for (k
= atapiDev
? 0 : 200; k
; k
--) {
5032 GetBaseStatus(chan
, statusByte
);
5033 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5034 AtapiStallExecution(50);
5041 /* if this is a UDMA CRC error, reinject request */
5044 if(AtaReq
->retry
< MAX_RETRIES
) {
5045 #ifdef IO_STATISTICS
5046 chan
->lun
[DeviceNumber
]->ModeErrorCount
[AtaReq
->retry
]++;
5047 #endif //IO_STATISTICS
5049 (error & IDE_ERROR_ICRC)*/) {
5050 KdPrint2((PRINT_PREFIX
"Errors in DMA mode\n"));
5051 if(AtaReq
->retry
< MAX_RETRIES
) {
5053 if(!(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
5054 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5055 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5056 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5058 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5062 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5065 KdPrint2((PRINT_PREFIX
"Errors in PIO mode\n"));
5069 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5070 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason
));
5072 if(DmaTransfer
&& (chan
->lun
[DeviceNumber
]->TransferMode
> ATA_UDMA2
) &&
5073 ((error
>> 4) == SCSI_SENSE_HARDWARE_ERROR
)) {
5074 if(AtaReq
->retry
< MAX_RETRIES
) {
5076 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5077 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5078 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5079 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5083 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5086 KdPrint3((PRINT_PREFIX
"Errors in PIO mode\n"));
5090 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error\n"));
5091 if (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
5092 // Fail this request.
5093 status
= SRB_STATUS_ERROR
;
5094 goto CompleteRequest
;
5096 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n"));
5099 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE_LBA48
) {
5100 KdPrint2((PRINT_PREFIX
"DMA doesn't work right with LBA48\n"));
5101 deviceExtension
->HbaCtrlFlags
|= HBAFLAGS_DMA_DISABLED_LBA48
;
5103 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
) {
5104 #ifdef IO_STATISTICS
5105 KdPrint2((PRINT_PREFIX
"Some higher mode doesn't work right :((\n"));
5106 KdPrint2((PRINT_PREFIX
"Recovery stats[%d]: %d vs %d\n",
5108 LunExt
->RecoverCount
[AtaReq
->retry
],
5109 LunExt
->BlockIoCount
5111 LunExt
->RecoverCount
[AtaReq
->retry
]++;
5112 if(LunExt
->RecoverCount
[AtaReq
->retry
] >= chan
->lun
[DeviceNumber
]->BlockIoCount
/3 ||
5113 (deviceExtension
->HwFlags
& UNIATA_NO80CHK
)
5116 if(deviceExtension
->HwFlags
& UNIATA_NO80CHK
) {
5117 #endif //IO_STATISTICS
5118 KdPrint2((PRINT_PREFIX
"Limit transfer rate to %x\n", LunExt
->TransferMode
));
5119 LunExt
->LimitedTransferMode
=
5120 LunExt
->TransferMode
;
5123 #ifdef IO_STATISTICS
5124 if(AtaReq
->bcount
) {
5125 // we need stats for Read/Write operations
5126 LunExt
->BlockIoCount
++;
5129 #endif //IO_STATISTICS
5133 // check reason for this interrupt.
5136 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI branch\n"));
5139 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5140 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
5142 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5144 wordsThisInterrupt
= DEV_BSIZE
/2;
5152 // simulate DRQ for DMA transfers
5153 statusByte
|= IDE_STATUS_DRQ
;
5155 if (statusByte
& IDE_STATUS_DRQ
) {
5158 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5160 if (LunExt
->MaximumBlockXfer
) {
5161 wordsThisInterrupt
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5164 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5166 interruptReason
= ATAPI_IR_IO_toHost
;
5168 } else if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5169 interruptReason
= ATAPI_IR_IO_toDev
;
5172 status
= SRB_STATUS_ERROR
;
5173 goto CompleteRequest
;
5176 } else if (statusByte
& IDE_STATUS_BUSY
) {
5178 //AtapiEnableInterrupts(deviceExtension, lChannel);
5179 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
5184 if (AtaReq
->WordsLeft
) {
5186 // Funky behaviour seen with PCI IDE (not all, just one).
5188 // The ISR hits with DRQ low, but comes up later.
5189 for (k
= 0; k
< 5000; k
++) {
5190 GetBaseStatus(chan
, statusByte
);
5191 if (statusByte
& IDE_STATUS_DRQ
) {
5196 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ0
;
5198 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq0)\n"));
5202 AtapiStallExecution(TimerValue
);
5203 goto ServiceInterrupt
;
5204 #endif //UNIATA_CORE
5206 AtapiStallExecution(100);
5209 // reset the controller.
5210 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
5212 IntrPrepareResetController
:
5213 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
);
5214 goto ReturnEnableIntr
;
5217 interruptReason
= (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? ATAPI_IR_IO_toHost
: ATAPI_IR_IO_toDev
;
5221 // Command complete - verify, write, or the SMART enable/disable.
5222 // Also get_media_status
5223 interruptReason
= ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
;
5228 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason
, statusByte
));
5229 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5230 KdPrint2((PRINT_PREFIX
" AHCI path, WordsTransfered %x, WordsLeft %x\n", AtaReq
->WordsTransfered
, AtaReq
->WordsLeft
));
5231 /* if(chan->AhciLastIS & ATA_AHCI_P_IX_OF) {
5232 //status = SRB_STATUS_DATA_OVERRUN;
5235 status = SRB_STATUS_SUCCESS;
5237 if(AtaReq
->WordsTransfered
>= AtaReq
->WordsLeft
) {
5238 AtaReq
->WordsLeft
= 0;
5240 AtaReq
->WordsLeft
-= AtaReq
->WordsTransfered
;
5242 //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
5243 // status = SRB_STATUS_DATA_OVERRUN;
5245 status
= SRB_STATUS_SUCCESS
;
5246 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5247 goto CompleteRequest
;
5249 if (interruptReason
== ATAPI_IR_COD_Cmd
&& (statusByte
& IDE_STATUS_DRQ
)) {
5250 // Write the packet.
5251 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Writing Atapi packet.\n"));
5252 // Send CDB to device.
5253 WriteBuffer(chan
, (PUSHORT
)srb
->Cdb
,
5254 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
5256 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5258 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
5259 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: AtapiDmaStart().\n"));
5260 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, srb
);
5263 goto ReturnEnableIntr
;
5265 } else if (interruptReason
== ATAPI_IR_IO_toDev
&& (statusByte
& IDE_STATUS_DRQ
)) {
5270 // Pick up bytes to transfer and convert to words.
5272 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
5275 (USHORT
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
5277 // Covert bytes to words.
5279 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get W wordCount %#x\n", wordCount
));
5281 if (wordCount
!= AtaReq
->WordsLeft
) {
5282 KdPrint2((PRINT_PREFIX
5283 "AtapiInterrupt: %d words requested; %d words xferred\n",
5288 // Verify this makes sense.
5289 if (wordCount
> AtaReq
->WordsLeft
) {
5290 wordCount
= AtaReq
->WordsLeft
;
5291 KdPrint2((PRINT_PREFIX
5292 "AtapiInterrupt: Write underrun\n"));
5298 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
5299 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5300 // Transfer only words requested.
5301 wordCount
= AtaReq
->WordsLeft
;
5303 // Transfer next block.
5304 wordCount
= wordsThisInterrupt
;
5309 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5310 //ASSERT(AtaReq->WordsLeft == wordCount);
5311 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5312 KdPrint2((PRINT_PREFIX
5313 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5314 if(AtaReq
->WordsLeft
> wordCount
) {
5315 AtaReq
->WordsLeft
-= wordCount
;
5316 AtaReq
->WordsTransfered
+= wordCount
;
5317 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5318 goto ReturnEnableIntr
;
5320 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5322 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5323 AtaReq
->WordsLeft
= 0;
5324 status
= SRB_STATUS_SUCCESS
;
5325 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5326 goto CompleteRequest
;
5329 // Ensure that this is a write command.
5330 if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5332 KdPrint2((PRINT_PREFIX
5333 "AtapiInterrupt: Write interrupt\n"));
5335 statusByte
= WaitOnBusy(chan
);
5337 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
5342 UniataGetPioTiming(LunExt
));
5346 (PULONG
)(AtaReq
->DataBuffer
),
5348 UniataGetPioTiming(LunExt
));
5352 KdPrint3((PRINT_PREFIX
5353 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5357 // Fail this request.
5358 status
= SRB_STATUS_ERROR
;
5359 goto CompleteRequest
;
5361 // Advance data buffer pointer and bytes left.
5362 AtaReq
->DataBuffer
+= wordCount
;
5363 AtaReq
->WordsLeft
-= wordCount
;
5364 AtaReq
->WordsTransfered
+= wordCount
;
5367 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5370 goto ReturnEnableIntr
;
5372 } else if (interruptReason
== ATAPI_IR_IO_toHost
&& (statusByte
& IDE_STATUS_DRQ
)) {
5377 // Pick up bytes to transfer and convert to words.
5379 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
) |
5380 (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8);
5382 // Convert bytes to words.
5384 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get R wordCount %#x\n", wordCount
));
5386 if (wordCount
!= AtaReq
->WordsLeft
) {
5387 KdPrint2((PRINT_PREFIX
5388 "AtapiInterrupt: %d words requested; %d words xferred\n",
5393 // Verify this makes sense.
5394 if (wordCount
> AtaReq
->WordsLeft
) {
5395 wordCount
= AtaReq
->WordsLeft
;
5401 // Check if words left is at least 256.
5402 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5403 // Transfer only words requested.
5404 wordCount
= AtaReq
->WordsLeft
;
5406 // Transfer next block.
5407 wordCount
= wordsThisInterrupt
;
5412 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5413 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5414 KdPrint2((PRINT_PREFIX
5415 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5416 if(AtaReq
->WordsLeft
> wordCount
) {
5417 AtaReq
->WordsLeft
-= wordCount
;
5418 AtaReq
->WordsTransfered
+= wordCount
;
5419 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5420 goto ReturnEnableIntr
;
5422 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5424 //ASSERT(AtaReq->WordsLeft == wordCount);
5425 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5426 AtaReq
->WordsLeft
= 0;
5427 status
= SRB_STATUS_SUCCESS
;
5428 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5429 goto CompleteRequest
;
5431 // Ensure that this is a read command.
5432 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5435 "AtapiInterrupt: Read interrupt\n"));*/
5437 statusByte
= WaitOnBusy(chan
);
5439 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
5440 KdPrint2((PRINT_PREFIX
5441 "IdeIntr: Read %#x words\n", wordCount
));
5446 UniataGetPioTiming(LunExt
));
5447 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)-1) ));
5448 //KdDump(AtaReq->DataBuffer, wordCount*2);
5449 if(srb
&& atapiDev
&& srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
5450 KdDump(AtaReq
->DataBuffer
, wordCount
*2);
5453 GetBaseStatus(chan
, statusByte
);
5454 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
5457 KdPrint2((PRINT_PREFIX
" DataOverrun\n"));
5458 AtapiSuckPort2(chan
);
5459 GetBaseStatus(chan
, statusByte
);
5462 if(statusByte
& IDE_STATUS_BUSY
) {
5463 for (i
= 0; i
< 2; i
++) {
5464 AtapiStallExecution(10);
5465 GetBaseStatus(chan
, statusByte
);
5466 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5473 KdPrint2((PRINT_PREFIX
5474 "IdeIntr: Read %#x Dwords\n", wordCount
/2));
5477 (PULONG
)(AtaReq
->DataBuffer
),
5479 UniataGetPioTiming(LunExt
));
5483 KdPrint3((PRINT_PREFIX
5484 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5488 // Fail this request.
5489 status
= SRB_STATUS_ERROR
;
5490 goto CompleteRequest
;
5493 // Advance data buffer pointer and bytes left.
5494 AtaReq
->DataBuffer
+= wordCount
;
5495 AtaReq
->WordsLeft
-= wordCount
;
5496 AtaReq
->WordsTransfered
+= wordCount
;
5498 // Check for read command complete.
5499 if (AtaReq
->WordsLeft
== 0) {
5501 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
5504 // Work around to make many atapi devices return correct sector size
5505 // of 2048. Also certain devices will have sector count == 0x00, check
5507 if ((srb
->Cdb
[0] == SCSIOP_READ_CAPACITY
) &&
5508 (LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
)) {
5510 AtaReq
->DataBuffer
-= wordCount
;
5511 if (AtaReq
->DataBuffer
[0] == 0x00) {
5513 *((ULONG
*) &(AtaReq
->DataBuffer
[0])) = 0xFFFFFF7F;
5517 *((ULONG
*) &(AtaReq
->DataBuffer
[2])) = 0x00080000;
5518 AtaReq
->DataBuffer
+= wordCount
;
5521 GetStatus(chan
, statusByte
);
5522 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5523 // Assume command is completed if BUSY is cleared
5524 // and all data read
5525 // Optionally, we may receive COMPLETE interrupt later and
5526 // treat it as unexpected
5527 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete ? status %x\n", statusByte
));
5529 status
= SRB_STATUS_SUCCESS
;
5530 goto CompleteRequest
;
5536 // Completion for IDE drives.
5537 if (AtaReq->WordsLeft) {
5538 status = SRB_STATUS_DATA_OVERRUN;
5540 status = SRB_STATUS_SUCCESS;
5543 goto CompleteRequest;
5545 status
= SRB_STATUS_SUCCESS
;
5546 goto CompleteRequest
;
5551 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5552 GetStatus(chan
, statusByte
);
5553 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5554 // Assume command is completed if BUSY is cleared
5555 // even if NOT all data read
5556 // Optionally, we may receive COMPLETE interrupt later and
5557 // treat it as unexpected
5558 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete + underrun ? status %x\n", statusByte
));
5560 status
= SRB_STATUS_SUCCESS
;
5561 goto CompleteRequest
;
5566 goto ReturnEnableIntr
;
5568 } else if (interruptReason
== (ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
) && !(statusByte
& IDE_STATUS_DRQ
)) {
5570 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: interruptReason = CompleteRequest\n"));
5571 // Command complete. We exactly know this because os IReason.
5574 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
5575 AtaReq
->WordsTransfered
+= AtaReq
->WordsLeft
;
5576 AtaReq
->WordsLeft
= 0;
5578 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was PIO\n"));
5580 wordCount
= AtaReq
->WordsLeft
;
5581 // Advance data buffer pointer and bytes left.
5582 AtaReq
->DataBuffer
+= wordCount
;
5583 AtaReq
->WordsLeft
-= wordCount
;
5584 AtaReq
->WordsTransfered
+= wordCount
;
5586 //if (AtaReq->WordsLeft) {
5587 // status = SRB_STATUS_DATA_OVERRUN;
5589 status
= SRB_STATUS_SUCCESS
;
5592 #ifdef UNIATA_DUMP_ATAPI
5594 srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5598 PCHAR ModeSelectData
;
5600 PSCSI_REQUEST_BLOCK Srb
= srb
;
5602 Cdb
= (PCDB
)(Srb
->Cdb
);
5603 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
5604 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
5605 CdbDataLen
= Srb
->DataTransferLength
;
5607 if(CdbDataLen
> 0x1000) {
5608 CdbDataLen
= 0x1000;
5612 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
5613 KdPrint2(("P:T:D=%d:%d:%d\n",
5617 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand
));
5620 if(ScsiCommand
== SCSIOP_MODE_SENSE
) {
5621 KdPrint(("ModeSense 6\n"));
5622 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5623 ModeSelectData
= CdbData
+4;
5624 KdDump(CdbData
, CdbDataLen
);
5626 if(ScsiCommand
== SCSIOP_MODE_SENSE10
) {
5627 KdPrint(("ModeSense 10\n"));
5628 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5629 ModeSelectData
= CdbData
+8;
5630 KdDump(CdbData
, CdbDataLen
);
5632 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5633 KdPrint(("Read buffer from device:\n"));
5634 KdDump(CdbData
, CdbDataLen
);
5639 #endif //UNIATA_DUMP_ATAPI
5643 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, srbstatus %x\n", status
));
5644 // Check and see if we are processing our secret (mechanism status/request sense) srb
5646 if(AtaReq
->WordsLeft
&& (status
== SRB_STATUS_SUCCESS
)) {
5647 KdPrint2((PRINT_PREFIX
"WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq
->WordsLeft
));
5648 status
= SRB_STATUS_DATA_OVERRUN
;
5651 if (AtaReq
->OriginalSrb
) {
5655 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: OriginalSrb != NULL\n"));
5656 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
5658 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
5659 if (status
== SRB_STATUS_SUCCESS
) {
5661 AtapiHwInitializeChanger (HwDeviceExtension
,
5663 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
5665 // Get ready to issue the original srb
5666 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5667 AtaReq
->OriginalSrb
= NULL
;
5670 // failed! Get the sense key and maybe try again
5671 srb
= AtaReq
->Srb
= BuildRequestSenseSrb (
5673 AtaReq
->OriginalSrb
);
5676 // do not enable interrupts in DPC, do not waste time, do it now!
5677 if(UseDpc && chan->DisableIntr) {
5678 AtapiEnableInterrupts(HwDeviceExtension, c);
5680 RestoreUseDpc = TRUE;
5683 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
5685 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
5687 if (srbStatus
== SRB_STATUS_PENDING
) {
5688 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
5689 goto ReturnEnableIntr
;
5693 // restore state on error
5695 AtapiDisableInterrupts(HwDeviceExtension, c);
5699 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
5701 PSENSE_DATA senseData
= (PSENSE_DATA
) srb
->DataBuffer
;
5703 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI command status %#x\n", status
));
5704 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5705 // Check to see if we at least get mininum number of bytes
5706 if ((srb
->DataTransferLength
- AtaReq
->WordsLeft
) >
5707 (FIELD_OFFSET (SENSE_DATA
, AdditionalSenseLength
) + sizeof(senseData
->AdditionalSenseLength
))) {
5708 status
= SRB_STATUS_SUCCESS
;
5712 if (status
== SRB_STATUS_SUCCESS
) {
5714 if ((senseData
->SenseKey
!= SCSI_SENSE_ILLEGAL_REQUEST
) &&
5715 chan
->MechStatusRetryCount
) {
5717 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: MechStatusRetryCount %#x\n", chan
->MechStatusRetryCount
));
5718 // The sense key doesn't say the last request is illegal, so try again
5719 chan
->MechStatusRetryCount
--;
5720 srb
= AtaReq
->Srb
= BuildMechanismStatusSrb (
5722 AtaReq
->OriginalSrb
);
5725 // last request was illegal. No point trying again.
5726 // Do-nothing call ?
5727 AtapiHwInitializeChanger (HwDeviceExtension
,
5729 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
5731 // Get ready to issue the original srb
5732 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5733 AtaReq
->OriginalSrb
= NULL
;
5735 #endif //UNIATA_CORE
5737 // do not enable interrupts in DPC, do not waste time, do it now!
5738 if(UseDpc && chan->DisableIntr) {
5739 AtapiEnableInterrupts(HwDeviceExtension, c);
5741 RestoreUseDpc = TRUE;
5744 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
5746 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan
->ExpectingInterrupt
));
5748 if (srbStatus
== SRB_STATUS_PENDING
) {
5749 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
5750 goto ReturnEnableIntr
;
5754 // restore state on error
5756 AtapiDisableInterrupts(HwDeviceExtension, c);
5762 // If we get here, it means AtapiSendCommand() has failed
5763 // Can't recover. Pretend the original srb has failed and complete it.
5765 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. complete OriginalSrb\n"));
5767 if (AtaReq
->OriginalSrb
) {
5768 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
5769 // Do-nothing call ?
5770 AtapiHwInitializeChanger (HwDeviceExtension
,
5772 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
5773 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5774 AtaReq
->OriginalSrb
= NULL
;
5777 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan
->ExpectingInterrupt
));
5779 // fake an error and read no data
5780 status
= SRB_STATUS_ERROR
;
5781 srb
->ScsiStatus
= 0;
5782 AtaReq
->DataBuffer
= (PUSHORT
)(srb
->DataBuffer
);
5783 AtaReq
->WordsLeft
= srb
->DataTransferLength
;
5786 } else if (status
== SRB_STATUS_ERROR
) {
5788 // Map error to specific SRB status and handle request sense.
5789 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. Begin mapping...\n"));
5790 status
= MapError(deviceExtension
,
5795 } else if(!DmaTransfer
) {
5797 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion\n"));
5798 // Command complete.
5800 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion, wait BUSY\n"));
5801 // Wait for busy to drop.
5802 for (i
= 0; i
< 5*30; i
++) {
5803 GetBaseStatus(chan
, statusByte
);
5804 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5809 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY
;
5811 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (busy)\n"));
5815 AtapiStallExecution(TimerValue
);
5816 goto ServiceInterrupt
;
5817 #endif //UNIATA_CORE
5819 AtapiStallExecution(100);
5824 // reset the controller.
5825 KdPrint2((PRINT_PREFIX
5826 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
5828 goto IntrPrepareResetController
;
5830 // Check to see if DRQ is still up.
5831 if(statusByte
& IDE_STATUS_DRQ
) {
5832 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DRQ...\n"));
5834 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5835 KdPrint2((PRINT_PREFIX
"srb %x data in\n", srb
));
5837 KdPrint2((PRINT_PREFIX
"srb %x data out\n", srb
));
5840 KdPrint2((PRINT_PREFIX
"srb NULL\n"));
5843 KdPrint2((PRINT_PREFIX
"AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq
, AtaReq
->WordsLeft
));
5845 KdPrint2((PRINT_PREFIX
"AtaReq NULL\n"));
5847 if(AtaReq
&& AtaReq
->WordsLeft
/*&&
5848 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
5849 KdPrint2((PRINT_PREFIX
"DRQ+AtaReq->WordsLeft -> next portion\n"));
5853 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
5854 //if ((statusByte & IDE_STATUS_DRQ)) {}
5855 if((statusByte
& IDE_STATUS_DRQ
) &&
5856 (LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_TAPE_DEVICE
| DFLAGS_LBA_ENABLED
)) ) {
5859 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO_wait_DRQ\n"));
5860 for (i
= 0; i
< 200; i
++) {
5861 GetBaseStatus(chan
, statusByte
);
5862 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5867 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq)\n"));
5868 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ
;
5873 AtapiStallExecution(TimerValue
);
5874 goto ServiceInterrupt
;
5875 #endif //UNIATA_CORE
5877 AtapiStallExecution(100);
5881 // reset the controller.
5882 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
5884 goto IntrPrepareResetController
;
5888 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
5889 AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)(-1)), srb
->DataTransferLength
));
5890 //KdDump(srb->DataBuffer, srb->DataTransferLength);
5892 if(!AtapiDmaPioSync(HwDeviceExtension
, srb
, (PUCHAR
)(srb
->DataBuffer
), srb
->DataTransferLength
)) {
5893 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
5897 // Clear interrupt expecting flag.
5898 UniataExpectChannelInterrupt(chan
, FALSE
);
5899 // clear this flag now, it can be set again in sub-calls
5900 InterlockedExchange(&(chan
->CheckIntr
),
5903 // Sanity check that there is a current request.
5905 // Set status in SRB.
5906 srb
->SrbStatus
= (UCHAR
)status
;
5908 // Check for underflow.
5909 if(AtaReq
->WordsLeft
) {
5911 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq
->WordsLeft
));
5912 // Subtract out residual words and update if filemark hit,
5913 // setmark hit , end of data, end of media...
5914 if (!(LunExt
->DeviceFlags
& DFLAGS_TAPE_DEVICE
)) {
5915 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5916 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5918 srb
->DataTransferLength
= 0;
5921 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5924 if(status
== SRB_STATUS_SUCCESS
) {
5925 //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) {
5926 // // This should be set in UniataAhciEndTransaction() for AHCI
5927 // AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
5930 AtaReq
->WordsTransfered
*2 < AtaReq
->TransferLength
) {
5931 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
5932 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5933 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5934 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_NEXT
;
5937 KdPrint2((PRINT_PREFIX
" Transfered %x, full size %x\n",
5938 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5942 if (srb
->Function
!= SRB_FUNCTION_IO_CONTROL
) {
5945 // Indicate command complete.
5947 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete\n"));
5950 if (status
== SRB_STATUS_SUCCESS
&&
5951 srb
->SenseInfoBuffer
&&
5952 srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
5954 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)srb
->SenseInfoBuffer
;
5956 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: set AutoSense\n"));
5957 senseBuffer
->ErrorCode
= 0;
5958 senseBuffer
->Valid
= 1;
5959 senseBuffer
->AdditionalSenseLength
= 0xb;
5960 senseBuffer
->SenseKey
= 0;
5961 senseBuffer
->AdditionalSenseCode
= 0;
5962 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
5964 srb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
5966 AtapiDmaDBSync(chan
, srb
);
5967 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove srb %#x, status %x\n", srb
, status
));
5968 UniataRemoveRequest(chan
, srb
);
5969 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete, srb %#x\n", srb
));
5970 ScsiPortNotification(RequestComplete
,
5976 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: IOCTL completion\n"));
5978 if (status
!= SRB_STATUS_SUCCESS
) {
5979 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5980 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: error %#x\n", error
));
5983 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
5985 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5986 // Build the SMART status block depending upon the completion status.
5987 cmdOutParameters
->cBufferSize
= wordCount
;
5988 cmdOutParameters
->DriverStatus
.bDriverError
= (error
) ? SMART_IDE_ERROR
: 0;
5989 cmdOutParameters
->DriverStatus
.bIDEError
= error
;
5991 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
5993 if (chan
->SmartCommand
== RETURN_SMART_STATUS
) {
5994 PIDEREGS_EX regs
= (PIDEREGS_EX
)&(cmdOutParameters
->bBuffer
);
5997 UniataSnapAtaRegs(chan
, 0, regs
);
5999 regs
->bCommandReg
= SMART_CMD
;
6000 regs
->bFeaturesReg
= RETURN_SMART_STATUS
;
6002 cmdOutParameters
->cBufferSize
= 8;
6004 chan
->SmartCommand
= 0; // cleanup after execution
6006 // Indicate command complete.
6007 goto IntrCompleteReq
;
6012 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: No SRB!\n"));
6017 for (i
= 0; i
< 5; i
++) {
6018 GetBaseStatus(chan
, statusByte
);
6019 if(!(statusByte
& IDE_STATUS_BUSY
)) {
6020 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RDP + cleared BUSY\n"));
6024 if (statusByte
& IDE_STATUS_DSC
) {
6025 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Clear RDP\n"));
6029 AtapiStallExecution(50);
6032 // RDP can be cleared since previous check
6034 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestTimerCall 2000\n"));
6040 AtapiStallExecution(TimerValue
);
6041 goto ServiceInterrupt
;
6042 #endif //UNIATA_CORE
6045 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
6048 srb
= UniataGetCurRequest(chan
);
6053 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: NextRequest, srb=%#x\n",srb
));
6055 ScsiPortNotification(NextRequest
,
6059 ScsiPortNotification(NextLuRequest
,
6064 // in simplex mode next command must NOT be sent here
6065 if(!deviceExtension
->simplexOnly
) {
6066 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6069 // Try to get SRB fron any non-empty queue (later)
6070 if(deviceExtension
->simplexOnly
) {
6073 #endif //UNIATA_CORE
6075 goto ReturnEnableIntr
;
6079 // Unexpected int. Catch it
6080 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
6084 if(OldReqState
== REQ_STATE_DPC_WAIT_BUSY0
&&
6085 AtaReq
->WordsLeft
== 0) {
6086 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: pending WAIT_BUSY0. Complete.\n"));
6087 status
= SRB_STATUS_SUCCESS
;
6088 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6089 goto CompleteRequest
;
6095 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ReturnEnableIntr\n",srb
));
6096 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6097 deviceExtension
->ExpectingInterrupt
= TRUE
;
6099 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
6100 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
6101 #ifdef UNIATA_USE_XXableInterrupts
6102 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
6103 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
6104 // must be called on DISPATCH_LEVEL
6105 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
6106 AtapiEnableInterrupts__
);
6108 AtapiEnableInterrupts(HwDeviceExtension
, c
);
6109 InterlockedExchange(&(chan
->CheckIntr
),
6111 // Will raise IRQL to DIRQL
6113 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
6114 AtapiEnableInterrupts__
,
6116 #endif // UNIATA_CORE
6117 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
6118 #endif // UNIATA_USE_XXableInterrupts
6122 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
6123 // in simplex mode next command must be sent here if
6125 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc
, NoStartIo
));
6128 if(!UseDpc
&& /*deviceExtension->simplexOnly &&*/ !NoStartIo
) {
6129 chan
= UniataGetNextChannel(chan
);
6131 srb
= UniataGetCurRequest(chan
);
6135 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: run srb %x\n", srb
));
6137 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6140 #endif //UNIATA_CORE
6143 } // end AtapiInterrupt__()
6149 Routine Description:
6151 This routine handles SMART enable, disable, read attributes and threshold commands.
6155 HwDeviceExtension - HBA miniport driver's adapter data storage
6156 Srb - IO request packet
6165 IdeSendSmartCommand(
6166 IN PVOID HwDeviceExtension
,
6167 IN PSCSI_REQUEST_BLOCK Srb
,
6168 IN ULONG targetId
// assume it is always valid
6171 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6172 ULONG c
; // = GET_CHANNEL(Srb); may be invalid
6173 PHW_CHANNEL chan
; // = &(deviceExtension->chan[c]);
6174 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6175 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6176 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6177 PIDEREGS regs
= &cmdInParameters
.irDriveRegs
;
6182 if (regs
->bCommandReg
!= SMART_CMD
) {
6183 KdPrint2((PRINT_PREFIX
6184 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
6185 return SRB_STATUS_INVALID_REQUEST
;
6188 c
= targetId
/ deviceExtension
->NumberLuns
;
6189 DeviceNumber
= targetId
% deviceExtension
->NumberLuns
;
6190 KdPrint2((PRINT_PREFIX
" c %d, dev %d\n", c
, DeviceNumber
));
6192 chan
= &(deviceExtension
->chan
[c
]);
6194 chan
->SmartCommand
= regs
->bFeaturesReg
;
6196 // Determine which of the commands to carry out.
6197 switch(regs
->bFeaturesReg
) {
6198 case READ_ATTRIBUTES
:
6199 case READ_THRESHOLDS
:
6200 case READ_LOG_SECTOR
:
6201 case WRITE_LOG_SECTOR
:
6203 if(Srb
->DataTransferLength
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1) {
6204 KdPrint2((PRINT_PREFIX
6205 "IdeSendSmartCommand: wrong buffer size\n"));
6206 return SRB_STATUS_DATA_OVERRUN
;
6209 statusByte
= WaitOnBusy(chan
);
6211 if (statusByte
& IDE_STATUS_BUSY
) {
6212 KdPrint2((PRINT_PREFIX
6213 "IdeSendSmartCommand: Returning BUSY status\n"));
6214 return SRB_STATUS_BUSY
;
6217 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6218 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1);
6220 // Set data buffer pointer and words left.
6221 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6222 AtaReq
->WordsLeft
= READ_ATTRIBUTE_BUFFER_SIZE
/ 2;
6224 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6226 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6228 regs
->bSectorNumberReg
,
6229 regs
->bSectorCountReg
,
6233 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6234 // Wait for interrupt.
6235 return SRB_STATUS_PENDING
;
6237 return SRB_STATUS_ERROR
;
6241 case RETURN_SMART_STATUS
:
6242 case ENABLE_DISABLE_AUTOSAVE
:
6243 case EXECUTE_OFFLINE_DIAGS
:
6244 case SAVE_ATTRIBUTE_VALUES
:
6247 statusByte
= WaitOnBusy(chan
);
6249 if (statusByte
& IDE_STATUS_BUSY
) {
6250 KdPrint2((PRINT_PREFIX
6251 "IdeSendSmartCommand: Returning BUSY status\n"));
6252 return SRB_STATUS_BUSY
;
6255 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6256 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) - 1);
6258 // Set data buffer pointer and indicate no data transfer.
6259 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6260 AtaReq
->WordsLeft
= 0;
6262 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6264 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6266 regs
->bSectorNumberReg
,
6267 regs
->bSectorCountReg
,
6271 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6272 // Wait for interrupt.
6273 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6274 return SRB_STATUS_PENDING
;
6276 return SRB_STATUS_ERROR
;
6277 } // end switch(regs->bFeaturesReg)
6279 return SRB_STATUS_INVALID_REQUEST
;
6281 } // end IdeSendSmartCommand()
6283 #endif //UNIATA_CORE
6287 UniAtaCalculateLBARegs(
6288 PHW_LU_EXTENSION LunExt
,
6289 ULONGLONG startingSector
,
6293 UCHAR drvSelect
,sectorNumber
;
6297 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6298 if(LunExt
->LimitedTransferMode
>= ATA_DMA
) {
6299 if(LunExt
->DeviceExtension
) {
6300 (*max_bcount
) = LunExt
->DeviceExtension
->MaximumDmaTransferLength
/ DEV_BSIZE
;
6303 return startingSector
;
6305 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6306 LunExt
->IdentifyData
.NumberOfHeads
;
6308 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
6312 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
;
6314 cylinder
= (USHORT
)(startingSector
/ tmp
);
6315 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
6316 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
6317 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
- sectorNumber
+ 1;
6318 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
6319 cylinder
, drvSelect
, sectorNumber
, (*max_bcount
)));
6323 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
6324 } // end UniAtaCalculateLBARegs()
6328 UniAtaCalculateLBARegsBack(
6329 PHW_LU_EXTENSION LunExt
,
6333 ULONG drvSelect
,sectorNumber
;
6337 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6340 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6341 LunExt
->IdentifyData
.NumberOfHeads
;
6343 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
6344 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
6345 sectorNumber
= (UCHAR
)(lba
& 0xff);
6347 lba
= sectorNumber
-1 +
6348 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
6352 } // end UniAtaCalculateLBARegsBack()
6357 Routine Description:
6359 This routine handles IDE read and writes.
6363 HwDeviceExtension - HBA miniport driver's adapter data storage
6364 Srb - IO request packet
6374 IN PVOID HwDeviceExtension
,
6375 IN PSCSI_REQUEST_BLOCK Srb
,
6379 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6380 UCHAR lChannel
= GET_CHANNEL(Srb
);
6381 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6382 PHW_LU_EXTENSION LunExt
;
6383 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6384 //ULONG ldev = GET_LDEV(Srb);
6385 UCHAR DeviceNumber
= GET_CDEV(Srb
);;
6386 ULONGLONG startingSector
=0;
6388 ULONG wordCount
= 0;
6389 UCHAR statusByte
,statusByte2
;
6392 BOOLEAN use_dma
= FALSE
;
6395 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6396 LunExt
= chan
->lun
[DeviceNumber
];
6398 if((CmdAction
& CMD_ACTION_PREPARE
) &&
6399 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
6401 if(LunExt
->opt_ReadOnly
&&
6402 (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) {
6403 if(LunExt
->opt_ReadOnly
== 1) {
6404 KdPrint2((PRINT_PREFIX
"Abort WRITE (Soft R/O)\n"));
6405 return SRB_STATUS_ERROR
;
6407 KdPrint2((PRINT_PREFIX
"Ignore WRITE (Soft R/O)\n"));
6408 return SRB_STATUS_SUCCESS
;
6412 // Set data buffer pointer and words left.
6413 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6415 if(AtaReq
->WordsTransfered
) {
6416 AtaReq
->DataBuffer
= ((PUSHORT
)(Srb
->DataBuffer
)) + AtaReq
->WordsTransfered
;
6417 startingSector
= (UniAtaCalculateLBARegsBack(LunExt
, AtaReq
->lba
)) /* latest lba */ + AtaReq
->bcount
/* previous bcount */;
6418 AtaReq
->bcount
= (AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2 + DEV_BSIZE
-1) / DEV_BSIZE
;
6419 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Chained REQ): Starting sector %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
6421 AtaReq
->TransferLength
/2,
6422 AtaReq
->WordsTransfered
,
6425 AtaReq
->DataBuffer
= (PUSHORT
)(Srb
->DataBuffer
);
6426 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
6427 // Set up 1st block.
6428 switch(Srb
->Cdb
[0]) {
6431 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6432 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6435 case SCSIOP_WRITE12
:
6436 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
6437 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6440 case SCSIOP_WRITE16
:
6441 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6442 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6445 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Orig REQ): Starting sector %I64x, OrigWordsRequested %#x, DevSize %#x\n",
6447 AtaReq
->TransferLength
/2,
6450 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6453 AtaReq
->bcount
= min(AtaReq
->bcount
, max_bcount
);
6455 AtaReq
->WordsLeft
= min(AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2,
6456 AtaReq
->bcount
* DEV_BSIZE
) / 2;
6458 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n",
6465 // assume best case here
6466 // we cannot reinit Dma until previous request is completed
6467 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6468 UniataAhciSetupCmdPtr(AtaReq
);
6469 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6470 (PUCHAR
)(AtaReq
->DataBuffer
),
6471 AtaReq
->bcount
* DEV_BSIZE
)) {
6472 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !DMA\n"));
6473 return SRB_STATUS_ERROR
;
6476 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
6478 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6479 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6480 (PUCHAR
)(AtaReq
->DataBuffer
),
6481 AtaReq
->bcount
* DEV_BSIZE
)) {
6486 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6487 KdPrint2((PRINT_PREFIX
"IdeReadWrite: setup AHCI FIS\n"));
6488 RtlZeroMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
), sizeof(AtaReq
->ahci_cmd0
.cfis
));
6490 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
6491 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
6492 (AtaReq
->Flags
& REQ_FLAG_READ
) ? IDE_COMMAND_READ_DMA
: IDE_COMMAND_WRITE_DMA
,
6494 (USHORT
)(AtaReq
->bcount
),
6496 /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/
6500 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !FIS\n"));
6501 return SRB_STATUS_ERROR
;
6504 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0, (AtaReq
->Flags
& REQ_FLAG_READ
) ? 0 : ATA_AHCI_CMD_WRITE
, fis_size
, DeviceNumber
);
6505 KdPrint2((PRINT_PREFIX
"IdeReadWrite ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
6508 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
6510 } else { // exec_only
6511 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
6514 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6518 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
6520 return SRB_STATUS_PENDING
;
6523 // if this is queued request, reinit DMA and check
6524 // if DMA mode is still available
6525 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
6526 if (/*EnableDma &&*/
6527 (LunExt
->TransferMode
>= ATA_DMA
)) {
6530 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6534 // Check if write request.
6535 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6537 // Prepare read command.
6539 cmd
= IDE_COMMAND_READ_DMA
;
6541 if(LunExt
->MaximumBlockXfer
) {
6542 cmd
= IDE_COMMAND_READ_MULTIPLE
;
6544 cmd
= IDE_COMMAND_READ
;
6548 // Prepare write command.
6550 wordCount
= AtaReq
->bcount
*DEV_BSIZE
/2;
6551 cmd
= IDE_COMMAND_WRITE_DMA
;
6553 if (LunExt
->MaximumBlockXfer
) {
6554 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
6556 if (AtaReq
->WordsLeft
< wordCount
) {
6557 // Transfer only words requested.
6558 wordCount
= AtaReq
->WordsLeft
;
6560 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
6563 wordCount
= DEV_BSIZE
/2;
6564 cmd
= IDE_COMMAND_WRITE
;
6569 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
6570 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
6572 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
6574 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6577 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6578 // AHCI doesn't distinguish DMA and PIO
6579 //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
6580 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
6581 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6582 InterlockedExchange(&(chan
->CheckIntr
),
6584 return SRB_STATUS_PENDING
;
6587 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
6589 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
6591 (USHORT
)(AtaReq
->bcount
),
6592 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6594 if(statusByte2
!= IDE_STATUS_WRONG
) {
6595 GetStatus(chan
, statusByte2
);
6597 if(statusByte2
& IDE_STATUS_ERROR
) {
6598 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6599 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
6600 return SRB_STATUS_ERROR
;
6603 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
6605 return SRB_STATUS_PENDING
;
6608 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
6610 (USHORT
)(AtaReq
->bcount
),
6611 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6614 if (!(statusByte
& IDE_STATUS_DRQ
) ||
6615 statusByte
== IDE_STATUS_WRONG
) {
6617 if(statusByte
== IDE_STATUS_WRONG
) {
6618 KdPrint2((PRINT_PREFIX
6619 "IdeReadWrite: error sending command (%#x)\n",
6622 KdPrint2((PRINT_PREFIX
6623 "IdeReadWrite: DRQ never asserted (%#x)\n",
6627 AtaReq
->WordsLeft
= 0;
6629 // Clear interrupt expecting flag.
6630 UniataExpectChannelInterrupt(chan
, FALSE
);
6631 InterlockedExchange(&(chan
->CheckIntr
),
6634 // Clear current SRB.
6635 UniataRemoveRequest(chan
, Srb
);
6637 return (statusByte
== IDE_STATUS_WRONG
) ? SRB_STATUS_ERROR
: SRB_STATUS_TIMEOUT
;
6640 UniataExpectChannelInterrupt(chan
, TRUE
);
6641 InterlockedExchange(&(chan
->CheckIntr
),
6644 // Write next DEV_BSIZE/2*N words.
6645 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
)) {
6646 KdPrint2((PRINT_PREFIX
6647 "IdeReadWrite: Write %#x words\n", wordCount
));
6652 UniataGetPioTiming(LunExt
));
6656 KdPrint2((PRINT_PREFIX
6657 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
6660 (PULONG
)(AtaReq
->DataBuffer
),
6662 UniataGetPioTiming(LunExt
));
6665 // Adjust buffer address and words left count.
6666 AtaReq
->WordsLeft
-= wordCount
;
6667 AtaReq
->DataBuffer
+= wordCount
;
6669 // Wait for interrupt.
6670 return SRB_STATUS_PENDING
;
6672 } // end IdeReadWrite()
6678 Routine Description:
6679 This routine handles IDE Verify.
6682 HwDeviceExtension - HBA miniport driver's adapter data storage
6683 Srb - IO request packet
6692 IN PVOID HwDeviceExtension
,
6693 IN PSCSI_REQUEST_BLOCK Srb
6696 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6697 UCHAR lChannel
= GET_CHANNEL(Srb
);
6698 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6699 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6700 PHW_LU_EXTENSION LunExt
;
6701 //ULONG ldev = GET_LDEV(Srb);
6702 ULONG DeviceNumber
= GET_CDEV(Srb
);
6704 ULONGLONG startingSector
=0;
6707 ULONGLONG endSector
;
6708 ULONG sectorCount
=0;
6711 LunExt
= chan
->lun
[DeviceNumber
];
6712 // Drive has these number sectors.
6713 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
6714 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
6715 LunExt
->IdentifyData
.NumberOfHeads
*
6716 LunExt
->IdentifyData
.NumberOfCylinders
;
6719 KdPrint2((PRINT_PREFIX
6720 "IdeVerify: Total sectors %#x\n",
6723 // Get starting sector number from CDB.
6724 switch(Srb
->Cdb
[0]) {
6726 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6727 MOV_SWP_DW2DD(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6729 case SCSIOP_VERIFY12
:
6730 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
6731 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6733 case SCSIOP_VERIFY16
:
6734 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6735 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6739 KdPrint2((PRINT_PREFIX
6740 "IdeVerify: Starting sector %#I64x. Number of blocks %#x\n",
6744 endSector
= startingSector
+ sectorCount
;
6746 KdPrint2((PRINT_PREFIX
6747 "IdeVerify: Ending sector %#I64x\n",
6750 if (endSector
> sectors
) {
6752 // Too big, round down.
6753 KdPrint2((PRINT_PREFIX
6754 "IdeVerify: Truncating request to %#x blocks\n",
6755 sectors
- startingSector
- 1));
6757 sectorCount
= (ULONG
)(sectors
- startingSector
- 1);
6761 // Set up sector count register. Round up to next block.
6762 if (sectorCount
> 0xFF) {
6763 sectorCount
= (USHORT
)0xFF;
6767 // Set data buffer pointer and words left.
6768 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
6769 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
6771 // Indicate expecting an interrupt.
6772 InterlockedExchange(&(chan
->CheckIntr
),
6775 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6777 statusByte
= AtaCommand48(deviceExtension
, LunExt
->Lun
, GET_CHANNEL(Srb
),
6778 IDE_COMMAND_VERIFY
, lba
,
6779 (USHORT
)sectorCount
,
6782 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6783 // Wait for interrupt.
6784 return SRB_STATUS_PENDING
;
6786 return SRB_STATUS_ERROR
;
6788 } // end IdeVerify()
6790 #endif //UNIATA_CORE
6794 Routine Description:
6795 Send ATAPI packet command to device.
6798 HwDeviceExtension - HBA miniport driver's adapter data storage
6799 Srb - IO request packet
6807 IN PVOID HwDeviceExtension
,
6808 IN PSCSI_REQUEST_BLOCK Srb
,
6812 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6813 UCHAR lChannel
= GET_CHANNEL(Srb
);
6814 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6815 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6816 PHW_LU_EXTENSION LunExt
;
6817 //ULONG ldev = GET_LDEV(Srb);
6818 ULONG DeviceNumber
= GET_CDEV(Srb
);
6820 UCHAR statusByte
,statusByte0
,byteCountLow
,byteCountHigh
;
6821 BOOLEAN use_dma
= FALSE
;
6822 BOOLEAN dma_reinited
= FALSE
;
6823 BOOLEAN retried
= FALSE
;
6827 LunExt
= chan
->lun
[DeviceNumber
];
6829 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: req state %#x, Action %x\n", AtaReq
->ReqState
, CmdAction
));
6830 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
6831 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
6834 #ifdef UNIATA_DUMP_ATAPI
6835 if(CmdAction
& CMD_ACTION_PREPARE
) {
6839 PCHAR ModeSelectData
;
6842 Cdb
= (PCDB
)(Srb
->Cdb
);
6843 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
6844 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
6845 CdbDataLen
= Srb
->DataTransferLength
;
6847 if(CdbDataLen
> 0x1000) {
6848 CdbDataLen
= 0x1000;
6852 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
6853 KdPrint2(("P:T:D=%d:%d:%d\n",
6857 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
6860 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
6861 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
6862 Cdb
->WRITE_CD
.LBA
[0],
6863 Cdb
->WRITE_CD
.LBA
[1],
6864 Cdb
->WRITE_CD
.LBA
[2],
6865 Cdb
->WRITE_CD
.LBA
[3]
6868 if(ScsiCommand
== SCSIOP_WRITE12
) {
6869 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
6870 Cdb
->CDB12READWRITE
.LBA
[0],
6871 Cdb
->CDB12READWRITE
.LBA
[1],
6872 Cdb
->CDB12READWRITE
.LBA
[2],
6873 Cdb
->CDB12READWRITE
.LBA
[3]
6876 if(ScsiCommand
== SCSIOP_WRITE16
) {
6877 KdPrint(("Write16, LBA %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
6878 Cdb
->CDB16READWRITE
.LBA
[0],
6879 Cdb
->CDB16READWRITE
.LBA
[1],
6880 Cdb
->CDB16READWRITE
.LBA
[2],
6881 Cdb
->CDB16READWRITE
.LBA
[3],
6882 Cdb
->CDB16READWRITE
.LBA
[4],
6883 Cdb
->CDB16READWRITE
.LBA
[5],
6884 Cdb
->CDB16READWRITE
.LBA
[6],
6885 Cdb
->CDB16READWRITE
.LBA
[7]
6888 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
6889 KdPrint(("ModeSelect 6\n"));
6890 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6891 ModeSelectData
= CdbData
+4;
6892 KdDump(CdbData
, CdbDataLen
);
6894 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
6895 KdPrint(("ModeSelect 10\n"));
6896 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6897 ModeSelectData
= CdbData
+8;
6898 KdDump(CdbData
, CdbDataLen
);
6900 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
6901 KdPrint(("Send buffer to device:\n"));
6902 KdDump(CdbData
, CdbDataLen
);
6907 #endif //UNIATA_DUMP_ATAPI
6910 if(CmdAction
== CMD_ACTION_PREPARE
) {
6911 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb
->Cdb
)));
6913 switch (Srb
->Cdb
[0]) {
6914 case SCSIOP_RECEIVE
:
6919 case SCSIOP_WRITE12
:
6921 case SCSIOP_WRITE16
:
6925 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
6926 return SRB_STATUS_BUSY
;
6929 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6930 !AtaReq
->OriginalSrb
) {
6931 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
6932 return SRB_STATUS_BUSY
;
6937 // We need to know how many platters our atapi cd-rom device might have.
6938 // Before anyone tries to send a srb to our target for the first time,
6939 // we must "secretly" send down a separate mechanism status srb in order to
6940 // initialize our device extension changer data. That's how we know how
6941 // many platters our target has.
6943 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6944 !AtaReq
->OriginalSrb
) {
6948 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
6949 // Set this flag now. If the device hangs on the mech. status
6950 // command, we will not have the chance to set it.
6951 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
6953 chan
->MechStatusRetryCount
= 3;
6954 AtaReq
->OriginalSrb
= Srb
;
6955 AtaReq
->Srb
= BuildMechanismStatusSrb (
6959 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
6960 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
6961 if (srbStatus
== SRB_STATUS_PENDING
) {
6962 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
6966 // failed! Get the sense key and maybe try again
6967 AtaReq
->Srb
= BuildRequestSenseSrb ( HwDeviceExtension
,
6968 AtaReq
->OriginalSrb
);
6970 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
6972 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
6974 if (srbStatus
== SRB_STATUS_PENDING
) {
6975 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n"));
6979 // failed again ? should not get here
6981 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6982 AtaReq
->OriginalSrb
= NULL
;
6984 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiHwInitializeChanger()\n"));
6985 // Do-nothing call ?
6986 AtapiHwInitializeChanger (HwDeviceExtension
, Srb
,
6987 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
6991 #endif //UNIATA_CORE
6993 if((CmdAction
& CMD_ACTION_PREPARE
) &&
6994 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
6996 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb
->Cdb
[0], &(Srb
->Cdb
)));
6998 if(!LunExt
->IdentifyData
.AtapiCmdSize
&&
6999 (Srb
->CdbLength
> 12)) {
7000 KdPrint2((PRINT_PREFIX
"Cdb16 not supported\n"));
7001 return SRB_STATUS_INVALID_REQUEST
;
7004 // Set data buffer pointer and words left.
7005 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
7006 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
7007 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
7008 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7009 // reset this to force PRD init. May be already setup by recursive SRB
7010 AtaReq
->dma_entries
= 0;
7012 // check if reorderable
7013 switch(Srb
->Cdb
[0]) {
7015 case SCSIOP_WRITE16
:
7017 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
7018 MOV_QD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
7022 case SCSIOP_WRITE12
:
7024 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
7030 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
7032 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
7034 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
7035 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7036 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
7037 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
7038 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ?
7039 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
7042 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7043 if(!AtaReq
->TransferLength
) {
7044 KdPrint((" assume 0-transfer\n"));
7046 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
7047 KdPrint((" assume OUT\n"));
7048 AtaReq
->Flags
|= REQ_FLAG_WRITE
;
7050 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7051 KdPrint((" assume IN\n"));
7052 AtaReq
->Flags
|= REQ_FLAG_READ
;
7057 // check if DMA read/write
7058 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7059 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: force use dma (ahci)\n"));
7063 /* if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) {
7064 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n"));
7068 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
7069 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
7071 if(AtaReq
->TransferLength
) {
7073 switch(Srb
->Cdb
[0]) {
7075 case SCSIOP_WRITE12
:
7076 case SCSIOP_WRITE16
:
7078 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
7081 case SCSIOP_RECEIVE
:
7086 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
7088 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7089 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7092 if(AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7093 (PUCHAR
)(AtaReq
->DataBuffer
),
7094 Srb
->DataTransferLength
7095 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
7097 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7102 case SCSIOP_READ_CD
:
7103 if(deviceExtension
->opt_AtapiDmaRawRead
)
7104 goto call_dma_setup
;
7108 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
7109 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7114 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
7115 KdPrint2((PRINT_PREFIX
"dma RO\n"));
7127 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7128 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7131 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7132 (PUCHAR
)(AtaReq
->DataBuffer
),
7133 Srb
->DataTransferLength
)) {
7134 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
7137 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7141 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer, no DMA setup\n"));
7145 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7147 UniataAhciSetupCmdPtr(AtaReq
);
7149 if(!Srb
->DataTransferLength
) {
7150 KdPrint2((PRINT_PREFIX
"zero-transfer\n"));
7153 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7154 (PUCHAR
)(AtaReq
->DataBuffer
),
7155 Srb
->DataTransferLength
)) {
7156 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no AHCI dma!\n"));
7157 return SRB_STATUS_ERROR
;
7160 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7162 FeatureReg
|= ATA_F_DMA
;
7163 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7164 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7165 FeatureReg
|= ATA_F_DMAREAD
;
7169 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: setup AHCI FIS\n"));
7170 // this is done in UniataAhciSetupFIS_H2D()
7171 //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
7172 RtlCopyMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), Srb
->Cdb
, Srb
->CdbLength
);
7174 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
7175 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
7176 IDE_COMMAND_ATAPI_PACKET
/* command */,
7178 (Srb
->DataTransferLength
>= 0x10000) ? (USHORT
)(0xffff) : (USHORT
)(Srb
->DataTransferLength
),
7179 FeatureReg
/* feature */
7183 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AHCI !FIS\n"));
7184 return SRB_STATUS_ERROR
;
7187 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0,
7188 ((Srb
->DataTransferLength
&& (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) ? ATA_AHCI_CMD_WRITE
: 0) |
7189 (ATA_AHCI_CMD_ATAPI
| ATA_AHCI_CMD_PREFETCH
),
7190 fis_size
, DeviceNumber
);
7192 KdPrint2((PRINT_PREFIX
"AtapiSendCommand ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
7196 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7197 // if this is queued request, reinit DMA and check
7198 // if DMA mode is still available
7199 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
7200 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7201 if (/*EnableDma &&*/
7202 (LunExt
->TransferMode
>= ATA_DMA
)) {
7203 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
7206 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7207 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
7210 dma_reinited
= TRUE
;
7214 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
7215 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
7216 return SRB_STATUS_PENDING
;
7218 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma
, Srb
->Cdb
[0]));
7219 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7220 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7223 if((Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) && !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7224 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
7226 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7227 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7228 } if(AtaReq
->TransferLength
) {
7230 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
7231 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7232 if (/*EnableDma &&*/
7233 (LunExt
->TransferMode
>= ATA_DMA
)) {
7236 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7241 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
7243 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7244 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7245 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
7246 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7249 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
7250 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7251 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7254 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
7256 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
7257 &(Srb
->Cdb
), Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
7259 // Make sure command is to ATAPI device.
7260 flags
= LunExt
->DeviceFlags
;
7261 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7262 if((Srb
->Lun
) > (LunExt
->DiscsPresent
- 1)) {
7264 // Indicate no device found at this address.
7265 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7266 return SRB_STATUS_SELECTION_TIMEOUT
;
7268 } else if(Srb
->Lun
> 0) {
7269 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7270 return SRB_STATUS_SELECTION_TIMEOUT
;
7273 if(!(flags
& DFLAGS_ATAPI_DEVICE
)) {
7274 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7275 return SRB_STATUS_SELECTION_TIMEOUT
;
7278 // Select device 0 or 1. Or more for PM
7279 SelectDrive(chan
, DeviceNumber
);
7281 // Verify that controller is ready for next command.
7282 GetStatus(chan
, statusByte
);
7283 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
7285 if(statusByte
== IDE_STATUS_WRONG
) {
7286 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
7289 if(statusByte
& IDE_STATUS_BUSY
) {
7290 if(statusByte
& IDE_STATUS_DSC
) {
7291 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
7293 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
7294 // We have to make reset here, since we are expecting device to be available
7295 //return SRB_STATUS_BUSY; // this cause queue freeze
7299 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7301 // Check if command list is free
7302 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
7304 // controller is busy, however we expect it to be free
7305 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI
));
7309 if(statusByte
& IDE_STATUS_ERROR
) {
7310 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
7312 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
7313 // Read the error reg. to clear it and fail this request.
7314 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7315 return MapError(deviceExtension
, Srb
);
7317 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
7320 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
7321 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
7322 if((!(statusByte
& IDE_STATUS_DSC
)) &&
7323 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
7325 AtapiStallExecution(200);
7326 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
7327 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7328 return SRB_STATUS_PENDING
;
7331 if(IS_RDP(Srb
->Cdb
[0])) {
7333 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
7337 if(statusByte
& IDE_STATUS_DRQ
) {
7339 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
7341 // Try to drain the data that one preliminary device thinks that it has
7342 // to transfer. Hopefully this random assertion of DRQ will not be present
7343 // in production devices.
7344 statusByte
= AtapiSuckPort2(chan
);
7346 for (i = 0; i < 0x10000; i++) {
7347 GetStatus(chan, statusByte);
7348 if(statusByte & IDE_STATUS_DRQ) {
7349 AtapiReadPort2(chan, IDX_IO1_i_Data);
7355 if (statusByte
& IDE_STATUS_DRQ
) {
7357 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte
));
7359 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7361 AtapiSoftReset(chan
, DeviceNumber
);
7363 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
7364 // Re-initialize Atapi device.
7365 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), DeviceNumber
, TRUE
);
7367 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
7368 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
7370 // Inform the port driver that the bus has been reset.
7371 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
7372 // Clean up device extension fields that AtapiStartIo won't.
7373 UniataExpectChannelInterrupt(chan
, FALSE
);
7375 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
7378 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7380 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7381 return SRB_STATUS_BUS_RESET;
7384 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
7388 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
7389 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7390 return SRB_STATUS_SELECTION_TIMEOUT
;
7394 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7395 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
7396 Srb
->Cdb
[1] &= ~0xE0;
7397 if((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
7398 // Torisan changer. TUR's are overloaded to be platter switches.
7399 Srb
->Cdb
[7] = Srb
->Lun
;
7406 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
7408 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
7411 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7412 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AHCI, begin transaction\n"));
7413 //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
7414 UniataExpectChannelInterrupt(chan
, TRUE
);
7415 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
7416 return SRB_STATUS_PENDING
;
7419 statusByte
= WaitOnBusy(chan
);
7420 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
7424 FeatureReg
|= ATA_F_DMA
;
7425 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7426 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7427 FeatureReg
|= ATA_F_DMAREAD
;
7431 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, FeatureReg
);
7433 // Write transfer byte count to registers.
7434 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
7435 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
7437 if (Srb
->DataTransferLength
>= 0x10000) {
7438 byteCountLow
= byteCountHigh
= 0xFF;
7441 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
7442 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
7444 if (flags
& DFLAGS_INT_DRQ
) {
7446 // This device interrupts when ready to receive the packet.
7448 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
7451 UniataExpectChannelInterrupt(chan
, TRUE
);
7452 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
7453 InterlockedExchange(&(chan
->CheckIntr
),
7456 // Write ATAPI packet command.
7457 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7459 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
7460 return SRB_STATUS_PENDING
;
7464 // This device quickly sets DRQ when ready to receive the packet.
7466 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
7469 UniataExpectChannelInterrupt(chan
, TRUE
);
7470 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
7471 InterlockedExchange(&(chan
->CheckIntr
),
7474 if(g_opt_AtapiSendDisableIntr
) {
7475 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7477 // remember status. Later we may check if error appeared after cmd packet
7478 statusByte0
= statusByte
;
7480 // Write ATAPI packet command.
7481 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7485 statusByte
= WaitForDrq(chan
);
7487 // Need to read status register and clear interrupt (if any)
7488 GetBaseStatus(chan
, statusByte
);
7490 if (!(statusByte
& IDE_STATUS_DRQ
)) {
7492 if(g_opt_AtapiSendDisableIntr
) {
7493 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7495 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte
));
7496 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7497 return SRB_STATUS_ERROR
;
7500 GetStatus(chan
, statusByte
);
7501 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
7503 // Send CDB to device.
7504 statusByte
= WaitOnBaseBusy(chan
);
7506 // Indicate expecting an interrupt and wait for it.
7507 UniataExpectChannelInterrupt(chan
, TRUE
);
7508 InterlockedExchange(&(chan
->CheckIntr
),
7510 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
7512 GetBaseStatus(chan
, statusByte
);
7514 if(g_opt_AtapiSendDisableIntr
) {
7515 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7520 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
7523 GetStatus(chan
, statusByte
);
7524 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: cmd status (%#x)\n", statusByte
));
7526 // When we operate in DMA mode, we should not start transfer when there is an error on entry
7527 // Interrupt may never come in such case.
7528 if(statusByte
& IDE_STATUS_ERROR
) {
7529 UCHAR interruptReason
;
7531 GetBaseStatus(chan
, statusByte
);
7532 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on cmd: (%#x)\n", statusByte
));
7534 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
7535 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: iReason %x\n", interruptReason
));
7537 // TODO: we should check interruptReason and decide what to do now
7539 // Read the error reg. to clear it and fail this request.
7540 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7541 return MapError(deviceExtension
, Srb
);
7543 /* if(statusByte & IDE_STATUS_DSC) {
7544 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DSC on cmd: (%#x)\n", statusByte));
7545 // Read the error reg. to clear it and fail this request.
7546 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7547 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte));
7548 if(statusByte >> 4) {
7549 GetBaseStatus(chan, statusByte);
7550 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7551 return MapError(deviceExtension, Srb);
7555 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
7556 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
7559 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
7561 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
7562 return SRB_STATUS_PENDING
;
7564 } // end AtapiSendCommand()
7571 Routine Description:
7572 Program ATA registers for IDE disk transfer.
7575 HwDeviceExtension - ATAPI driver storage.
7576 Srb - System request block.
7579 SRB status (pending if all goes well).
7584 ULONG check_point
= 0;
7585 #define SetCheckPoint(cp) { check_point = (cp) ; }
7587 #define SetCheckPoint(cp)
7593 IN PVOID HwDeviceExtension
,
7594 IN PSCSI_REQUEST_BLOCK Srb
,
7599 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
7602 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7607 PHW_LU_EXTENSION LunExt
;
7611 UCHAR statusByte
,errorByte
;
7612 ULONG status
= SRB_STATUS_INVALID_REQUEST
;
7615 PMODE_PARAMETER_HEADER modeData
;
7622 //ULONG __ebp__ = 0;
7624 SetCheckPoint(0x20);
7625 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
7630 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
7631 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
7632 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
7633 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
7634 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
7636 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
7637 Srb->SrbExtension));
7638 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
7641 SetCheckPoint(0x30);
7642 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7644 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
7646 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
7648 KdPrint2((PRINT_PREFIX
"** --- **\n"));
7650 lChannel
= GET_CHANNEL(Srb
);
7651 chan
= &(deviceExtension
->chan
[lChannel
]);
7652 //ldev = GET_LDEV(Srb);
7653 DeviceNumber
= GET_CDEV(Srb
);
7654 LunExt
= chan
->lun
[DeviceNumber
];
7656 SetCheckPoint(0x40);
7657 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
7658 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
7660 cdb
= (PCDB
)(Srb
->Cdb
);
7662 if(CmdAction
== CMD_ACTION_PREPARE
) {
7663 switch (Srb
->Cdb
[0]) {
7664 case SCSIOP_SERVICE_ACTION16
:
7665 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
7668 goto default_no_prep
;
7671 case SCSIOP_INQUIRY
: // now it requires device access
7673 case SCSIOP_READ_CAPACITY
:
7677 case SCSIOP_WRITE12
:
7679 case SCSIOP_WRITE16
:
7680 case SCSIOP_REQUEST_SENSE
:
7682 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
7688 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
7689 return SRB_STATUS_BUSY
;
7693 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
7694 switch (Srb
->Cdb
[0]) {
7695 case SCSIOP_INQUIRY
:
7697 KdPrint2((PRINT_PREFIX
7698 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
7699 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7700 // Filter out wrong TIDs.
7701 if ((Srb
->Lun
!= 0) ||
7702 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
7703 (Srb
->TargetId
>= deviceExtension
->NumberLuns
)) {
7705 KdPrint2((PRINT_PREFIX
7706 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
7707 // Indicate no device found at this address.
7708 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7713 KdPrint2((PRINT_PREFIX
7714 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
7715 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
7716 PIDENTIFY_DATA2 identifyData
= &(LunExt
->IdentifyData
);
7718 if (!(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7720 if(!CheckDevice(HwDeviceExtension
, lChannel
, DeviceNumber
, FALSE
)) {
7721 KdPrint2((PRINT_PREFIX
7722 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
7723 // Indicate no device found at this address.
7725 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7729 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, DeviceNumber
)) {
7730 KdPrint2((PRINT_PREFIX
7731 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
7732 // Indicate no device found at this address.
7733 UniataForgetDevice(chan
->lun
[DeviceNumber
]);
7735 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7740 // Zero INQUIRY data structure.
7741 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
7743 // Standard IDE interface only supports disks.
7744 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
7746 // Set the removable bit, if applicable.
7747 if (LunExt
->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
7748 KdPrint2((PRINT_PREFIX
7749 "RemovableMedia\n"));
7750 inquiryData
->RemovableMedia
= 1;
7752 // Set the Relative Addressing (LBA) bit, if applicable.
7753 if (LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
7754 inquiryData
->RelativeAddressing
= 1;
7755 KdPrint2((PRINT_PREFIX
7756 "RelativeAddressing\n"));
7758 // Set the CommandQueue bit
7759 inquiryData
->CommandQueue
= 1;
7761 // Fill in vendor identification fields.
7762 for (i
= 0; i
< 24; i
+= 2) {
7763 MOV_DW_SWP(inquiryData
->DeviceIdentificationString
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
7766 // Initialize unused portion of product id.
7767 for (i = 0; i < 4; i++) {
7768 inquiryData->ProductId[12+i] = ' ';
7771 // Move firmware revision from IDENTIFY data to
7772 // product revision in INQUIRY data.
7773 for (i
= 0; i
< 4; i
+= 2) {
7774 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
7777 status
= SRB_STATUS_SUCCESS
;
7782 case SCSIOP_REPORT_LUNS
: {
7785 PREPORT_LUNS_INFO_HDR LunInfo
;
7787 KdPrint2((PRINT_PREFIX
7788 "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
7789 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7791 MOV_DD_SWP(alen
, cdb
->REPORT_LUNS
.AllocationLength
);
7798 LunInfo
= (PREPORT_LUNS_INFO_HDR
)(Srb
->DataBuffer
);
7799 RtlZeroMemory(LunInfo
, 16);
7801 MOV_DD_SWP( LunInfo
->ListLength
, alen
);
7802 Srb
->DataTransferLength
= 16;
7803 status
= SRB_STATUS_SUCCESS
;
7807 case SCSIOP_MODE_SENSE
:
7809 KdPrint2((PRINT_PREFIX
7810 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
7811 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7813 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_POWER_CONDITION
) {
7814 PMODE_POWER_CONDITION_PAGE modeData
;
7816 KdPrint2((PRINT_PREFIX
"MODE_PAGE_POWER_CONDITION\n"));
7817 modeData
= (PMODE_POWER_CONDITION_PAGE
)(Srb
->DataBuffer
);
7818 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_POWER_CONDITION_PAGE
)) {
7819 status
= SRB_STATUS_DATA_OVERRUN
;
7821 RtlZeroMemory(modeData
, sizeof(MODE_POWER_CONDITION_PAGE
));
7822 modeData
->PageCode
= MODE_PAGE_POWER_CONDITION
;
7823 modeData
->PageLength
= sizeof(MODE_POWER_CONDITION_PAGE
)-sizeof(MODE_PARAMETER_HEADER
);
7824 modeData
->Byte3
.Fields
.Idle
= LunExt
->PowerState
<= StartStop_Power_Idle
;
7825 modeData
->Byte3
.Fields
.Standby
= LunExt
->PowerState
== StartStop_Power_Standby
;
7826 Srb
->DataTransferLength
= sizeof(MODE_POWER_CONDITION_PAGE
);
7827 status
= SRB_STATUS_SUCCESS
;
7830 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_CACHING
) {
7831 PMODE_CACHING_PAGE modeData
;
7833 KdPrint2((PRINT_PREFIX
"MODE_PAGE_CACHING\n"));
7834 modeData
= (PMODE_CACHING_PAGE
)(Srb
->DataBuffer
);
7835 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_CACHING_PAGE
)) {
7836 status
= SRB_STATUS_DATA_OVERRUN
;
7838 RtlZeroMemory(modeData
, sizeof(MODE_CACHING_PAGE
));
7839 modeData
->PageCode
= MODE_PAGE_CACHING
;
7840 modeData
->PageLength
= sizeof(MODE_CACHING_PAGE
)-sizeof(MODE_PARAMETER_HEADER
);
7841 modeData
->ReadDisableCache
= (LunExt
->DeviceFlags
& DFLAGS_RCACHE_ENABLED
) ? 0 : 1;
7842 modeData
->WriteCacheEnable
= (LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) ? 1 : 0;
7843 Srb
->DataTransferLength
= sizeof(MODE_CACHING_PAGE
);
7844 status
= SRB_STATUS_SUCCESS
;
7847 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
7849 // This is used to determine if the media is write-protected.
7850 // Since IDE does not support mode sense then we will modify just the portion we need
7851 // so the higher level driver can determine if media is protected.
7853 //SelectDrive(chan, DeviceNumber);
7854 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7855 //statusByte = WaitOnBusy(chan);
7856 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
7858 if (!(statusByte
& IDE_STATUS_ERROR
)) {
7860 // no error occured return success, media is not protected
7861 UniataExpectChannelInterrupt(chan
, FALSE
);
7862 InterlockedExchange(&(chan
->CheckIntr
),
7864 status
= SRB_STATUS_SUCCESS
;
7868 // error occured, handle it locally, clear interrupt
7869 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7871 GetBaseStatus(chan
, statusByte
);
7872 UniataExpectChannelInterrupt(chan
, FALSE
);
7873 InterlockedExchange(&(chan
->CheckIntr
),
7875 status
= SRB_STATUS_SUCCESS
;
7877 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
7879 //media is write-protected, set bit in mode sense buffer
7880 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
7882 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
7883 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
7886 status
= SRB_STATUS_SUCCESS
;
7888 status
= SRB_STATUS_INVALID_REQUEST
;
7892 case SCSIOP_TEST_UNIT_READY
:
7894 KdPrint2((PRINT_PREFIX
7895 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
7896 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7897 if (chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
7899 // Select device 0 or 1.
7900 //SelectDrive(chan, DeviceNumber);
7901 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7902 // Wait for busy. If media has not changed, return success
7903 //statusByte = WaitOnBusy(chan);
7904 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
7906 if (!(statusByte
& IDE_STATUS_ERROR
)){
7907 UniataExpectChannelInterrupt(chan
, FALSE
);
7908 InterlockedExchange(&(chan
->CheckIntr
),
7910 status
= SRB_STATUS_SUCCESS
;
7912 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7913 if (errorByte
== IDE_ERROR_DATA_ERROR
){
7915 // Special case: If current media is write-protected,
7916 // the 0xDA command will always fail since the write-protect bit
7917 // is sticky,so we can ignore this error
7918 GetBaseStatus(chan
, statusByte
);
7919 UniataExpectChannelInterrupt(chan
, FALSE
);
7920 InterlockedExchange(&(chan
->CheckIntr
),
7922 status
= SRB_STATUS_SUCCESS
;
7926 // Request sense buffer to be build
7927 UniataExpectChannelInterrupt(chan
, TRUE
);
7928 InterlockedExchange(&(chan
->CheckIntr
),
7930 status
= SRB_STATUS_PENDING
;
7934 status
= SRB_STATUS_SUCCESS
;
7939 case SCSIOP_READ_CAPACITY
:
7941 KdPrint2((PRINT_PREFIX
7942 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7943 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7944 // Claim 512 byte blocks (big-endian).
7945 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7947 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY_DATA
));
7948 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
7950 // Calculate last sector.
7951 if(!(i
= (ULONG
)LunExt
->NumOfSectors
)) {
7952 i
= LunExt
->IdentifyData
.SectorsPerTrack
*
7953 LunExt
->IdentifyData
.NumberOfHeads
*
7954 LunExt
->IdentifyData
.NumberOfCylinders
;
7958 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
7959 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
7960 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
7962 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
7964 KdPrint2((PRINT_PREFIX
7965 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
7967 LunExt
->IdentifyData
.SectorsPerTrack
,
7968 LunExt
->IdentifyData
.NumberOfHeads
,
7969 LunExt
->IdentifyData
.NumberOfCylinders
));
7972 status
= SRB_STATUS_SUCCESS
;
7975 case SCSIOP_SERVICE_ACTION16
:
7977 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
7978 KdPrint2((PRINT_PREFIX
7979 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7980 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7981 // Claim 512 byte blocks (big-endian).
7982 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7984 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY16_DATA
));
7985 MOV_DD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
7987 // Calculate last sector.
7988 if(!(lba
= LunExt
->NumOfSectors
)) {
7989 lba
= LunExt
->IdentifyData
.SectorsPerTrack
*
7990 LunExt
->IdentifyData
.NumberOfHeads
*
7991 LunExt
->IdentifyData
.NumberOfCylinders
;
7994 MOV_QD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, lba
);
7996 KdPrint2((PRINT_PREFIX
7997 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n",
7999 LunExt
->IdentifyData
.SectorsPerTrack
,
8000 LunExt
->IdentifyData
.NumberOfHeads
,
8001 LunExt
->IdentifyData
.NumberOfCylinders
));
8003 status
= SRB_STATUS_SUCCESS
;
8010 case SCSIOP_VERIFY12
:
8011 case SCSIOP_VERIFY16
:
8013 KdPrint2((PRINT_PREFIX
8014 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
8015 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8016 status
= IdeVerify(HwDeviceExtension
,Srb
);
8023 case SCSIOP_WRITE12
:
8025 case SCSIOP_WRITE16
:
8027 KdPrint2((PRINT_PREFIX
8028 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
8029 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
8030 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8031 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
8032 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
8033 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
8034 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
8035 status
= IdeReadWrite(HwDeviceExtension
,
8039 case SCSIOP_START_STOP_UNIT
:
8041 KdPrint2((PRINT_PREFIX
8042 "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
8043 cdb
->START_STOP
.Immediate
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8044 //Determine what type of operation we should perform
8048 if(cdb
->START_STOP
.FL
||
8049 cdb
->START_STOP
.FormatLayerNumber
||
8050 cdb
->START_STOP
.Reserved2
||
8051 cdb
->START_STOP
.Reserved2_2
||
8052 cdb
->START_STOP
.Reserved3
||
8057 if (cdb
->START_STOP
.PowerConditions
) {
8058 KdPrint2((PRINT_PREFIX
"START_STOP Power %d\n", cdb
->START_STOP
.PowerConditions
));
8059 switch(cdb
->START_STOP
.PowerConditions
) {
8060 case StartStop_Power_Idle
:
8061 command
= IDE_COMMAND_IDLE_IMMED
;
8063 case StartStop_Power_Standby
:
8064 command
= IDE_COMMAND_STANDBY_IMMED
;
8066 case StartStop_Power_Sleep
:
8067 // TODO: we should save power state in order to know
8068 // that RESET sould be issued to revert device into
8071 command
= IDE_COMMAND_SLEEP
;
8076 LunExt
->PowerState
= cdb
->START_STOP
.PowerConditions
;
8078 if (cdb
->START_STOP
.LoadEject
== 1) {
8079 KdPrint2((PRINT_PREFIX
"START_STOP eject\n"));
8081 // first select device 0 or 1.
8082 //SelectDrive(chan, DeviceNumber);
8083 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
8084 command
= IDE_COMMAND_MEDIA_EJECT
;
8086 if (cdb
->START_STOP
.Start
== 0) {
8087 KdPrint2((PRINT_PREFIX
"START_STOP standby\n"));
8088 command
= IDE_COMMAND_STANDBY_IMMED
;
8090 // TODO: we may need to perform hard reset (after sleep) or
8091 // issue IDE_COMMAND_IDLE_IMMED in order to activate device
8092 KdPrint2((PRINT_PREFIX
"START_STOP activate\n"));
8094 if(LunExt
->PowerState
== StartStop_Power_Sleep
) {
8095 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
8096 status
= SRB_STATUS_SUCCESS
;
8099 if(LunExt
->PowerState
> StartStop_Power_Idle
) {
8100 KdPrint2((PRINT_PREFIX
" issue IDLE\n"));
8101 command
= IDE_COMMAND_IDLE_IMMED
;
8103 KdPrint2((PRINT_PREFIX
" do nothing\n"));
8104 status
= SRB_STATUS_SUCCESS
;
8109 statusByte
= WaitOnBaseBusy(chan
);
8110 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, command
, 0, 0, 0, 0, 0,
8111 cdb
->START_STOP
.Immediate
? ATA_IMMEDIATE
: ATA_WAIT_READY
);
8112 status
= (statusByte
& IDE_STATUS_ERROR
) ? SRB_STATUS_ERROR
: SRB_STATUS_SUCCESS
;
8113 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
8117 KdPrint2((PRINT_PREFIX
"START_STOP invalid\n"));
8118 if (Srb
->SenseInfoBuffer
) {
8120 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8122 senseBuffer
->ErrorCode
= 0x70;
8123 senseBuffer
->Valid
= 1;
8124 senseBuffer
->AdditionalSenseLength
= 0xb;
8125 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
8126 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_CDB
;
8127 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8129 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8130 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8132 status
= SRB_STATUS_ERROR
;
8136 case SCSIOP_MEDIUM_REMOVAL
:
8138 cdb
= (PCDB
)Srb
->Cdb
;
8140 if(LunExt
->IdentifyData
.Removable
) {
8141 statusByte
= WaitOnBaseBusy(chan
);
8143 //SelectDrive(chan, DeviceNumber);
8144 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
8145 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
8146 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_LOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8148 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
8149 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_UNLOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8151 status
= SRB_STATUS_SUCCESS
;
8153 status
= SRB_STATUS_INVALID_REQUEST
;
8158 // Note: I don't implement this, because NTFS driver too often issues this command
8159 // It causes awful performance degrade. However, if somebody wants, I will implement
8160 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
8161 case SCSIOP_FLUSH_BUFFER
:
8162 case SCSIOP_SYNCHRONIZE_CACHE
:
8164 SelectDrive(chan
, DeviceNumber
);
8165 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
8166 status
= SRB_STATUS_SUCCESS
;
8167 // status = SRB_STATUS_PENDING;
8168 statusByte
= WaitOnBusy(chan
);
8172 case SCSIOP_REQUEST_SENSE
:
8173 // this function makes sense buffers to report the results
8174 // of the original GET_MEDIA_STATUS command
8176 KdPrint2((PRINT_PREFIX
8177 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8178 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8179 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8180 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
8183 status
= SRB_STATUS_INVALID_REQUEST
;
8187 case SCSIOP_ATA_PASSTHROUGH
:
8190 BOOLEAN use_dma
= FALSE
;
8193 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
8195 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
8196 //lChannel = Srb->TargetId >> 1;
8198 DeviceNumber
= max(DeviceNumber
, 1);
8199 regs
->bDriveHeadReg
&= 0x0f;
8200 regs
->bDriveHeadReg
|= (UCHAR
) (((DeviceNumber
& 0x1) << 4) | 0xA0);
8203 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
8205 KdPrint2((PRINT_PREFIX
8206 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
8207 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8209 if((regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) == UNIATA_SPTI_EX_SPEC_TO
) {
8210 to_lim
= Srb
->TimeOutValue
;
8212 if(Srb
->TimeOutValue
<= 2) {
8213 to_lim
= Srb
->TimeOutValue
*900;
8215 to_lim
= (Srb
->TimeOutValue
*999) - 500;
8219 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8221 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
8223 statusByte
= UniataAhciSendPIOCommandDirect(
8232 if(statusByte
== IDE_STATUS_WRONG
) {
8233 goto passthrough_err
;
8235 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8236 UniataAhciAbortOperation(chan
);
8237 goto passthrough_err
;
8239 goto passthrough_done
;
8243 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
8244 if((chan
->lun
[DeviceNumber
]->LimitedTransferMode
>= ATA_DMA
)) {
8246 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
8247 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
8248 (PUCHAR
)(Srb
->DataBuffer
),
8249 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
8255 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
8256 AtapiStallExecution(10);
8258 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
8259 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8260 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8261 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8262 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8263 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8265 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
8266 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8267 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
8268 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8269 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
8270 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8271 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
8272 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8273 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
8274 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8276 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
8279 GetBaseStatus(chan
, statusByte
);
8280 if(statusByte
& IDE_STATUS_ERROR
) {
8281 goto passthrough_err
;
8283 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
8286 ScsiPortStallExecution(1); // wait for busy to be set
8288 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
8289 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
8290 GetBaseStatus(chan
, statusByte
);
8291 if(statusByte
& IDE_STATUS_ERROR
) {
8294 if(!(statusByte
& IDE_STATUS_BUSY
)) {
8299 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
8301 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8302 goto passthrough_err
;
8306 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
8308 AtapiDmaDone(deviceExtension
, DeviceNumber
, lChannel
, NULL
);
8309 GetBaseStatus(chan
, statusByte
);
8311 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8312 AtapiSuckPort2(chan
);
8314 if (Srb
->SenseInfoBuffer
) {
8316 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8318 senseBuffer
->ErrorCode
= 0x70;
8319 senseBuffer
->Valid
= 1;
8320 senseBuffer
->AdditionalSenseLength
= 0xb;
8321 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
8322 senseBuffer
->AdditionalSenseCode
= 0;
8323 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8325 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8326 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8328 status
= SRB_STATUS_ERROR
;
8332 if (statusByte
& IDE_STATUS_DRQ
) {
8333 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
8335 (PUSHORT
) Srb
->DataBuffer
,
8336 Srb
->DataTransferLength
/ 2,
8338 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
8340 (PUSHORT
) Srb
->DataBuffer
,
8341 Srb
->DataTransferLength
/ 2,
8346 status
= SRB_STATUS_SUCCESS
;
8349 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8351 } else { // read task register
8354 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
8356 KdPrint2((PRINT_PREFIX
8357 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
8358 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8360 if((Srb
->DataTransferLength
>= sizeof(IDEREGS_EX
)) &&
8361 (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
)) {
8364 if(Srb
->DataTransferLength
>= sizeof(IDEREGS
)) {
8367 KdPrint2((PRINT_PREFIX
" buffer too small \n"));
8368 status
= SRB_STATUS_DATA_OVERRUN
;
8371 RtlZeroMemory(regs
, use48
? sizeof(IDEREGS_EX
) : sizeof(IDEREGS
));
8372 regs
->bOpFlags
= use48
? ATA_FLAGS_48BIT_COMMAND
: 0;
8373 UniataSnapAtaRegs(chan
, 0, regs
);
8375 status
= SRB_STATUS_SUCCESS
;
8382 KdPrint2((PRINT_PREFIX
8383 "IdeSendCommand: Unsupported command %#x\n",
8386 status
= SRB_STATUS_INVALID_REQUEST
;
8390 if(status
== SRB_STATUS_PENDING
) {
8391 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
8392 if(CmdAction
& CMD_ACTION_EXEC
) {
8393 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
8394 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
8397 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
8398 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8403 } // end IdeSendCommand()
8408 Routine Description:
8409 Enables disables media status notification
8412 HwDeviceExtension - ATAPI driver storage.
8419 IN PVOID HwDeviceExtension
,
8421 IN ULONG DeviceNumber
8424 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8426 UCHAR statusByte
,errorByte
;
8428 chan
= &(deviceExtension
->chan
[lChannel
]);
8429 SelectDrive(chan
, DeviceNumber
);
8431 if (EnableMSN
== TRUE
){
8433 // If supported enable Media Status Notification support
8434 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
8437 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8438 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8439 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8441 if (statusByte
& IDE_STATUS_ERROR
) {
8442 // Read the error register.
8443 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8445 KdPrint2((PRINT_PREFIX
8446 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
8450 chan
->lun
[DeviceNumber
]->DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
8451 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
8452 chan
->ReturningMediaStatus
= 0;
8457 } else { // end if EnableMSN == TRUE
8459 // disable if previously enabled
8460 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
8462 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8463 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8464 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8465 chan
->lun
[DeviceNumber
]->DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
8472 } // end IdeMediaStatus()
8477 Routine Description:
8479 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
8480 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
8483 HwDeviceExtension - ATAPI driver storage.
8484 Srb - System request block.
8488 SRB status (ALWAYS SUCCESS).
8493 IdeBuildSenseBuffer(
8494 IN PVOID HwDeviceExtension
,
8495 IN PSCSI_REQUEST_BLOCK Srb
8498 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8500 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
8501 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
8505 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
8507 senseBuffer
->ErrorCode
= 0x70;
8508 senseBuffer
->Valid
= 1;
8509 senseBuffer
->AdditionalSenseLength
= 0xb;
8510 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8511 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8512 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8513 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
8515 senseBuffer
->ErrorCode
= 0x70;
8516 senseBuffer
->Valid
= 1;
8517 senseBuffer
->AdditionalSenseLength
= 0xb;
8518 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8519 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8520 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8521 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
8523 senseBuffer
->ErrorCode
= 0x70;
8524 senseBuffer
->Valid
= 1;
8525 senseBuffer
->AdditionalSenseLength
= 0xb;
8526 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
8527 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
8528 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8529 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
8531 senseBuffer
->ErrorCode
= 0x70;
8532 senseBuffer
->Valid
= 1;
8533 senseBuffer
->AdditionalSenseLength
= 0xb;
8534 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
8535 senseBuffer
->AdditionalSenseCode
= 0;
8536 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8538 return SRB_STATUS_SUCCESS
;
8540 return SRB_STATUS_ERROR
;
8542 }// End of IdeBuildSenseBuffer
8546 UniataUserDeviceReset(
8547 PHW_DEVICE_EXTENSION deviceExtension
,
8548 PHW_LU_EXTENSION LunExt
,
8553 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8554 if ((LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
8555 (LunExt
->PowerState
!= StartStop_Power_Sleep
)) {
8556 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
8557 AtapiSoftReset(&(deviceExtension
->chan
[lChannel
]), LunExt
->Lun
);
8559 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
8560 AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8561 for(i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
8562 deviceExtension
->chan
[lChannel
].lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
8565 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
8566 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8568 } // end UniataUserDeviceReset()
8573 PHW_DEVICE_EXTENSION deviceExtension
,
8578 BOOLEAN PostReq
= FALSE
;
8580 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
8581 if(chan
->queue_depth
> 0) {
8584 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
8585 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
8586 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
8588 status
= SRB_STATUS_BUSY
;
8597 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
8601 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
8604 } // end UniataNeedQueueing()
8608 Routine Description:
8610 This routine is called from the SCSI port driver synchronized
8611 with the kernel to start an IO request.
8616 HwDeviceExtension - HBA miniport driver's adapter data storage
8617 Srb - IO request packet
8627 IN PVOID HwDeviceExtension
,
8628 IN PSCSI_REQUEST_BLOCK Srb
8631 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
8632 } // end AtapiStartIo()
8637 IN PVOID HwDeviceExtension
,
8638 IN PSCSI_REQUEST_BLOCK Srb
,
8642 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8645 PHW_LU_EXTENSION LunExt
;
8653 PSCSI_REQUEST_BLOCK tmpSrb
;
8654 BOOLEAN PostReq
= FALSE
;
8656 BOOLEAN commPort
= FALSE
;
8658 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
8659 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
8660 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
8661 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
8663 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
8665 /* KeBugCheckEx(0xc000000e,
8666 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8668 TopLevel, 0x80000001);
8670 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
8671 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
8672 //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
8673 UniAtaClearAtaReq(Srb
->SrbExtension
);
8676 do { // fetch all queued commands for the channel (if valid)
8678 lChannel
= GET_CHANNEL(Srb
);
8679 //ldev = GET_LDEV(Srb);
8682 DeviceNumber
= GET_CDEV(Srb
);
8685 //ASSERT(deviceExtension);
8688 KdPrint2((PRINT_PREFIX
8689 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8690 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8691 KdPrint2((PRINT_PREFIX
" VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
8693 if(lChannel
== deviceExtension
->NumberChannels
&&
8694 !Srb
->Lun
&& !Srb
->TargetId
&&
8695 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
8696 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
8698 // This is our virtual device
8699 KdPrint2((PRINT_PREFIX
8700 "AtapiStartIo: Communication port\n"));
8701 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
8703 if(Srb
->DataTransferLength
< sizeof(PINQUIRYDATA
)) {
8704 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", Srb
->DataTransferLength
,
8705 sizeof(PINQUIRYDATA
) ));
8707 status
= SRB_STATUS_DATA_OVERRUN
;
8711 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
8713 KdPrint2((PRINT_PREFIX
8715 // Zero INQUIRY data structure.
8716 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
8718 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
8720 // Fill in vendor identification fields.
8721 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
8723 status
= SRB_STATUS_SUCCESS
;
8727 /* Pass IOCTL request down */
8729 if(lChannel
>= deviceExtension
->NumberChannels
||
8730 Srb
->TargetId
/*DeviceNumber*/ >= deviceExtension
->NumberLuns
||
8733 if(lChannel
>= deviceExtension
->NumberChannels
) {
8738 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8739 KdPrint3((PRINT_PREFIX
8740 "AtapiStartIo: SRB rejected\n"));
8741 // Indicate no device found at this address.
8742 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
8743 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8747 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
8748 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
8753 chan
= &(deviceExtension
->chan
[lChannel
]);
8754 LunExt
= chan
->lun
[DeviceNumber
];
8758 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
8764 if(!commPort
&& !LunExt
) {
8766 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
8769 deviceExtension
->NumberChannels
);
8770 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
8771 lChannel
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
8772 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8773 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
8777 for(i=0; i<1000; i++) {
8778 AtapiStallExecution(3*1000);
8785 // Determine which function.
8786 switch (Srb
->Function
) {
8788 case SRB_FUNCTION_EXECUTE_SCSI
:
8790 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8791 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
8792 // let passthrough go
8794 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
8798 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8799 KdPrint2((PRINT_PREFIX
8800 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
8801 // Indicate no device found at this address.
8802 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
8803 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8808 KdPrint2((PRINT_PREFIX
8809 " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb
, &(Srb
->Cdb
), Srb
->SrbExtension
, Srb
->Cdb
[0]));
8813 if(Srb->DataTransferLength) {
8815 a = ((PUCHAR)(Srb->DataBuffer))[0];
8818 } __except(EXCEPTION_EXECUTE_HANDLER) {
8819 KdPrint3((PRINT_PREFIX
8820 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
8821 // Indicate no device found at this address.
8822 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
8823 status = SRB_STATUS_ERROR;
8824 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
8829 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
8833 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
8835 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
8836 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
8838 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
8840 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
8841 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
8843 /*KeBugCheckEx(0xc000000e,
8844 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8846 status, 0x80000001);*/
8847 if(status
== SRB_STATUS_BUSY
)
8848 status
= SRB_STATUS_PENDING
;
8849 // Insert requests AFTER they have been initialized on
8850 // CMD_ACTION_PREPARE stage
8851 // we should not check TopLevel here (it is always TRUE)
8852 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8853 UniataQueueRequest(chan
, Srb
);
8855 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
8859 // Send command to device.
8860 KdPrint2((PRINT_PREFIX
"Send to device %x\n", Srb
->Cdb
[0]));
8862 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
8863 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8864 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
8865 //ASSERT(!AtaReq->Flags);
8866 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8867 UniataQueueRequest(chan
, Srb
);
8868 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
8869 //ASSERT(!AtaReq->Flags);
8870 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
8871 //ASSERT(!AtaReq->Flags);
8875 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8879 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
8880 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, DeviceNumber
)) {
8881 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, DeviceNumber
, TRUE
)) {
8885 if(!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8889 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
8898 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)/* &&
8899 (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
8900 KdPrint3((PRINT_PREFIX
"Try ATAPI send %x\n", Srb
->Cdb
[0]));
8901 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
8903 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
8908 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
8915 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
8917 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
8919 /* KeBugCheckEx(0xc000000e,
8920 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8922 status, 0x80000002);*/
8930 case SRB_FUNCTION_ABORT_COMMAND
:
8932 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
8934 // Verify that SRB to abort is still outstanding.
8935 if((tmpSrb
!= Srb
->NextSrb
) ||
8936 !chan
->queue_depth
) {
8938 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
8940 // Complete abort SRB.
8941 status
= SRB_STATUS_ABORT_FAILED
;
8945 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
8946 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
8947 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
8948 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
8949 // Log reset failure.
8950 KdPrint3((PRINT_PREFIX
8951 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
8952 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
8954 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
8955 status
= SRB_STATUS_ERROR
;
8958 status
= SRB_STATUS_SUCCESS
;
8961 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
8962 if (tmpSrb
->SenseInfoBuffer
&&
8963 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
8965 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
8967 senseBuffer
->ErrorCode
= 0;
8968 senseBuffer
->Valid
= 1;
8969 senseBuffer
->AdditionalSenseLength
= 0xb;
8970 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
8971 senseBuffer
->AdditionalSenseCode
= 0;
8972 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8974 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
8976 AtapiDmaDBSync(chan
, tmpSrb
);
8977 UniataRemoveRequest(chan
, tmpSrb
);
8978 // Indicate command complete.
8979 ScsiPortNotification(RequestComplete
,
8982 status
= SRB_STATUS_SUCCESS
;
8986 // Abort function indicates that a request timed out.
8987 // Call reset routine. Card will only be reset if
8988 // status indicates something is wrong.
8989 // Fall through to reset code.
8991 case SRB_FUNCTION_RESET_DEVICE
:
8992 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
8994 // Reset single device.
8995 // For now we support only Lun=0
8997 // Note: reset is immediate command, it cannot be queued since it is usually used to
8998 // revert not-responding device to operational state
8999 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
9000 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
9001 status
= SRB_STATUS_SUCCESS
;
9004 case SRB_FUNCTION_RESET_BUS
:
9006 // Reset Atapi and SCSI bus.
9008 // Note: reset is immediate command, it cannot be queued since it is usually used to
9009 // revert not- responding device to operational state
9010 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
9011 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
9012 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
9013 // Log reset failure.
9014 KdPrint3((PRINT_PREFIX
9015 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
9016 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
9018 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
9019 status
= SRB_STATUS_ERROR
;
9022 status
= SRB_STATUS_SUCCESS
;
9027 case SRB_FUNCTION_SHUTDOWN
:
9029 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
9030 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9031 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
9034 // FLUSH ATAPI device - do nothing
9035 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
9037 // FLUSH IDE/ATA device
9038 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
9039 AtapiDisableInterrupts(deviceExtension
, lChannel
);
9040 status
= AtaCommand(deviceExtension
, DeviceNumber
, GET_CHANNEL(Srb
),
9041 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
9042 // If supported & allowed, reset write cacheing
9043 if(LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
9045 // Disable write cache
9046 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9047 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9048 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
9049 // Check for errors.
9050 if (status
& IDE_STATUS_ERROR
) {
9051 KdPrint2((PRINT_PREFIX
9052 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
9055 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9057 // Re-enable write cache
9058 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9059 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9060 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
9061 // Check for errors.
9062 if (status
& IDE_STATUS_ERROR
) {
9063 KdPrint2((PRINT_PREFIX
9064 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
9066 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9068 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
9072 AtapiEnableInterrupts(deviceExtension
, lChannel
);
9074 status
= SRB_STATUS_SUCCESS
;
9078 case SRB_FUNCTION_FLUSH
:
9080 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
9081 status
= SRB_STATUS_SUCCESS
;
9084 case SRB_FUNCTION_IO_CONTROL
: {
9088 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
9090 len
= Srb
->DataTransferLength
;
9092 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
9094 ULONG targetId
= (ULONG
)(-1);
9096 if(len
< sizeof(SRB_IO_CONTROL
)) {
9097 goto wrong_buffer_size
;
9100 // extract bogus bus address
9101 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9102 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9103 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9105 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(GETVERSIONINPARAMS
)) {
9106 goto wrong_buffer_size
;
9109 targetId
= versionParameters
->bIDEDeviceMap
;
9110 KdPrint2((PRINT_PREFIX
"targetId (smart ver) %d\n", targetId
));
9112 case IOCTL_SCSI_MINIPORT_IDENTIFY
:
9113 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
9114 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
9115 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
9116 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
9117 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
9118 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
9119 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
9120 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
9121 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE
:
9122 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG
:
9123 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG
:
9125 PSENDCMDINPARAMS cmdInParameters
= (PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9127 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDINPARAMS
) - 1) {
9128 goto wrong_buffer_size
;
9131 targetId
= cmdInParameters
->bDriveNumber
;
9132 KdPrint2((PRINT_PREFIX
"targetId (smart/ident) %d\n", targetId
));
9136 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9137 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
9138 status
= SRB_STATUS_INVALID_REQUEST
;
9142 // adjust (if necessary) bus address
9143 if(targetId
!= (ULONG
)(-1)) {
9145 // This is done because of how the IOCTL_SCSI_MINIPORT
9146 // determines 'targetid's'. Disk.sys places the real target id value
9147 // in the DeviceMap field. Once we do some parameter checking, the value passed
9148 // back to the application will be determined.
9150 if (deviceExtension
->NumberChannels
== 1) {
9151 // do this for legacy controllers and legacy callers
9152 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call\n"));
9153 DeviceNumber
= (targetId
& 0x01);
9157 // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
9158 // due to DISK.SYS design bug, we have invalid SCSI address in SRB
9159 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call (2)\n"));
9160 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
9161 lChannel
= (UCHAR
)targetId
/ 2;
9164 lChannel
= (UCHAR
)(targetId
/ 2);
9165 DeviceNumber
= targetId
& 0x01;
9168 // otherwise assume lChannel and DeviceNumber from Srb are ok
9170 if(lChannel
>= deviceExtension
->NumberChannels
||
9171 DeviceNumber
>= deviceExtension
->NumberLuns
) {
9172 KdPrint2((PRINT_PREFIX
9173 "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
9175 // Indicate no device found at this address.
9178 targetId
= lChannel
*deviceExtension
->NumberLuns
+DeviceNumber
;
9179 chan
= &(deviceExtension
->chan
[lChannel
]);
9180 LunExt
= chan
->lun
[DeviceNumber
];
9184 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
9186 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9191 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9192 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9194 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9195 UCHAR deviceNumberMap
;
9197 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
9199 // Version and revision per SMART 1.03
9201 versionParameters
->bVersion
= 1;
9202 versionParameters
->bRevision
= 1;
9203 versionParameters
->bReserved
= 0;
9205 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
9206 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
9209 goto invalid_request
;
9212 // NOTE: This will only set the bit
9213 // corresponding to this drive's target id.
9214 // The bit mask is as follows:
9220 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
9221 deviceNumberMap
= 1 << lChannel
;
9224 if (deviceExtension
->NumberChannels
== 1) {
9225 if (chan
->PrimaryAddress
) {
9226 deviceNumberMap
= 1 << DeviceNumber
;
9228 deviceNumberMap
= 4 << DeviceNumber
;
9231 deviceNumberMap
= 1 << (DeviceNumber
+lChannel
*2);
9234 versionParameters
->bIDEDeviceMap
= deviceNumberMap
;
9236 status
= SRB_STATUS_SUCCESS
;
9240 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
9242 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9243 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9245 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
9246 // Extract the target.
9247 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
9249 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
9252 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
9253 goto invalid_request
;
9259 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
9260 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
9261 goto invalid_request
;
9264 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
9265 // Zero the output buffer
9266 RtlZeroMemory(cmdOutParameters
, len
);
9267 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
9268 ((PUCHAR)cmdOutParameters)[i] = 0;
9271 // Build status block.
9272 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
9273 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
9274 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
9276 // Extract the identify data from the device extension.
9277 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &(LunExt
->IdentifyData
),
9278 cmdOutParameters
->cBufferSize
);
9280 if((cmdOutParameters
->cBufferSize
== IDENTIFY_BUFFER_SIZE
) &&
9281 (LunExt
->IdentifyData
.ChecksumValid
== ATA_ChecksumValid
)) {
9282 // adjust checksum if it is possible
9286 for(i
=0; i
< IDENTIFY_BUFFER_SIZE
-1; i
++) {
9287 csum
+= (CHAR
)(cmdOutParameters
->bBuffer
[i
]);
9289 cmdOutParameters
->bBuffer
[i
] = -csum
;
9290 KdPrint2((PRINT_PREFIX
"AtapiStartIo: adjust checksum %d\n"));
9292 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
9294 status
= SRB_STATUS_SUCCESS
;
9298 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
9299 cmdInParameters
.irDriveRegs
.bCommandReg
));
9300 status
= SRB_STATUS_INVALID_REQUEST
;
9306 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9307 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9308 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9309 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9310 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9311 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9312 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9313 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9316 // *all* IOCTLs here are SMART
9318 KdPrint2((PRINT_PREFIX
9319 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
9322 goto invalid_request
;
9325 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9327 if(PostReq
|| TopLevel
) {
9328 UniataQueueRequest(chan
, Srb
);
9329 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9330 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9335 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
9336 status
= SRB_STATUS_PENDING
;
9338 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9341 status
= IdeSendSmartCommand(HwDeviceExtension
, Srb
, targetId
);
9345 // we should not get here, checked above
9347 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9348 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9349 status = SRB_STATUS_INVALID_REQUEST;
9354 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
9356 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
9357 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
9358 ULONG DeviceNumber
= AtaCtl
->addr
.TargetId
;
9362 pos
= FIELD_OFFSET(UNIATA_CTL
, RawData
);
9363 //chan = &(deviceExtension->chan[lChannel]);
9365 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9366 FIELD_OFFSET(UNIATA_CTL
, RawData
) ));
9367 goto wrong_buffer_size
;
9370 if(AtaCtl
->addr
.Lun
||
9371 AtaCtl
->addr
.TargetId
>= deviceExtension
->NumberLuns
||
9372 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
9380 lChannel
= AtaCtl
->addr
.PathId
;
9381 chan
= &(deviceExtension
->chan
[lChannel
]);
9382 LunExt
= chan
->lun
[DeviceNumber
];
9385 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl
->hdr
.ControlCode
, DeviceNumber
));
9387 /* check for valid LUN */
9388 switch (AtaCtl
->hdr
.ControlCode
) {
9389 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9390 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
9391 // this would be BUS reset
9393 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
9394 AtaCtl
->addr
.TargetId
!= 0xff ||
9395 AtaCtl
->addr
.Lun
!= 0
9397 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
9398 DeviceNumber
< deviceExtension
->NumberLuns
) { // AtaCtl->addr.TargetId != 0xff
9399 lChannel
= AtaCtl
->addr
.PathId
;
9400 chan
= &(deviceExtension
->chan
[lChannel
]);
9401 LunExt
= chan
->lun
[DeviceNumber
];
9404 goto handle_bad_ldev
;
9407 lChannel
= AtaCtl
->addr
.PathId
;
9408 chan
= &(deviceExtension
->chan
[lChannel
]);
9411 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
9412 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9413 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
9414 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9415 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
9418 KdPrint2((PRINT_PREFIX
9419 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
9420 // Indicate no device found at this address.
9425 /* check if queueing is necessary */
9426 switch (AtaCtl
->hdr
.ControlCode
) {
9427 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9428 if(!LunExt
->nBadBlocks
) {
9431 goto uata_ctl_queue
;
9432 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9433 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9434 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9435 pos
+sizeof(AtaCtl
->SetMode
) ));
9436 goto wrong_buffer_size
;
9438 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
9441 goto uata_ctl_queue
;
9442 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9443 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
9445 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
9446 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9448 if(PostReq
|| TopLevel
) {
9449 UniataQueueRequest(chan
, Srb
);
9450 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9451 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9454 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
9455 status
= SRB_STATUS_PENDING
;
9457 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9460 } // end switch (AtaCtl->hdr.ControlCode)
9462 /* process request */
9463 switch (AtaCtl
->hdr
.ControlCode
) {
9464 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9466 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
9468 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9469 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9470 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9471 goto wrong_buffer_size
;
9473 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
9474 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
9475 if(AtaCtl
->addr
.TargetId
!= 0xff) {
9476 LunExt
->DeviceFlags
&= ~DFLAGS_HIDDEN
;
9481 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9482 AtapiStallExecution(1000 * 1000);
9485 FindDevices(HwDeviceExtension
,
9486 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
9487 ? UNIATA_FIND_DEV_UNHIDE
: 0,
9488 AtaCtl
->addr
.PathId
);
9489 status
= SRB_STATUS_SUCCESS
;
9493 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
9495 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
9497 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9498 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9499 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9500 goto wrong_buffer_size
;
9502 LunExt
->DeviceFlags
= 0;
9503 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
9504 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
9505 //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
9506 UniataForgetDevice(LunExt
);
9509 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9510 AtapiStallExecution(1000 * 1000);
9513 status
= SRB_STATUS_SUCCESS
;
9516 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
9518 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
9520 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9521 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9522 pos
+sizeof(AtaCtl
->SetMode
) ));
9523 goto wrong_buffer_size
;
9525 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
9526 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
9528 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
9529 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
9530 if(LunExt
->LimitedTransferMode
>
9531 LunExt
->OrigTransferMode
) {
9532 // check for incorrect value
9533 LunExt
->LimitedTransferMode
=
9534 LunExt
->OrigTransferMode
;
9537 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
9539 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
9540 if(AtaCtl
->SetMode
.ApplyImmediately
) {
9541 AtapiDmaInit__(deviceExtension
, LunExt
);
9543 /* LunExt->TransferMode =
9544 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
9545 status
= SRB_STATUS_SUCCESS
;
9548 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
9550 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
9552 if(len
< pos
+sizeof(AtaCtl
->GetMode
)) {
9553 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9554 pos
+sizeof(AtaCtl
->GetMode
) ));
9555 goto wrong_buffer_size
;
9557 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
9558 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
9559 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
9560 AtaCtl
->GetMode
.PhyMode
= LunExt
->PhyTransferMode
;
9562 status
= SRB_STATUS_SUCCESS
;
9565 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION
: {
9567 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get version\n"));
9569 if(len
< pos
+sizeof(AtaCtl
->Version
)) {
9570 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9571 pos
+sizeof(AtaCtl
->Version
) ));
9572 goto wrong_buffer_size
;
9574 AtaCtl
->Version
.Length
= sizeof(GETDRVVERSION
);
9575 AtaCtl
->Version
.VersionMj
= UNIATA_VER_MJ
;
9576 AtaCtl
->Version
.VersionMn
= UNIATA_VER_MN
;
9577 AtaCtl
->Version
.SubVerMj
= UNIATA_VER_SUB_MJ
;
9578 AtaCtl
->Version
.SubVerMn
= UNIATA_VER_SUB_MN
;
9580 status
= SRB_STATUS_SUCCESS
;
9583 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
9585 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
9587 if(len
< pos
+sizeof(AtaCtl
->AdapterInfo
)) {
9588 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9589 pos
+sizeof(AtaCtl
->AdapterInfo
) ));
9590 goto wrong_buffer_size
;
9592 AtaCtl
->AdapterInfo
.HeaderLength
= sizeof(ADAPTERINFO
);
9594 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
9595 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
9596 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
9597 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
9598 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
9599 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
9600 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
9601 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
9602 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
9603 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
9604 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
9605 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
9606 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
9607 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
9608 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
9609 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
9610 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
9611 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
9612 AtaCtl
->AdapterInfo
.NumberLuns
= (UCHAR
)deviceExtension
->NumberLuns
;
9613 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
9614 if(deviceExtension
->FullDevName
) {
9615 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
9617 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
9618 AtaCtl
->AdapterInfo
.LunInfoValid
= FALSE
;
9619 AtaCtl
->AdapterInfo
.ChanHeaderLengthValid
= TRUE
;
9621 pos
+= AtaCtl
->AdapterInfo
.HeaderLength
;
9624 RtlZeroMemory(((PCHAR
)AtaCtl
)+pos
,
9627 if(len
>= pos
+AtaCtl
->AdapterInfo
.NumberChannels
*sizeof(CHANINFO
)) {
9628 PCHANINFO ChanInfo
= (PCHANINFO
)( ((PCHAR
)AtaCtl
)+pos
);
9629 PHW_CHANNEL cur_chan
;
9630 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Fill channel info\n"));
9631 for(i
=0;i
<AtaCtl
->AdapterInfo
.NumberChannels
;i
++) {
9632 KdPrint2((PRINT_PREFIX
"chan[%d] %x\n", i
, cur_chan
));
9633 cur_chan
= &(deviceExtension
->chan
[i
]);
9634 ChanInfo
->MaxTransferMode
= cur_chan
->MaxTransferMode
;
9635 ChanInfo
->ChannelCtrlFlags
= cur_chan
->ChannelCtrlFlags
;
9636 RtlCopyMemory(&(ChanInfo
->QueueStat
), &(cur_chan
->QueueStat
), sizeof(ChanInfo
->QueueStat
));
9637 ChanInfo
->ReorderCount
= cur_chan
->ReorderCount
;
9638 ChanInfo
->IntersectCount
= cur_chan
->IntersectCount
;
9639 ChanInfo
->TryReorderCount
= cur_chan
->TryReorderCount
;
9640 ChanInfo
->TryReorderHeadCount
= cur_chan
->TryReorderHeadCount
;
9641 ChanInfo
->TryReorderTailCount
= cur_chan
->TryReorderTailCount
;
9642 //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
9645 AtaCtl
->AdapterInfo
.ChanInfoValid
= TRUE
;
9646 AtaCtl
->AdapterInfo
.ChanHeaderLength
= sizeof(*ChanInfo
);
9649 status
= SRB_STATUS_SUCCESS
;
9652 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
9654 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
9656 ForgetBadBlocks(LunExt
);
9658 status
= SRB_STATUS_SUCCESS
;
9661 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
9663 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
9668 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
);
9671 status
= SRB_STATUS_SUCCESS
;
9675 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
9676 AtaCtl
->hdr
.ControlCode
));
9677 status
= SRB_STATUS_INVALID_REQUEST
;
9682 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
9683 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
9684 "SCSIDISK", "-UNIATA-"));
9686 status
= SRB_STATUS_INVALID_REQUEST
;
9691 } // end SRB_FUNCTION_IO_CONTROL
9694 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
9695 // Indicate unsupported command.
9696 status
= SRB_STATUS_INVALID_REQUEST
;
9704 PathId
= Srb
->PathId
;
9705 TargetId
= Srb
->TargetId
;
9708 if (status
!= SRB_STATUS_PENDING
) {
9710 KdPrint2((PRINT_PREFIX
9711 "AtapiStartIo: Srb %#x complete with status %#x\n",
9715 // Set status in SRB.
9716 Srb
->SrbStatus
= (UCHAR
)status
;
9719 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan
, Srb
));
9720 AtapiDmaDBSync(chan
, Srb
);
9722 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan
, Srb
));
9723 UniataRemoveRequest(chan
, Srb
);
9724 // Indicate command complete.
9725 KdPrint2((PRINT_PREFIX
"AtapiStartIo: ScsiPortNotification\n"));
9726 ScsiPortNotification(RequestComplete
,
9730 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataGetCurRequest\n"));
9731 // Remove current Srb & get next one
9732 if((Srb
= UniataGetCurRequest(chan
))) {
9733 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9734 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
9735 // current request is under precessing, thus
9736 // we should do nothing here
9740 KdPrint2((PRINT_PREFIX
"AtapiStartIo: chan %x, Src %x\n", chan
, Srb
));
9745 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
9747 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
9749 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
9750 // Indicate ready for next request.
9751 ScsiPortNotification(NextRequest
,
9755 ScsiPortNotification(NextLuRequest
,
9763 } // end AtapiStartIo__()
9768 UniataInitAtaCommands()
9774 KdPrint2((PRINT_PREFIX
"UniataInitAtaCommands:\n"));
9776 for(i
=0; i
<256; i
++) {
9781 //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
9784 case IDE_COMMAND_READ_DMA48
:
9785 case IDE_COMMAND_READ_DMA_Q48
:
9786 case IDE_COMMAND_READ_STREAM_DMA48
:
9787 case IDE_COMMAND_READ_STREAM48
:
9788 case IDE_COMMAND_WRITE_DMA48
:
9789 case IDE_COMMAND_WRITE_DMA_Q48
:
9790 case IDE_COMMAND_READ_DMA_Q
:
9791 case IDE_COMMAND_READ_DMA
:
9792 case IDE_COMMAND_WRITE_DMA
:
9793 case IDE_COMMAND_WRITE_DMA_Q
:
9794 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9795 case IDE_COMMAND_WRITE_STREAM48
:
9796 case IDE_COMMAND_WRITE_FUA_DMA48
:
9797 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9798 case IDE_COMMAND_READ_LOG_DMA48
:
9799 case IDE_COMMAND_WRITE_LOG_DMA48
:
9800 case IDE_COMMAND_TRUSTED_RCV_DMA
:
9801 case IDE_COMMAND_TRUSTED_SEND_DMA
:
9802 case IDE_COMMAND_DATA_SET_MGMT
:
9803 //KdPrint2((PRINT_PREFIX "DMA "));
9804 flags
|= ATA_CMD_FLAG_DMA
;
9808 case IDE_COMMAND_WRITE_FUA_DMA48
:
9809 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9810 case IDE_COMMAND_WRITE_MUL_FUA48
:
9812 flags
|= ATA_CMD_FLAG_FUA
;
9815 case IDE_COMMAND_READ48
:
9816 case IDE_COMMAND_READ_DMA48
:
9817 case IDE_COMMAND_READ_DMA_Q48
:
9818 case IDE_COMMAND_READ_MUL48
:
9819 case IDE_COMMAND_READ_STREAM_DMA48
:
9820 case IDE_COMMAND_READ_STREAM48
:
9821 case IDE_COMMAND_WRITE48
:
9822 case IDE_COMMAND_WRITE_DMA48
:
9823 case IDE_COMMAND_WRITE_DMA_Q48
:
9824 case IDE_COMMAND_WRITE_MUL48
:
9825 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9826 case IDE_COMMAND_WRITE_STREAM48
:
9827 case IDE_COMMAND_FLUSH_CACHE48
:
9828 case IDE_COMMAND_VERIFY48
:
9830 //KdPrint2((PRINT_PREFIX "48 "));
9831 flags
|= ATA_CMD_FLAG_48
;
9834 case IDE_COMMAND_READ
:
9835 case IDE_COMMAND_READ_MULTIPLE
:
9836 case IDE_COMMAND_READ_DMA
:
9837 case IDE_COMMAND_READ_DMA_Q
:
9838 case IDE_COMMAND_WRITE
:
9839 case IDE_COMMAND_WRITE_MULTIPLE
:
9840 case IDE_COMMAND_WRITE_DMA
:
9841 case IDE_COMMAND_WRITE_DMA_Q
:
9842 case IDE_COMMAND_FLUSH_CACHE
:
9843 case IDE_COMMAND_VERIFY
:
9845 //KdPrint2((PRINT_PREFIX "LBA "));
9846 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
9850 case IDE_COMMAND_READ_NATIVE_SIZE48
:
9851 case IDE_COMMAND_SET_NATIVE_SIZE48
:
9852 // we cannot set LBA flag for these commands to avoid BadBlock handling
9853 //flags |= ATA_CMD_FLAG_LBAIOsupp;
9854 flags
|= ATA_CMD_FLAG_48
;
9856 case IDE_COMMAND_READ_NATIVE_SIZE
:
9857 case IDE_COMMAND_SET_NATIVE_SIZE
:
9859 flags
|= ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_FUA
;
9862 flags
|= ATA_CMD_FLAG_48supp
;
9865 case IDE_COMMAND_READ
:
9866 command
= IDE_COMMAND_READ48
; break;
9867 case IDE_COMMAND_READ_MULTIPLE
:
9868 command
= IDE_COMMAND_READ_MUL48
; break;
9869 case IDE_COMMAND_READ_DMA
:
9870 command
= IDE_COMMAND_READ_DMA48
; break;
9871 case IDE_COMMAND_READ_DMA_Q
:
9872 command
= IDE_COMMAND_READ_DMA_Q48
; break;
9873 case IDE_COMMAND_WRITE
:
9874 command
= IDE_COMMAND_WRITE48
; break;
9875 case IDE_COMMAND_WRITE_MULTIPLE
:
9876 command
= IDE_COMMAND_WRITE_MUL48
; break;
9877 case IDE_COMMAND_WRITE_DMA
:
9878 command
= IDE_COMMAND_WRITE_DMA48
; break;
9879 case IDE_COMMAND_WRITE_DMA_Q
:
9880 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
9881 case IDE_COMMAND_FLUSH_CACHE
:
9882 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
9883 // case IDE_COMMAND_READ_NATIVE_SIZE:
9884 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
9885 case IDE_COMMAND_SET_NATIVE_SIZE
:
9886 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
9887 case IDE_COMMAND_VERIFY
:
9888 command
= IDE_COMMAND_VERIFY48
; break;
9890 //KdPrint2((PRINT_PREFIX "!28->48 "));
9891 flags
&= ~ATA_CMD_FLAG_48supp
;
9895 case IDE_COMMAND_READ
:
9896 case IDE_COMMAND_READ_MULTIPLE
:
9897 case IDE_COMMAND_READ_DMA48
:
9898 case IDE_COMMAND_READ_DMA_Q48
:
9899 case IDE_COMMAND_READ_STREAM_DMA48
:
9900 case IDE_COMMAND_READ_STREAM48
:
9901 case IDE_COMMAND_READ_DMA_Q
:
9902 case IDE_COMMAND_READ_DMA
:
9903 case IDE_COMMAND_READ_LOG_DMA48
:
9904 case IDE_COMMAND_TRUSTED_RCV_DMA
:
9905 case IDE_COMMAND_IDENTIFY
:
9906 case IDE_COMMAND_ATAPI_IDENTIFY
:
9907 //KdPrint2((PRINT_PREFIX "RD "));
9908 flags
|= ATA_CMD_FLAG_In
;
9910 case IDE_COMMAND_WRITE
:
9911 case IDE_COMMAND_WRITE_MULTIPLE
:
9912 case IDE_COMMAND_WRITE_DMA48
:
9913 case IDE_COMMAND_WRITE_DMA_Q48
:
9914 case IDE_COMMAND_WRITE_DMA
:
9915 case IDE_COMMAND_WRITE_DMA_Q
:
9916 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9917 case IDE_COMMAND_WRITE_STREAM48
:
9918 case IDE_COMMAND_WRITE_FUA_DMA48
:
9919 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9920 //KdPrint2((PRINT_PREFIX "WR "));
9921 flags
|= ATA_CMD_FLAG_Out
;
9925 //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
9926 AtaCommands48
[i
] = command
;
9927 AtaCommandFlags
[i
] = flags
;
9929 } // end UniataInitAtaCommands()
9933 Routine Description:
9935 Installable driver initialization entry point for system.
9943 Status from ScsiPortInitialize()
9950 IN PVOID DriverObject
,
9954 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
9957 ULONG statusToReturn
, newStatus
;
9958 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
9959 BOOLEAN ReEnter
= FALSE
;
9961 #ifndef USE_REACTOS_DDK
9965 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
9966 BOOLEAN PrimaryClaimed
= FALSE
;
9967 BOOLEAN SecondaryClaimed
= FALSE
;
9969 LARGE_INTEGER t0
, t1
;
9972 KdPrint2((PRINT_PREFIX
"%s", (PCCHAR
)ver_string
));
9973 //a = (WCHAR)strlen(ver_string);
9975 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
9977 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
9980 if(!SavedDriverObject
) {
9981 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
9982 #ifdef USE_REACTOS_DDK
9983 KdPrint(("UniATA Init: OS should be ReactOS\n"));
9988 // we are here for the 1st time
9989 // init CrossNT and get OS version
9990 if(!NT_SUCCESS(status
= CrNtInit(SavedDriverObject
, RegistryPath
))) {
9991 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status
));
9992 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
9995 #endif // USE_REACTOS_DDK
9996 KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion
, MinorVersion
, BuildNumber
, KeNumberProcessors
));
9998 KeQuerySystemTime(&t0
);
10000 KeQuerySystemTime(&t1
);
10001 } while(t0
.QuadPart
== t1
.QuadPart
);
10005 KeQuerySystemTime(&t1
);
10007 } while(t0
.QuadPart
== t1
.QuadPart
);
10008 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
10009 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
10011 KdPrint(("UniATA Init: ReEnter\n"));
10015 // (re)read bad block list
10016 InitBadBlocks(NULL
);
10019 // init ATA command translation table
10020 UniataInitAtaCommands();
10021 // get registry path to settings
10022 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
10023 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
10024 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
10025 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
10026 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
10027 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
10030 if(WinVer_Id() >= WinVer_2k
) {
10031 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
10032 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
10033 WinVer_WDM_Model
= TRUE
;
10035 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
10036 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
10037 WinVer_WDM_Model
= TRUE
;
10041 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
10042 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
10044 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
10047 statusToReturn
= 0xffffffff;
10049 // Zero out structure.
10050 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
10052 // Set size of hwInitializationData.
10053 hwInitializationData
.comm
.HwInitializationDataSize
=
10054 sizeof(hwInitializationData
.comm
) +
10055 // sizeof(hwInitializationData.nt4) +
10056 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
10057 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
10059 // Set entry points.
10060 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
10061 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
10062 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
10063 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
10065 // Specify size of extensions.
10066 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
10067 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
10068 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
10070 // Indicate PIO device.
10071 hwInitializationData
.comm
.MapBuffers
= TRUE
;
10072 // Set PnP-specific API
10073 if(WinVer_Id() > WinVer_NT
) {
10074 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
10075 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
10076 KdPrint(("set AtapiAdapterControl() ptr\n"));
10077 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
10080 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE enum supported BusMaster Devices\n"));
10084 g_opt_VirtualMachine
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualMachineType", g_opt_VirtualMachine
);
10085 if(g_opt_VirtualMachine
> VM_MAX_KNOWN
) {
10086 g_opt_VirtualMachine
= 0;
10088 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualBox", (g_opt_VirtualMachine
== VM_VBOX
))) {
10089 g_opt_VirtualMachine
= VM_VBOX
;
10091 // Pre-scan PCI bus, also check if we are under VM
10092 UniataEnumBusMasterController(DriverObject
, Argument2
);
10094 switch(g_opt_VirtualMachine
) {
10096 KdPrint2((PRINT_PREFIX
"adjust options for VirtualBox\n"));
10097 // adjust options for VirtualBox
10098 g_opt_WaitBusyCount
= 20000;
10099 g_opt_WaitBusyDelay
= 150;
10100 g_opt_WaitDrqDelay
= 100;
10101 g_opt_WaitBusyLongCount
= 20000;
10102 g_opt_MaxIsrWait
= 200;
10103 g_opt_AtapiSendDisableIntr
= 0;
10104 g_opt_AtapiDmaRawRead
= FALSE
;
10109 KdPrint2((PRINT_PREFIX
"old slow machine, adjust timings\n"));
10110 // old slow machine, adjust timings
10111 g_opt_WaitBusyCount
= 20000;
10112 g_opt_WaitBusyDelay
= 150;
10113 g_opt_WaitDrqDelay
= 100;
10114 g_opt_WaitBusyLongCount
= 20000;
10115 g_opt_MaxIsrWait
= 200;
10118 g_opt_WaitBusyCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyCount", g_opt_WaitBusyCount
); // 200 vs 20000
10119 g_opt_WaitBusyDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyDelay", g_opt_WaitBusyDelay
); // 10 vs 150
10120 g_opt_WaitDrqDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitDrqDelay", g_opt_WaitDrqDelay
); // 10 vs 100
10121 g_opt_WaitBusyLongCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongCount", g_opt_WaitBusyLongCount
); // 2000 vs 20000
10122 g_opt_WaitBusyLongDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongDelay", g_opt_WaitBusyLongDelay
); // 250 vs 250
10123 g_opt_AtapiSendDisableIntr
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr
); // 1 vs 0
10124 g_opt_AtapiDmaRawRead
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiDmaRawRead", g_opt_AtapiDmaRawRead
); // 1 vs 0
10125 g_opt_MaxIsrWait
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"MaxIsrWait", g_opt_MaxIsrWait
); // 40 vs xxx
10128 // Look for legacy ISA-bridged PCI IDE controller (onboard)
10129 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
10130 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
10131 for (i
=0; i
<BMListLen
; i
++) {
10133 if(!BMList
[i
].MasterDev
) {
10134 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
10137 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10141 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
10142 if(BMList
[i
].ChanInitOk
& 0x03) {
10143 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
10145 newStatus
= STATUS_SUCCESS
;
10149 //BMList[i].AltInitMasterDev = (UCHAR)0xff;
10151 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
10152 PrimaryClaimed
= TRUE
;
10153 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
10154 SecondaryClaimed
= TRUE
;
10156 if(!WinVer_WDM_Model
&& !PrimaryClaimed
&& !SecondaryClaimed
&&
10157 !(BMList
[i
].ChanInitOk
& 0x80)) {
10158 newStatus
= UniataClaimLegacyPCIIDE(i
);
10159 if(newStatus
!= STATUS_SUCCESS
) {
10160 KdPrint2((PRINT_PREFIX
"Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
10165 if(g_opt_Verbose
) {
10166 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
10170 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
10172 for(c
=0; c
<2; c
++) {
10174 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10178 if(PrimaryClaimed
) {
10179 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
10184 if(SecondaryClaimed
) {
10185 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
10190 if((WinVer_Id() < WinVer_2k
)) {
10191 // do not even try if already claimed
10193 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
10196 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
10199 if(!WinVer_WDM_Model
) {
10200 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10202 // in WDM model things are different....
10203 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
10204 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
10206 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10207 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10209 if(!WinVer_WDM_Model
) {
10210 BMList
[i
].channel
= (UCHAR
)c
;
10213 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
10214 newStatus
= ScsiPortInitialize(DriverObject
,
10216 &hwInitializationData
.comm
,
10217 (PVOID
)(i
| (alt
? 0x80000000 : 0)));
10218 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10219 if (newStatus
< statusToReturn
) {
10220 statusToReturn
= newStatus
;
10222 if (newStatus
== STATUS_SUCCESS
) {
10223 if(WinVer_Id() < WinVer_2k
) {
10224 // This should be done in HwInitialize under w2k+ to ensure that
10225 // channel is actually initialized
10226 BMList
[i
].ChanInitOk
|= 0x01 << c
;
10228 if(BMList
[i
].ChanInitOk
& (0x01 << c
)) {
10229 KdPrint2((PRINT_PREFIX
"HwInit passed\n"));
10233 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
10234 c = 1; // this will break our for()
10235 BMList[i].ChanInitOk |= 0x01 << c;
10240 /* if(WinVer_Id() >= WinVer_2k) {
10241 // the following didn't work under higher OSes,
10242 // until we move setting of FLAGS to HwInit
10243 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
10246 if(BMList
[i
].ChanInitOk
& 0x03) {
10247 // Under NT we receive status immediately, so
10248 // we can omit alternative init method if STATUS_SUCCESS returned.
10249 // Under w2k+ we relay on flags, set in HwInitialize.
10250 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
10253 if(WinVer_Id() >= WinVer_2k
) {
10254 // try AltInit if HwInit was not called immediately under w2k+
10255 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10257 // if (WinVer_Id() == WinVer_NT) and some error occured
10258 // try alternative init method
10259 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10262 if(g_opt_Verbose
) {
10263 if(BMList
[i
].ChanInitOk
& 0x03) {
10264 _PrintNtConsole(" OK\n");
10266 _PrintNtConsole(" failed\n");
10272 /* KeBugCheckEx(0xc000000e,
10273 (i << 16) | BMList[0].ChanInitOk,
10275 newStatus, statusToReturn);*/
10277 // Look for PCI IDE controller
10278 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
10279 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
10280 for (; i
<BMListLen
; i
++) {
10282 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", 0)) {
10285 /* if(BMList[i].MasterDev)
10287 if(g_opt_Verbose
) {
10288 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
10289 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
10290 BMList
[i
].busNumber
,
10291 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
10292 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
10295 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10296 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10297 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
10299 hwInitializationData
.comm
.VendorId
= (PVOID
)BMList
[i
].VendorId
;
10300 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
10301 hwInitializationData
.comm
.DeviceId
= (PVOID
)BMList
[i
].DeviceId
;
10302 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
10304 BMList
[i
].channel
= 0/*(UCHAR)c*/;
10306 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
10307 hwInitializationData
.comm
.VendorId
,
10308 hwInitializationData
.comm
.DeviceId
));
10309 newStatus
= ScsiPortInitialize(DriverObject
,
10311 &hwInitializationData
.comm
,
10313 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10314 if(newStatus
== (ULONG
)STATUS_DEVICE_DOES_NOT_EXIST
&& BMList
[i
].NeedAltInit
) {
10315 // Note: this is actually a BUG in scsiport.sys
10316 // It stops scanning PCI bus when reaches empty PCI Function inside Slot
10317 // However, this PCI Slot may have higher non-empty Functions
10318 // UniATA will perform all staff instead of ScsiPort under NT,
10319 // but for ReactOS it is better to patch ScsiPort.
10320 KdPrint2((PRINT_PREFIX
"STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
10321 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10322 newStatus
= ScsiPortInitialize(DriverObject
,
10324 &hwInitializationData
.comm
,
10325 (PVOID
)(i
| 0x80000000));
10326 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x (2)\n", newStatus
));
10328 if (newStatus
< statusToReturn
)
10329 statusToReturn
= newStatus
;
10331 if(g_opt_Verbose
) {
10332 if(newStatus
== STATUS_SUCCESS
) {
10333 _PrintNtConsole(" OK\n");
10335 _PrintNtConsole(" failed\n");
10341 /* KeBugCheckEx(0xc000000e,
10344 newStatus, statusToReturn);*/
10348 hwInitializationData
.comm
.VendorId
= 0;
10349 hwInitializationData
.comm
.VendorIdLength
= 0;
10350 hwInitializationData
.comm
.DeviceId
= 0;
10351 hwInitializationData
.comm
.DeviceIdLength
= 0;
10354 hwInitializationData
.comm
.SrbExtensionSize
= //FIELD_OFFSET(ATA_REQ, ata);
10356 KdPrint2((PRINT_PREFIX
"using AtaReq sz %x\n", hwInitializationData
.comm
.SrbExtensionSize
));
10359 // The adapter count is used by the find adapter routine to track how
10360 // which adapter addresses have been tested.
10362 // Indicate 2 access ranges and reset FindAdapter.
10363 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
10364 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindController
;
10366 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
10367 // Indicate ISA bustype.
10368 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10371 // Call initialization for ISA bustype.
10372 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
10373 newStatus
= ScsiPortInitialize(DriverObject
,
10375 &hwInitializationData
.comm
,
10377 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10378 if (newStatus
< statusToReturn
)
10379 statusToReturn
= newStatus
;
10381 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
10383 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
10384 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
10387 newStatus
= ScsiPortInitialize(DriverObject
,
10389 &hwInitializationData
.comm
,
10391 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10392 if (newStatus
< statusToReturn
)
10393 statusToReturn
= newStatus
;
10395 InDriverEntry
= FALSE
;
10397 KdPrint2((PRINT_PREFIX
"\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn
));
10399 return statusToReturn
;
10401 } // end DriverEntry()
10404 PSCSI_REQUEST_BLOCK
10406 BuildMechanismStatusSrb(
10407 IN PVOID HwDeviceExtension
,
10408 IN PSCSI_REQUEST_BLOCK Srb
10411 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10412 PSCSI_REQUEST_BLOCK srb
;
10414 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10416 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10418 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10420 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10421 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10422 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10423 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10425 // Set flags to disable synchronous negociation.
10426 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10428 // Set timeout to 4 seconds.
10429 srb
->TimeOutValue
= 4;
10431 srb
->CdbLength
= 6;
10432 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
10433 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10434 srb
->SrbExtension
= AtaReq
;
10436 // Set CDB operation code.
10437 cdb
= (PCDB
)srb
->Cdb
;
10438 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
10439 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10441 KdPrint2((PRINT_PREFIX
" MechanismStatusSrb %#x\n", srb
));
10444 } // end BuildMechanismStatusSrb()
10446 #endif //UNIATA_CORE
10448 PSCSI_REQUEST_BLOCK
10450 BuildRequestSenseSrb (
10451 IN PVOID HwDeviceExtension
,
10452 IN PSCSI_REQUEST_BLOCK Srb
10455 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10456 PSCSI_REQUEST_BLOCK srb
;
10458 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10460 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10462 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10464 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10465 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10466 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10467 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10469 // Set flags to disable synchronous negociation.
10470 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10472 // Set timeout to 2 seconds.
10473 srb
->TimeOutValue
= 4;
10475 srb
->CdbLength
= 6;
10476 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
10477 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
10478 srb
->SrbExtension
= AtaReq
;
10480 // Set CDB operation code.
10481 cdb
= (PCDB
)srb
->Cdb
;
10482 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
10483 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
10485 KdPrint2((PRINT_PREFIX
" RequestSenseSrb %#x\n", srb
));
10488 } // end BuildRequestSenseSrb()
10490 #ifndef UNIATA_CORE
10494 AtapiRegCheckDevLunValue(
10495 IN PVOID HwDeviceExtension
,
10496 IN PCWCH NamePrefix
,
10504 ULONG val
= Default
;
10506 val
= AtapiRegCheckParameterValue(
10507 HwDeviceExtension
, NamePrefix
, Name
, val
);
10509 if(chan
!= CHAN_NOT_SPECIFIED
) {
10510 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
10511 val
= AtapiRegCheckParameterValue(
10512 HwDeviceExtension
, namex
, Name
, val
);
10513 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
10514 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
10515 val
= AtapiRegCheckParameterValue(
10516 HwDeviceExtension
, namex
, Name
, val
);
10520 } // end AtapiRegCheckDevLunValue()
10533 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
10552 swprintf(Buffer
+j
, L
"%2.2x", a
);
10560 } // end EncodeVendorStr()
10564 AtapiRegCheckDevValue(
10565 IN PVOID HwDeviceExtension
,
10572 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10573 // WCHAR name0[11];
10574 // WCHAR name1[11+4+5];
10575 // WCHAR name2[11+4+4+10];
10576 // WCHAR name3[11+4+4+5+20];
10577 // WCHAR name3[11+4+4+5+20+1];
10586 IN ULONG SlotNumber
;
10588 ULONG val
= Default
;
10590 KdPrint(( " Parameter %ws\n", Name
));
10592 if(deviceExtension
) {
10593 VendorID
= deviceExtension
->DevID
& 0xffff;
10594 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
10595 SlotNumber
= deviceExtension
->slotNumber
;
10599 SlotNumber
= 0xffffffff;
10602 val
= AtapiRegCheckDevLunValue(
10603 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
10605 if(deviceExtension
) {
10606 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
10608 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
10609 swprintf(namex
, L
"Parameters%s", namev
);
10610 val
= AtapiRegCheckDevLunValue(
10611 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10614 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
10615 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
10616 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
10618 swprintf(namex
, L
"Parameters%s", namev
);
10619 val
= AtapiRegCheckDevLunValue(
10620 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10622 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
10623 val
= AtapiRegCheckDevLunValue(
10624 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10626 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
10627 val
= AtapiRegCheckDevLunValue(
10628 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10630 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
10632 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
10633 swprintf(namex
, L
"Parameters%s", namev
);
10634 val
= AtapiRegCheckDevLunValue(
10635 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10637 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
10638 swprintf(namex
, L
"Parameters%s", namev
);
10639 val
= AtapiRegCheckDevLunValue(
10640 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10643 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
10645 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
10646 swprintf(namex
, L
"Parameters%s", namev
);
10647 val
= AtapiRegCheckDevLunValue(
10648 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10650 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
10651 swprintf(namex
, L
"Parameters%s", namev
);
10652 val
= AtapiRegCheckDevLunValue(
10653 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10658 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
10661 } // end AtapiRegCheckDevValue()
10664 The user must specify that Xxx is to run on the platform
10665 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
10666 Services\UniATA\Xxx:REG_DWORD:Zzz.
10668 The user can override the global setting to enable or disable Xxx on a
10669 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
10670 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
10672 If this registry value does not exist or contains the value zero then
10673 the timer to check for media change does not run.
10677 RegistryPath - pointer to the unicode string inside
10678 ...\CurrentControlSet\Services\UniATA
10679 DeviceNumber - The number of the HBA device object
10681 Returns: Registry Key value
10685 AtapiRegCheckParameterValue(
10686 IN PVOID HwDeviceExtension
,
10687 IN PCWSTR PathSuffix
,
10692 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
10694 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10696 LONG zero
= Default
;
10698 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
10701 LONG doRun
= Default
;
10703 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
10705 UNICODE_STRING paramPath
;
10707 // <SavedRegPath>\<PathSuffix> -> <Name>
10708 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
10709 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
10711 paramPath
.Length
= 0;
10712 paramPath
.MaximumLength
= RegistryPath
->Length
+
10713 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
10714 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
10715 if(!paramPath
.Buffer
) {
10716 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
10720 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
10721 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
10722 RtlAppendUnicodeToString(¶mPath
, L
"\\");
10723 RtlAppendUnicodeToString(¶mPath
, REGRTL_STR_PTYPE PathSuffix
);
10725 // Check for the Xxx value.
10726 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
10728 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
10729 parameters
[0].Name
= REGRTL_STR_PTYPE Name
;
10730 parameters
[0].EntryContext
= &doRun
;
10731 parameters
[0].DefaultType
= REG_DWORD
;
10732 parameters
[0].DefaultData
= &zero
;
10733 parameters
[0].DefaultLength
= sizeof(ULONG
);
10735 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
10736 paramPath
.Buffer
, parameters
, NULL
, NULL
);
10737 if(NT_SUCCESS(status
)) {
10738 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix
, Name
, doRun
));
10741 ExFreePool(paramPath
.Buffer
);
10743 if(!NT_SUCCESS(status
)) {
10749 #undef ITEMS_TO_QUERY
10751 } // end AtapiRegCheckParameterValue()
10754 SCSI_ADAPTER_CONTROL_STATUS
10756 AtapiAdapterControl(
10757 IN PVOID HwDeviceExtension
,
10758 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
10759 IN PVOID Parameters
10762 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10763 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
10764 ULONG numberChannels
= deviceExtension
->NumberChannels
;
10768 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
10770 switch(ControlType
) {
10771 case ScsiQuerySupportedControlTypes
: {
10772 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
10773 TRUE
, // ScsiQuerySupportedControlTypes
10774 TRUE
, // ScsiStopAdapter
10775 TRUE
, // ScsiRestartAdapter
10776 FALSE
, // ScsiSetBootConfig
10777 FALSE
// ScsiSetRunningConfig
10780 ULONG lim
= ScsiAdapterControlMax
;
10783 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
10785 if(pControlTypeList
->MaxControlType
< lim
) {
10786 lim
= pControlTypeList
->MaxControlType
;
10789 for(i
= 0; i
< lim
; i
++) {
10790 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
10796 case ScsiStopAdapter
: {
10798 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
10799 // Shut down all interrupts on the adapter. They'll get re-enabled
10800 // by the initialization routines.
10801 for (c
= 0; c
< numberChannels
; c
++) {
10802 AtapiResetController(deviceExtension
, c
);
10803 AtapiDisableInterrupts(deviceExtension
, c
);
10805 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
10806 // we must never get here for non-PCI
10807 /*status =*/ UniataDisconnectIntr2(HwDeviceExtension
);
10808 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
10812 case ScsiRestartAdapter
: {
10814 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
10815 // Enable all the interrupts on the adapter while port driver call
10816 // for power up an HBA that was shut down for power management
10818 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
10819 status
= UniataConnectIntr2(HwDeviceExtension
);
10820 if(NT_SUCCESS(status
)) {
10821 for (c
= 0; c
< numberChannels
; c
++) {
10822 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
10823 FindDevices(HwDeviceExtension
, 0, c
);
10824 AtapiEnableInterrupts(deviceExtension
, c
);
10825 AtapiHwInitialize__(deviceExtension
, c
);
10827 if(deviceExtension
->Isr2DevObj
) {
10828 // we must never get here for non-PCI
10829 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
10837 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
10838 return ScsiAdapterControlUnsuccessful
;
10842 return ScsiAdapterControlSuccess
;
10843 } // end AtapiAdapterControl()
10845 #endif //UNIATA_CORE
10855 #define DEBUG_MSG_BUFFER_SIZE 512
10866 UCHAR dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
];
10867 // UNICODE_STRING msgBuff;
10869 va_start(ap
, DebugMessage
);
10871 /*len =*/ _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], DEBUG_MSG_BUFFER_SIZE
-1, DebugMessage
, ap
);
10873 dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
-1] = 0;
10875 //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro
10876 HalDisplayString(dbg_print_tmp_buff
);
10879 if(g_LogToDisplay
> 1) {
10880 AtapiStallExecution(g_LogToDisplay
*1000);
10886 } // end PrintNtConsole()