3 Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
9 This is the miniport driver for ATA/ATAPI IDE controllers
10 with Busmaster DMA and Serial ATA support
13 Alexander A. Telyatnikov (Alter)
20 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 The skeleton was taken from standard ATAPI.SYS from NT4 DDK by
37 Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by
38 Søren Schmidt, Copyright (c) 1998-2007
40 All parts of code are greatly changed/updated by
41 Alter, Copyright (c) 2002-2007:
43 1. Internal command queueing/reordering
44 2. Drive identification
45 3. Support for 2 _independent_ channels in a single PCI device
46 4. Smart host<->drive transfer rate slowdown (for bad cable)
47 5. W2k support (binary compatibility)
48 6. HDD hot swap under NT4
49 7. XP support (binary compatibility)
50 8. Serial ATA (SATA/SATA2/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 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_RESET
);
729 AtapiStallExecution(30);
731 // Wait for BUSY assertion, in some cases delay may occure
732 while (!(AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
735 AtapiStallExecution(30);
738 // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
739 // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
740 // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
741 // implementation. (which is around 1 second)
742 while ((AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
745 AtapiStallExecution(30);
749 SelectDrive(chan
, DeviceNumber
);
751 GetBaseStatus(chan
, statusByte2
);
752 AtapiStallExecution(500);
754 GetBaseStatus(chan
, statusByte2
);
755 if(chan
&& chan
->DeviceExtension
) {
756 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
757 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
759 KdPrint2((PRINT_PREFIX
" can't get DMA status\n"));
761 if(dma_status
& BM_STATUS_INTR
) {
762 // bullshit, we have DMA interrupt, but had never initiate DMA operation
763 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr on ATAPI reset\n"));
764 AtapiDmaDone(chan
->DeviceExtension
, DeviceNumber
, chan
->lChannel
, NULL
);
765 GetBaseStatus(chan
, statusByte2
);
767 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
768 UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, DeviceNumber
);
769 /* if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
770 UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1);
775 } // end AtapiSoftReset()
778 Send command to device.
779 Translate to 48-Lba form if required
784 IN PHW_DEVICE_EXTENSION deviceExtension
,
785 IN ULONG DeviceNumber
,
794 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
799 KdPrint2((PRINT_PREFIX
"AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
800 deviceExtension
->DevIndex
, deviceExtension
->Channel
, DeviceNumber
, command
, lba
, count
, feature
));
802 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
803 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
805 KdPrint3((" (ahci)\n"));
807 statusByte
= UniataAhciSendPIOCommand(deviceExtension
, lChannel
, DeviceNumber
,
808 (PSCSI_REQUEST_BLOCK
)NULL
,
816 1000 /* timeout 1 sec */
822 SelectDrive(chan
, DeviceNumber
);
824 statusByte
= WaitOnBusy(chan
);
826 /* ready to issue command ? */
827 if (statusByte
& IDE_STATUS_BUSY
) {
828 KdPrint2((PRINT_PREFIX
" Returning BUSY status\n"));
831 // !!! We should not check ERROR condition here
832 // ERROR bit may be asserted durring previous operation
833 // and not cleared after SELECT
835 //>>>>>> NV: 2006/08/03
836 if(((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
|ATA_CMD_FLAG_FUA
)) == ATA_CMD_FLAG_LBAIOsupp
) &&
837 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
838 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
839 return IDE_STATUS_ERROR
;
840 //return SRB_STATUS_ERROR;
842 //<<<<<< NV: 2006/08/03
844 /* only use 48bit addressing if needed because of the overhead */
845 if (UniAta_need_lba48(command
, lba
, count
,
846 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
)) {
848 KdPrint2((PRINT_PREFIX
" dev %#x USE_LBA_48\n", DeviceNumber
));
849 /* translate command into 48bit version */
850 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
851 command
= AtaCommands48
[command
];
853 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
857 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
860 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)(feature
>>8));
861 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
862 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)(count
>>8));
863 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
864 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[3]));
865 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[0]));
866 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[4]));
867 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[1]));
868 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[5]));
869 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[2]));
871 //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber ));
872 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
) );
875 plba
= (PUCHAR
)&lba
; //ktp
876 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
879 // (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
880 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
882 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
883 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)plba
[0]);
884 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)plba
[1]);
885 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)plba
[2]);
886 if(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
887 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber ));
888 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
890 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber ));
891 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
895 // write command code to device
896 AtapiWritePort1(chan
, IDX_IO1_o_Command
, command
);
898 switch (wait_flags
) {
901 // caller requested wait for interrupt
904 statusByte
= WaitForDrq(chan
);
905 if (statusByte
& IDE_STATUS_DRQ
)
907 AtapiStallExecution(500);
908 KdPrint2((PRINT_PREFIX
" retry waiting DRQ, status %#x\n", statusByte
));
915 // caller requested wait for entering Wait state
916 for (i
=0; i
<30 * 1000; i
++) {
918 GetStatus(chan
, statusByte
);
919 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
920 if(statusByte
== IDE_STATUS_WRONG
) {
924 if(statusByte
& IDE_STATUS_ERROR
) {
927 if(statusByte
& IDE_STATUS_BUSY
) {
928 AtapiStallExecution(100);
931 if(statusByte
== IDE_STATUS_IDLE
) {
934 //if(deviceExtension->HwFlags & UNIATA_SATA) {
935 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
938 AtapiStallExecution(100);
941 //statusByte |= IDE_STATUS_BUSY;
945 statusByte
= WaitOnBusyLong(chan
);
947 case ATA_WAIT_BASE_READY
:
948 statusByte
= WaitOnBaseBusyLong(chan
);
951 GetStatus(chan
, statusByte
);
952 if (statusByte
& IDE_STATUS_ERROR
) {
953 KdPrint2((PRINT_PREFIX
" Warning: Immed Status %#x :(\n", statusByte
));
954 if(statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_ERROR
)) {
957 KdPrint2((PRINT_PREFIX
" try to continue\n"));
958 statusByte
&= ~IDE_STATUS_ERROR
;
960 UniataExpectChannelInterrupt(chan
, TRUE
);
962 InterlockedExchange(&(chan
->CheckIntr
),
968 KdPrint2((PRINT_PREFIX
" Status %#x\n", statusByte
));
971 } // end AtaCommand48()
974 Send command to device.
975 This is simply wrapper for AtaCommand48()
980 IN PHW_DEVICE_EXTENSION deviceExtension
,
981 IN ULONG DeviceNumber
,
992 if(!(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
993 return AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
995 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
996 count
, feature
, wait_flags
);
998 return UniataAhciSendPIOCommand(deviceExtension
, lChannel
, DeviceNumber
,
999 (PSCSI_REQUEST_BLOCK
)NULL
,
1003 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
1006 0 /* ahci flags */ ,
1008 1000 /* timeout 1 sec */
1012 } // end AtaCommand()
1016 AtaPio2Mode(LONG pio
)
1019 default: return ATA_PIO
;
1020 case 0: return ATA_PIO0
;
1021 case 1: return ATA_PIO1
;
1022 case 2: return ATA_PIO2
;
1023 case 3: return ATA_PIO3
;
1024 case 4: return ATA_PIO4
;
1025 case 5: return ATA_PIO5
;
1027 } // end AtaPio2Mode()
1031 AtaPioMode(PIDENTIFY_DATA2 ident
)
1033 if (ident
->PioTimingsValid
) {
1034 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_5
)
1036 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_4
)
1038 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_3
)
1041 if (ident
->PioCycleTimingMode
== 2)
1043 if (ident
->PioCycleTimingMode
== 1)
1045 if (ident
->PioCycleTimingMode
== 0)
1047 return IOMODE_NOT_SPECIFIED
;
1048 } // end AtaPioMode()
1052 AtaWmode(PIDENTIFY_DATA2 ident
)
1054 if (ident
->MultiWordDMASupport
& 0x04)
1056 if (ident
->MultiWordDMASupport
& 0x02)
1058 if (ident
->MultiWordDMASupport
& 0x01)
1060 return IOMODE_NOT_SPECIFIED
;
1065 AtaUmode(PIDENTIFY_DATA2 ident
)
1067 if (!ident
->UdmaModesValid
)
1068 return IOMODE_NOT_SPECIFIED
;
1069 if (ident
->UltraDMASupport
& 0x40)
1071 if (ident
->UltraDMASupport
& 0x20)
1073 if (ident
->UltraDMASupport
& 0x10)
1075 if (ident
->UltraDMASupport
& 0x08)
1077 if (ident
->UltraDMASupport
& 0x04)
1079 if (ident
->UltraDMASupport
& 0x02)
1081 if (ident
->UltraDMASupport
& 0x01)
1083 return IOMODE_NOT_SPECIFIED
;
1088 AtaSAmode(PIDENTIFY_DATA2 ident
) {
1089 if(!ident
->SataCapabilities
||
1090 ident
->SataCapabilities
== 0xffff) {
1091 return IOMODE_NOT_SPECIFIED
;
1093 if(ident
->SataCapabilities
& ATA_SATA_GEN3
) {
1096 if(ident
->SataCapabilities
& ATA_SATA_GEN2
) {
1099 if(ident
->SataCapabilities
& ATA_SATA_GEN1
) {
1102 return IOMODE_NOT_SPECIFIED
;
1103 } // end AtaSAmode()
1110 IN PVOID HwDeviceExtension
1113 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1114 PHW_TIMER HwScsiTimer
;
1116 ULONG MiniportTimerValue
;
1117 BOOLEAN recall
= FALSE
;
1121 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc:\n"));
1123 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1124 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1125 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no items\n"));
1128 chan
= &(deviceExtension
->chan
[lChannel
]);
1132 HwScsiTimer
= chan
->HwScsiTimer
;
1133 chan
->HwScsiTimer
= NULL
;
1135 deviceExtension
->FirstDpcChan
= chan
->NextDpcChan
;
1136 if(deviceExtension
->FirstDpcChan
!= CHAN_NOT_SPECIFIED
) {
1140 HwScsiTimer(HwDeviceExtension
);
1142 chan
->NextDpcChan
= CHAN_NOT_SPECIFIED
;
1144 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1145 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1146 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no more items\n"));
1147 deviceExtension
->FirstDpcChan
=
1148 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1152 KeQuerySystemTime(&time
);
1153 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1155 chan
= &deviceExtension
->chan
[lChannel
];
1156 if(time
.QuadPart
>= chan
->DpcTime
- 10) {
1158 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1159 (ULONG
)(chan
->DpcTime
>> 32), (ULONG
)(chan
->DpcTime
)));
1166 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1167 MiniportTimerValue
= (ULONG
)(time
.QuadPart
- chan
->DpcTime
)/10;
1168 if(!MiniportTimerValue
)
1169 MiniportTimerValue
= 1;
1171 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: recall AtapiTimerDpc\n"));
1172 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1179 } // end AtapiTimerDpc()
1182 Wrapper for ScsiPort, that implements smart Dpc
1183 queueing. We need it to allow parallel functioning
1184 of IDE channles with shared interrupt. Standard Dpc mechanism
1185 cancels previous Dpc request (if any), but we need Dpc queue.
1190 IN PVOID HwDeviceExtension
,
1192 IN PHW_TIMER HwScsiTimer
,
1193 IN ULONG MiniportTimerValue
1196 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1198 LARGE_INTEGER time2
;
1200 PHW_CHANNEL prev_chan
;
1202 // BOOLEAN UseRequestTimerCall = TRUE;
1204 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1205 KeQuerySystemTime(&time
);
1207 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1208 time
.QuadPart
+= MiniportTimerValue
*10;
1209 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1211 KdPrint2((PRINT_PREFIX
" ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension
->ActiveDpcChan
, deviceExtension
->FirstDpcChan
));
1213 i
= deviceExtension
->FirstDpcChan
;
1214 chan
= prev_chan
= NULL
;
1215 while(i
!= CHAN_NOT_SPECIFIED
) {
1217 chan
= &(deviceExtension
->chan
[i
]);
1218 if(chan
->DpcTime
> time
.QuadPart
) {
1221 i
= chan
->NextDpcChan
;
1223 chan
= &(deviceExtension
->chan
[lChannel
]);
1225 deviceExtension
->FirstDpcChan
= lChannel
;
1227 prev_chan
->NextDpcChan
= lChannel
;
1229 chan
->NextDpcChan
= i
;
1230 chan
->HwScsiTimer
= HwScsiTimer
;
1231 chan
->DpcTime
= time
.QuadPart
;
1233 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2
.HighPart
, time2
.LowPart
));
1234 if(time
.QuadPart
<= time2
.QuadPart
) {
1235 MiniportTimerValue
= 1;
1237 MiniportTimerValue
= (ULONG
)((time
.QuadPart
- time2
.QuadPart
) / 10);
1240 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1241 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1243 MiniportTimerValue
);
1245 } // end AtapiQueueTimerDpc()
1247 #endif //UNIATA_CORE
1257 UCHAR statusByteAlt
;
1259 GetStatus(chan
, statusByteAlt
);
1260 KdPrint2((PRINT_PREFIX
" AltStatus (%#x)\n", statusByteAlt
));
1262 for(j
=1; j
<IDX_IO1_SZ
; j
++) {
1263 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1264 KdPrint2((PRINT_PREFIX
1265 " Reg_%#x (%#x) = %#x\n",
1267 chan
->RegTranslation
[IDX_IO1
+j
].Addr
,
1270 for(j
=0; j
<IDX_BM_IO_SZ
-1; j
++) {
1271 statusByteAlt
= AtapiReadPort1(chan
, IDX_BM_IO
+j
);
1272 KdPrint2((PRINT_PREFIX
1273 " BM_%#x (%#x) = %#x\n",
1275 chan
->RegTranslation
[IDX_BM_IO
+j
].Addr
,
1279 } // end UniataDumpATARegs()
1285 IN PHW_CHANNEL chan
,
1286 IN ULONG DeviceNumber
,
1287 IN OUT PIDEREGS_EX regs
1290 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
1292 UniataAhciSnapAtaRegs(chan
, DeviceNumber
, regs
);
1294 // SATA/PATA, assume drive is selected
1296 UCHAR statusByteAlt
;
1298 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) {
1299 for(j
=IDX_IO1_i_Error
; j
<=IDX_IO1_i_Status
; j
++) {
1300 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1301 ((PUCHAR
)regs
)[j
-1] = statusByteAlt
;
1305 regs
->bDriveHeadReg
= AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
);
1306 for(j
=IDX_IO1_i_Error
; j
<IDX_IO1_i_DriveSelect
; j
++) {
1307 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1308 ((PUCHAR
)regs
)[j
-1] = statusByteAlt
;
1309 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1310 ((PUCHAR
)regs
)[j
+8-1] = statusByteAlt
;
1312 regs
->bCommandReg
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
1316 } // end UniataSnapAtaRegs()
1320 Routine Description:
1322 Issue IDENTIFY command to a device.
1326 HwDeviceExtension - HBA miniport driver's adapter data storage
1327 DeviceNumber - Indicates which device.
1328 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1332 TRUE if all goes well.
1338 IN PVOID HwDeviceExtension
,
1339 IN ULONG DeviceNumber
,
1345 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1346 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
1347 ULONG waitCount
= 50000;
1353 BOOLEAN atapiDev
= FALSE
;
1354 BOOLEAN use_ahci
= FALSE
;
1355 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
1357 use_ahci
= UniataIsSATARangeAvailable(deviceExtension
, lChannel
) &&
1358 (deviceExtension
->HwFlags
& UNIATA_AHCI
);
1360 if(chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) {
1361 if(chan
->PmLunMap
& (1 << DeviceNumber
)) {
1364 KdPrint2((PRINT_PREFIX
"IssueIdentify: PM empty port\n"));
1368 if(DeviceNumber
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
1369 KdPrint2((PRINT_PREFIX
"IssueIdentify: NO SLAVE\n"));
1372 if(LunExt
->DeviceFlags
& DFLAGS_HIDDEN
) {
1373 KdPrint2((PRINT_PREFIX
"IssueIdentify: HIDDEN\n"));
1378 statusByte
= WaitOnBusyLong(chan
);
1380 if(!chan
->AhciInternalAtaReq
) {
1381 KdPrint2((PRINT_PREFIX
"!AhciInternalAtaReq\n"));
1385 SelectDrive(chan
, DeviceNumber
);
1386 AtapiStallExecution(10);
1387 statusByte
= WaitOnBusyLong(chan
);
1388 // Check that the status register makes sense.
1389 GetBaseStatus(chan
, statusByte2
);
1392 if (Command
== IDE_COMMAND_IDENTIFY
) {
1393 // Mask status byte ERROR bits.
1394 statusByte
= UniataIsIdle(deviceExtension
, statusByte
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
));
1395 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte
));
1396 // Check if register value is reasonable.
1398 if(statusByte
!= IDE_STATUS_IDLE
) {
1400 // No reset here !!!
1401 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1403 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1404 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1405 SelectDrive(chan
, DeviceNumber
);
1406 WaitOnBusyLong(chan
);
1408 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1409 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1411 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1412 signatureHigh
== ATAPI_MAGIC_MSB
) {
1414 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber
));
1418 // We really should wait up to 31 seconds
1419 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1420 // (30 seconds for device 1)
1422 // Wait for Busy to drop.
1423 AtapiStallExecution(100);
1424 GetStatus(chan
, statusByte
);
1425 if(statusByte
== IDE_STATUS_WRONG
) {
1426 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_WRONG (dev %d)\n", DeviceNumber
));
1430 } while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
--);
1431 GetBaseStatus(chan
, statusByte2
);
1433 SelectDrive(chan
, DeviceNumber
);
1435 GetBaseStatus(chan
, statusByte2
);
1437 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1439 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1440 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1442 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1443 signatureHigh
== ATAPI_MAGIC_MSB
) {
1444 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber
));
1449 statusByte
= UniataIsIdle(deviceExtension
, statusByte
) & ~IDE_STATUS_INDEX
;
1450 if (statusByte
!= IDE_STATUS_IDLE
) {
1452 KdPrint2((PRINT_PREFIX
"IssueIdentify: no dev (dev %d)\n", DeviceNumber
));
1457 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte
));
1458 if(statusByte
== IDE_STATUS_WRONG
) {
1461 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1462 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1463 statusByte
= WaitForIdleLong(chan
);
1464 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte
));
1469 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1471 statusByte
= UniataAhciSendPIOCommand(HwDeviceExtension
, lChannel
, DeviceNumber
,
1472 (PSCSI_REQUEST_BLOCK
)NULL
,
1473 (PUCHAR
)(&deviceExtension
->FullIdentifyData
),
1478 0 /* ahci flags */ ,
1480 1000 /* timeout 1 sec */
1482 j
= 9; // AHCI is rather different, skip loop at all
1484 if(LunExt
->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
1485 j
= 9; // don't send IDENTIFY, assume it is not supported
1486 KdPrint2((PRINT_PREFIX
"IssueIdentify: Manual CHS\n"));
1487 RtlZeroMemory(&(deviceExtension
->FullIdentifyData
), sizeof(deviceExtension
->FullIdentifyData
));
1488 RtlCopyMemory(&(deviceExtension
->FullIdentifyData
), &(LunExt
->IdentifyData
), sizeof(LunExt
->IdentifyData
));
1490 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1491 j
= 4; // skip old-style checks
1495 for (; j
< 4*2; j
++) {
1496 // Send IDENTIFY command.
1498 // Load CylinderHigh and CylinderLow with number bytes to transfer for old devices, use 0 for newer.
1500 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, Command
, (j
< 4) ? DEV_BSIZE
: 0 /* cyl */, 0, 0, 0, 0, ATA_WAIT_INTR
);
1503 if (statusByte
& IDE_STATUS_DRQ
) {
1504 // Read status to acknowledge any interrupts generated.
1505 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte
));
1506 GetBaseStatus(chan
, statusByte
);
1507 // One last check for Atapi.
1508 if (Command
== IDE_COMMAND_IDENTIFY
) {
1509 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1510 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1512 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1513 signatureHigh
== ATAPI_MAGIC_MSB
) {
1514 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber
));
1521 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte
));
1522 if (Command
== IDE_COMMAND_IDENTIFY
) {
1523 // Check the signature. If DRQ didn't come up it's likely Atapi.
1524 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1525 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1527 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1528 signatureHigh
== ATAPI_MAGIC_MSB
) {
1530 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber
));
1534 if(!(statusByte
& IDE_STATUS_ERROR
) && (statusByte
& IDE_STATUS_BUSY
)) {
1535 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n"));
1539 // Device didn't respond correctly. It will be given one more chance.
1540 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1541 statusByte
, AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
1542 GetBaseStatus(chan
, statusByte
);
1543 AtapiSoftReset(chan
,DeviceNumber
);
1545 AtapiDisableInterrupts(deviceExtension
, lChannel
);
1546 AtapiEnableInterrupts(deviceExtension
, lChannel
);
1548 GetBaseStatus(chan
, statusByte
);
1549 //GetStatus(chan, statusByte);
1550 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after soft reset (%#x)\n", statusByte
));
1553 // Check for error on really stupid master devices that assert random
1554 // patterns of bits in the status register at the slave address.
1555 if ((Command
== IDE_COMMAND_IDENTIFY
) && (statusByte
& IDE_STATUS_ERROR
)) {
1556 KdPrint2((PRINT_PREFIX
"IssueIdentify: Exit on error (%#x)\n", statusByte
));
1561 // everything should already be done by controller
1563 if(LunExt
->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
1564 j
= 9; // don't send IDENTIFY, assume it is not supported
1565 KdPrint2((PRINT_PREFIX
"IssueIdentify: Manual CHS (2)\n"));
1566 statusByte
= WaitForDrq(chan
);
1567 statusByte
= WaitOnBusyLong(chan
);
1568 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1569 GetBaseStatus(chan
, statusByte
);
1572 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status before read words %#x\n", statusByte
));
1573 // Suck out 256 words. After waiting for one model that asserts busy
1574 // after receiving the Packet Identify command.
1575 statusByte
= WaitForDrq(chan
);
1576 statusByte
= WaitOnBusyLong(chan
);
1577 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1579 if (!(statusByte
& IDE_STATUS_DRQ
)) {
1580 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte
));
1581 GetBaseStatus(chan
, statusByte
);
1584 GetBaseStatus(chan
, statusByte
);
1585 KdPrint2((PRINT_PREFIX
"IssueIdentify: BASE statusByte %#x\n", statusByte
));
1587 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
1589 KdPrint2((PRINT_PREFIX
" use 16bit IO\n"));
1591 // ATI/SII chipsets with memory-mapped IO hangs when
1592 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1593 // Unfortunately, I don't know yet how to workaround it except
1594 // spacifying manual delay in the way you see below.
1595 ReadBuffer(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256, PIO0_TIMING
);
1597 // Work around for some IDE and one model Atapi that will present more than
1598 // 256 bytes for the Identify data.
1599 KdPrint2((PRINT_PREFIX
"IssueIdentify: suck data port\n", statusByte
));
1600 statusByte
= AtapiSuckPort2(chan
);
1602 KdPrint2((PRINT_PREFIX
" use 32bit IO\n"));
1603 ReadBuffer2(chan
, (PULONG
)&deviceExtension
->FullIdentifyData
, 256/2, PIO0_TIMING
);
1606 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1607 statusByte
= WaitForDrq(chan
);
1608 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1609 GetBaseStatus(chan
, statusByte
);
1611 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after read words %#x\n", statusByte
));
1614 KdPrint2((PRINT_PREFIX
"IssueIdentify: no setup, exiting\n"));
1618 KdPrint2((PRINT_PREFIX
"Model: %20.20s\n", deviceExtension
->FullIdentifyData
.ModelNumber
));
1619 KdPrint2((PRINT_PREFIX
"FW: %4.4s\n", deviceExtension
->FullIdentifyData
.FirmwareRevision
));
1620 KdPrint2((PRINT_PREFIX
"S/N: %20.20s\n", deviceExtension
->FullIdentifyData
.SerialNumber
));
1621 KdPrint2((PRINT_PREFIX
"Pio: %x\n", deviceExtension
->FullIdentifyData
.PioCycleTimingMode
));
1622 if(deviceExtension
->FullIdentifyData
.PioTimingsValid
) {
1623 KdPrint2((PRINT_PREFIX
"APio: %x\n", deviceExtension
->FullIdentifyData
.AdvancedPIOModes
));
1625 KdPrint2((PRINT_PREFIX
"SWDMA: %x\n", deviceExtension
->FullIdentifyData
.SingleWordDMAActive
));
1626 KdPrint2((PRINT_PREFIX
"MWDMA: %x\n", deviceExtension
->FullIdentifyData
.MultiWordDMAActive
));
1627 if(deviceExtension
->FullIdentifyData
.UdmaModesValid
) {
1628 KdPrint2((PRINT_PREFIX
"UDMA: %x/%x\n", deviceExtension
->FullIdentifyData
.UltraDMAActive
, deviceExtension
->FullIdentifyData
.UltraDMASupport
));
1630 KdPrint2((PRINT_PREFIX
"SATA: %x\n", deviceExtension
->FullIdentifyData
.SataEnable
));
1631 KdPrint2((PRINT_PREFIX
"SATA support: %x, CAPs %#x\n",
1632 deviceExtension
->FullIdentifyData
.SataSupport
,
1633 deviceExtension
->FullIdentifyData
.SataCapabilities
));
1635 LunExt
->LimitedTransferMode
=
1636 LunExt
->OrigTransferMode
=
1637 (UCHAR
)ata_cur_mode_from_ident(&(deviceExtension
->FullIdentifyData
), IDENT_MODE_MAX
);
1638 LunExt
->TransferMode
=
1639 (UCHAR
)ata_cur_mode_from_ident(&(deviceExtension
->FullIdentifyData
), IDENT_MODE_ACTIVE
);
1641 KdPrint2((PRINT_PREFIX
"OrigTransferMode: %x, Active: %x\n", LunExt
->OrigTransferMode
, LunExt
->TransferMode
));
1642 KdPrint2((PRINT_PREFIX
"Accoustic %d, cur %d\n",
1643 deviceExtension
->FullIdentifyData
.VendorAcoustic
,
1644 deviceExtension
->FullIdentifyData
.CurrentAcoustic
1646 KdPrint2((PRINT_PREFIX
"AdvPowerMode %d, cur %d\n",
1647 deviceExtension
->FullIdentifyData
.CfAdvPowerMode
1650 // Check out a few capabilities / limitations of the device.
1651 if (deviceExtension
->FullIdentifyData
.RemovableStatus
& 1) {
1652 // Determine if this drive supports the MSN functions.
1653 KdPrint2((PRINT_PREFIX
"IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1655 deviceExtension
->FullIdentifyData
.RemovableStatus
));
1656 LunExt
->DeviceFlags
|= DFLAGS_REMOVABLE_DRIVE
;
1659 // AHCI doesn't recommend using PIO and multiblock
1660 LunExt
->MaximumBlockXfer
= 0;
1662 if (deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
) {
1663 // Determine max. block transfer for this device.
1664 LunExt
->MaximumBlockXfer
=
1665 (UCHAR
)(deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
& 0xFF);
1667 LunExt
->NumOfSectors
= 0;
1668 if (Command
== IDE_COMMAND_IDENTIFY
) {
1669 ULONGLONG NumOfSectors
=0;
1670 ULONGLONG NativeNumOfSectors
=0;
1671 ULONGLONG cylinders
=0;
1672 ULONGLONG tmp_cylinders
=0;
1673 // Read very-old-style drive geometry
1674 KdPrint2((PRINT_PREFIX
"CHS %#x:%#x:%#x\n",
1675 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1676 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1677 deviceExtension
->FullIdentifyData
.SectorsPerTrack
1679 NumOfSectors
= deviceExtension
->FullIdentifyData
.NumberOfCylinders
*
1680 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1681 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1682 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1683 // Check for HDDs > 8Gb
1684 if ((deviceExtension
->FullIdentifyData
.NumberOfCylinders
== 0x3fff) &&
1685 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1686 (NumOfSectors
< deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1687 KdPrint2((PRINT_PREFIX
"NumberOfCylinders == 0x3fff\n"));
1689 (deviceExtension
->FullIdentifyData
.UserAddressableSectors
/
1690 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1691 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1693 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1695 NumOfSectors
= cylinders
*
1696 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1697 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1699 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1703 // Check for LBA mode
1704 KdPrint2((PRINT_PREFIX
"SupportLba flag %#x\n", deviceExtension
->FullIdentifyData
.SupportLba
));
1705 KdPrint2((PRINT_PREFIX
"MajorRevision %#x\n", deviceExtension
->FullIdentifyData
.MajorRevision
));
1706 KdPrint2((PRINT_PREFIX
"UserAddressableSectors %#x\n", deviceExtension
->FullIdentifyData
.UserAddressableSectors
));
1707 if ( deviceExtension
->FullIdentifyData
.SupportLba
1709 (deviceExtension
->FullIdentifyData
.MajorRevision
&&
1710 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1711 deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1712 KdPrint2((PRINT_PREFIX
"LBA mode\n"));
1713 LunExt
->DeviceFlags
|= DFLAGS_LBA_ENABLED
;
1715 KdPrint2((PRINT_PREFIX
"Keep orig geometry\n"));
1716 LunExt
->DeviceFlags
|= DFLAGS_ORIG_GEOMETRY
;
1717 goto skip_lba_staff
;
1719 // Check for LBA48 support
1720 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1721 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
&&
1722 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Address48
&&
1723 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
> NumOfSectors
)
1725 KdPrint2((PRINT_PREFIX
"LBA48\n"));
1727 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
/
1728 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1729 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1731 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1733 NativeNumOfSectors
= cylinders
*
1734 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1735 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1737 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1739 if(NativeNumOfSectors
> NumOfSectors
) {
1740 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1741 NumOfSectors
= NativeNumOfSectors
;
1745 // Check drive capacity report for LBA48-capable drives.
1746 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
) {
1747 ULONG hNativeNumOfSectors
;
1748 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1750 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1751 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1753 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1755 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1757 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1758 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1759 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) ;
1761 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
1764 KdPrint2((PRINT_PREFIX
"Read high order bytes\n"));
1765 NativeNumOfSectors
|=
1766 (ULONG
)((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24 );
1767 hNativeNumOfSectors
=
1768 (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) |
1769 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 8) ;
1770 ((PULONG
)&NativeNumOfSectors
)[1] = hNativeNumOfSectors
;
1772 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1774 // Some drives report LBA48 capability while has capacity below 128Gb
1775 // Probably they support large block-counters.
1776 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
1777 // Here we check this
1778 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1779 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!!\n"));
1781 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1782 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1784 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1786 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1788 NativeNumOfSectors
= (ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1789 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24) |
1790 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8 ) |
1791 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 32) |
1792 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1793 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 40)
1798 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1799 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!! (2)\n"));
1800 NativeNumOfSectors
= 0;
1804 if(NumOfSectors
<= ATA_MAX_LBA28
&&
1805 NativeNumOfSectors
> NumOfSectors
) {
1807 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
1808 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1810 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1811 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1812 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1813 NumOfSectors
= NativeNumOfSectors
;
1819 if(NumOfSectors
< 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
1820 // check for native LBA size
1821 // some drives report ~32Gb in Identify Block
1822 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
1824 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_READ_NATIVE_SIZE
,
1825 0, IDE_USE_LBA
, 0, 0, 0, ATA_WAIT_READY
);
1827 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1829 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1831 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1832 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1833 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1834 (((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
) & 0xf) << 24);
1836 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1838 if(NativeNumOfSectors
> NumOfSectors
) {
1840 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
1841 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1843 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1844 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1845 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1846 NumOfSectors
= NativeNumOfSectors
;
1852 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
1854 // fill IdentifyData with bogus geometry
1855 KdPrint2((PRINT_PREFIX
"requested LunExt->GeomType=%x\n", LunExt
->opt_GeomType
));
1856 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*
1857 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
);
1858 KdPrint2((PRINT_PREFIX
"tmp_cylinders = %#I64x\n", tmp_cylinders
));
1859 if((tmp_cylinders
< 0xffff) || (LunExt
->opt_GeomType
== GEOM_ORIG
)) {
1860 // ok, we can keep original values
1861 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1862 LunExt
->opt_GeomType
= GEOM_ORIG
;
1865 tmp_cylinders
= NumOfSectors
/ (255*63);
1866 if(tmp_cylinders
< 0xffff) {
1867 // we can use generic values for H/S for generic geometry approach
1868 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1869 LunExt
->opt_GeomType
= GEOM_STD
;
1872 // we should use UNIATA geometry approach
1873 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1874 LunExt
->opt_GeomType
= GEOM_UNIATA
;
1879 if(LunExt
->opt_GeomType
== GEOM_STD
) {
1880 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
=
1881 deviceExtension
->FullIdentifyData
.SectorsPerTrack
= 63;
1883 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
=
1884 deviceExtension
->FullIdentifyData
.NumberOfHeads
= 255;
1886 cylinders
= NumOfSectors
/ (255*63);
1887 KdPrint2((PRINT_PREFIX
"Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders
, 255, 63));
1889 if(LunExt
->opt_GeomType
== GEOM_UNIATA
) {
1890 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x80)) {
1892 KdPrint2((PRINT_PREFIX
"cylinders /= 2\n"));
1893 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1894 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1896 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x80)) {
1898 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (2)\n"));
1899 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1900 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1902 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x8000)) {
1904 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (3)\n"));
1905 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1906 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1908 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x8000)) {
1910 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (4)\n"));
1911 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1912 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1914 KdPrint2((PRINT_PREFIX
"Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders
,
1915 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
,
1916 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
));
1919 KdPrint2((PRINT_PREFIX
"cylinders = tmp_cylinders (%x = %x)\n", cylinders
, tmp_cylinders
));
1920 cylinders
= tmp_cylinders
;
1922 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
=
1923 deviceExtension
->FullIdentifyData
.NumberOfCylinders
= (USHORT
)cylinders
;
1927 KdPrint2((PRINT_PREFIX
"Geometry: C %#x (%#x)\n",
1928 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1929 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
1931 KdPrint2((PRINT_PREFIX
"Geometry: H %#x (%#x)\n",
1932 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1933 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
1935 KdPrint2((PRINT_PREFIX
"Geometry: S %#x (%#x)\n",
1936 deviceExtension
->FullIdentifyData
.SectorsPerTrack
,
1937 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
1941 LunExt
->NumOfSectors
= NumOfSectors
;
1942 /* if(deviceExtension->FullIdentifyData.MajorRevision &&
1943 deviceExtension->FullIdentifyData.DoubleWordIo) {
1944 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
1948 ScsiPortMoveMemory(&LunExt
->IdentifyData
,
1949 &deviceExtension
->FullIdentifyData
,sizeof(IDENTIFY_DATA2
));
1951 InitBadBlocks(LunExt
);
1953 if ((LunExt
->IdentifyData
.DrqType
& ATAPI_DRQT_INTR
) &&
1954 (Command
!= IDE_COMMAND_IDENTIFY
)) {
1956 // This device interrupts with the assertion of DRQ after receiving
1957 // Atapi Packet Command
1958 LunExt
->DeviceFlags
|= DFLAGS_INT_DRQ
;
1959 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
1962 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
1965 if(Command
!= IDE_COMMAND_IDENTIFY
) {
1967 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_TAPE
) {
1969 LunExt
->DeviceFlags
|= DFLAGS_TAPE_DEVICE
;
1970 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is a tape drive.\n"));
1972 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
||
1973 LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_OPTICAL
) {
1974 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is CD/Optical drive.\n"));
1975 // set CD default costs
1976 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_CD
;
1977 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_CD
;
1978 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_CD
;
1979 statusByte
= WaitForDrq(chan
);
1981 KdPrint2((PRINT_PREFIX
"IssueIdentify: ATAPI drive type %#x.\n",
1982 LunExt
->IdentifyData
.DeviceType
));
1985 KdPrint2((PRINT_PREFIX
"IssueIdentify: hard drive.\n"));
1988 GetBaseStatus(chan
, statusByte
);
1989 KdPrint2((PRINT_PREFIX
"IssueIdentify: final Status on exit (%#x)\n", statusByte
));
1992 } // end IssueIdentify()
1997 Routine Description:
1998 Set drive parameters using the IDENTIFY data.
2001 HwDeviceExtension - HBA miniport driver's adapter data storage
2002 DeviceNumber - Indicates which device.
2005 TRUE if all goes well.
2011 IN PVOID HwDeviceExtension
,
2012 IN ULONG DeviceNumber
,
2016 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2017 PIDENTIFY_DATA2 identifyData
;
2018 PHW_LU_EXTENSION LunExt
;
2023 LunExt
= deviceExtension
->chan
[lChannel
].lun
[DeviceNumber
];
2024 identifyData
= &(LunExt
->IdentifyData
);
2026 if(LunExt
->DeviceFlags
&
2027 (DFLAGS_LBA_ENABLED
| DFLAGS_ORIG_GEOMETRY
))
2030 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Number of heads %#x\n", identifyData
->NumberOfHeads
));
2031 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Sectors per track %#x\n", identifyData
->SectorsPerTrack
));
2033 // Send SET PARAMETER command.
2034 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
2035 IDE_COMMAND_SET_DRIVE_PARAMETERS
, 0,
2036 (identifyData
->NumberOfHeads
- 1), 0,
2037 (UCHAR
)identifyData
->SectorsPerTrack
, 0, ATA_WAIT_IDLE
);
2039 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2040 if(statusByte
& IDE_STATUS_ERROR
) {
2041 errorByte
= AtapiReadPort1(&deviceExtension
->chan
[lChannel
], IDX_IO1_i_Error
);
2042 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Error bit set. Status %#x, error %#x\n",
2043 errorByte
, statusByte
));
2047 if(statusByte
== IDE_STATUS_IDLE
) {
2053 } // end SetDriveParameters()
2058 PHW_LU_EXTENSION LunExt
2061 // keep only DFLAGS_HIDDEN flag
2062 LunExt
->DeviceFlags
&= DFLAGS_HIDDEN
;
2063 LunExt
->AtapiReadyWaitDelay
= 0;
2064 } // end UniataForgetDevice()
2069 Routine Description:
2070 Reset IDE controller and/or Atapi device.
2074 HwDeviceExtension - HBA miniport driver's adapter data storage
2083 AtapiResetController(
2084 IN PVOID HwDeviceExtension
,
2088 KdPrint2((PRINT_PREFIX
"AtapiResetController(%x)\n", PathId
));
2089 return AtapiResetController__(HwDeviceExtension
, PathId
, RESET_COMPLETE_ALL
);
2090 } // end AtapiResetController()
2094 AtapiResetController__(
2095 IN PVOID HwDeviceExtension
,
2097 IN BOOLEAN CompleteType
2100 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2101 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2102 PHW_CHANNEL chan
= NULL
;
2106 PSCSI_REQUEST_BLOCK CurSrb
;
2107 ULONG ChannelCtrlFlags
;
2108 UCHAR dma_status
= 0;
2110 ULONG slotNumber
= deviceExtension
->slotNumber
;
2111 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
2112 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
2114 ULONG DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
2116 //ULONG RevID = deviceExtension->RevID;
2117 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
2121 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID
, DeviceID
, slotNumber
));
2122 KdPrint2((PRINT_PREFIX
"simplexOnly %d\n", deviceExtension
->simplexOnly
));
2124 if(!deviceExtension
->simplexOnly
&& (PathId
!= CHAN_NOT_SPECIFIED
)) {
2125 // we shall reset both channels on SimplexOnly devices,
2126 // It's not worth doing so on normal controllers
2128 numberChannels
= min(j
+1, deviceExtension
->NumberChannels
);
2131 numberChannels
= deviceExtension
->NumberChannels
;
2134 for (; j
< numberChannels
; j
++) {
2136 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset channel %d\n", j
));
2137 chan
= &(deviceExtension
->chan
[j
]);
2138 MaxLuns
= chan
->NumberLuns
;
2139 KdPrint2((PRINT_PREFIX
" CompleteType %#x, Luns %d, chan %#x, sptr %#x\n", CompleteType
, MaxLuns
, chan
, &chan
));
2140 //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
2141 if(CompleteType
!= RESET_COMPLETE_NONE
) {
2143 while((CurSrb
= UniataGetCurRequest(chan
))) {
2145 PATA_REQ AtaReq
= (PATA_REQ
)(CurSrb
->SrbExtension
);
2147 KdPrint2((PRINT_PREFIX
"AtapiResetController: pending SRB %#x, chan %#x\n", CurSrb
, chan
));
2148 // Check and see if we are processing an internal srb
2149 if (AtaReq
->OriginalSrb
) {
2150 KdPrint2((PRINT_PREFIX
" restore original SRB %#x\n", AtaReq
->OriginalSrb
));
2151 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
2152 CurSrb
->SrbExtension
= NULL
;
2153 AtaReq
->OriginalSrb
= NULL
;
2154 // NOTE: internal SRB doesn't get to SRB queue !!!
2155 CurSrb
= AtaReq
->Srb
;
2158 // Remove current request from queue
2159 UniataRemoveRequest(chan
, CurSrb
);
2161 // Check if request is in progress.
2162 ASSERT(AtaReq
->Srb
== CurSrb
);
2164 // Complete outstanding request with SRB_STATUS_BUS_RESET.
2165 UCHAR PathId
= CurSrb
->PathId
;
2166 UCHAR TargetId
= CurSrb
->TargetId
;
2167 UCHAR Lun
= CurSrb
->Lun
;
2169 CurSrb
->SrbStatus
= ((CompleteType
== RESET_COMPLETE_ALL
) ? SRB_STATUS_BUS_RESET
: SRB_STATUS_ABORTED
) | SRB_STATUS_AUTOSENSE_VALID
;
2170 CurSrb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2172 if (CurSrb
->SenseInfoBuffer
) {
2174 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)CurSrb
->SenseInfoBuffer
;
2175 KdPrint2((PRINT_PREFIX
" senseBuffer %#x, chan %#x\n", senseBuffer
, chan
));
2177 senseBuffer
->ErrorCode
= 0x70;
2178 senseBuffer
->Valid
= 1;
2179 senseBuffer
->AdditionalSenseLength
= 0xb;
2180 if(CompleteType
== RESET_COMPLETE_ALL
) {
2181 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
2182 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2183 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_BUS_RESET
;
2184 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_SCSI_BUS
;
2186 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
2187 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2188 senseBuffer
->AdditionalSenseCode
= 0;
2189 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2193 // Clear request tracking fields.
2194 AtaReq
->WordsLeft
= 0;
2195 AtaReq
->DataBuffer
= NULL
;
2196 AtaReq
->TransferLength
= 0;
2197 KdPrint2((PRINT_PREFIX
"chan %#x\n", chan
));
2199 ScsiPortNotification(RequestComplete
,
2203 // Indicate ready for next request.
2204 ScsiPortNotification(NextLuRequest
,
2210 if(CompleteType
!= RESET_COMPLETE_ALL
)
2213 #endif //UNIATA_CORE
2214 } // end if (!CompleteType != RESET_COMPLETE_NONE)
2216 // Save control flags
2217 ChannelCtrlFlags
= chan
->ChannelCtrlFlags
;
2218 // Clear expecting interrupt flag.
2219 UniataExpectChannelInterrupt(chan
, FALSE
);
2221 chan
->ChannelCtrlFlags
= 0;
2222 InterlockedExchange(&(chan
->CheckIntr
),
2225 for (i
= 0; i
< MaxLuns
; i
++) {
2226 chan
->lun
[i
]->PowerState
= 0;
2229 if(ChipFlags
& UNIATA_AHCI
) {
2230 KdPrint2((PRINT_PREFIX
" AHCI path\n"));
2231 if(UniataAhciChanImplemented(deviceExtension
, j
)) {
2233 UniataDumpAhciPortRegs(chan
);
2235 AtapiDisableInterrupts(deviceExtension
, j
);
2236 UniataAhciReset(HwDeviceExtension
, j
);
2238 KdPrint2((PRINT_PREFIX
" skip not implemented\n"));
2241 KdPrint2((PRINT_PREFIX
" ATA path, chan %#x\n", chan
));
2242 KdPrint2((PRINT_PREFIX
" disable intr (0)\n"));
2243 AtapiDisableInterrupts(deviceExtension
, j
);
2244 KdPrint2((PRINT_PREFIX
" done\n"));
2246 case ATA_INTEL_ID
: {
2250 if(!(ChipFlags
& UNIATA_SATA
)) {
2253 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2258 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2259 if(ChipFlags
& UNIATA_AHCI
) {
2262 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2263 GetPciConfig1(0x90, tmp8
);
2271 mask
= 1 << chan
->lun
[0]->SATA_lun_map
;
2273 mask
|= (1 << chan
->lun
[1]->SATA_lun_map
);
2276 ChangePciConfig2(0x92, a
& ~mask
);
2277 AtapiStallExecution(10);
2278 ChangePciConfig2(0x92, a
| mask
);
2281 /* Wait up to 1 sec for "connect well". */
2282 if (ChipFlags
& (I6CH
| I6CH2
)) {
2288 GetPciConfig2(0x92, tmp16
);
2289 if (((tmp16
>> pshift
) & mask
) == mask
) {
2290 GetBaseStatus(chan
, statusByte
);
2291 if(statusByte
!= IDE_STATUS_WRONG
) {
2295 AtapiStallExecution(10000);
2299 case ATA_NVIDIA_ID
: {
2300 KdPrint2((PRINT_PREFIX
" SIS/nVidia\n"));
2301 if(!(ChipFlags
& UNIATA_SATA
))
2304 case ATA_SILICON_IMAGE_ID
: {
2306 ULONG Channel
= deviceExtension
->Channel
+ j
;
2307 if(!(ChipFlags
& UNIATA_SATA
))
2309 offset
= ((Channel
& 1) << 7) + ((Channel
& 2) << 8);
2310 /* disable PHY state change interrupt */
2311 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x148 + offset
, 0);
2313 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2315 /* reset controller part for this channel */
2316 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2317 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) | (0xc0 >> Channel
));
2318 AtapiStallExecution(1000);
2319 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2320 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) & ~(0xc0 >> Channel
));
2324 case ATA_PROMISE_ID
: {
2327 if(ChipFlags
& UNIATA_SATA
) {
2328 KdPrint2((PRINT_PREFIX
" SATA generic reset\n"));
2329 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2332 KdPrint2((PRINT_PREFIX
" send reset\n"));
2333 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
|
2334 IDE_DC_RESET_CONTROLLER
);
2335 KdPrint2((PRINT_PREFIX
" wait a little\n"));
2336 AtapiStallExecution(10000);
2337 // Disable interrupts
2338 KdPrint2((PRINT_PREFIX
" disable intr\n"));
2339 AtapiDisableInterrupts(deviceExtension
, j
);
2340 AtapiStallExecution(100);
2341 KdPrint2((PRINT_PREFIX
" re-enable intr\n"));
2342 AtapiEnableInterrupts(deviceExtension
, j
);
2343 KdPrint2((PRINT_PREFIX
" wait a little (2)\n"));
2344 AtapiStallExecution(100000);
2345 KdPrint2((PRINT_PREFIX
" done\n"));
2350 //if(!(ChipFlags & UNIATA_SATA)) {}
2351 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2352 // Reset DMA engine if active
2353 KdPrint2((PRINT_PREFIX
" check DMA engine\n"));
2354 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
2355 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
2356 if((ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
2357 (dma_status
& BM_STATUS_INTR
)) {
2358 AtapiDmaDone(HwDeviceExtension
, 0, j
, NULL
);
2363 // all these shall be performed inside AtapiHwInitialize__() ?
2365 KdPrint2((PRINT_PREFIX
" process connected devices 0 - %d\n", MaxLuns
-1));
2366 // Do special processing for ATAPI and IDE disk devices.
2367 for (i
= 0; i
< MaxLuns
; i
++) {
2369 // Check if device present.
2370 KdPrint2((PRINT_PREFIX
" Chan %#x\n", chan
));
2371 KdPrint2((PRINT_PREFIX
" Lun %#x\n", i
));
2372 KdPrint2((PRINT_PREFIX
" Lun ptr %#x\n", chan
->lun
[i
]));
2373 if (!(chan
->lun
[i
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2374 if(ChipFlags
& UNIATA_AHCI
) {
2375 // everything is done in UniataAhciReset()
2376 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2382 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2383 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2386 if(!CheckDevice(HwDeviceExtension
, j
, i
, TRUE
)) {
2390 if(ChipFlags
& UNIATA_AHCI
) {
2391 // everything is done in UniataAhciReset()
2392 KdPrint2((PRINT_PREFIX
" found some device\n"));
2394 if(!IssueIdentify(HwDeviceExtension
,
2396 ATAPI_DEVICE(chan
, i
) ?
2397 IDE_COMMAND_ATAPI_IDENTIFY
: IDE_COMMAND_IDENTIFY
,
2399 KdPrint2((PRINT_PREFIX
" identify failed !\n"));
2400 UniataForgetDevice(chan
->lun
[i
]);
2404 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2405 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2406 UniataForgetDevice(chan
->lun
[i
]);
2411 SelectDrive(chan
, i
);
2412 AtapiStallExecution(10);
2413 statusByte
= WaitOnBusyLong(chan
);
2414 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2415 if(statusByte
== IDE_STATUS_WRONG
) {
2416 KdPrint2((PRINT_PREFIX
2417 "no drive, status %#x\n",
2419 UniataForgetDevice(chan
->lun
[i
]);
2421 // Check for ATAPI disk.
2422 if (ATAPI_DEVICE(chan
, i
)) {
2423 // Issue soft reset and issue identify.
2424 GetStatus(chan
, statusByte
);
2425 KdPrint2((PRINT_PREFIX
"AtapiResetController: Status before Atapi reset (%#x).\n",
2428 AtapiDisableInterrupts(deviceExtension
, j
);
2429 AtapiSoftReset(chan
, i
);
2430 AtapiEnableInterrupts(deviceExtension
, j
);
2432 GetStatus(chan
, statusByte
);
2434 if(statusByte
== IDE_STATUS_SUCCESS
) {
2436 IssueIdentify(HwDeviceExtension
,
2438 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
2441 KdPrint2((PRINT_PREFIX
2442 "AtapiResetController: Status after soft reset %#x\n",
2445 GetBaseStatus(chan
, statusByte
);
2448 // Issue identify and reinit after channel reset.
2450 if (statusByte
!= IDE_STATUS_IDLE
&&
2451 statusByte
!= IDE_STATUS_SUCCESS
&&
2452 statusByte
!= IDE_STATUS_DRDY
) {
2454 KdPrint2((PRINT_PREFIX
"AtapiResetController: IdeHardReset failed\n"));
2456 if(!IssueIdentify(HwDeviceExtension
,
2458 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2460 KdPrint2((PRINT_PREFIX
"AtapiResetController: IDE IssueIdentify failed\n"));
2462 // Set disk geometry parameters.
2463 if (!SetDriveParameters(HwDeviceExtension
, i
, j
)) {
2464 KdPrint2((PRINT_PREFIX
"AtapiResetController: SetDriveParameters failed\n"));
2466 GetBaseStatus(chan
, statusByte
);
2468 // force DMA mode reinit
2469 chan
->lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
2473 // Enable interrupts, note, we can have here recursive disable
2474 AtapiStallExecution(10);
2475 KdPrint2((PRINT_PREFIX
"AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2477 chan
->DisableIntr
));
2478 AtapiEnableInterrupts(deviceExtension
, j
);
2480 // Call the HwInitialize routine to setup multi-block.
2481 AtapiHwInitialize__(deviceExtension
, j
);
2483 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
2487 } // end AtapiResetController__()
2492 Routine Description:
2493 This routine maps ATAPI and IDE errors to specific SRB statuses.
2496 HwDeviceExtension - HBA miniport driver's adapter data storage
2497 Srb - IO request packet
2506 IN PVOID HwDeviceExtension
,
2507 IN PSCSI_REQUEST_BLOCK Srb
2510 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2511 ULONG lChannel
= GET_CHANNEL(Srb
);
2512 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2514 UCHAR errorByte
= 0;
2515 UCHAR srbStatus
= SRB_STATUS_SUCCESS
;
2517 ULONG DeviceNumber
= GET_CDEV(Srb
);
2518 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
2520 // Read the error register.
2522 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
2523 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2525 errorByte
= AtaReq
->ahci
.in_error
;
2529 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2531 KdPrint2((PRINT_PREFIX
2532 "MapError: Error register is %#x\n",
2535 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2537 switch (errorByte
>> 4) {
2538 case SCSI_SENSE_NO_SENSE
:
2540 KdPrint2((PRINT_PREFIX
2541 "ATAPI: No sense information\n"));
2542 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2543 srbStatus
= SRB_STATUS_ERROR
;
2546 case SCSI_SENSE_RECOVERED_ERROR
:
2548 KdPrint2((PRINT_PREFIX
2549 "ATAPI: Recovered error\n"));
2551 srbStatus
= SRB_STATUS_SUCCESS
;
2554 case SCSI_SENSE_NOT_READY
:
2556 KdPrint2((PRINT_PREFIX
2557 "ATAPI: Device not ready\n"));
2558 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2559 srbStatus
= SRB_STATUS_ERROR
;
2562 case SCSI_SENSE_MEDIUM_ERROR
:
2564 KdPrint2((PRINT_PREFIX
2565 "ATAPI: Media error\n"));
2566 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2567 srbStatus
= SRB_STATUS_ERROR
;
2570 case SCSI_SENSE_HARDWARE_ERROR
:
2572 KdPrint2((PRINT_PREFIX
2573 "ATAPI: Hardware error\n"));
2574 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2575 srbStatus
= SRB_STATUS_ERROR
;
2578 case SCSI_SENSE_ILLEGAL_REQUEST
:
2580 KdPrint2((PRINT_PREFIX
2581 "ATAPI: Illegal request\n"));
2582 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2583 srbStatus
= SRB_STATUS_ERROR
;
2586 case SCSI_SENSE_UNIT_ATTENTION
:
2588 KdPrint2((PRINT_PREFIX
2589 "ATAPI: Unit attention\n"));
2590 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2591 srbStatus
= SRB_STATUS_ERROR
;
2594 case SCSI_SENSE_DATA_PROTECT
:
2596 KdPrint2((PRINT_PREFIX
2597 "ATAPI: Data protect\n"));
2598 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2599 srbStatus
= SRB_STATUS_ERROR
;
2602 case SCSI_SENSE_BLANK_CHECK
:
2604 KdPrint2((PRINT_PREFIX
2605 "ATAPI: Blank check\n"));
2606 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2607 srbStatus
= SRB_STATUS_ERROR
;
2610 case SCSI_SENSE_ABORTED_COMMAND
:
2611 KdPrint2((PRINT_PREFIX
2612 "Atapi: Command Aborted\n"));
2613 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2614 srbStatus
= SRB_STATUS_ERROR
;
2619 KdPrint2((PRINT_PREFIX
2620 "ATAPI: Invalid sense information\n"));
2622 srbStatus
= SRB_STATUS_ERROR
;
2630 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
2631 chan
->ReturningMediaStatus
= errorByte
;
2633 if (errorByte
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
2634 KdPrint2((PRINT_PREFIX
2635 "IDE: Media change\n"));
2636 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2637 srbStatus
= SRB_STATUS_ERROR
;
2639 if (Srb
->SenseInfoBuffer
) {
2641 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2643 senseBuffer
->ErrorCode
= 0x70;
2644 senseBuffer
->Valid
= 1;
2645 senseBuffer
->AdditionalSenseLength
= 0xb;
2646 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2647 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2648 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2650 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2653 } else if (errorByte
& IDE_ERROR_COMMAND_ABORTED
) {
2654 KdPrint2((PRINT_PREFIX
2655 "IDE: Command abort\n"));
2656 srbStatus
= SRB_STATUS_ABORTED
;
2657 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2659 if (Srb
->SenseInfoBuffer
) {
2661 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2663 senseBuffer
->ErrorCode
= 0x70;
2664 senseBuffer
->Valid
= 1;
2665 senseBuffer
->AdditionalSenseLength
= 0xb;
2666 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2667 senseBuffer
->AdditionalSenseCode
= 0;
2668 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2670 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2673 LunExt
->ErrorCount
++;
2675 } else if (errorByte
& IDE_ERROR_END_OF_MEDIA
) {
2677 KdPrint2((PRINT_PREFIX
2678 "IDE: End of media\n"));
2679 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2680 srbStatus
= SRB_STATUS_ERROR
;
2682 if (Srb
->SenseInfoBuffer
) {
2684 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2686 senseBuffer
->ErrorCode
= 0x70;
2687 senseBuffer
->Valid
= 1;
2688 senseBuffer
->AdditionalSenseLength
= 0xb;
2689 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2690 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIA_STATE
;
2691 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_END_OF_MEDIUM
;
2692 senseBuffer
->EndOfMedia
= 1;
2694 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2697 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2698 LunExt
->ErrorCount
++;
2701 } else if (errorByte
& IDE_ERROR_ILLEGAL_LENGTH
) {
2703 KdPrint2((PRINT_PREFIX
2704 "IDE: Illegal length\n"));
2705 srbStatus
= SRB_STATUS_INVALID_REQUEST
;
2707 if (Srb
->SenseInfoBuffer
) {
2709 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2711 senseBuffer
->ErrorCode
= 0x70;
2712 senseBuffer
->Valid
= 1;
2713 senseBuffer
->AdditionalSenseLength
= 0xb;
2714 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
2715 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_VALUE
;
2716 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_PARAM_INVALID_VALUE
;
2717 senseBuffer
->IncorrectLength
= 1;
2719 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2722 } else if (errorByte
& IDE_ERROR_BAD_BLOCK
) {
2724 KdPrint2((PRINT_PREFIX
2725 "IDE: Bad block\n"));
2726 srbStatus
= SRB_STATUS_ERROR
;
2727 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2728 if (Srb
->SenseInfoBuffer
) {
2730 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2732 senseBuffer
->ErrorCode
= 0x70;
2733 senseBuffer
->Valid
= 1;
2734 senseBuffer
->AdditionalSenseLength
= 0xb;
2735 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2736 senseBuffer
->AdditionalSenseCode
= 0;
2737 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2739 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2742 } else if (errorByte
& IDE_ERROR_ID_NOT_FOUND
) {
2744 KdPrint2((PRINT_PREFIX
2745 "IDE: Id not found\n"));
2746 srbStatus
= SRB_STATUS_ERROR
;
2747 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2749 if (Srb
->SenseInfoBuffer
) {
2751 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2753 senseBuffer
->ErrorCode
= 0x70;
2754 senseBuffer
->Valid
= 1;
2755 senseBuffer
->AdditionalSenseLength
= 0xb;
2756 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2757 senseBuffer
->AdditionalSenseCode
= 0;
2758 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2760 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2763 LunExt
->ErrorCount
++;
2765 } else if (errorByte
& IDE_ERROR_MEDIA_CHANGE
) {
2767 KdPrint2((PRINT_PREFIX
2768 "IDE: Media change\n"));
2769 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2770 srbStatus
= SRB_STATUS_ERROR
;
2772 if (Srb
->SenseInfoBuffer
) {
2774 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2776 senseBuffer
->ErrorCode
= 0x70;
2777 senseBuffer
->Valid
= 1;
2778 senseBuffer
->AdditionalSenseLength
= 0xb;
2779 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2780 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2781 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2783 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2786 } else if (errorByte
& IDE_ERROR_DATA_ERROR
) {
2788 KdPrint2((PRINT_PREFIX
2789 "IDE: Data error\n"));
2790 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2791 srbStatus
= SRB_STATUS_ERROR
;
2793 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2794 LunExt
->ErrorCount
++;
2797 // Build sense buffer
2798 if (Srb
->SenseInfoBuffer
) {
2800 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2802 senseBuffer
->ErrorCode
= 0x70;
2803 senseBuffer
->Valid
= 1;
2804 senseBuffer
->AdditionalSenseLength
= 0xb;
2805 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2806 senseBuffer
->AdditionalSenseCode
= 0;
2807 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2809 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2813 if (LunExt
->ErrorCount
>= MAX_ERRORS
) {
2814 // deviceExtension->DWordIO = FALSE;
2816 KdPrint2((PRINT_PREFIX
2817 "MapError: ErrorCount >= MAX_ERRORS\n"));
2819 LunExt
->DeviceFlags
&= ~DFLAGS_DWORDIO_ENABLED
;
2820 LunExt
->MaximumBlockXfer
= 0;
2823 KdPrint2((PRINT_PREFIX
2824 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
2827 KdPrint2((PRINT_PREFIX
2828 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
2837 ScsiPortLogError( HwDeviceExtension
,
2845 // Reprogram to not use Multi-sector.
2848 if (LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
&&
2849 !(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
2851 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY
);
2853 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2854 // command was aborted.
2855 if (statusByte
& IDE_STATUS_ERROR
) {
2857 // Read the error register.
2858 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2860 KdPrint2((PRINT_PREFIX
"MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
2864 // Adjust the devExt. value, if necessary.
2865 LunExt
->MaximumBlockXfer
= 0;
2873 // Set SCSI status to indicate a check condition.
2874 Srb
->ScsiStatus
= scsiStatus
;
2883 Routine Description:
2886 HwDeviceExtension - HBA miniport driver's adapter data storage
2890 TRUE - if initialization successful.
2891 FALSE - if initialization unsuccessful.
2897 IN PVOID HwDeviceExtension
2900 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2901 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2904 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base)\n"));
2906 if(WinVer_WDM_Model
) {
2907 AtapiResetController__(HwDeviceExtension
, CHAN_NOT_SPECIFIED
, RESET_COMPLETE_ALL
);
2909 if(deviceExtension
->MasterDev
) {
2910 KdPrint2((PRINT_PREFIX
" mark chan %d of master controller [%x] as inited\n",
2911 deviceExtension
->Channel
, deviceExtension
->DevIndex
));
2912 BMList
[deviceExtension
->DevIndex
].ChanInitOk
|= 0x01 << deviceExtension
->Channel
;
2915 /* do extra chipset specific setups */
2916 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
2918 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
2919 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
2920 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
2923 for (c
= 0; c
< numberChannels
; c
++) {
2924 AtapiHwInitialize__(deviceExtension
, c
);
2926 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base) done\n"));
2928 } // end AtapiHwInitialize()
2932 AtapiHwInitialize__(
2933 IN PHW_DEVICE_EXTENSION deviceExtension
,
2938 UCHAR statusByte
, errorByte
;
2939 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2940 PHW_LU_EXTENSION LunExt
;
2942 ULONG PreferedMode
= 0xffffffff;
2944 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
2945 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
2949 AtapiChipInit(deviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
);
2950 FindDevices(deviceExtension
, 0, lChannel
);
2952 for (i
= 0; i
< chan
->NumberLuns
; i
++) {
2954 KdPrint3((PRINT_PREFIX
"AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel
, i
));
2956 LunExt
= chan
->lun
[i
];
2958 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2962 AtapiDisableInterrupts(deviceExtension
, lChannel
);
2963 AtapiStallExecution(1);
2965 if (!(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
2967 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: IDE branch\n"));
2968 // Enable media status notification
2969 IdeMediaStatus(TRUE
,deviceExtension
,lChannel
,(UCHAR
)i
);
2971 // If supported, setup Multi-block transfers.
2972 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
2973 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2974 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2976 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2977 // command was aborted.
2978 if (statusByte
& IDE_STATUS_ERROR
) {
2980 // Read the error register.
2981 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2983 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
2987 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
2988 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2989 0, 0, ATA_WAIT_BASE_READY
);
2991 if (statusByte
& IDE_STATUS_ERROR
) {
2992 // Read the error register.
2993 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2995 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
2999 // Adjust the devExt. value, if necessary.
3000 LunExt
->MaximumBlockXfer
= 0;
3003 KdPrint2((PRINT_PREFIX
3004 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
3006 LunExt
->MaximumBlockXfer
));
3009 if(LunExt
->IdentifyData
.MajorRevision
) {
3011 if(LunExt
->opt_ReadCacheEnable
) {
3012 KdPrint2((PRINT_PREFIX
" Try Enable Read Cache\n"));
3013 // If supported, setup read/write cacheing
3014 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3015 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3016 0, ATA_C_F_ENAB_RCACHE
, ATA_WAIT_BASE_READY
);
3018 // Check for errors.
3019 if (statusByte
& IDE_STATUS_ERROR
) {
3020 KdPrint2((PRINT_PREFIX
3021 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
3023 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3025 LunExt
->DeviceFlags
|= DFLAGS_RCACHE_ENABLED
;
3028 KdPrint2((PRINT_PREFIX
" Disable Read Cache\n"));
3029 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3030 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3031 0, ATA_C_F_DIS_RCACHE
, ATA_WAIT_BASE_READY
);
3032 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3034 if(LunExt
->opt_WriteCacheEnable
) {
3035 KdPrint2((PRINT_PREFIX
" Try Enable Write Cache\n"));
3036 // If supported & allowed, setup write cacheing
3037 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3038 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3039 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
3040 // Check for errors.
3041 if (statusByte
& IDE_STATUS_ERROR
) {
3042 KdPrint2((PRINT_PREFIX
3043 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
3045 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3047 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
3050 KdPrint2((PRINT_PREFIX
" Disable Write Cache\n"));
3051 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3052 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3053 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
3054 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3057 if(LunExt
->IdentifyData
.FeaturesSupport
.PowerMngt
||
3058 LunExt
->IdentifyData
.FeaturesSupport
.APM
) {
3060 if(LunExt
->opt_AdvPowerMode
) {
3061 KdPrint2((PRINT_PREFIX
" Try Enable Adv. Power Mgmt\n"));
3063 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3064 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3065 LunExt
->opt_AdvPowerMode
, ATA_C_F_ENAB_APM
, ATA_WAIT_BASE_READY
);
3066 // Check for errors.
3067 if (statusByte
& IDE_STATUS_ERROR
) {
3068 KdPrint2((PRINT_PREFIX
3069 "AtapiHwInitialize: Enable APM on Device %d failed\n",
3073 KdPrint2((PRINT_PREFIX
" Disable Adv. Power Mgmt\n"));
3074 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3075 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3076 0, ATA_C_F_DIS_APM
, ATA_WAIT_BASE_READY
);
3079 if(LunExt
->IdentifyData
.FeaturesSupport
.AutoAcoustic
) {
3080 if(LunExt
->opt_AcousticMode
) {
3081 KdPrint2((PRINT_PREFIX
" Try Enable Acoustic Mgmt\n"));
3082 // setup acoustic mgmt
3083 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3084 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3085 LunExt
->opt_AcousticMode
, ATA_C_F_ENAB_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3086 // Check for errors.
3087 if (statusByte
& IDE_STATUS_ERROR
) {
3088 KdPrint2((PRINT_PREFIX
3089 "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n",
3093 KdPrint2((PRINT_PREFIX
" Disable Acoustic Mgmt\n"));
3094 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3095 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3096 0, ATA_C_F_DIS_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3099 if(LunExt
->IdentifyData
.FeaturesSupport
.Standby
) {
3100 KdPrint2((PRINT_PREFIX
" Try init standby timer: %d\n"));
3101 // setup standby timer
3102 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3103 IDE_COMMAND_IDLE
, 0, 0, 0,
3104 LunExt
->opt_StandbyTimer
, 0, ATA_WAIT_BASE_READY
);
3105 // Check for errors.
3106 if (statusByte
& IDE_STATUS_ERROR
) {
3107 KdPrint2((PRINT_PREFIX
3108 "AtapiHwInitialize: standby timer on Device %d failed\n",
3114 } else if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)){
3117 BOOLEAN isSanyo
= FALSE
;
3120 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: ATAPI/Changer branch\n"));
3122 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
3123 for (j
= 0; j
< 26; j
+= 2) {
3125 // Build a buffer based on the identify data.
3126 MOV_DW_SWP(vendorId
[j
], ((PUCHAR
)LunExt
->IdentifyData
.ModelNumber
)[j
]);
3129 if (!AtapiStringCmp (vendorId
, "CD-ROM CDR", 11)) {
3131 // Inquiry string for older model had a '-', newer is '_'
3132 if (vendorId
[12] == 'C') {
3134 // Torisan changer. Set the bit. This will be used in several places
3135 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
3136 LunExt
->DeviceFlags
|= (DFLAGS_CHANGER_INITED
| DFLAGS_SANYO_ATAPI_CHANGER
);
3137 LunExt
->DiscsPresent
= 3;
3143 PreferedMode
= LunExt
->opt_MaxTransferMode
;
3144 if((PreferedMode
== 0xffffffff) || (PreferedMode
> chan
->MaxTransferMode
)) {
3145 KdPrint2((PRINT_PREFIX
"MaxTransferMode (overriden): %#x\n", chan
->MaxTransferMode
));
3146 PreferedMode
= chan
->MaxTransferMode
;
3149 if(LunExt
->opt_PreferedTransferMode
!= 0xffffffff) {
3150 KdPrint2((PRINT_PREFIX
"PreferedTransferMode: %#x\n", PreferedMode
));
3151 PreferedMode
= min(LunExt
->opt_PreferedTransferMode
, PreferedMode
);
3154 KdPrint2((PRINT_PREFIX
" try mode %#x\n", PreferedMode
));
3155 LunExt
->LimitedTransferMode
=
3156 LunExt
->TransferMode
=
3159 AtapiDmaInit__(deviceExtension
, LunExt
);
3161 LunExt
->LimitedTransferMode
=
3162 LunExt
->TransferMode
;
3163 KdPrint2((PRINT_PREFIX
"Using %#x mode\n", LunExt
->TransferMode
));
3165 // We need to get our device ready for action before
3166 // returning from this function
3168 // According to the atapi spec 2.5 or 2.6, an atapi device
3169 // clears its status BSY bit when it is ready for atapi commands.
3170 // However, some devices (Panasonic SQ-TC500N) are still
3171 // not ready even when the status BSY is clear. They don't react
3172 // to atapi commands.
3174 // Since there is really no other indication that tells us
3175 // the drive is really ready for action. We are going to check BSY
3176 // is clear and then just wait for an arbitrary amount of time!
3178 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3181 // have to get out of the loop sometime!
3182 // 10000 * 100us = 1000,000us = 1000ms = 1s
3184 GetStatus(chan
, statusByte
);
3185 if(statusByte
== IDE_STATUS_WRONG
) {
3188 while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
) {
3190 KdPrint2((PRINT_PREFIX
"Wait for ATAPI (status %x)\n", statusByte
));
3191 // Wait for Busy to drop.
3192 AtapiStallExecution(100);
3193 GetStatus(chan
, statusByte
);
3197 // 5000 * 100us = 500,000us = 500ms = 0.5s
3198 if(statusByte
!= IDE_STATUS_WRONG
) {
3201 AtapiStallExecution(100);
3202 } while (waitCount
--);
3205 GetBaseStatus(chan
, statusByte
);
3206 AtapiEnableInterrupts(deviceExtension
, lChannel
);
3207 AtapiStallExecution(10);
3212 } // end AtapiHwInitialize__()
3219 AtapiHwInitializeChanger(
3220 IN PVOID HwDeviceExtension
,
3221 IN PSCSI_REQUEST_BLOCK Srb
,
3222 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus
)
3224 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3225 ULONG lChannel
= GET_CHANNEL(Srb
);
3226 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3227 ULONG DeviceNumber
= GET_CDEV(Srb
);
3228 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
3230 if (MechanismStatus
) {
3231 LunExt
->DiscsPresent
= MechanismStatus
->NumberAvailableSlots
;
3232 if (LunExt
->DiscsPresent
> 1) {
3233 LunExt
->DeviceFlags
|= DFLAGS_ATAPI_CHANGER
;
3237 } // end AtapiHwInitializeChanger()
3242 Routine Description:
3243 This routine will parse the string for a match on the keyword, then
3244 calculate the value for the keyword and return it to the caller.
3247 String - The ASCII string to parse.
3248 KeyWord - The keyword for the value desired.
3251 Zero if value not found
3252 Value converted from ASCII to binary.
3257 AtapiParseArgumentString(
3265 ULONG stringLength
= 0;
3266 ULONG keyWordLength
= 0;
3276 // Calculate the string length and lower case all characters.
3282 // Calculate the keyword length.
3288 if (keyWordLength
> stringLength
) {
3290 // Can't possibly have a match.
3294 // Now setup and start the compare.
3299 // The input string may start with white space. Skip it.
3300 while (*cptr
== ' ' || *cptr
== '\t') {
3304 if (*cptr
== '\0') {
3310 while ((*cptr
== *kptr
) ||
3311 (*cptr
>= 'A' && *cptr
<= 'Z' && *cptr
+ ('a' - 'A') == *kptr
) ||
3312 (*cptr
>= 'a' && *cptr
<= 'z' && *cptr
- ('a' - 'A') == *kptr
)) {
3316 if (*cptr
== '\0') {
3322 if (*kptr
== '\0') {
3324 // May have a match backup and check for blank or equals.
3325 while (*cptr
== ' ' || *cptr
== '\t') {
3329 // Found a match. Make sure there is an equals.
3332 // Not a match so move to the next semicolon.
3334 if (*cptr
++ == ';') {
3335 goto ContinueSearch
;
3340 // Skip the equals sign.
3343 // Skip white space.
3344 while ((*cptr
== ' ') || (*cptr
== '\t')) {
3348 if (*cptr
== '\0') {
3349 // Early end of string, return not found
3354 // This isn't it either.
3356 goto ContinueSearch
;
3360 if ((*cptr
== '0') && ((*(cptr
+ 1) == 'x') || (*(cptr
+ 1) == 'X'))) {
3361 // Value is in Hex. Skip the "0x"
3363 for (index
= 0; *(cptr
+ index
); index
++) {
3365 if (*(cptr
+ index
) == ' ' ||
3366 *(cptr
+ index
) == '\t' ||
3367 *(cptr
+ index
) == ';') {
3371 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3372 value
= (16 * value
) + (*(cptr
+ index
) - '0');
3374 if ((*(cptr
+ index
) >= 'a') && (*(cptr
+ index
) <= 'f')) {
3375 value
= (16 * value
) + (*(cptr
+ index
) - 'a' + 10);
3376 } else if ((*(cptr
+ index
) >= 'A') && (*(cptr
+ index
) <= 'F')) {
3377 value
= (16 * value
) + (*(cptr
+ index
) - 'A' + 10);
3379 // Syntax error, return not found.
3386 // Value is in Decimal.
3387 for (index
= 0; *(cptr
+ index
); index
++) {
3389 if (*(cptr
+ index
) == ' ' ||
3390 *(cptr
+ index
) == '\t' ||
3391 *(cptr
+ index
) == ';') {
3395 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3396 value
= (10 * value
) + (*(cptr
+ index
) - '0');
3399 // Syntax error return not found.
3408 // Not a match check for ';' to continue search.
3410 if (*cptr
++ == ';') {
3411 goto ContinueSearch
;
3417 } // end AtapiParseArgumentString()_
3425 IN PVOID HwDeviceExtension
,
3430 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3431 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3434 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3437 KdPrint2((PRINT_PREFIX
"AtapiCallBack:\n"));
3438 // If the last command was DSC restrictive, see if it's set. If so, the device is
3439 // ready for a new request. Otherwise, reset the timer and come back to here later.
3441 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3442 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3443 // we shall have no problem with interrupt handler.
3444 if (!srb
|| chan
->ExpectingInterrupt
) {
3445 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Calling ISR directly due to BUSY\n"));
3446 chan
->DpcState
= DPC_STATE_TIMER
;
3447 if(!AtapiInterrupt__(HwDeviceExtension
, lChannel
)) {
3448 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3449 KdPrint2((PRINT_PREFIX
"AtapiCallBack: What's fucking this ???\n"));
3451 goto ReturnCallback
;
3455 if (!IS_RDP((srb
->Cdb
[0]))) {
3456 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb
->Cdb
[0]));
3460 goto ReturnEnableIntr
;
3462 GetStatus(chan
, statusByte
);
3463 if (statusByte
& IDE_STATUS_DSC
) {
3465 UCHAR PathId
= srb
->PathId
;
3466 UCHAR TargetId
= srb
->TargetId
;
3467 UCHAR Lun
= srb
->Lun
;
3469 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Found DSC for RDP - %#x\n", srb
->Cdb
[0]));
3470 AtapiDmaDBSync(chan
, srb
);
3471 UniataRemoveRequest(chan
, srb
);
3472 ScsiPortNotification(RequestComplete
, deviceExtension
, srb
);
3473 // Clear current SRB.
3474 if(!deviceExtension
->simplexOnly
) {
3475 srb
= UniataGetCurRequest(chan
);
3481 // Ask for next request.
3482 ScsiPortNotification(NextLuRequest
,
3487 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
3490 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3494 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Requesting another timer for Op %#x\n",
3497 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3501 goto ReturnCallback
;
3506 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
3507 KdPrint2((PRINT_PREFIX
"AtapiCallBack: CallDisableInterrupts\n"));
3508 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3509 #ifdef UNIATA_USE_XXableInterrupts
3510 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
3511 // must be called on DISPATCH_LEVEL
3512 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
3513 AtapiEnableInterrupts__
);
3515 AtapiEnableInterrupts(HwDeviceExtension
, lChannel
);
3516 InterlockedExchange(&(chan
->CheckIntr
),
3518 // Will raise IRQL to DIRQL
3519 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3520 AtapiEnableInterrupts__
,
3522 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
3523 #endif // UNIATA_USE_XXableInterrupts
3525 //ASSERT(!deviceExtension->simplexOnly);
3530 // Check other channel
3531 // In simplex mode no interrupts must appear on other channels
3532 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3533 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3539 chan
= &(deviceExtension
->chan
[c
]);
3541 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
3542 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3543 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) == CHECK_INTR_DETECTED
)
3545 //ASSERT(!deviceExtension->simplexOnly);
3546 chan
->DpcState
= DPC_STATE_ISR
;
3547 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3548 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3552 KdPrint2((PRINT_PREFIX
"AtapiCallBack: return\n"));
3555 } // end AtapiCallBack__()
3560 IN PVOID HwDeviceExtension
3563 AtapiCallBack__(HwDeviceExtension
, (UCHAR
)((PHW_DEVICE_EXTENSION
)HwDeviceExtension
)->ActiveDpcChan
);
3564 } // end AtapiCallBack_X()
3566 #endif //UNIATA_CORE
3570 Routine Description:
3572 This is the interrupt service routine for ATAPI IDE miniport driver.
3576 HwDeviceExtension - HBA miniport driver's adapter data storage
3580 TRUE if expecting an interrupt.
3586 IN PVOID HwDeviceExtension
3589 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3591 BOOLEAN status
= FALSE
;
3595 //BOOLEAN checked[AHCI_MAX_PORT];
3599 KdPrint2((PRINT_PREFIX
"Intr: VendorID+DeviceID/Rev %#x/%#x (ex %d)\n",
3600 deviceExtension
->DevID
, deviceExtension
->RevID
, deviceExtension
->ExpectingInterrupt
));
3602 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3603 // AHCI may generate state change notification, never skip this check
3604 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
3605 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3609 // assume all non-interrupted ports to be already checked
3611 // assume all not implemented ports to be already checked
3612 checked
|= ~deviceExtension
->AHCI_PI
;
3614 checked
= 0; // assume all ports are not checked
3617 if(!deviceExtension
->ExpectingInterrupt
) {
3618 // if we do not expect interrupt, exit now,
3619 // but keep in mind that it can be unexpected one
3620 // Note: this is just a hint, not exact counter
3621 KdPrint2((PRINT_PREFIX
"unexpected, 1st chance\n"));
3622 //deviceExtension->ExpectingInterrupt++;
3625 // clear this flag now, it can be set again in sub-calls
3626 deviceExtension
->ExpectingInterrupt
=0;
3629 // for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
3630 // checked[_c] = (UCHAR)((hIS >> _c) & 0x01);
3634 for(pass
=0; pass
<2; pass
++) {
3635 //KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): pass %d\n", pass));
3636 if(status
&& pass
) {
3637 // we catched some expected interrupts now.
3638 // do not touch unexpected until next ISR call
3641 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3643 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3645 if((checked
>>c
) & 0x01)
3648 // check non-empty and expecting interrupt channels first
3649 if(!pass
&& !deviceExtension
->chan
[c
].ExpectingInterrupt
)
3652 checked
|= (ULONG
)1 << c
;
3654 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3656 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3657 // we get here on idle channels or when ISR is posted to DPC
3658 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): disabled INTR on ch %d\n", c
));
3661 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
3663 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): try lock\n"));
3664 // c_state = deviceExtension->chan[c].CheckIntr;
3665 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
3666 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
3669 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3670 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3671 CRNT_ILK_TYPE CHECK_INTR_DETECTED
);
3672 if(c_state
== CHECK_INTR_IDLE
) {
3673 // c_state = deviceExtension->chan[c].CheckIntr;
3674 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
3675 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
3678 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3679 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3680 CRNT_ILK_TYPE CHECK_INTR_IDLE
);
3682 } while(c_state
== CHECK_INTR_CHECK
);
3683 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): locked\n"));
3684 // check if already serviced
3685 if(c_state
== CHECK_INTR_ACTIVE
) {
3686 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
3690 if((c_state
== CHECK_INTR_DETECTED
) ||
3691 (i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3693 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
3694 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): Catch unexpected\n"));
3695 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3700 // disable interrupts on other channel of legacy mode
3701 // ISA-bridged onboard controller
3702 if(deviceExtension
->simplexOnly
/*||
3703 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3704 AtapiDisableInterrupts(deviceExtension
, !c
);
3707 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_ISR
;
3708 if(AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3709 deviceExtension
->LastInterruptedChannel
= (UCHAR
)c
;
3710 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): return status TRUE\n"));
3713 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
3714 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3717 // re-enable interrupts on other channel
3718 if(deviceExtension
->simplexOnly
/*||
3719 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3720 AtapiEnableInterrupts(deviceExtension
, !c
);
3724 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
3725 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3730 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): exit with status %#x\n", status
));
3732 deviceExtension
->FirstChannelToCheck
++;
3733 if(deviceExtension
->FirstChannelToCheck
>= deviceExtension
->NumberChannels
)
3734 deviceExtension
->FirstChannelToCheck
= 0;
3737 } // end AtapiInterrupt()
3745 IN PKINTERRUPT Interrupt
,
3746 IN PVOID Isr2HwDeviceExtension
3749 // This ISR is intended to catch interrupts when we are already in other ISR instance
3750 // for the same device. This may happen when we have multiple channels,
3751 // especially on SMP machines
3753 PISR2_DEVICE_EXTENSION Isr2DeviceExtension
= (PISR2_DEVICE_EXTENSION
)Isr2HwDeviceExtension
;
3754 PHW_DEVICE_EXTENSION deviceExtension
= Isr2DeviceExtension
->HwDeviceExtension
;
3756 BOOLEAN status
= FALSE
;
3762 // we should never get here for ISA/MCA
3763 if(!BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
3764 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3768 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3769 // AHCI may generate state change notification, never skip this check
3770 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
3771 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3775 // assume all non-interrupted ports to be already checked
3777 // assume all not implemented ports to be already checked
3778 checked
|= ~deviceExtension
->AHCI_PI
;
3781 checked
= 0; // assume all ports are not checked
3783 if(!deviceExtension
->ExpectingInterrupt
) {
3784 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !deviceExtension->ExpectingInterrupt\n"));
3785 deviceExtension
->ExpectingInterrupt
++;
3788 //deviceExtension->ExpectingInterrupt = 0;
3790 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3791 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3793 if((checked
>>c
) & 0x01)
3796 checked
|= (ULONG
)1 << c
;
3798 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3799 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: disabled INTR\n"));
3803 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3804 CRNT_ILK_TYPE CHECK_INTR_CHECK
,
3805 CRNT_ILK_TYPE CHECK_INTR_IDLE
) != CHECK_INTR_IDLE
)
3807 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
3808 // hunt on unexpected intr (Some devices generate double interrupts,
3809 // some controllers (at least CMD649) interrupt twice with small delay.
3810 // If interrupts are disabled, they queue interrupt and re-issue it later,
3811 // when we do not expect it.
3816 if((i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3818 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: intr\n"));
3819 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
3820 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: Catch unexpected\n"));
3821 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3826 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_DETECTED
);
3828 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3831 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: status %d, c_count %d\n", status
, c_count
));
3832 if(status
&& (c_count
!= deviceExtension
->NumberChannels
)) {
3833 // there is an active ISR/DPC for one channel, but
3834 // we have an interrupt from another one
3835 // Lets inform current ISR/DPC about new interrupt
3836 InterlockedExchange(&(deviceExtension
->ReCheckIntr
), CHECK_INTR_DETECTED
);
3840 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: return %d\n", status
));
3843 } // end AtapiInterrupt2()
3845 RETTYPE_XXableInterrupts
3848 IN PVOID HwDeviceExtension
3851 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3854 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3855 KdPrint2((PRINT_PREFIX
"AtapiInterruptDpc: %#x\n",c
));
3857 if(!(deviceExtension
->chan
[c
].ChannelCtrlFlags
& CTRFLAGS_DPC_REQ
)) {
3859 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3860 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3861 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
)
3867 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_DPC_REQ
;
3870 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
3871 AtapiDisableInterrupts(deviceExtension, lChannel);
3874 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_DPC
;
3875 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3876 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3879 return RETVAL_XXableInterrupts
;
3880 } // end AtapiInterruptDpc()
3883 RETTYPE_XXableInterrupts
3885 AtapiEnableInterrupts__(
3886 IN PVOID HwDeviceExtension
3889 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3890 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__():\n"));
3892 PHW_CHANNEL chan
= NULL
;
3894 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3895 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__(2): %#x\n",c
));
3896 chan
= &(deviceExtension
->chan
[c
]);
3898 if(chan
->ChannelCtrlFlags
& CTRFLAGS_ENABLE_INTR_REQ
) {
3899 // enable intrs on requested channel
3900 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_ENABLE_INTR_REQ
;
3901 AtapiEnableInterrupts(HwDeviceExtension
, c
);
3902 InterlockedExchange(&(chan
->CheckIntr
),
3905 // check if current or other channel(s) interrupted
3906 //AtapiInterrupt(HwDeviceExtension);
3908 if(deviceExtension
->simplexOnly
) {
3912 // check if other channel(s) interrupted
3913 // must do nothing in simplex mode
3914 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
3915 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3916 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
3919 //ASSERT(!deviceExtension->simplexOnly);
3920 chan
->DpcState
= DPC_STATE_ISR
;
3921 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3922 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3926 // In simplex mode next command must be sent to device here
3927 if(deviceExtension
->simplexOnly
&& chan
) {
3928 PSCSI_REQUEST_BLOCK srb
;
3929 chan
= UniataGetNextChannel(chan
);
3931 srb
= UniataGetCurRequest(chan
);
3936 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3940 return RETVAL_XXableInterrupts
;
3942 } // end AtapiEnableInterrupts__()
3944 #endif //UNIATA_CORE
3949 AtapiEnableInterrupts(
3950 IN PVOID HwDeviceExtension
,
3954 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3958 if(c
>= deviceExtension
->NumberChannels
) {
3959 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c
));
3962 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
3963 !UniataAhciChanImplemented(deviceExtension
, c
)) {
3964 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c
));
3968 chan
= &(deviceExtension
->chan
[c
]);
3969 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
3970 if(!InterlockedDecrement(&chan
->DisableIntr
)) {
3971 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3972 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
3973 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
3974 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_INF
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
3975 ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
: 0) |
3976 ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
| /* DEBUG */
3978 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
3979 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
)
3982 //SelectDrive(chan, 0);
3983 //GetBaseStatus(chan, statusByte);
3984 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
3986 //if(chan->NumberLuns) {
3987 // SelectDrive(chan, 1);
3988 // GetBaseStatus(chan, statusByte);
3989 // AtapiWritePort1(chan, IDX_IO2_o_Control,
3991 // SelectDrive(chan, chan->cur_cdev);
3994 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_INTR_DISABLED
;
3996 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
3997 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4000 } // end AtapiEnableInterrupts()
4004 AtapiDisableInterrupts(
4005 IN PVOID HwDeviceExtension
,
4009 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4011 if(c
>= deviceExtension
->NumberChannels
) {
4012 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c
));
4015 chan
= &(deviceExtension
->chan
[c
]);
4016 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
4017 // mark channel as busy
4018 if(InterlockedIncrement(&chan
->DisableIntr
)) {
4019 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4020 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
4022 //SelectDrive(chan, 0);
4023 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4024 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4025 //if(chan->NumberLuns) {
4026 // SelectDrive(chan, 1);
4027 // AtapiWritePort1(chan, IDX_IO2_o_Control,
4028 // IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4029 // SelectDrive(chan, chan->cur_cdev);
4032 chan
->ChannelCtrlFlags
|= CTRFLAGS_INTR_DISABLED
;
4036 } // end AtapiDisableInterrupts()
4039 UniataExpectChannelInterrupt(
4040 IN
struct _HW_CHANNEL
* chan
,
4041 IN BOOLEAN Expecting
4044 chan
->ExpectingInterrupt
= Expecting
;
4046 chan
->DeviceExtension
->ExpectingInterrupt
++;
4048 if(chan
->DeviceExtension
->ExpectingInterrupt
) {
4049 chan
->DeviceExtension
->ExpectingInterrupt
--;
4052 } // end UniataExpectChannelInterrupt()
4055 Check hardware for interrupt state
4059 AtapiCheckInterrupt__(
4060 IN PVOID HwDeviceExtension
,
4061 IN UCHAR c
// logical channel
4064 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4065 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4066 PHW_LU_EXTENSION LunExt
;
4068 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
4069 ULONG ChipType
= deviceExtension
->HwFlags
& CHIPTYPE_MASK
;
4072 ULONG pr_status
= 0;
4073 UCHAR dma_status
= 0;
4076 UCHAR statusByte
= 0;
4077 ULONG slotNumber
= deviceExtension
->slotNumber
;
4078 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
4079 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
4082 BOOLEAN DmaTransfer
= FALSE
;
4083 BOOLEAN OurInterrupt
= FALSE
;
4084 BOOLEAN StatusValid
= FALSE
;
4086 UCHAR interruptReason
;
4087 BOOLEAN EarlyIntr
= FALSE
;
4088 BOOLEAN SingleBlockIntr
= FALSE
;
4090 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__:\n"));
4093 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4094 LunExt
= chan
->lun
[chan
->cur_cdev
];
4096 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ chan %#x:\n", chan));
4097 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ (%d/%d):\n", Channel, chan->cur_cdev));
4099 if((ChipFlags
& UNIATA_AHCI
) &&
4100 UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4102 if(!UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
4103 return OurInterrupt
;
4106 OurInterrupt
= UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
4107 if((OurInterrupt
== INTERRUPT_REASON_UNEXPECTED
) &&
4108 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
4109 UniataAhciWaitCommandReady(chan
, 2 /* ms */ );
4110 statusByte
= (UCHAR
)UniataAhciWaitReady(chan
, 0 /* immediate */);
4111 if(!(statusByte
& (IDE_STATUS_BUSY
)) ) {
4112 KdPrint2((PRINT_PREFIX
"ATAPI special case READY\n"));
4113 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
4114 OurInterrupt
= INTERRUPT_REASON_OUR
;
4116 if((statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
)) == (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
) ) {
4117 KdPrint2((PRINT_PREFIX
"ATAPI special case pre ERR-READY\n"));
4118 OurInterrupt
= INTERRUPT_REASON_OUR
;
4120 if(statusByte
& IDE_STATUS_ERROR
) {
4121 KdPrint2((PRINT_PREFIX
"ATAPI special case ERR-READY\n"));
4122 OurInterrupt
= INTERRUPT_REASON_OUR
;
4124 KdPrint2((PRINT_PREFIX
"ATAPI special case ? %x\n", statusByte
));
4125 OurInterrupt
= INTERRUPT_REASON_OUR
;
4128 return OurInterrupt
;
4131 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4133 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension
->DevIndex
,
4134 deviceExtension
->Channel
+ c
, c
));
4136 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension
->DevIndex
,
4137 deviceExtension
->Channel
+ c
, c
));
4138 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4139 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
4142 // do controller-specific interrupt servicing staff
4143 if(deviceExtension
->UnknownDev
) {
4144 KdPrint2((PRINT_PREFIX
" UnknownDev\n"));
4149 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
4150 // Such behavior was observed with Intel ICH-xxx chips
4151 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
4155 case ATA_PROMISE_ID
: {
4159 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x1c);
4163 ((Channel
) ? 0x00004000 : 0x00000400))) {
4164 KdPrint2((PRINT_PREFIX
" Promise old/new unexpected\n"));
4165 return INTERRUPT_REASON_IGNORE
;
4169 AtapiWritePort1(chan
, IDX_BM_DeviceSpecific0
, 0x0b);
4170 status
= AtapiReadPort1(chan
, IDX_BM_DeviceSpecific1
);
4173 if(!(status
& 0x20)) {
4174 KdPrint2((PRINT_PREFIX
" Promise tx unexpected\n"));
4175 return INTERRUPT_REASON_IGNORE
;
4179 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x0040);
4180 if(ChipFlags
& PRSATA
) {
4181 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c);
4182 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c, pr_status
& 0x000000ff);
4184 if(pr_status
& (0x11 << Channel
)) {
4185 // TODO: reset channel
4186 KdPrint2((PRINT_PREFIX
" Promise mio unexpected + reset req\n"));
4187 return INTERRUPT_REASON_IGNORE
;
4189 if(!(status
& (0x01 << Channel
))) {
4190 KdPrint2((PRINT_PREFIX
" Promise mio unexpected\n"));
4191 return INTERRUPT_REASON_IGNORE
;
4193 AtapiWritePort4(chan
, IDX_BM_DeviceSpecific0
, 0x00000001);
4197 case ATA_NVIDIA_ID
: {
4198 if(!(ChipFlags
& UNIATA_SATA
))
4201 KdPrint2((PRINT_PREFIX
"NVIDIA\n"));
4203 ULONG offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
4204 ULONG shift
= Channel
<< ((ChipFlags
& NVQ
) ? 4 : 2);
4206 /* get and clear interrupt status */
4207 if(ChipFlags
& NVQ
) {
4208 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4209 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0fUL
<< shift
) | 0x00f000f0);
4211 pr_status
= AtapiReadPortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4212 AtapiWritePortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0f << shift
));
4214 KdPrint2((PRINT_PREFIX
" pr_status %x\n", pr_status
));
4216 /* check for and handle connect events */
4217 if(((pr_status
& (0x0cUL
<< shift
)) == (0x04UL
<< shift
)) ) {
4218 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, 0);
4220 /* check for and handle disconnect events */
4221 if((pr_status
& (0x08UL
<< shift
)) &&
4222 !((pr_status
& (0x04UL
<< shift
) &&
4223 UniataSataReadPort4(chan
, IDX_SATA_SStatus
, 0))) ) {
4224 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, 0);
4226 /* do we have any device action ? */
4227 if(!(pr_status
& (0x01UL
<< shift
))) {
4228 KdPrint2((PRINT_PREFIX
" nVidia unexpected\n"));
4229 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4230 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4232 return INTERRUPT_REASON_IGNORE
;
4238 KdPrint2((PRINT_PREFIX
"ATI\n"));
4239 if(ChipType
== SIIMIO
) {
4244 case ATA_SILICON_IMAGE_ID
:
4246 if(ChipType
== SIIMIO
) {
4248 reg32
= AtapiReadPort4(chan
, IDX_BM_DeviceSpecific0
);
4249 KdPrint2((PRINT_PREFIX
" Sii DS0 %x\n", reg32
));
4250 if(reg32
== 0xffffffff) {
4251 KdPrint2((PRINT_PREFIX
" Sii mio unexpected\n"));
4252 return INTERRUPT_REASON_IGNORE
;
4254 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
))) {
4255 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (2)\n"));
4256 return INTERRUPT_REASON_IGNORE
;
4259 if(ChipFlags
& UNIATA_SATA
) {
4260 if(reg32
& (BM_DS0_SII_DMA_SATA_IRQ
| BM_DS0_SII_IRQ
)) {
4262 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
4263 * controllers continue to assert IRQ as long as
4264 * SError bits are pending. Clear SError immediately.
4266 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4267 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4274 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4275 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (3)\n"));
4276 return OurInterrupt
;
4278 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
& ~BM_STATUS_ERR
);
4279 goto skip_dma_stat_check
;
4282 if(!(deviceExtension
->HwFlags
& SIIINTR
))
4284 GetPciConfig1(0x71, reg8
);
4285 KdPrint2((PRINT_PREFIX
" 0x71 = %#x\n", reg8
));
4287 (Channel
? 0x08 : 0x04))) {
4288 return INTERRUPT_REASON_IGNORE
;
4291 KdPrint2((PRINT_PREFIX
" cmd our\n"));
4292 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4294 SetPciConfig1(0x71, (Channel
? 0x08 : 0x04));
4301 //dma_status = GetDmaStatus(deviceExtension, lChannel);
4302 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4303 KdPrint2((PRINT_PREFIX
" Acard unexpected\n"));
4304 return INTERRUPT_REASON_IGNORE
;
4306 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
| BM_STATUS_INTR
);
4307 AtapiStallExecution(1);
4308 AtapiWritePort1(chan
, IDX_BM_Command
,
4309 AtapiReadPort1(chan
, IDX_BM_Command
) & ~BM_COMMAND_START_STOP
);
4310 goto skip_dma_stat_check
;
4312 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4313 if(ChipFlags
& UNIATA_AHCI
) {
4316 if(ChipFlags
& UNIATA_SATA
) {
4317 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4318 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4320 if(!(chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
4321 if(UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, 1)) {
4322 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4329 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4330 if(ChipFlags
& UNIATA_AHCI
) {
4333 if(ChipFlags
& UNIATA_SATA
) {
4334 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4335 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4341 KdPrint2((PRINT_PREFIX
" perform generic check\n"));
4343 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4344 KdPrint2((PRINT_PREFIX
" DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status
));
4345 if(dma_status
& BM_STATUS_ERR
) {
4346 KdPrint2((PRINT_PREFIX
" DmaTransfer + BM_STATUS_ERR -> our\n"));
4347 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4349 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4350 GetStatus(chan
, statusByte
);
4352 KdPrint2((PRINT_PREFIX
" status %#x\n", statusByte
));
4353 if(statusByte
& IDE_STATUS_ERROR
) {
4354 KdPrint2((PRINT_PREFIX
" IDE_STATUS_ERROR -> our\n", statusByte
));
4355 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4357 if ((statusByte
& IDE_STATUS_DSC
) &&
4358 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
4359 (dma_status
== BM_STATUS_ACTIVE
)) {
4360 KdPrint2((PRINT_PREFIX
" special case DMA + ATAPI + IDE_STATUS_DSC -> our\n", statusByte
));
4361 // some devices interrupts on each block transfer even in DMA mode
4362 if(LunExt
->TransferMode
>= ATA_SDMA
&& LunExt
->TransferMode
<= ATA_WDMA2
) {
4363 KdPrint2((PRINT_PREFIX
" wait for completion\n"));
4364 ///* clear interrupt and get status */
4365 //GetBaseStatus(chan, statusByte);
4366 //return INTERRUPT_REASON_IGNORE;
4367 SingleBlockIntr
= TRUE
;
4370 return INTERRUPT_REASON_IGNORE
;
4375 if(dma_status
& BM_STATUS_INTR
) {
4376 // bullshit, we have DMA interrupt, but had never initiate DMA operation
4377 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr\n"));
4378 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4380 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4383 skip_dma_stat_check
:
4384 if(!(ChipFlags
& UNIATA_SATA
) && chan
->ExpectingInterrupt
) {
4385 AtapiStallExecution(1);
4388 /* if drive is busy it didn't interrupt */
4389 /* the exception is DCS + BSY state of ATAPI devices */
4391 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4392 GetStatus(chan
, statusByte
);
4394 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4395 KdPrint3((PRINT_PREFIX
" ATAPI status %#x\n", statusByte
));
4397 KdPrint2((PRINT_PREFIX
" IDE status %#x\n", statusByte
));
4399 if (statusByte
== IDE_STATUS_WRONG
) {
4400 // interrupt from empty controller ?
4402 if (statusByte
& IDE_STATUS_BUSY
) {
4403 if(!chan
->ExpectingInterrupt
) {
4404 KdPrint3((PRINT_PREFIX
" unexpected intr + BUSY\n"));
4405 return OurInterrupt
;
4408 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4409 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4411 KdPrint2((PRINT_PREFIX
" expecting intr + BUSY (3), non ATAPI\n"));
4412 return INTERRUPT_REASON_IGNORE
;
4414 if((statusByte
& ~IDE_STATUS_DRQ
) != (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
| IDE_STATUS_DSC
)) {
4415 KdPrint3((PRINT_PREFIX
" unexpected status, seems it is not our\n"));
4416 return INTERRUPT_REASON_IGNORE
;
4418 if(!(LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
) && (statusByte
& IDE_STATUS_DRQ
)) {
4419 KdPrint3((PRINT_PREFIX
" unexpected DRQ, seems it is not our\n"));
4420 return INTERRUPT_REASON_IGNORE
;
4425 if(dma_status
& BM_STATUS_INTR
) {
4426 KdPrint3((PRINT_PREFIX
" our interrupt with BSY set, try wait in ISR or post to DPC\n"));
4427 /* clear interrupt and get status */
4428 GetBaseStatus(chan
, statusByte
);
4429 if(!(dma_status
& BM_STATUS_ACTIVE
)) {
4430 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4432 KdPrint3((PRINT_PREFIX
" base status %#x (+BM_STATUS_INTR)\n", statusByte
));
4433 return INTERRUPT_REASON_OUR
;
4436 if(g_WaitBusyInISR
) {
4437 GetStatus(chan
, statusByte
);
4438 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4439 reg8
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4440 KdPrint2((PRINT_PREFIX
" Error reg (%#x)\n", reg8
));
4441 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4442 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4444 if (statusByte
& IDE_STATUS_BUSY
) {
4445 KdPrint2((PRINT_PREFIX
" still BUSY, seems it is not our\n"));
4446 return INTERRUPT_REASON_IGNORE
;
4452 /* clear interrupt and get status */
4453 GetBaseStatus(chan
, statusByte
);
4454 KdPrint2((PRINT_PREFIX
" base status %#x\n", statusByte
));
4455 if (statusByte
== IDE_STATUS_WRONG
) {
4456 // interrupt from empty controller ?
4458 if(!(statusByte
& (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
))) {
4459 KdPrint2((PRINT_PREFIX
" no DRQ/DRDY set\n"));
4460 return OurInterrupt
;
4463 #ifndef UNIATA_PIO_ONLY
4465 if(!SingleBlockIntr
&& (!EarlyIntr
|| g_WaitBusyInISR
)) {
4466 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4468 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4469 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4473 if(SingleBlockIntr
) {
4474 KdPrint2((PRINT_PREFIX
" set REQ_STATE_ATAPI_EXPECTING_DATA_INTR2.\n"));
4476 KdPrint2((PRINT_PREFIX
" set REQ_STATE_EARLY_INTR.\n"));
4479 AtaReq
->ReqState
= SingleBlockIntr
? REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
: REQ_STATE_EARLY_INTR
;
4485 if (!(chan
->ExpectingInterrupt
)) {
4487 KdPrint2((PRINT_PREFIX
" Unexpected interrupt.\n"));
4489 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4490 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4492 KdPrint2((PRINT_PREFIX
" OurInterrupt = %d\n", OurInterrupt
));
4493 return OurInterrupt
;
4495 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
4496 KdPrint3((PRINT_PREFIX
"AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason
));
4497 return OurInterrupt
;
4499 //ASSERT(!chan->queue_depth || chan->cur_req);
4501 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__: exit with TRUE\n"));
4502 return INTERRUPT_REASON_OUR
;
4504 } // end AtapiCheckInterrupt__()
4510 IN PVOID HwDeviceExtension
,
4514 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4515 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4517 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4518 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4520 ULONG wordCount
= 0, wordsThisInterrupt
= DEV_BSIZE
/2;
4521 ULONG status
= SRB_STATUS_SUCCESS
;
4522 UCHAR dma_status
= 0;
4525 UCHAR statusByte
= 0,interruptReason
;
4527 BOOLEAN atapiDev
= FALSE
;
4532 BOOLEAN DmaTransfer
= FALSE
;
4534 ULONG TimerValue
= 1000;
4535 ULONG TotalTimerValue
= 0;
4536 #ifdef UNIATA_USE_XXableInterrupts
4537 BOOLEAN InDpc
= (KeGetCurrentIrql() == DISPATCH_LEVEL
);
4539 BOOLEAN InDpc
= (chan
->DpcState
!= DPC_STATE_ISR
);
4540 #endif // UNIATA_USE_XXableInterrupts
4541 BOOLEAN UseDpc
= deviceExtension
->UseDpc
;
4542 // BOOLEAN RestoreUseDpc = FALSE;
4543 BOOLEAN DataOverrun
= FALSE
;
4544 BOOLEAN NoStartIo
= TRUE
;
4546 KdPrint2((PRINT_PREFIX
"AtapiInterrupt:\n"));
4548 KdPrint2((PRINT_PREFIX
" InDpc = TRUE\n"));
4549 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
4555 UCHAR OldReqState
= REQ_STATE_NONE
;
4557 PHW_LU_EXTENSION LunExt
;
4560 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4562 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension
->DevIndex
, Channel
, KeGetCurrentIrql(), c
));
4564 if((chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
4565 (AtaReq
&& (AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
)) ||
4566 (deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
4568 KdPrint2((PRINT_PREFIX
" DmaTransfer = TRUE\n"));
4572 PathId
= srb
->PathId
;
4573 TargetId
= srb
->TargetId
;
4579 goto enqueue_next_req
;
4582 //ldev = GET_LDEV2(PathId, TargetId, Lun);
4583 DeviceNumber
= (UCHAR
)(TargetId
);
4584 LunExt
= chan
->lun
[DeviceNumber
];
4585 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
4586 KdPrint2((PRINT_PREFIX
" dev_type %s\n", atapiDev
? "ATAPI" : "IDE"));
4588 // check if we are in ISR DPC
4590 KdPrint2((PRINT_PREFIX
" InDpc -> CTRFLAGS_INTR_DISABLED\n"));
4591 goto ServiceInterrupt
;
4595 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4598 if (!(chan
->ExpectingInterrupt
)) {
4600 KdPrint2((PRINT_PREFIX
" Unexpected interrupt for this channel.\n"));
4604 // change request state
4606 OldReqState
= AtaReq
->ReqState
;
4607 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4608 KdPrint2((PRINT_PREFIX
" OldReqState = %x\n", OldReqState
));
4611 // We don't want using DPC for fast operations, like
4612 // DMA completion, sending CDB, short ATAPI transfers, etc.
4614 // We MUST use DPC, because of interprocessor synchronization
4615 // on multiprocessor platforms
4618 goto ServiceInterrupt
;
4620 switch(OldReqState
) {
4621 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR
:
4622 KdPrint3((PRINT_PREFIX
" EXPECTING_CMD_INTR\n"));
4623 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR
:
4624 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
:
4625 case REQ_STATE_DPC_WAIT_BUSY0
:
4626 case REQ_STATE_DPC_WAIT_BUSY1
:
4627 KdPrint2((PRINT_PREFIX
" continue service interrupt\n"));
4628 goto ServiceInterrupt
;
4629 case REQ_STATE_ATAPI_DO_NOTHING_INTR
:
4630 KdPrint2((PRINT_PREFIX
" do nothing on interrupt\n"));
4634 if(!DmaTransfer
&& !atapiDev
) {
4635 KdPrint2((PRINT_PREFIX
" service PIO HDD\n"));
4642 goto ServiceInterrupt
;
4644 #ifdef UNIATA_USE_XXableInterrupts
4646 KdPrint2((PRINT_PREFIX
" Unexpected InDpc\n"));
4648 // shall never get here
4653 KdPrint2((PRINT_PREFIX
" this is direct DPC call on DRQL\n"));
4655 AtaReq
->ReqState
= REQ_STATE_DPC_INTR_REQ
;
4656 KdPrint2((PRINT_PREFIX
" ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
4658 KdPrint2((PRINT_PREFIX
" DPC without AtaReq!!!\n"));
4661 KdPrint2((PRINT_PREFIX
"call service interrupt\n"));
4662 goto ServiceInterrupt
;
4663 #endif // UNIATA_USE_XXableInterrupts
4668 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
4669 // We always get here when are called from timer callback, which is invoked on DRQL.
4670 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
4672 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: start DPC init...\n"));
4673 // disable interrupts for this channel,
4674 // but avoid recursion and double-disable
4675 if(OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4676 UniataExpectChannelInterrupt(chan
, FALSE
);
4677 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4680 chan
->ChannelCtrlFlags
|= CTRFLAGS_DPC_REQ
;
4682 #ifdef UNIATA_USE_XXableInterrupts
4683 // Will lower IRQL to DISPATCH_LEVEL
4684 ScsiPortNotification(CallEnableInterrupts
, HwDeviceExtension
,
4685 /*c ?*/ AtapiInterruptDpc
/*_1 : AtapiInterruptDpc_0*/);
4686 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DPC inited\n"));
4688 // Will raise IRQL to DIRQL
4689 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4692 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
4693 #endif // UNIATA_USE_XXableInterrupts
4698 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4700 if(!InDpc
&& OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4701 // we must block interrupts from this channel
4702 // If device generate new interrupt before we get to DPC,
4703 // ISR will assume, that it is NOT our interrupt
4704 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4705 // We should not clean ExpectingInterrupt flag on channel, since it is used in DPC
4707 // Will raise IRQL to DIRQL
4708 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4712 #endif //UNIATA_CORE
4716 if(AtaReq
&& InDpc
) {
4717 switch(AtaReq
->ReqState
) {
4718 case REQ_STATE_DPC_WAIT_DRQ0
:
4720 case REQ_STATE_DPC_WAIT_BUSY
:
4722 case REQ_STATE_DPC_WAIT_DRQ
:
4724 case REQ_STATE_DPC_WAIT_DRQ_ERR
:
4726 case REQ_STATE_DPC_WAIT_BUSY0
:
4727 case REQ_STATE_DPC_WAIT_BUSY1
:
4728 // continue normal execution
4734 #endif //UNIATA_CORE
4736 // make additional delay for old devices (if we are not in DPC)
4737 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
4741 !(deviceExtension->HwFlags & UNIATA_SATA)
4743 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
4744 AtapiStallExecution(10);
4748 /* clear interrupt and get status */
4749 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4750 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, srb
);
4751 statusByte
= (UCHAR
)(AtaReq
->ahci
.in_status
& IDE_STATUS_MASK
);
4753 if(chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
)) {
4754 KdPrint3((PRINT_PREFIX
"Err intr (%#x)\n", chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
)));
4755 if(chan
->AhciLastIS
& ~ATA_AHCI_P_IX_OF
) {
4756 //KdPrint3((PRINT_PREFIX "Err mask (%#x)\n", chan->AhciLastIS & ~ATA_AHCI_P_IX_OF));
4757 // We have some other error except Overflow
4758 // Just signal ERROR, operation will be aborted in ERROR branch.
4759 statusByte
|= IDE_STATUS_ERROR
;
4761 // We have only Overflow. Abort operation and continue
4763 UniataDumpAhciPortRegs(chan
);
4765 if(!UniataAhciAbortOperation(chan
)) {
4766 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
4769 UniataDumpAhciPortRegs(chan
);
4771 UniataAhciWaitCommandReady(chan
, 10);
4776 GetBaseStatus(chan
, statusByte
);
4779 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte
));
4781 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Entered with status (%#x)\n", statusByte
));
4785 KdPrint2((PRINT_PREFIX
" operate like in DPC\n"));
4791 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4792 KdPrint3((PRINT_PREFIX
" AHCI branch (IDE)\n"));
4794 if (statusByte
& IDE_STATUS_BUSY
) {
4795 if (deviceExtension
->DriverMustPoll
) {
4796 // Crashdump is polling and we got caught with busy asserted.
4797 // Just go away, and we will be polled again shortly.
4798 KdPrint2((PRINT_PREFIX
" Hit BUSY while polling during crashdump.\n"));
4799 goto ReturnEnableIntr
;
4802 // Ensure BUSY is non-asserted.
4803 // make a very small idle before falling to DPC
4804 k
= (InDpc
&& UseDpc
) ? 1000 : 2;
4806 for (i
= 0; i
< k
; i
++) {
4808 GetBaseStatus(chan
, statusByte
);
4809 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4812 AtapiStallExecution(10);
4815 if (!InDpc
&& UseDpc
&& i
== 2) {
4817 KdPrint2((PRINT_PREFIX
" BUSY on entry. Status %#x, Base IO %#x\n", statusByte
));
4820 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4825 AtapiStallExecution(TimerValue
);
4826 goto ServiceInterrupt
;
4827 #endif //UNIATA_CORE
4829 if (InDpc
&& i
== k
) {
4830 // reset the controller.
4831 KdPrint2((PRINT_PREFIX
4832 " Resetting due to BUSY on entry - %#x.\n",
4834 goto IntrPrepareResetController
;
4839 if(!LunExt
->IdentifyData
.MajorRevision
&&
4842 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
4844 //KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n"));
4845 //AtapiStallExecution(10);
4847 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4848 KdPrint3((PRINT_PREFIX
" AHCI branch (ATAPI)\n"));
4850 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
4851 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
4854 if (statusByte
& IDE_STATUS_BUSY
) {
4855 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
4858 // This is just workaround
4859 // We should DISABLE interrupts before entering WAIT state
4860 UniataExpectChannelInterrupt(chan, TRUE);
4861 #endif //UNIATA_CORE
4863 KdPrint3((PRINT_PREFIX
" BUSY on ATAPI device, waiting %d us\n", LunExt
->AtapiReadyWaitDelay
));
4865 if(LunExt
->AtapiReadyWaitDelay
&& (LunExt
->AtapiReadyWaitDelay
> g_opt_MaxIsrWait
) && !InDpc
&& UseDpc
) {
4866 TimerValue
= LunExt
->AtapiReadyWaitDelay
;
4867 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC (0)\n"));
4868 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4871 #endif //UNIATA_CORE
4874 GetBaseStatus(chan
, statusByte
);
4875 KdPrint3((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4876 KdPrint3((PRINT_PREFIX
" Error reg (%#x)\n",
4877 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Error
)));
4878 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4879 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4882 TotalTimerValue
+= TimerValue
;
4884 KdPrint3((PRINT_PREFIX
" too long wait -> DPC\n"));
4886 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC\n"));
4888 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4890 KdPrint2((PRINT_PREFIX
" too long wait: DPC -> DPC\n"));
4892 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY1
;
4896 if(!LunExt
->AtapiReadyWaitDelay
) {
4897 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
4901 #endif //UNIATA_CORE
4904 AtapiStallExecution(TimerValue
);
4907 if(!LunExt
->AtapiReadyWaitDelay
) {
4908 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
4909 KdPrint2((PRINT_PREFIX
" store AtapiReadyWaitDelay: %d\n", LunExt
->AtapiReadyWaitDelay
));
4911 if (statusByte
& IDE_STATUS_BUSY
) {
4912 KdPrint3((PRINT_PREFIX
" expecting intr + BUSY (2), try DPC wait\n"));
4918 if(AtaReq
&& DmaTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
4919 switch(OldReqState
) {
4920 case REQ_STATE_EARLY_INTR
:
4921 case REQ_STATE_DPC_WAIT_BUSY0
:
4923 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4924 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DMA still active\n"));
4925 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4932 // Check for error conditions.
4933 if ((statusByte
& IDE_STATUS_ERROR
) ||
4934 (dma_status
& BM_STATUS_ERR
)) {
4936 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4937 error
= AtaReq
->ahci
.in_error
;
4940 UniataDumpAhciPortRegs(chan
);
4942 if(!UniataAhciAbortOperation(chan
)) {
4943 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
4945 // clear interrupts again
4946 UniataAhciWaitCommandReady(chan
, 10);
4948 UniataDumpAhciPortRegs(chan
);
4950 UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
4952 UniataDumpAhciPortRegs(chan
);
4955 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4957 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error %#x\n", error
));
4959 if(error & IDE_STATUS_CORRECTED_ERROR) {
4960 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
4961 statusByte &= ~IDE_STATUS_ERROR;
4966 KdPrint2((PRINT_PREFIX
" Bad Lba %#I64x\n", AtaReq
->lba
));
4968 KdPrint2((PRINT_PREFIX
" Bad Lba unknown\n"));
4973 KdPrint2((PRINT_PREFIX
" wait 100 ready after IDE error\n"));
4974 AtapiStallExecution(100);
4976 KdPrint2((PRINT_PREFIX
" wait 10 ready after ATAPI error\n"));
4977 AtapiStallExecution(10);
4981 KdPrint3((PRINT_PREFIX
" Intr on DRQ %x\n",
4982 LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
));
4984 for (k
= atapiDev
? 0 : 200; k
; k
--) {
4985 GetBaseStatus(chan
, statusByte
);
4986 if (!(statusByte
& IDE_STATUS_DRQ
)) {
4987 AtapiStallExecution(50);
4994 /* if this is a UDMA CRC error, reinject request */
4997 if(AtaReq
->retry
< MAX_RETRIES
) {
4998 #ifdef IO_STATISTICS
4999 chan
->lun
[DeviceNumber
]->ModeErrorCount
[AtaReq
->retry
]++;
5000 #endif //IO_STATISTICS
5002 (error & IDE_ERROR_ICRC)*/) {
5003 if(AtaReq
->retry
< MAX_RETRIES
) {
5005 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5006 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5007 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5008 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5012 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5015 KdPrint2((PRINT_PREFIX
"Errors in PIO mode\n"));
5019 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
5020 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason
));
5022 if(DmaTransfer
&& (chan
->lun
[DeviceNumber
]->TransferMode
> ATA_UDMA2
) &&
5023 ((error
>> 4) == SCSI_SENSE_HARDWARE_ERROR
)) {
5024 if(AtaReq
->retry
< MAX_RETRIES
) {
5026 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5027 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5028 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5029 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5033 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5036 KdPrint3((PRINT_PREFIX
"Errors in PIO mode\n"));
5040 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error\n"));
5041 if (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
5042 // Fail this request.
5043 status
= SRB_STATUS_ERROR
;
5044 goto CompleteRequest
;
5046 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n"));
5049 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE_LBA48
) {
5050 KdPrint2((PRINT_PREFIX
"DMA doesn't work right with LBA48\n"));
5051 deviceExtension
->HbaCtrlFlags
|= HBAFLAGS_DMA_DISABLED_LBA48
;
5053 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
) {
5054 #ifdef IO_STATISTICS
5055 KdPrint2((PRINT_PREFIX
"Some higher mode doesn't work right :((\n"));
5056 KdPrint2((PRINT_PREFIX
"Recovery stats[%d]: %d vs %d\n",
5058 LunExt
->RecoverCount
[AtaReq
->retry
],
5059 LunExt
->BlockIoCount
5061 LunExt
->RecoverCount
[AtaReq
->retry
]++;
5062 if(LunExt
->RecoverCount
[AtaReq
->retry
] >= chan
->lun
[DeviceNumber
]->BlockIoCount
/3 ||
5063 (deviceExtension
->HwFlags
& UNIATA_NO80CHK
)
5066 if(deviceExtension
->HwFlags
& UNIATA_NO80CHK
) {
5067 #endif //IO_STATISTICS
5068 KdPrint2((PRINT_PREFIX
"Limit transfer rate to %x\n", LunExt
->TransferMode
));
5069 LunExt
->LimitedTransferMode
=
5070 LunExt
->TransferMode
;
5073 #ifdef IO_STATISTICS
5074 if(AtaReq
->bcount
) {
5075 // we need stats for Read/Write operations
5076 LunExt
->BlockIoCount
++;
5079 #endif //IO_STATISTICS
5083 // check reason for this interrupt.
5086 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI branch\n"));
5089 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & 0x3);
5090 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
5092 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5094 wordsThisInterrupt
= DEV_BSIZE
/2;
5102 // simulate DRQ for DMA transfers
5103 statusByte
|= IDE_STATUS_DRQ
;
5105 if (statusByte
& IDE_STATUS_DRQ
) {
5108 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5110 if (LunExt
->MaximumBlockXfer
) {
5111 wordsThisInterrupt
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5114 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5116 interruptReason
= 0x2;
5118 } else if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5119 interruptReason
= 0x0;
5122 status
= SRB_STATUS_ERROR
;
5123 goto CompleteRequest
;
5126 } else if (statusByte
& IDE_STATUS_BUSY
) {
5128 //AtapiEnableInterrupts(deviceExtension, lChannel);
5129 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
5134 if (AtaReq
->WordsLeft
) {
5136 // Funky behaviour seen with PCI IDE (not all, just one).
5138 // The ISR hits with DRQ low, but comes up later.
5139 for (k
= 0; k
< 5000; k
++) {
5140 GetBaseStatus(chan
, statusByte
);
5141 if (statusByte
& IDE_STATUS_DRQ
) {
5146 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ0
;
5148 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq0)\n"));
5152 AtapiStallExecution(TimerValue
);
5153 goto ServiceInterrupt
;
5154 #endif //UNIATA_CORE
5156 AtapiStallExecution(100);
5159 // reset the controller.
5160 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
5162 IntrPrepareResetController
:
5163 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
);
5164 goto ReturnEnableIntr
;
5167 interruptReason
= (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? 0x2 : 0x0;
5171 // Command complete - verify, write, or the SMART enable/disable.
5172 // Also get_media_status
5173 interruptReason
= 0x3;
5178 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason
, statusByte
));
5179 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5180 KdPrint2((PRINT_PREFIX
" AHCI path, WordsTransfered %x, WordsLeft %x\n", AtaReq
->WordsTransfered
, AtaReq
->WordsLeft
));
5181 /* if(chan->AhciLastIS & ATA_AHCI_P_IX_OF) {
5182 //status = SRB_STATUS_DATA_OVERRUN;
5185 status = SRB_STATUS_SUCCESS;
5187 if(AtaReq
->WordsTransfered
>= AtaReq
->WordsLeft
) {
5188 AtaReq
->WordsLeft
= 0;
5190 AtaReq
->WordsLeft
-= AtaReq
->WordsTransfered
;
5192 //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
5193 // status = SRB_STATUS_DATA_OVERRUN;
5195 status
= SRB_STATUS_SUCCESS
;
5196 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5197 goto CompleteRequest
;
5199 if (interruptReason
== 0x1 && (statusByte
& IDE_STATUS_DRQ
)) {
5200 // Write the packet.
5201 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Writing Atapi packet.\n"));
5202 // Send CDB to device.
5203 WriteBuffer(chan
, (PUSHORT
)srb
->Cdb
,
5204 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
5206 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5208 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
5209 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: AtapiDmaStart().\n"));
5210 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, srb
);
5213 goto ReturnEnableIntr
;
5215 } else if (interruptReason
== 0x0 && (statusByte
& IDE_STATUS_DRQ
)) {
5220 // Pick up bytes to transfer and convert to words.
5222 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
5225 (USHORT
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
5227 // Covert bytes to words.
5229 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get W wordCount %#x\n", wordCount
));
5231 if (wordCount
!= AtaReq
->WordsLeft
) {
5232 KdPrint2((PRINT_PREFIX
5233 "AtapiInterrupt: %d words requested; %d words xferred\n",
5238 // Verify this makes sense.
5239 if (wordCount
> AtaReq
->WordsLeft
) {
5240 wordCount
= AtaReq
->WordsLeft
;
5241 KdPrint2((PRINT_PREFIX
5242 "AtapiInterrupt: Write underrun\n"));
5248 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
5249 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5250 // Transfer only words requested.
5251 wordCount
= AtaReq
->WordsLeft
;
5253 // Transfer next block.
5254 wordCount
= wordsThisInterrupt
;
5259 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5260 //ASSERT(AtaReq->WordsLeft == wordCount);
5261 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5262 KdPrint2((PRINT_PREFIX
5263 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5264 if(AtaReq
->WordsLeft
> wordCount
) {
5265 AtaReq
->WordsLeft
-= wordCount
;
5266 AtaReq
->WordsTransfered
+= wordCount
;
5267 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5268 goto ReturnEnableIntr
;
5270 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5272 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5273 AtaReq
->WordsLeft
= 0;
5274 status
= SRB_STATUS_SUCCESS
;
5275 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5276 goto CompleteRequest
;
5279 // Ensure that this is a write command.
5280 if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5282 KdPrint2((PRINT_PREFIX
5283 "AtapiInterrupt: Write interrupt\n"));
5285 statusByte
= WaitOnBusy(chan
);
5287 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
5292 UniataGetPioTiming(LunExt
));
5296 (PULONG
)(AtaReq
->DataBuffer
),
5298 UniataGetPioTiming(LunExt
));
5302 KdPrint3((PRINT_PREFIX
5303 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5307 // Fail this request.
5308 status
= SRB_STATUS_ERROR
;
5309 goto CompleteRequest
;
5311 // Advance data buffer pointer and bytes left.
5312 AtaReq
->DataBuffer
+= wordCount
;
5313 AtaReq
->WordsLeft
-= wordCount
;
5314 AtaReq
->WordsTransfered
+= wordCount
;
5317 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5320 goto ReturnEnableIntr
;
5322 } else if (interruptReason
== 0x2 && (statusByte
& IDE_STATUS_DRQ
)) {
5327 // Pick up bytes to transfer and convert to words.
5329 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
) |
5330 (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8);
5332 // Convert bytes to words.
5334 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get R wordCount %#x\n", wordCount
));
5336 if (wordCount
!= AtaReq
->WordsLeft
) {
5337 KdPrint2((PRINT_PREFIX
5338 "AtapiInterrupt: %d words requested; %d words xferred\n",
5343 // Verify this makes sense.
5344 if (wordCount
> AtaReq
->WordsLeft
) {
5345 wordCount
= AtaReq
->WordsLeft
;
5351 // Check if words left is at least 256.
5352 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5353 // Transfer only words requested.
5354 wordCount
= AtaReq
->WordsLeft
;
5356 // Transfer next block.
5357 wordCount
= wordsThisInterrupt
;
5362 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5363 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5364 KdPrint2((PRINT_PREFIX
5365 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5366 if(AtaReq
->WordsLeft
> wordCount
) {
5367 AtaReq
->WordsLeft
-= wordCount
;
5368 AtaReq
->WordsTransfered
+= wordCount
;
5369 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5370 goto ReturnEnableIntr
;
5372 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5374 //ASSERT(AtaReq->WordsLeft == wordCount);
5375 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5376 AtaReq
->WordsLeft
= 0;
5377 status
= SRB_STATUS_SUCCESS
;
5378 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5379 goto CompleteRequest
;
5381 // Ensure that this is a read command.
5382 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5385 "AtapiInterrupt: Read interrupt\n"));*/
5387 statusByte
= WaitOnBusy(chan
);
5389 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
5390 KdPrint2((PRINT_PREFIX
5391 "IdeIntr: Read %#x words\n", wordCount
));
5396 UniataGetPioTiming(LunExt
));
5397 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)-1) ));
5398 //KdDump(AtaReq->DataBuffer, wordCount*2);
5399 if(srb
&& atapiDev
&& srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
5400 KdDump(AtaReq
->DataBuffer
, wordCount
*2);
5403 GetBaseStatus(chan
, statusByte
);
5404 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
5407 KdPrint2((PRINT_PREFIX
" DataOverrun\n"));
5408 AtapiSuckPort2(chan
);
5409 GetBaseStatus(chan
, statusByte
);
5412 if(statusByte
& IDE_STATUS_BUSY
) {
5413 for (i
= 0; i
< 2; i
++) {
5414 AtapiStallExecution(10);
5415 GetBaseStatus(chan
, statusByte
);
5416 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5423 KdPrint2((PRINT_PREFIX
5424 "IdeIntr: Read %#x Dwords\n", wordCount
/2));
5427 (PULONG
)(AtaReq
->DataBuffer
),
5429 UniataGetPioTiming(LunExt
));
5433 KdPrint3((PRINT_PREFIX
5434 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5438 // Fail this request.
5439 status
= SRB_STATUS_ERROR
;
5440 goto CompleteRequest
;
5443 // Advance data buffer pointer and bytes left.
5444 AtaReq
->DataBuffer
+= wordCount
;
5445 AtaReq
->WordsLeft
-= wordCount
;
5446 AtaReq
->WordsTransfered
+= wordCount
;
5448 // Check for read command complete.
5449 if (AtaReq
->WordsLeft
== 0) {
5451 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
5454 // Work around to make many atapi devices return correct sector size
5455 // of 2048. Also certain devices will have sector count == 0x00, check
5457 if ((srb
->Cdb
[0] == SCSIOP_READ_CAPACITY
) &&
5458 (LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
)) {
5460 AtaReq
->DataBuffer
-= wordCount
;
5461 if (AtaReq
->DataBuffer
[0] == 0x00) {
5463 *((ULONG
*) &(AtaReq
->DataBuffer
[0])) = 0xFFFFFF7F;
5467 *((ULONG
*) &(AtaReq
->DataBuffer
[2])) = 0x00080000;
5468 AtaReq
->DataBuffer
+= wordCount
;
5471 GetStatus(chan
, statusByte
);
5472 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5473 // Assume command is completed if BUSY is cleared
5474 // and all data read
5475 // Optionally, we may receive COMPLETE interrupt later and
5476 // treat it as unexpected
5477 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete ? status %x\n", statusByte
));
5479 status
= SRB_STATUS_SUCCESS
;
5480 goto CompleteRequest
;
5486 // Completion for IDE drives.
5487 if (AtaReq->WordsLeft) {
5488 status = SRB_STATUS_DATA_OVERRUN;
5490 status = SRB_STATUS_SUCCESS;
5493 goto CompleteRequest;
5495 status
= SRB_STATUS_SUCCESS
;
5496 goto CompleteRequest
;
5501 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5502 GetStatus(chan
, statusByte
);
5503 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5504 // Assume command is completed if BUSY is cleared
5505 // even if NOT all data read
5506 // Optionally, we may receive COMPLETE interrupt later and
5507 // treat it as unexpected
5508 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete + underrun ? status %x\n", statusByte
));
5510 status
= SRB_STATUS_SUCCESS
;
5511 goto CompleteRequest
;
5516 goto ReturnEnableIntr
;
5518 } else if (interruptReason
== 0x3 && !(statusByte
& IDE_STATUS_DRQ
)) {
5520 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: interruptReason = CompleteRequest\n"));
5521 // Command complete.
5523 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
5524 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5525 AtaReq
->WordsLeft
= 0;
5527 //if (AtaReq->WordsLeft) {
5528 // status = SRB_STATUS_DATA_OVERRUN;
5530 status
= SRB_STATUS_SUCCESS
;
5533 #ifdef UNIATA_DUMP_ATAPI
5535 srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5539 PCHAR ModeSelectData
;
5541 PSCSI_REQUEST_BLOCK Srb
= srb
;
5543 Cdb
= (PCDB
)(Srb
->Cdb
);
5544 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
5545 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
5546 CdbDataLen
= Srb
->DataTransferLength
;
5548 if(CdbDataLen
> 0x1000) {
5549 CdbDataLen
= 0x1000;
5553 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
5554 KdPrint2(("P:T:D=%d:%d:%d\n",
5558 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand
));
5561 if(ScsiCommand
== SCSIOP_MODE_SENSE
) {
5562 KdPrint(("ModeSense 6\n"));
5563 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5564 ModeSelectData
= CdbData
+4;
5565 KdDump(CdbData
, CdbDataLen
);
5567 if(ScsiCommand
== SCSIOP_MODE_SENSE10
) {
5568 KdPrint(("ModeSense 10\n"));
5569 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5570 ModeSelectData
= CdbData
+8;
5571 KdDump(CdbData
, CdbDataLen
);
5573 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5574 KdPrint(("Read buffer from device:\n"));
5575 KdDump(CdbData
, CdbDataLen
);
5580 #endif //UNIATA_DUMP_ATAPI
5584 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, srbstatus %x\n", status
));
5585 // Check and see if we are processing our secret (mechanism status/request sense) srb
5587 if(AtaReq
->WordsLeft
&& (status
== SRB_STATUS_SUCCESS
)) {
5588 KdPrint2((PRINT_PREFIX
"WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq
->WordsLeft
));
5589 status
= SRB_STATUS_DATA_OVERRUN
;
5592 if (AtaReq
->OriginalSrb
) {
5596 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: OriginalSrb != NULL\n"));
5597 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
5599 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
5600 if (status
== SRB_STATUS_SUCCESS
) {
5602 AtapiHwInitializeChanger (HwDeviceExtension
,
5604 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
5606 // Get ready to issue the original srb
5607 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5608 AtaReq
->OriginalSrb
= NULL
;
5611 // failed! Get the sense key and maybe try again
5612 srb
= AtaReq
->Srb
= BuildRequestSenseSrb (
5614 AtaReq
->OriginalSrb
);
5617 // do not enable interrupts in DPC, do not waste time, do it now!
5618 if(UseDpc && chan->DisableIntr) {
5619 AtapiEnableInterrupts(HwDeviceExtension, c);
5621 RestoreUseDpc = TRUE;
5624 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
5626 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
5628 if (srbStatus
== SRB_STATUS_PENDING
) {
5629 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
5630 goto ReturnEnableIntr
;
5634 // restore state on error
5636 AtapiDisableInterrupts(HwDeviceExtension, c);
5640 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
5642 PSENSE_DATA senseData
= (PSENSE_DATA
) srb
->DataBuffer
;
5644 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI command status %#x\n", status
));
5645 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5646 // Check to see if we at least get mininum number of bytes
5647 if ((srb
->DataTransferLength
- AtaReq
->WordsLeft
) >
5648 (FIELD_OFFSET (SENSE_DATA
, AdditionalSenseLength
) + sizeof(senseData
->AdditionalSenseLength
))) {
5649 status
= SRB_STATUS_SUCCESS
;
5653 if (status
== SRB_STATUS_SUCCESS
) {
5655 if ((senseData
->SenseKey
!= SCSI_SENSE_ILLEGAL_REQUEST
) &&
5656 chan
->MechStatusRetryCount
) {
5658 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: MechStatusRetryCount %#x\n", chan
->MechStatusRetryCount
));
5659 // The sense key doesn't say the last request is illegal, so try again
5660 chan
->MechStatusRetryCount
--;
5661 srb
= AtaReq
->Srb
= BuildMechanismStatusSrb (
5663 AtaReq
->OriginalSrb
);
5666 // last request was illegal. No point trying again
5667 AtapiHwInitializeChanger (HwDeviceExtension
,
5669 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
5671 // Get ready to issue the original srb
5672 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5673 AtaReq
->OriginalSrb
= NULL
;
5675 #endif //UNIATA_CORE
5677 // do not enable interrupts in DPC, do not waste time, do it now!
5678 if(UseDpc && chan->DisableIntr) {
5679 AtapiEnableInterrupts(HwDeviceExtension, c);
5681 RestoreUseDpc = TRUE;
5684 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
5686 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan
->ExpectingInterrupt
));
5688 if (srbStatus
== SRB_STATUS_PENDING
) {
5689 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
5690 goto ReturnEnableIntr
;
5694 // restore state on error
5696 AtapiDisableInterrupts(HwDeviceExtension, c);
5702 // If we get here, it means AtapiSendCommand() has failed
5703 // Can't recover. Pretend the original srb has failed and complete it.
5705 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. complete OriginalSrb\n"));
5707 if (AtaReq
->OriginalSrb
) {
5708 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
5709 AtapiHwInitializeChanger (HwDeviceExtension
,
5711 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
5712 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5713 AtaReq
->OriginalSrb
= NULL
;
5716 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan
->ExpectingInterrupt
));
5718 // fake an error and read no data
5719 status
= SRB_STATUS_ERROR
;
5720 srb
->ScsiStatus
= 0;
5721 AtaReq
->DataBuffer
= (PUSHORT
)(srb
->DataBuffer
);
5722 AtaReq
->WordsLeft
= srb
->DataTransferLength
;
5725 } else if (status
== SRB_STATUS_ERROR
) {
5727 // Map error to specific SRB status and handle request sense.
5728 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. Begin mapping...\n"));
5729 status
= MapError(deviceExtension
,
5734 } else if(!DmaTransfer
) {
5736 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion\n"));
5737 // Command complete.
5739 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion, wait BUSY\n"));
5740 // Wait for busy to drop.
5741 for (i
= 0; i
< 5*30; i
++) {
5742 GetBaseStatus(chan
, statusByte
);
5743 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5748 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY
;
5750 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (busy)\n"));
5754 AtapiStallExecution(TimerValue
);
5755 goto ServiceInterrupt
;
5756 #endif //UNIATA_CORE
5758 AtapiStallExecution(100);
5763 // reset the controller.
5764 KdPrint2((PRINT_PREFIX
5765 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
5767 goto IntrPrepareResetController
;
5769 // Check to see if DRQ is still up.
5770 if(statusByte
& IDE_STATUS_DRQ
) {
5771 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DRQ...\n"));
5773 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5774 KdPrint2((PRINT_PREFIX
"srb %x data in\n", srb
));
5776 KdPrint2((PRINT_PREFIX
"srb %x data out\n", srb
));
5779 KdPrint2((PRINT_PREFIX
"srb NULL\n"));
5782 KdPrint2((PRINT_PREFIX
"AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq
, AtaReq
->WordsLeft
));
5784 KdPrint2((PRINT_PREFIX
"AtaReq NULL\n"));
5786 if(AtaReq
&& AtaReq
->WordsLeft
/*&&
5787 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
5788 KdPrint2((PRINT_PREFIX
"DRQ+AtaReq->WordsLeft -> next portion\n"));
5792 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
5793 //if ((statusByte & IDE_STATUS_DRQ)) {}
5794 if((statusByte
& IDE_STATUS_DRQ
) &&
5795 (LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_TAPE_DEVICE
| DFLAGS_LBA_ENABLED
)) ) {
5798 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO_wait_DRQ\n"));
5799 for (i
= 0; i
< 200; i
++) {
5800 GetBaseStatus(chan
, statusByte
);
5801 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5806 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq)\n"));
5807 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ
;
5812 AtapiStallExecution(TimerValue
);
5813 goto ServiceInterrupt
;
5814 #endif //UNIATA_CORE
5816 AtapiStallExecution(100);
5820 // reset the controller.
5821 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
5823 goto IntrPrepareResetController
;
5827 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
5828 AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)(-1)), srb
->DataTransferLength
));
5829 //KdDump(srb->DataBuffer, srb->DataTransferLength);
5831 if(!AtapiDmaPioSync(HwDeviceExtension
, srb
, (PUCHAR
)(srb
->DataBuffer
), srb
->DataTransferLength
)) {
5832 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
5836 // Clear interrupt expecting flag.
5837 UniataExpectChannelInterrupt(chan
, FALSE
);
5838 // clear this flag now, it can be set again in sub-calls
5839 InterlockedExchange(&(chan
->CheckIntr
),
5842 // Sanity check that there is a current request.
5844 // Set status in SRB.
5845 srb
->SrbStatus
= (UCHAR
)status
;
5847 // Check for underflow.
5848 if(AtaReq
->WordsLeft
) {
5850 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq
->WordsLeft
));
5851 // Subtract out residual words and update if filemark hit,
5852 // setmark hit , end of data, end of media...
5853 if (!(LunExt
->DeviceFlags
& DFLAGS_TAPE_DEVICE
)) {
5854 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5855 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5857 srb
->DataTransferLength
= 0;
5860 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5863 if(status
== SRB_STATUS_SUCCESS
) {
5864 //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) {
5865 // // This should be set in UniataAhciEndTransaction() for AHCI
5866 // AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
5869 AtaReq
->WordsTransfered
*2 < AtaReq
->TransferLength
) {
5870 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
5871 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5872 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5873 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_NEXT
;
5876 KdPrint2((PRINT_PREFIX
" Transfered %x, full size %x\n",
5877 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5881 if (srb
->Function
!= SRB_FUNCTION_IO_CONTROL
) {
5884 // Indicate command complete.
5886 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete\n"));
5889 if (status
== SRB_STATUS_SUCCESS
&&
5890 srb
->SenseInfoBuffer
&&
5891 srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
5893 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)srb
->SenseInfoBuffer
;
5895 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: set AutoSense\n"));
5896 senseBuffer
->ErrorCode
= 0;
5897 senseBuffer
->Valid
= 1;
5898 senseBuffer
->AdditionalSenseLength
= 0xb;
5899 senseBuffer
->SenseKey
= 0;
5900 senseBuffer
->AdditionalSenseCode
= 0;
5901 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
5903 srb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
5905 AtapiDmaDBSync(chan
, srb
);
5906 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove srb %#x, status %x\n", srb
, status
));
5907 UniataRemoveRequest(chan
, srb
);
5908 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete, srb %#x\n", srb
));
5909 ScsiPortNotification(RequestComplete
,
5915 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: IOCTL completion\n"));
5917 if (status
!= SRB_STATUS_SUCCESS
) {
5918 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5919 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: error %#x\n", error
));
5922 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
5924 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5925 // Build the SMART status block depending upon the completion status.
5926 cmdOutParameters
->cBufferSize
= wordCount
;
5927 cmdOutParameters
->DriverStatus
.bDriverError
= (error
) ? SMART_IDE_ERROR
: 0;
5928 cmdOutParameters
->DriverStatus
.bIDEError
= error
;
5930 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
5932 if (chan
->SmartCommand
== RETURN_SMART_STATUS
) {
5933 PIDEREGS_EX regs
= (PIDEREGS_EX
)&(cmdOutParameters
->bBuffer
);
5936 UniataSnapAtaRegs(chan
, 0, regs
);
5938 regs
->bCommandReg
= SMART_CMD
;
5939 regs
->bFeaturesReg
= RETURN_SMART_STATUS
;
5941 cmdOutParameters
->cBufferSize
= 8;
5943 chan
->SmartCommand
= 0; // cleanup after execution
5945 // Indicate command complete.
5946 goto IntrCompleteReq
;
5951 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: No SRB!\n"));
5956 for (i
= 0; i
< 5; i
++) {
5957 GetBaseStatus(chan
, statusByte
);
5958 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5959 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RDP + cleared BUSY\n"));
5963 if (statusByte
& IDE_STATUS_DSC
) {
5964 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Clear RDP\n"));
5968 AtapiStallExecution(50);
5971 // RDP can be cleared since previous check
5973 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestTimerCall 2000\n"));
5979 AtapiStallExecution(TimerValue
);
5980 goto ServiceInterrupt
;
5981 #endif //UNIATA_CORE
5984 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
5987 srb
= UniataGetCurRequest(chan
);
5992 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: NextRequest, srb=%#x\n",srb
));
5994 ScsiPortNotification(NextRequest
,
5998 ScsiPortNotification(NextLuRequest
,
6003 // in simplex mode next command must NOT be sent here
6004 if(!deviceExtension
->simplexOnly
) {
6005 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6008 // Try to get SRB fron any non-empty queue (later)
6009 if(deviceExtension
->simplexOnly
) {
6012 #endif //UNIATA_CORE
6014 goto ReturnEnableIntr
;
6018 // Unexpected int. Catch it
6019 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
6023 if(OldReqState
== REQ_STATE_DPC_WAIT_BUSY0
&&
6024 AtaReq
->WordsLeft
== 0) {
6025 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: pending WAIT_BUSY0. Complete.\n"));
6026 status
= SRB_STATUS_SUCCESS
;
6027 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6028 goto CompleteRequest
;
6034 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ReturnEnableIntr\n",srb
));
6035 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6036 deviceExtension
->ExpectingInterrupt
= TRUE
;
6038 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
6039 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
6040 #ifdef UNIATA_USE_XXableInterrupts
6041 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
6042 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
6043 // must be called on DISPATCH_LEVEL
6044 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
6045 AtapiEnableInterrupts__
);
6047 AtapiEnableInterrupts(HwDeviceExtension
, c
);
6048 InterlockedExchange(&(chan
->CheckIntr
),
6050 // Will raise IRQL to DIRQL
6052 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
6053 AtapiEnableInterrupts__
,
6055 #endif // UNIATA_CORE
6056 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
6057 #endif // UNIATA_USE_XXableInterrupts
6061 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
6062 // in simplex mode next command must be sent here if
6064 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc
, NoStartIo
));
6067 if(!UseDpc
&& /*deviceExtension->simplexOnly &&*/ !NoStartIo
) {
6068 chan
= UniataGetNextChannel(chan
);
6070 srb
= UniataGetCurRequest(chan
);
6074 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: run srb %x\n", srb
));
6076 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6079 #endif //UNIATA_CORE
6082 } // end AtapiInterrupt__()
6088 Routine Description:
6090 This routine handles SMART enable, disable, read attributes and threshold commands.
6094 HwDeviceExtension - HBA miniport driver's adapter data storage
6095 Srb - IO request packet
6104 IdeSendSmartCommand(
6105 IN PVOID HwDeviceExtension
,
6106 IN PSCSI_REQUEST_BLOCK Srb
,
6107 IN ULONG targetId
// assume it is always valid
6110 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6111 ULONG c
; // = GET_CHANNEL(Srb); may be invalid
6112 PHW_CHANNEL chan
; // = &(deviceExtension->chan[c]);
6113 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6114 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6115 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6116 PIDEREGS regs
= &cmdInParameters
.irDriveRegs
;
6121 if (regs
->bCommandReg
!= SMART_CMD
) {
6122 KdPrint2((PRINT_PREFIX
6123 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
6124 return SRB_STATUS_INVALID_REQUEST
;
6127 c
= targetId
/ deviceExtension
->NumberLuns
;
6128 DeviceNumber
= targetId
% deviceExtension
->NumberLuns
;
6129 KdPrint2((PRINT_PREFIX
" c %d, dev %d\n", c
, DeviceNumber
));
6131 chan
= &(deviceExtension
->chan
[c
]);
6133 chan
->SmartCommand
= regs
->bFeaturesReg
;
6135 // Determine which of the commands to carry out.
6136 switch(regs
->bFeaturesReg
) {
6137 case READ_ATTRIBUTES
:
6138 case READ_THRESHOLDS
:
6139 case READ_LOG_SECTOR
:
6140 case WRITE_LOG_SECTOR
:
6142 if(Srb
->DataTransferLength
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1) {
6143 KdPrint2((PRINT_PREFIX
6144 "IdeSendSmartCommand: wrong buffer size\n"));
6145 return SRB_STATUS_DATA_OVERRUN
;
6148 statusByte
= WaitOnBusy(chan
);
6150 if (statusByte
& IDE_STATUS_BUSY
) {
6151 KdPrint2((PRINT_PREFIX
6152 "IdeSendSmartCommand: Returning BUSY status\n"));
6153 return SRB_STATUS_BUSY
;
6156 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6157 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1);
6159 // Set data buffer pointer and words left.
6160 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6161 AtaReq
->WordsLeft
= READ_ATTRIBUTE_BUFFER_SIZE
/ 2;
6163 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6165 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6167 regs
->bSectorNumberReg
,
6168 regs
->bSectorCountReg
,
6172 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6173 // Wait for interrupt.
6174 return SRB_STATUS_PENDING
;
6176 return SRB_STATUS_ERROR
;
6180 case RETURN_SMART_STATUS
:
6181 case ENABLE_DISABLE_AUTOSAVE
:
6182 case EXECUTE_OFFLINE_DIAGS
:
6183 case SAVE_ATTRIBUTE_VALUES
:
6186 statusByte
= WaitOnBusy(chan
);
6188 if (statusByte
& IDE_STATUS_BUSY
) {
6189 KdPrint2((PRINT_PREFIX
6190 "IdeSendSmartCommand: Returning BUSY status\n"));
6191 return SRB_STATUS_BUSY
;
6194 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6195 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) - 1);
6197 // Set data buffer pointer and indicate no data transfer.
6198 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6199 AtaReq
->WordsLeft
= 0;
6201 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6203 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6205 regs
->bSectorNumberReg
,
6206 regs
->bSectorCountReg
,
6210 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6211 // Wait for interrupt.
6212 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6213 return SRB_STATUS_PENDING
;
6215 return SRB_STATUS_ERROR
;
6216 } // end switch(regs->bFeaturesReg)
6218 return SRB_STATUS_INVALID_REQUEST
;
6220 } // end IdeSendSmartCommand()
6222 #endif //UNIATA_CORE
6226 UniAtaCalculateLBARegs(
6227 PHW_LU_EXTENSION LunExt
,
6228 ULONGLONG startingSector
,
6232 UCHAR drvSelect
,sectorNumber
;
6236 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6237 if(LunExt
->LimitedTransferMode
>= ATA_DMA
) {
6238 if(LunExt
->DeviceExtension
) {
6239 (*max_bcount
) = LunExt
->DeviceExtension
->MaximumDmaTransferLength
/ DEV_BSIZE
;
6242 return startingSector
;
6244 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6245 LunExt
->IdentifyData
.NumberOfHeads
;
6247 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
6251 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
;
6253 cylinder
= (USHORT
)(startingSector
/ tmp
);
6254 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
6255 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
6256 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
- sectorNumber
+ 1;
6257 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
6258 cylinder
, drvSelect
, sectorNumber
, (*max_bcount
)));
6262 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
6263 } // end UniAtaCalculateLBARegs()
6267 UniAtaCalculateLBARegsBack(
6268 PHW_LU_EXTENSION LunExt
,
6272 ULONG drvSelect
,sectorNumber
;
6276 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6279 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6280 LunExt
->IdentifyData
.NumberOfHeads
;
6282 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
6283 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
6284 sectorNumber
= (UCHAR
)(lba
& 0xff);
6286 lba
= sectorNumber
-1 +
6287 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
6291 } // end UniAtaCalculateLBARegsBack()
6296 Routine Description:
6298 This routine handles IDE read and writes.
6302 HwDeviceExtension - HBA miniport driver's adapter data storage
6303 Srb - IO request packet
6313 IN PVOID HwDeviceExtension
,
6314 IN PSCSI_REQUEST_BLOCK Srb
,
6318 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6319 UCHAR lChannel
= GET_CHANNEL(Srb
);
6320 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6321 PHW_LU_EXTENSION LunExt
;
6322 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6323 //ULONG ldev = GET_LDEV(Srb);
6324 UCHAR DeviceNumber
= GET_CDEV(Srb
);;
6325 ULONGLONG startingSector
=0;
6327 ULONG wordCount
= 0;
6328 UCHAR statusByte
,statusByte2
;
6331 BOOLEAN use_dma
= FALSE
;
6334 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6335 LunExt
= chan
->lun
[DeviceNumber
];
6337 if((CmdAction
& CMD_ACTION_PREPARE
) &&
6338 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
6340 if(LunExt
->opt_ReadOnly
&&
6341 (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) {
6342 if(LunExt
->opt_ReadOnly
== 1) {
6343 KdPrint2((PRINT_PREFIX
"Abort WRITE (Soft R/O)\n"));
6344 return SRB_STATUS_ERROR
;
6346 KdPrint2((PRINT_PREFIX
"Ignore WRITE (Soft R/O)\n"));
6347 return SRB_STATUS_SUCCESS
;
6351 // Set data buffer pointer and words left.
6352 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6354 if(AtaReq
->WordsTransfered
) {
6355 AtaReq
->DataBuffer
= ((PUSHORT
)(Srb
->DataBuffer
)) + AtaReq
->WordsTransfered
;
6356 startingSector
= (UniAtaCalculateLBARegsBack(LunExt
, AtaReq
->lba
)) /* latest lba */ + AtaReq
->bcount
/* previous bcount */;
6357 AtaReq
->bcount
= (AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2 + DEV_BSIZE
-1) / DEV_BSIZE
;
6358 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Chained REQ): Starting sector %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
6360 AtaReq
->TransferLength
/2,
6361 AtaReq
->WordsTransfered
,
6364 AtaReq
->DataBuffer
= (PUSHORT
)(Srb
->DataBuffer
);
6365 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
6366 // Set up 1st block.
6367 switch(Srb
->Cdb
[0]) {
6370 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6371 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6374 case SCSIOP_WRITE12
:
6375 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
6376 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6379 case SCSIOP_WRITE16
:
6380 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6381 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6384 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Orig REQ): Starting sector %I64x, OrigWordsRequested %#x, DevSize %#x\n",
6386 AtaReq
->TransferLength
/2,
6389 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6392 AtaReq
->bcount
= min(AtaReq
->bcount
, max_bcount
);
6394 AtaReq
->WordsLeft
= min(AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2,
6395 AtaReq
->bcount
* DEV_BSIZE
) / 2;
6397 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n",
6404 // assume best case here
6405 // we cannot reinit Dma until previous request is completed
6406 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6407 UniataAhciSetupCmdPtr(AtaReq
);
6408 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6409 (PUCHAR
)(AtaReq
->DataBuffer
),
6410 AtaReq
->bcount
* DEV_BSIZE
)) {
6411 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !DMA\n"));
6412 return SRB_STATUS_ERROR
;
6415 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
6417 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6418 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6419 (PUCHAR
)(AtaReq
->DataBuffer
),
6420 AtaReq
->bcount
* DEV_BSIZE
)) {
6425 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6426 KdPrint2((PRINT_PREFIX
"IdeReadWrite: setup AHCI FIS\n"));
6427 RtlZeroMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
), sizeof(AtaReq
->ahci_cmd0
.cfis
));
6429 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
6430 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
6431 (AtaReq
->Flags
& REQ_FLAG_READ
) ? IDE_COMMAND_READ_DMA
: IDE_COMMAND_WRITE_DMA
,
6433 (USHORT
)(AtaReq
->bcount
),
6435 /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/
6439 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !FIS\n"));
6440 return SRB_STATUS_ERROR
;
6443 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0, (AtaReq
->Flags
& REQ_FLAG_READ
) ? 0 : ATA_AHCI_CMD_WRITE
, fis_size
, DeviceNumber
);
6444 KdPrint2((PRINT_PREFIX
"IdeReadWrite ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
6447 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
6449 } else { // exec_only
6450 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
6453 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6457 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
6459 return SRB_STATUS_PENDING
;
6462 // if this is queued request, reinit DMA and check
6463 // if DMA mode is still available
6464 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
6465 if (/*EnableDma &&*/
6466 (LunExt
->TransferMode
>= ATA_DMA
)) {
6469 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6473 // Check if write request.
6474 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6476 // Prepare read command.
6478 cmd
= IDE_COMMAND_READ_DMA
;
6480 if(LunExt
->MaximumBlockXfer
) {
6481 cmd
= IDE_COMMAND_READ_MULTIPLE
;
6483 cmd
= IDE_COMMAND_READ
;
6487 // Prepare write command.
6489 wordCount
= AtaReq
->bcount
*DEV_BSIZE
/2;
6490 cmd
= IDE_COMMAND_WRITE_DMA
;
6492 if (LunExt
->MaximumBlockXfer
) {
6493 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
6495 if (AtaReq
->WordsLeft
< wordCount
) {
6496 // Transfer only words requested.
6497 wordCount
= AtaReq
->WordsLeft
;
6499 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
6502 wordCount
= DEV_BSIZE
/2;
6503 cmd
= IDE_COMMAND_WRITE
;
6508 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
6509 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
6511 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
6513 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6516 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6517 // AHCI doesn't distinguish DMA and PIO
6518 //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
6519 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
6520 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6521 InterlockedExchange(&(chan
->CheckIntr
),
6523 return SRB_STATUS_PENDING
;
6526 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
6528 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
6530 (USHORT
)(AtaReq
->bcount
),
6531 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6533 if(statusByte2
!= IDE_STATUS_WRONG
) {
6534 GetStatus(chan
, statusByte2
);
6536 if(statusByte2
& IDE_STATUS_ERROR
) {
6537 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6538 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
6539 return SRB_STATUS_ERROR
;
6542 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
6544 return SRB_STATUS_PENDING
;
6547 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
6549 (USHORT
)(AtaReq
->bcount
),
6550 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6553 if (!(statusByte
& IDE_STATUS_DRQ
) ||
6554 statusByte
== IDE_STATUS_WRONG
) {
6556 if(statusByte
== IDE_STATUS_WRONG
) {
6557 KdPrint2((PRINT_PREFIX
6558 "IdeReadWrite: error sending command (%#x)\n",
6561 KdPrint2((PRINT_PREFIX
6562 "IdeReadWrite: DRQ never asserted (%#x)\n",
6566 AtaReq
->WordsLeft
= 0;
6568 // Clear interrupt expecting flag.
6569 UniataExpectChannelInterrupt(chan
, FALSE
);
6570 InterlockedExchange(&(chan
->CheckIntr
),
6573 // Clear current SRB.
6574 UniataRemoveRequest(chan
, Srb
);
6576 return (statusByte
== IDE_STATUS_WRONG
) ? SRB_STATUS_ERROR
: SRB_STATUS_TIMEOUT
;
6579 UniataExpectChannelInterrupt(chan
, TRUE
);
6580 InterlockedExchange(&(chan
->CheckIntr
),
6583 // Write next DEV_BSIZE/2*N words.
6584 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
)) {
6585 KdPrint2((PRINT_PREFIX
6586 "IdeReadWrite: Write %#x words\n", wordCount
));
6591 UniataGetPioTiming(LunExt
));
6595 KdPrint2((PRINT_PREFIX
6596 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
6599 (PULONG
)(AtaReq
->DataBuffer
),
6601 UniataGetPioTiming(LunExt
));
6604 // Adjust buffer address and words left count.
6605 AtaReq
->WordsLeft
-= wordCount
;
6606 AtaReq
->DataBuffer
+= wordCount
;
6608 // Wait for interrupt.
6609 return SRB_STATUS_PENDING
;
6611 } // end IdeReadWrite()
6617 Routine Description:
6618 This routine handles IDE Verify.
6621 HwDeviceExtension - HBA miniport driver's adapter data storage
6622 Srb - IO request packet
6631 IN PVOID HwDeviceExtension
,
6632 IN PSCSI_REQUEST_BLOCK Srb
6635 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6636 UCHAR lChannel
= GET_CHANNEL(Srb
);
6637 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6638 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6639 PHW_LU_EXTENSION LunExt
;
6640 //ULONG ldev = GET_LDEV(Srb);
6641 ULONG DeviceNumber
= GET_CDEV(Srb
);
6643 ULONGLONG startingSector
=0;
6646 ULONGLONG endSector
;
6647 ULONG sectorCount
=0;
6650 LunExt
= chan
->lun
[DeviceNumber
];
6651 // Drive has these number sectors.
6652 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
6653 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
6654 LunExt
->IdentifyData
.NumberOfHeads
*
6655 LunExt
->IdentifyData
.NumberOfCylinders
;
6658 KdPrint2((PRINT_PREFIX
6659 "IdeVerify: Total sectors %#x\n",
6662 // Get starting sector number from CDB.
6663 switch(Srb
->Cdb
[0]) {
6665 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6666 MOV_SWP_DW2DD(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6668 case SCSIOP_VERIFY12
:
6669 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
6670 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6672 case SCSIOP_VERIFY16
:
6673 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6674 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6678 KdPrint2((PRINT_PREFIX
6679 "IdeVerify: Starting sector %#I64x. Number of blocks %#x\n",
6683 endSector
= startingSector
+ sectorCount
;
6685 KdPrint2((PRINT_PREFIX
6686 "IdeVerify: Ending sector %#I64x\n",
6689 if (endSector
> sectors
) {
6691 // Too big, round down.
6692 KdPrint2((PRINT_PREFIX
6693 "IdeVerify: Truncating request to %#x blocks\n",
6694 sectors
- startingSector
- 1));
6696 sectorCount
= (ULONG
)(sectors
- startingSector
- 1);
6700 // Set up sector count register. Round up to next block.
6701 if (sectorCount
> 0xFF) {
6702 sectorCount
= (USHORT
)0xFF;
6706 // Set data buffer pointer and words left.
6707 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
6708 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
6710 // Indicate expecting an interrupt.
6711 InterlockedExchange(&(chan
->CheckIntr
),
6714 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6716 statusByte
= AtaCommand48(deviceExtension
, LunExt
->Lun
, GET_CHANNEL(Srb
),
6717 IDE_COMMAND_VERIFY
, lba
,
6718 (USHORT
)sectorCount
,
6721 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6722 // Wait for interrupt.
6723 return SRB_STATUS_PENDING
;
6725 return SRB_STATUS_ERROR
;
6727 } // end IdeVerify()
6729 #endif //UNIATA_CORE
6733 Routine Description:
6734 Send ATAPI packet command to device.
6737 HwDeviceExtension - HBA miniport driver's adapter data storage
6738 Srb - IO request packet
6746 IN PVOID HwDeviceExtension
,
6747 IN PSCSI_REQUEST_BLOCK Srb
,
6751 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6752 UCHAR lChannel
= GET_CHANNEL(Srb
);
6753 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6754 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6755 PHW_LU_EXTENSION LunExt
;
6756 //ULONG ldev = GET_LDEV(Srb);
6757 ULONG DeviceNumber
= GET_CDEV(Srb
);
6759 UCHAR statusByte
,byteCountLow
,byteCountHigh
;
6760 BOOLEAN use_dma
= FALSE
;
6761 BOOLEAN dma_reinited
= FALSE
;
6762 BOOLEAN retried
= FALSE
;
6766 LunExt
= chan
->lun
[DeviceNumber
];
6768 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: req state %#x, Action %x\n", AtaReq
->ReqState
, CmdAction
));
6769 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
6770 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
6773 #ifdef UNIATA_DUMP_ATAPI
6774 if(CmdAction
& CMD_ACTION_PREPARE
) {
6778 PCHAR ModeSelectData
;
6781 Cdb
= (PCDB
)(Srb
->Cdb
);
6782 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
6783 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
6784 CdbDataLen
= Srb
->DataTransferLength
;
6786 if(CdbDataLen
> 0x1000) {
6787 CdbDataLen
= 0x1000;
6791 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
6792 KdPrint2(("P:T:D=%d:%d:%d\n",
6796 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
6799 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
6800 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
6801 Cdb
->WRITE_CD
.LBA
[0],
6802 Cdb
->WRITE_CD
.LBA
[1],
6803 Cdb
->WRITE_CD
.LBA
[2],
6804 Cdb
->WRITE_CD
.LBA
[3]
6807 if(ScsiCommand
== SCSIOP_WRITE12
) {
6808 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
6809 Cdb
->CDB12READWRITE
.LBA
[0],
6810 Cdb
->CDB12READWRITE
.LBA
[1],
6811 Cdb
->CDB12READWRITE
.LBA
[2],
6812 Cdb
->CDB12READWRITE
.LBA
[3]
6815 if(ScsiCommand
== SCSIOP_WRITE16
) {
6816 KdPrint(("Write16, LBA %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
6817 Cdb
->CDB16READWRITE
.LBA
[0],
6818 Cdb
->CDB16READWRITE
.LBA
[1],
6819 Cdb
->CDB16READWRITE
.LBA
[2],
6820 Cdb
->CDB16READWRITE
.LBA
[3],
6821 Cdb
->CDB16READWRITE
.LBA
[4],
6822 Cdb
->CDB16READWRITE
.LBA
[5],
6823 Cdb
->CDB16READWRITE
.LBA
[6],
6824 Cdb
->CDB16READWRITE
.LBA
[7]
6827 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
6828 KdPrint(("ModeSelect 6\n"));
6829 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6830 ModeSelectData
= CdbData
+4;
6831 KdDump(CdbData
, CdbDataLen
);
6833 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
6834 KdPrint(("ModeSelect 10\n"));
6835 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6836 ModeSelectData
= CdbData
+8;
6837 KdDump(CdbData
, CdbDataLen
);
6839 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
6840 KdPrint(("Send buffer to device:\n"));
6841 KdDump(CdbData
, CdbDataLen
);
6846 #endif //UNIATA_DUMP_ATAPI
6849 if(CmdAction
== CMD_ACTION_PREPARE
) {
6850 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb
->Cdb
)));
6852 switch (Srb
->Cdb
[0]) {
6853 case SCSIOP_RECEIVE
:
6858 case SCSIOP_WRITE12
:
6860 case SCSIOP_WRITE16
:
6864 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
6865 return SRB_STATUS_BUSY
;
6868 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6869 !AtaReq
->OriginalSrb
) {
6870 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
6871 return SRB_STATUS_BUSY
;
6876 // We need to know how many platters our atapi cd-rom device might have.
6877 // Before anyone tries to send a srb to our target for the first time,
6878 // we must "secretly" send down a separate mechanism status srb in order to
6879 // initialize our device extension changer data. That's how we know how
6880 // many platters our target has.
6882 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6883 !AtaReq
->OriginalSrb
) {
6887 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
6888 // Set this flag now. If the device hangs on the mech. status
6889 // command, we will not have the chance to set it.
6890 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
6892 chan
->MechStatusRetryCount
= 3;
6893 AtaReq
->OriginalSrb
= Srb
;
6894 AtaReq
->Srb
= BuildMechanismStatusSrb (
6898 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
6899 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
6900 if (srbStatus
== SRB_STATUS_PENDING
) {
6901 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
6904 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6905 AtaReq
->OriginalSrb
= NULL
;
6906 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiHwInitializeChanger()\n"));
6907 AtapiHwInitializeChanger (HwDeviceExtension
, Srb
,
6908 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
6912 #endif //UNIATA_CORE
6914 if((CmdAction
& CMD_ACTION_PREPARE
) &&
6915 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
6917 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb
->Cdb
[0], &(Srb
->Cdb
)));
6919 if(!LunExt
->IdentifyData
.AtapiCmdSize
&&
6920 (Srb
->CdbLength
> 12)) {
6921 KdPrint2((PRINT_PREFIX
"Cdb16 not supported\n"));
6922 return SRB_STATUS_INVALID_REQUEST
;
6925 // Set data buffer pointer and words left.
6926 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
6927 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
6928 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
6929 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6930 // reset this to force PRD init. May be already setup by recursive SRB
6931 AtaReq
->dma_entries
= 0;
6933 // check if reorderable
6934 switch(Srb
->Cdb
[0]) {
6936 case SCSIOP_WRITE16
:
6938 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6939 MOV_QD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6943 case SCSIOP_WRITE12
:
6945 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6951 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6953 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6955 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6956 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6957 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
6958 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
6959 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ?
6960 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
6963 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6964 if(!AtaReq
->TransferLength
) {
6965 KdPrint((" assume 0-transfer\n"));
6967 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
6968 KdPrint((" assume OUT\n"));
6969 AtaReq
->Flags
|= REQ_FLAG_WRITE
;
6971 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6972 KdPrint((" assume IN\n"));
6973 AtaReq
->Flags
|= REQ_FLAG_READ
;
6978 // check if DMA read/write
6979 if(deviceExtension
->HwFlags
& UNIATA_SATA
) {
6980 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: force use dma (ahci)\n"));
6984 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
6985 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
6987 if(AtaReq
->TransferLength
) {
6989 switch(Srb
->Cdb
[0]) {
6991 case SCSIOP_WRITE12
:
6992 case SCSIOP_WRITE16
:
6994 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
6997 case SCSIOP_RECEIVE
:
7002 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
7004 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7005 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7008 if(AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7009 (PUCHAR
)(AtaReq
->DataBuffer
),
7010 Srb
->DataTransferLength
7011 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
7013 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7018 case SCSIOP_READ_CD
:
7019 if(deviceExtension
->opt_AtapiDmaRawRead
)
7020 goto call_dma_setup
;
7024 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
7025 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7030 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
7031 KdPrint2((PRINT_PREFIX
"dma RO\n"));
7043 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7044 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7047 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7048 (PUCHAR
)(AtaReq
->DataBuffer
),
7049 Srb
->DataTransferLength
)) {
7050 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
7053 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7057 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer, no DMA setup\n"));
7061 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7063 UniataAhciSetupCmdPtr(AtaReq
);
7065 if(!Srb
->DataTransferLength
) {
7066 KdPrint2((PRINT_PREFIX
"zero-transfer\n"));
7069 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7070 (PUCHAR
)(AtaReq
->DataBuffer
),
7071 Srb
->DataTransferLength
)) {
7072 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no AHCI dma!\n"));
7073 return SRB_STATUS_ERROR
;
7076 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7078 FeatureReg
|= ATA_F_DMA
;
7079 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7080 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7081 FeatureReg
|= ATA_F_DMAREAD
;
7085 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: setup AHCI FIS\n"));
7086 // this is done in UniataAhciSetupFIS_H2D()
7087 //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
7088 RtlCopyMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), Srb
->Cdb
, Srb
->CdbLength
);
7090 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
7091 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
7092 IDE_COMMAND_ATAPI_PACKET
/* command */,
7094 (Srb
->DataTransferLength
>= 0x10000) ? (USHORT
)(0xffff) : (USHORT
)(Srb
->DataTransferLength
),
7095 FeatureReg
/* feature */
7099 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AHCI !FIS\n"));
7100 return SRB_STATUS_ERROR
;
7103 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0,
7104 ((Srb
->DataTransferLength
&& (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) ? ATA_AHCI_CMD_WRITE
: 0) |
7105 (ATA_AHCI_CMD_ATAPI
| ATA_AHCI_CMD_PREFETCH
),
7106 fis_size
, DeviceNumber
);
7108 KdPrint2((PRINT_PREFIX
"AtapiSendCommand ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
7112 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7113 // if this is queued request, reinit DMA and check
7114 // if DMA mode is still available
7115 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
7116 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7117 if (/*EnableDma &&*/
7118 (LunExt
->TransferMode
>= ATA_DMA
)) {
7119 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
7122 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7123 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
7126 dma_reinited
= TRUE
;
7130 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
7131 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
7132 return SRB_STATUS_PENDING
;
7134 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma
, Srb
->Cdb
[0]));
7135 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7136 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7139 if((Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) && !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7140 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
7142 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7143 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7144 } if(AtaReq
->TransferLength
) {
7146 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
7147 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7148 if (/*EnableDma &&*/
7149 (LunExt
->TransferMode
>= ATA_DMA
)) {
7152 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7157 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
7159 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7160 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7161 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
7162 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7165 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
7166 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7167 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7170 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
7172 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
7173 &(Srb
->Cdb
), Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
7175 // Make sure command is to ATAPI device.
7176 flags
= LunExt
->DeviceFlags
;
7177 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7178 if((Srb
->Lun
) > (LunExt
->DiscsPresent
- 1)) {
7180 // Indicate no device found at this address.
7181 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7182 return SRB_STATUS_SELECTION_TIMEOUT
;
7184 } else if(Srb
->Lun
> 0) {
7185 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7186 return SRB_STATUS_SELECTION_TIMEOUT
;
7189 if(!(flags
& DFLAGS_ATAPI_DEVICE
)) {
7190 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7191 return SRB_STATUS_SELECTION_TIMEOUT
;
7194 // Select device 0 or 1. Or more for PM
7195 SelectDrive(chan
, DeviceNumber
);
7197 // Verify that controller is ready for next command.
7198 GetStatus(chan
, statusByte
);
7199 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
7201 if(statusByte
== IDE_STATUS_WRONG
) {
7202 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
7205 if(statusByte
& IDE_STATUS_BUSY
) {
7206 if(statusByte
& IDE_STATUS_DSC
) {
7207 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
7209 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
7210 // We have to make reset here, since we are expecting device to be available
7211 //return SRB_STATUS_BUSY; // this cause queue freeze
7215 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7217 // Check if command list is free
7218 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
7220 // controller is busy, however we expect it to be free
7221 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI
));
7225 if(statusByte
& IDE_STATUS_ERROR
) {
7226 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
7228 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
7229 // Read the error reg. to clear it and fail this request.
7230 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7231 return MapError(deviceExtension
, Srb
);
7233 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
7236 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
7237 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
7238 if((!(statusByte
& IDE_STATUS_DSC
)) &&
7239 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
7241 AtapiStallExecution(200);
7242 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
7243 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7244 return SRB_STATUS_PENDING
;
7247 if(IS_RDP(Srb
->Cdb
[0])) {
7249 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
7253 if(statusByte
& IDE_STATUS_DRQ
) {
7255 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
7257 // Try to drain the data that one preliminary device thinks that it has
7258 // to transfer. Hopefully this random assertion of DRQ will not be present
7259 // in production devices.
7260 statusByte
= AtapiSuckPort2(chan
);
7262 for (i = 0; i < 0x10000; i++) {
7263 GetStatus(chan, statusByte);
7264 if(statusByte & IDE_STATUS_DRQ) {
7265 AtapiReadPort2(chan, IDX_IO1_i_Data);
7271 if (statusByte
& IDE_STATUS_DRQ
) {
7273 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte
));
7275 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7277 AtapiSoftReset(chan
, DeviceNumber
);
7279 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
7280 // Re-initialize Atapi device.
7281 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), DeviceNumber
, TRUE
);
7283 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
7284 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
7286 // Inform the port driver that the bus has been reset.
7287 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
7288 // Clean up device extension fields that AtapiStartIo won't.
7289 UniataExpectChannelInterrupt(chan
, FALSE
);
7291 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
7294 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7296 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7297 return SRB_STATUS_BUS_RESET;
7300 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
7304 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
7305 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7306 return SRB_STATUS_SELECTION_TIMEOUT
;
7310 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7311 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
7312 Srb
->Cdb
[1] &= ~0xE0;
7313 if((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
7314 // Torisan changer. TUR's are overloaded to be platter switches.
7315 Srb
->Cdb
[7] = Srb
->Lun
;
7322 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
7324 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
7327 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7328 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AHCI, begin transaction\n"));
7329 //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
7330 UniataExpectChannelInterrupt(chan
, TRUE
);
7331 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
7332 return SRB_STATUS_PENDING
;
7335 statusByte
= WaitOnBusy(chan
);
7336 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
7340 FeatureReg
|= ATA_F_DMA
;
7341 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7342 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7343 FeatureReg
|= ATA_F_DMAREAD
;
7347 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, FeatureReg
);
7349 // Write transfer byte count to registers.
7350 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
7351 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
7353 if (Srb
->DataTransferLength
>= 0x10000) {
7354 byteCountLow
= byteCountHigh
= 0xFF;
7357 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
7358 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
7360 if (flags
& DFLAGS_INT_DRQ
) {
7362 // This device interrupts when ready to receive the packet.
7364 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
7367 UniataExpectChannelInterrupt(chan
, TRUE
);
7368 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
7369 InterlockedExchange(&(chan
->CheckIntr
),
7372 // Write ATAPI packet command.
7373 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7375 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
7376 return SRB_STATUS_PENDING
;
7380 // This device quickly sets DRQ when ready to receive the packet.
7382 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
7385 UniataExpectChannelInterrupt(chan
, TRUE
);
7386 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
7387 InterlockedExchange(&(chan
->CheckIntr
),
7390 if(g_opt_AtapiSendDisableIntr
) {
7391 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7394 // Write ATAPI packet command.
7395 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7399 statusByte
= WaitForDrq(chan
);
7401 // Need to read status register and clear interrupt (if any)
7402 GetBaseStatus(chan
, statusByte
);
7404 if (!(statusByte
& IDE_STATUS_DRQ
)) {
7406 if(g_opt_AtapiSendDisableIntr
) {
7407 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7409 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte
));
7410 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7411 return SRB_STATUS_ERROR
;
7414 GetStatus(chan
, statusByte
);
7415 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
7417 // Send CDB to device.
7418 statusByte
= WaitOnBaseBusy(chan
);
7420 // Indicate expecting an interrupt and wait for it.
7421 UniataExpectChannelInterrupt(chan
, TRUE
);
7422 InterlockedExchange(&(chan
->CheckIntr
),
7424 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
7426 GetBaseStatus(chan
, statusByte
);
7428 if(g_opt_AtapiSendDisableIntr
) {
7429 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7434 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
7437 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
7438 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
7441 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
7443 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
7444 return SRB_STATUS_PENDING
;
7446 } // end AtapiSendCommand()
7453 Routine Description:
7454 Program ATA registers for IDE disk transfer.
7457 HwDeviceExtension - ATAPI driver storage.
7458 Srb - System request block.
7461 SRB status (pending if all goes well).
7466 ULONG check_point
= 0;
7467 #define SetCheckPoint(cp) { check_point = (cp) ; }
7469 #define SetCheckPoint(cp)
7475 IN PVOID HwDeviceExtension
,
7476 IN PSCSI_REQUEST_BLOCK Srb
,
7481 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
7484 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7489 PHW_LU_EXTENSION LunExt
;
7493 UCHAR statusByte
,errorByte
;
7494 ULONG status
= SRB_STATUS_INVALID_REQUEST
;
7497 PMODE_PARAMETER_HEADER modeData
;
7504 //ULONG __ebp__ = 0;
7506 SetCheckPoint(0x20);
7507 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
7512 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
7513 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
7514 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
7515 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
7516 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
7518 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
7519 Srb->SrbExtension));
7520 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
7523 SetCheckPoint(0x30);
7524 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7526 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
7528 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
7530 KdPrint2((PRINT_PREFIX
"** --- **\n"));
7532 lChannel
= GET_CHANNEL(Srb
);
7533 chan
= &(deviceExtension
->chan
[lChannel
]);
7534 //ldev = GET_LDEV(Srb);
7535 DeviceNumber
= GET_CDEV(Srb
);
7536 LunExt
= chan
->lun
[DeviceNumber
];
7538 SetCheckPoint(0x40);
7539 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
7540 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
7542 cdb
= (PCDB
)(Srb
->Cdb
);
7544 if(CmdAction
== CMD_ACTION_PREPARE
) {
7545 switch (Srb
->Cdb
[0]) {
7546 case SCSIOP_SERVICE_ACTION16
:
7547 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
7550 goto default_no_prep
;
7553 case SCSIOP_INQUIRY
: // now it requires device access
7555 case SCSIOP_READ_CAPACITY
:
7559 case SCSIOP_WRITE12
:
7561 case SCSIOP_WRITE16
:
7562 case SCSIOP_REQUEST_SENSE
:
7564 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
7570 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
7571 return SRB_STATUS_BUSY
;
7575 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
7576 switch (Srb
->Cdb
[0]) {
7577 case SCSIOP_INQUIRY
:
7579 KdPrint2((PRINT_PREFIX
7580 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
7581 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7582 // Filter out wrong TIDs.
7583 if ((Srb
->Lun
!= 0) ||
7584 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
7585 (Srb
->TargetId
>= deviceExtension
->NumberLuns
)) {
7587 KdPrint2((PRINT_PREFIX
7588 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
7589 // Indicate no device found at this address.
7590 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7595 KdPrint2((PRINT_PREFIX
7596 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
7597 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
7598 PIDENTIFY_DATA2 identifyData
= &(LunExt
->IdentifyData
);
7600 if (!(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7602 if(!CheckDevice(HwDeviceExtension
, lChannel
, DeviceNumber
, FALSE
)) {
7603 KdPrint2((PRINT_PREFIX
7604 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
7605 // Indicate no device found at this address.
7607 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7611 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, DeviceNumber
)) {
7612 KdPrint2((PRINT_PREFIX
7613 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
7614 // Indicate no device found at this address.
7615 UniataForgetDevice(chan
->lun
[DeviceNumber
]);
7617 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7622 // Zero INQUIRY data structure.
7623 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
7625 // Standard IDE interface only supports disks.
7626 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
7628 // Set the removable bit, if applicable.
7629 if (LunExt
->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
7630 KdPrint2((PRINT_PREFIX
7631 "RemovableMedia\n"));
7632 inquiryData
->RemovableMedia
= 1;
7634 // Set the Relative Addressing (LBA) bit, if applicable.
7635 if (LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
7636 inquiryData
->RelativeAddressing
= 1;
7637 KdPrint2((PRINT_PREFIX
7638 "RelativeAddressing\n"));
7640 // Set the CommandQueue bit
7641 inquiryData
->CommandQueue
= 1;
7643 // Fill in vendor identification fields.
7644 for (i
= 0; i
< 24; i
+= 2) {
7645 MOV_DW_SWP(inquiryData
->VendorId
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
7648 // Initialize unused portion of product id.
7649 for (i = 0; i < 4; i++) {
7650 inquiryData->ProductId[12+i] = ' ';
7653 // Move firmware revision from IDENTIFY data to
7654 // product revision in INQUIRY data.
7655 for (i
= 0; i
< 4; i
+= 2) {
7656 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
7659 status
= SRB_STATUS_SUCCESS
;
7664 case SCSIOP_REPORT_LUNS
: {
7667 PREPORT_LUNS_INFO_HDR LunInfo
;
7669 KdPrint2((PRINT_PREFIX
7670 "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
7671 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7673 MOV_DD_SWP(alen
, cdb
->REPORT_LUNS
.AllocationLength
);
7680 LunInfo
= (PREPORT_LUNS_INFO_HDR
)(Srb
->DataBuffer
);
7681 RtlZeroMemory(LunInfo
, 16);
7683 MOV_DD_SWP( LunInfo
->ListLength
, alen
);
7684 Srb
->DataTransferLength
= 16;
7685 status
= SRB_STATUS_SUCCESS
;
7689 case SCSIOP_MODE_SENSE
:
7691 KdPrint2((PRINT_PREFIX
7692 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
7693 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7695 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_POWER_CONDITION
) {
7696 PMODE_POWER_CONDITION_PAGE modeData
;
7698 KdPrint2((PRINT_PREFIX
"MODE_PAGE_POWER_CONDITION\n"));
7699 modeData
= (PMODE_POWER_CONDITION_PAGE
)(Srb
->DataBuffer
);
7700 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_POWER_CONDITION_PAGE
)) {
7701 status
= SRB_STATUS_DATA_OVERRUN
;
7703 RtlZeroMemory(modeData
, sizeof(MODE_POWER_CONDITION_PAGE
));
7704 modeData
->PageCode
= MODE_PAGE_POWER_CONDITION
;
7705 modeData
->PageLength
= sizeof(MODE_PAGE_POWER_CONDITION
)-sizeof(MODE_PARAMETER_HEADER
);
7706 modeData
->Byte3
.Fields
.Idle
= LunExt
->PowerState
<= StartStop_Power_Idle
;
7707 modeData
->Byte3
.Fields
.Standby
= LunExt
->PowerState
== StartStop_Power_Standby
;
7708 Srb
->DataTransferLength
= sizeof(MODE_POWER_CONDITION_PAGE
);
7709 status
= SRB_STATUS_SUCCESS
;
7712 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_CACHING
) {
7713 PMODE_CACHING_PAGE modeData
;
7715 KdPrint2((PRINT_PREFIX
"MODE_PAGE_CACHING\n"));
7716 modeData
= (PMODE_CACHING_PAGE
)(Srb
->DataBuffer
);
7717 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_CACHING_PAGE
)) {
7718 status
= SRB_STATUS_DATA_OVERRUN
;
7720 RtlZeroMemory(modeData
, sizeof(MODE_CACHING_PAGE
));
7721 modeData
->PageCode
= MODE_PAGE_CACHING
;
7722 modeData
->PageLength
= sizeof(MODE_CACHING_PAGE
)-sizeof(MODE_PARAMETER_HEADER
);
7723 modeData
->ReadDisableCache
= (LunExt
->DeviceFlags
& DFLAGS_RCACHE_ENABLED
) ? 0 : 1;
7724 modeData
->WriteCacheEnable
= (LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) ? 1 : 0;
7725 Srb
->DataTransferLength
= sizeof(MODE_CACHING_PAGE
);
7726 status
= SRB_STATUS_SUCCESS
;
7729 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
7731 // This is used to determine if the media is write-protected.
7732 // Since IDE does not support mode sense then we will modify just the portion we need
7733 // so the higher level driver can determine if media is protected.
7735 //SelectDrive(chan, DeviceNumber);
7736 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7737 //statusByte = WaitOnBusy(chan);
7738 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
7740 if (!(statusByte
& IDE_STATUS_ERROR
)) {
7742 // no error occured return success, media is not protected
7743 UniataExpectChannelInterrupt(chan
, FALSE
);
7744 InterlockedExchange(&(chan
->CheckIntr
),
7746 status
= SRB_STATUS_SUCCESS
;
7750 // error occured, handle it locally, clear interrupt
7751 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7753 GetBaseStatus(chan
, statusByte
);
7754 UniataExpectChannelInterrupt(chan
, FALSE
);
7755 InterlockedExchange(&(chan
->CheckIntr
),
7757 status
= SRB_STATUS_SUCCESS
;
7759 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
7761 //media is write-protected, set bit in mode sense buffer
7762 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
7764 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
7765 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
7768 status
= SRB_STATUS_SUCCESS
;
7770 status
= SRB_STATUS_INVALID_REQUEST
;
7774 case SCSIOP_TEST_UNIT_READY
:
7776 KdPrint2((PRINT_PREFIX
7777 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
7778 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7779 if (chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
7781 // Select device 0 or 1.
7782 //SelectDrive(chan, DeviceNumber);
7783 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7784 // Wait for busy. If media has not changed, return success
7785 //statusByte = WaitOnBusy(chan);
7786 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
7788 if (!(statusByte
& IDE_STATUS_ERROR
)){
7789 UniataExpectChannelInterrupt(chan
, FALSE
);
7790 InterlockedExchange(&(chan
->CheckIntr
),
7792 status
= SRB_STATUS_SUCCESS
;
7794 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7795 if (errorByte
== IDE_ERROR_DATA_ERROR
){
7797 // Special case: If current media is write-protected,
7798 // the 0xDA command will always fail since the write-protect bit
7799 // is sticky,so we can ignore this error
7800 GetBaseStatus(chan
, statusByte
);
7801 UniataExpectChannelInterrupt(chan
, FALSE
);
7802 InterlockedExchange(&(chan
->CheckIntr
),
7804 status
= SRB_STATUS_SUCCESS
;
7808 // Request sense buffer to be build
7809 UniataExpectChannelInterrupt(chan
, TRUE
);
7810 InterlockedExchange(&(chan
->CheckIntr
),
7812 status
= SRB_STATUS_PENDING
;
7816 status
= SRB_STATUS_SUCCESS
;
7821 case SCSIOP_READ_CAPACITY
:
7823 KdPrint2((PRINT_PREFIX
7824 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7825 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7826 // Claim 512 byte blocks (big-endian).
7827 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7829 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY_DATA
));
7830 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
7832 // Calculate last sector.
7833 if(!(i
= (ULONG
)LunExt
->NumOfSectors
)) {
7834 i
= LunExt
->IdentifyData
.SectorsPerTrack
*
7835 LunExt
->IdentifyData
.NumberOfHeads
*
7836 LunExt
->IdentifyData
.NumberOfCylinders
;
7840 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
7841 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
7842 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
7844 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
7846 KdPrint2((PRINT_PREFIX
7847 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
7849 LunExt
->IdentifyData
.SectorsPerTrack
,
7850 LunExt
->IdentifyData
.NumberOfHeads
,
7851 LunExt
->IdentifyData
.NumberOfCylinders
));
7854 status
= SRB_STATUS_SUCCESS
;
7857 case SCSIOP_SERVICE_ACTION16
:
7859 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
7860 KdPrint2((PRINT_PREFIX
7861 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7862 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7863 // Claim 512 byte blocks (big-endian).
7864 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7866 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY16_DATA
));
7867 MOV_DD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
7869 // Calculate last sector.
7870 if(!(lba
= LunExt
->NumOfSectors
)) {
7871 lba
= LunExt
->IdentifyData
.SectorsPerTrack
*
7872 LunExt
->IdentifyData
.NumberOfHeads
*
7873 LunExt
->IdentifyData
.NumberOfCylinders
;
7876 MOV_QD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, lba
);
7878 KdPrint2((PRINT_PREFIX
7879 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n",
7881 LunExt
->IdentifyData
.SectorsPerTrack
,
7882 LunExt
->IdentifyData
.NumberOfHeads
,
7883 LunExt
->IdentifyData
.NumberOfCylinders
));
7885 status
= SRB_STATUS_SUCCESS
;
7892 case SCSIOP_VERIFY12
:
7893 case SCSIOP_VERIFY16
:
7895 KdPrint2((PRINT_PREFIX
7896 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
7897 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7898 status
= IdeVerify(HwDeviceExtension
,Srb
);
7905 case SCSIOP_WRITE12
:
7907 case SCSIOP_WRITE16
:
7909 KdPrint2((PRINT_PREFIX
7910 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
7911 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
7912 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7913 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7914 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
7915 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
7916 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
7917 status
= IdeReadWrite(HwDeviceExtension
,
7921 case SCSIOP_START_STOP_UNIT
:
7923 KdPrint2((PRINT_PREFIX
7924 "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
7925 cdb
->START_STOP
.Immediate
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7926 //Determine what type of operation we should perform
7930 if(cdb
->START_STOP
.FL
||
7931 cdb
->START_STOP
.FormatLayerNumber
||
7932 cdb
->START_STOP
.Reserved2
||
7933 cdb
->START_STOP
.Reserved2_2
||
7934 cdb
->START_STOP
.Reserved3
||
7939 if (cdb
->START_STOP
.PowerConditions
) {
7940 KdPrint2((PRINT_PREFIX
"START_STOP Power %d\n", cdb
->START_STOP
.PowerConditions
));
7941 switch(cdb
->START_STOP
.PowerConditions
) {
7942 case StartStop_Power_Idle
:
7943 command
= IDE_COMMAND_IDLE_IMMED
;
7945 case StartStop_Power_Standby
:
7946 command
= IDE_COMMAND_STANDBY_IMMED
;
7948 case StartStop_Power_Sleep
:
7949 // TODO: we should save power state in order to know
7950 // that RESET sould be issued to revert device into
7953 command
= IDE_COMMAND_SLEEP
;
7958 LunExt
->PowerState
= cdb
->START_STOP
.PowerConditions
;
7960 if (cdb
->START_STOP
.LoadEject
== 1) {
7961 KdPrint2((PRINT_PREFIX
"START_STOP eject\n"));
7963 // first select device 0 or 1.
7964 //SelectDrive(chan, DeviceNumber);
7965 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
7966 command
= IDE_COMMAND_MEDIA_EJECT
;
7968 if (cdb
->START_STOP
.Start
== 0) {
7969 KdPrint2((PRINT_PREFIX
"START_STOP standby\n"));
7970 command
= IDE_COMMAND_STANDBY_IMMED
;
7972 // TODO: we may need to perform hard reset (after sleep) or
7973 // issue IDE_COMMAND_IDLE_IMMED in order to activate device
7974 KdPrint2((PRINT_PREFIX
"START_STOP activate\n"));
7976 if(LunExt
->PowerState
== StartStop_Power_Sleep
) {
7977 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
7978 status
= SRB_STATUS_SUCCESS
;
7981 if(LunExt
->PowerState
> StartStop_Power_Idle
) {
7982 KdPrint2((PRINT_PREFIX
" issue IDLE\n"));
7983 command
= IDE_COMMAND_IDLE_IMMED
;
7985 KdPrint2((PRINT_PREFIX
" do nothing\n"));
7986 status
= SRB_STATUS_SUCCESS
;
7991 statusByte
= WaitOnBaseBusy(chan
);
7992 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, command
, 0, 0, 0, 0, 0,
7993 cdb
->START_STOP
.Immediate
? ATA_IMMEDIATE
: ATA_WAIT_READY
);
7994 status
= (statusByte
& IDE_STATUS_ERROR
) ? SRB_STATUS_ERROR
: SRB_STATUS_SUCCESS
;
7995 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
7999 KdPrint2((PRINT_PREFIX
"START_STOP invalid\n"));
8000 if (Srb
->SenseInfoBuffer
) {
8002 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8004 senseBuffer
->ErrorCode
= 0x70;
8005 senseBuffer
->Valid
= 1;
8006 senseBuffer
->AdditionalSenseLength
= 0xb;
8007 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
8008 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_CDB
;
8009 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8011 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8012 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8014 status
= SRB_STATUS_ERROR
;
8018 case SCSIOP_MEDIUM_REMOVAL
:
8020 cdb
= (PCDB
)Srb
->Cdb
;
8022 if(LunExt
->IdentifyData
.Removable
) {
8023 statusByte
= WaitOnBaseBusy(chan
);
8025 //SelectDrive(chan, DeviceNumber);
8026 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
8027 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
8028 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_LOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8030 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
8031 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_UNLOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8033 status
= SRB_STATUS_SUCCESS
;
8035 status
= SRB_STATUS_INVALID_REQUEST
;
8040 // Note: I don't implement this, because NTFS driver too often issues this command
8041 // It causes awful performance degrade. However, if somebody wants, I will implement
8042 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
8043 case SCSIOP_FLUSH_BUFFER
:
8044 case SCSIOP_SYNCHRONIZE_CACHE
:
8046 SelectDrive(chan
, DeviceNumber
);
8047 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
8048 status
= SRB_STATUS_SUCCESS
;
8049 // status = SRB_STATUS_PENDING;
8050 statusByte
= WaitOnBusy(chan
);
8054 case SCSIOP_REQUEST_SENSE
:
8055 // this function makes sense buffers to report the results
8056 // of the original GET_MEDIA_STATUS command
8058 KdPrint2((PRINT_PREFIX
8059 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8060 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8061 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8062 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
8065 status
= SRB_STATUS_INVALID_REQUEST
;
8069 case SCSIOP_ATA_PASSTHROUGH
:
8072 BOOLEAN use_dma
= FALSE
;
8075 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
8077 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
8078 //lChannel = Srb->TargetId >> 1;
8080 DeviceNumber
= max(DeviceNumber
, 1);
8081 regs
->bDriveHeadReg
&= 0x0f;
8082 regs
->bDriveHeadReg
|= (UCHAR
) (((DeviceNumber
& 0x1) << 4) | 0xA0);
8085 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
8087 KdPrint2((PRINT_PREFIX
8088 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
8089 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8091 if((regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) == UNIATA_SPTI_EX_SPEC_TO
) {
8092 to_lim
= Srb
->TimeOutValue
;
8094 if(Srb
->TimeOutValue
<= 2) {
8095 to_lim
= Srb
->TimeOutValue
*900;
8097 to_lim
= (Srb
->TimeOutValue
*999) - 500;
8101 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8103 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
8105 statusByte
= UniataAhciSendPIOCommandDirect(
8114 if(statusByte
== IDE_STATUS_WRONG
) {
8115 goto passthrough_err
;
8117 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8118 UniataAhciAbortOperation(chan
);
8119 goto passthrough_err
;
8121 goto passthrough_done
;
8125 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
8126 if((chan
->lun
[DeviceNumber
]->LimitedTransferMode
>= ATA_DMA
)) {
8128 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
8129 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
8130 (PUCHAR
)(Srb
->DataBuffer
),
8131 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
8137 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
8138 AtapiStallExecution(10);
8140 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
8141 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8142 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8143 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8144 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8145 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8147 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
8148 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8149 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
8150 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8151 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
8152 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8153 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
8154 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8155 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
8156 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8158 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
8161 GetBaseStatus(chan
, statusByte
);
8162 if(statusByte
& IDE_STATUS_ERROR
) {
8163 goto passthrough_err
;
8165 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
8168 ScsiPortStallExecution(1); // wait for busy to be set
8170 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
8171 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
8172 GetBaseStatus(chan
, statusByte
);
8173 if(statusByte
& IDE_STATUS_ERROR
) {
8176 if(!(statusByte
& IDE_STATUS_BUSY
)) {
8181 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
8183 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8184 goto passthrough_err
;
8188 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
8190 AtapiDmaDone(deviceExtension
, DeviceNumber
, lChannel
, NULL
);
8191 GetBaseStatus(chan
, statusByte
);
8193 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8194 AtapiSuckPort2(chan
);
8196 if (Srb
->SenseInfoBuffer
) {
8198 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8200 senseBuffer
->ErrorCode
= 0x70;
8201 senseBuffer
->Valid
= 1;
8202 senseBuffer
->AdditionalSenseLength
= 0xb;
8203 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
8204 senseBuffer
->AdditionalSenseCode
= 0;
8205 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8207 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8208 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8210 status
= SRB_STATUS_ERROR
;
8214 if (statusByte
& IDE_STATUS_DRQ
) {
8215 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
8217 (PUSHORT
) Srb
->DataBuffer
,
8218 Srb
->DataTransferLength
/ 2,
8220 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
8222 (PUSHORT
) Srb
->DataBuffer
,
8223 Srb
->DataTransferLength
/ 2,
8228 status
= SRB_STATUS_SUCCESS
;
8231 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8233 } else { // read task register
8236 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
8238 KdPrint2((PRINT_PREFIX
8239 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
8240 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8242 if((Srb
->DataTransferLength
>= sizeof(IDEREGS_EX
)) &&
8243 (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
)) {
8246 if(Srb
->DataTransferLength
>= sizeof(IDEREGS
)) {
8249 KdPrint2((PRINT_PREFIX
" buffer too small \n"));
8250 status
= SRB_STATUS_DATA_OVERRUN
;
8253 RtlZeroMemory(regs
, use48
? sizeof(IDEREGS_EX
) : sizeof(IDEREGS
));
8254 regs
->bOpFlags
= use48
? ATA_FLAGS_48BIT_COMMAND
: 0;
8255 UniataSnapAtaRegs(chan
, 0, regs
);
8257 status
= SRB_STATUS_SUCCESS
;
8264 KdPrint2((PRINT_PREFIX
8265 "IdeSendCommand: Unsupported command %#x\n",
8268 status
= SRB_STATUS_INVALID_REQUEST
;
8272 if(status
== SRB_STATUS_PENDING
) {
8273 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
8274 if(CmdAction
& CMD_ACTION_EXEC
) {
8275 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
8276 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
8279 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
8280 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8285 } // end IdeSendCommand()
8290 Routine Description:
8291 Enables disables media status notification
8294 HwDeviceExtension - ATAPI driver storage.
8301 IN PVOID HwDeviceExtension
,
8303 IN ULONG DeviceNumber
8306 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8308 UCHAR statusByte
,errorByte
;
8310 chan
= &(deviceExtension
->chan
[lChannel
]);
8311 SelectDrive(chan
, DeviceNumber
);
8313 if (EnableMSN
== TRUE
){
8315 // If supported enable Media Status Notification support
8316 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
8319 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8320 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8321 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8323 if (statusByte
& IDE_STATUS_ERROR
) {
8324 // Read the error register.
8325 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8327 KdPrint2((PRINT_PREFIX
8328 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
8332 chan
->lun
[DeviceNumber
]->DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
8333 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
8334 chan
->ReturningMediaStatus
= 0;
8339 } else { // end if EnableMSN == TRUE
8341 // disable if previously enabled
8342 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
8344 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8345 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8346 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8347 chan
->lun
[DeviceNumber
]->DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
8354 } // end IdeMediaStatus()
8359 Routine Description:
8361 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
8362 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
8365 HwDeviceExtension - ATAPI driver storage.
8366 Srb - System request block.
8370 SRB status (ALWAYS SUCCESS).
8375 IdeBuildSenseBuffer(
8376 IN PVOID HwDeviceExtension
,
8377 IN PSCSI_REQUEST_BLOCK Srb
8380 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8382 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
8383 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
8387 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
8389 senseBuffer
->ErrorCode
= 0x70;
8390 senseBuffer
->Valid
= 1;
8391 senseBuffer
->AdditionalSenseLength
= 0xb;
8392 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8393 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8394 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8395 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
8397 senseBuffer
->ErrorCode
= 0x70;
8398 senseBuffer
->Valid
= 1;
8399 senseBuffer
->AdditionalSenseLength
= 0xb;
8400 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8401 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8402 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8403 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
8405 senseBuffer
->ErrorCode
= 0x70;
8406 senseBuffer
->Valid
= 1;
8407 senseBuffer
->AdditionalSenseLength
= 0xb;
8408 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
8409 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
8410 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8411 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
8413 senseBuffer
->ErrorCode
= 0x70;
8414 senseBuffer
->Valid
= 1;
8415 senseBuffer
->AdditionalSenseLength
= 0xb;
8416 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
8417 senseBuffer
->AdditionalSenseCode
= 0;
8418 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8420 return SRB_STATUS_SUCCESS
;
8422 return SRB_STATUS_ERROR
;
8424 }// End of IdeBuildSenseBuffer
8428 UniataUserDeviceReset(
8429 PHW_DEVICE_EXTENSION deviceExtension
,
8430 PHW_LU_EXTENSION LunExt
,
8435 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8436 if ((LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
8437 (LunExt
->PowerState
!= StartStop_Power_Sleep
)) {
8438 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
8439 AtapiSoftReset(&(deviceExtension
->chan
[lChannel
]), LunExt
->Lun
);
8441 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
8442 AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8443 for(i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
8444 deviceExtension
->chan
[lChannel
].lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
8447 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
8448 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8450 } // end UniataUserDeviceReset()
8455 PHW_DEVICE_EXTENSION deviceExtension
,
8460 BOOLEAN PostReq
= FALSE
;
8462 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
8463 if(chan
->queue_depth
> 0) {
8466 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
8467 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
8468 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
8470 status
= SRB_STATUS_BUSY
;
8479 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
8483 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
8486 } // end UniataNeedQueueing()
8490 Routine Description:
8492 This routine is called from the SCSI port driver synchronized
8493 with the kernel to start an IO request.
8498 HwDeviceExtension - HBA miniport driver's adapter data storage
8499 Srb - IO request packet
8509 IN PVOID HwDeviceExtension
,
8510 IN PSCSI_REQUEST_BLOCK Srb
8513 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
8514 } // end AtapiStartIo()
8519 IN PVOID HwDeviceExtension
,
8520 IN PSCSI_REQUEST_BLOCK Srb
,
8524 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8527 PHW_LU_EXTENSION LunExt
;
8535 PSCSI_REQUEST_BLOCK tmpSrb
;
8536 BOOLEAN PostReq
= FALSE
;
8538 BOOLEAN commPort
= FALSE
;
8540 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
8541 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
8542 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
8543 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
8545 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
8547 /* KeBugCheckEx(0xc000000e,
8548 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8550 TopLevel, 0x80000001);
8552 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
8553 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
8554 //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
8555 UniAtaClearAtaReq(Srb
->SrbExtension
);
8558 do { // fetch all queued commands for the channel (if valid)
8560 lChannel
= GET_CHANNEL(Srb
);
8561 //ldev = GET_LDEV(Srb);
8564 DeviceNumber
= GET_CDEV(Srb
);
8567 //ASSERT(deviceExtension);
8570 KdPrint2((PRINT_PREFIX
8571 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8572 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8573 KdPrint2((PRINT_PREFIX
" VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
8575 if(lChannel
== deviceExtension
->NumberChannels
&&
8576 !Srb
->Lun
&& !Srb
->TargetId
&&
8577 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
8578 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
8580 // This is our virtual device
8581 KdPrint2((PRINT_PREFIX
8582 "AtapiStartIo: Communication port\n"));
8583 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
8585 if(Srb
->DataTransferLength
< sizeof(PINQUIRYDATA
)) {
8586 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", Srb
->DataTransferLength
,
8587 sizeof(PINQUIRYDATA
) ));
8589 status
= SRB_STATUS_DATA_OVERRUN
;
8593 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
8595 KdPrint2((PRINT_PREFIX
8597 // Zero INQUIRY data structure.
8598 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
8600 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
8602 // Fill in vendor identification fields.
8603 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
8605 status
= SRB_STATUS_SUCCESS
;
8609 /* Pass IOCTL request down */
8611 if(lChannel
>= deviceExtension
->NumberChannels
||
8612 Srb
->TargetId
/*DeviceNumber*/ >= deviceExtension
->NumberLuns
||
8615 if(lChannel
>= deviceExtension
->NumberChannels
) {
8620 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8621 KdPrint3((PRINT_PREFIX
8622 "AtapiStartIo: SRB rejected\n"));
8623 // Indicate no device found at this address.
8624 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
8625 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8629 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
8630 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
8635 chan
= &(deviceExtension
->chan
[lChannel
]);
8636 LunExt
= chan
->lun
[DeviceNumber
];
8640 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
8646 if(!commPort
&& !LunExt
) {
8648 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
8651 deviceExtension
->NumberChannels
);
8652 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
8653 lChannel
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
8654 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8655 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
8659 for(i=0; i<1000; i++) {
8660 AtapiStallExecution(3*1000);
8667 // Determine which function.
8668 switch (Srb
->Function
) {
8670 case SRB_FUNCTION_EXECUTE_SCSI
:
8672 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8673 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
8674 // let passthrough go
8676 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
8680 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8681 KdPrint2((PRINT_PREFIX
8682 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
8683 // Indicate no device found at this address.
8684 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
8685 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8690 KdPrint2((PRINT_PREFIX
8691 " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb
, &(Srb
->Cdb
), Srb
->SrbExtension
, Srb
->Cdb
[0]));
8695 if(Srb->DataTransferLength) {
8697 a = ((PUCHAR)(Srb->DataBuffer))[0];
8700 } __except(EXCEPTION_EXECUTE_HANDLER) {
8701 KdPrint3((PRINT_PREFIX
8702 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
8703 // Indicate no device found at this address.
8704 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
8705 status = SRB_STATUS_ERROR;
8706 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
8711 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
8715 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
8717 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
8718 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
8720 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
8722 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
8723 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
8725 /*KeBugCheckEx(0xc000000e,
8726 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8728 status, 0x80000001);*/
8729 if(status
== SRB_STATUS_BUSY
)
8730 status
= SRB_STATUS_PENDING
;
8731 // Insert requests AFTER they have been initialized on
8732 // CMD_ACTION_PREPARE stage
8733 // we should not check TopLevel here (it is always TRUE)
8734 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8735 UniataQueueRequest(chan
, Srb
);
8737 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
8741 // Send command to device.
8742 KdPrint2((PRINT_PREFIX
"Send to device %x\n", Srb
->Cdb
[0]));
8744 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
8745 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8746 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
8747 //ASSERT(!AtaReq->Flags);
8748 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8749 UniataQueueRequest(chan
, Srb
);
8750 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
8751 //ASSERT(!AtaReq->Flags);
8752 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
8753 //ASSERT(!AtaReq->Flags);
8757 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8761 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
8762 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, DeviceNumber
)) {
8763 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, DeviceNumber
, TRUE
)) {
8767 if(!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8771 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
8780 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)/* &&
8781 (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
8782 KdPrint3((PRINT_PREFIX
"Try ATAPI send %x\n", Srb
->Cdb
[0]));
8783 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
8785 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
8790 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
8797 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
8799 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
8801 /* KeBugCheckEx(0xc000000e,
8802 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8804 status, 0x80000002);*/
8812 case SRB_FUNCTION_ABORT_COMMAND
:
8814 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
8816 // Verify that SRB to abort is still outstanding.
8817 if((tmpSrb
!= Srb
->NextSrb
) ||
8818 !chan
->queue_depth
) {
8820 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
8822 // Complete abort SRB.
8823 status
= SRB_STATUS_ABORT_FAILED
;
8827 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
8828 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
8829 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
8830 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
8831 // Log reset failure.
8832 KdPrint3((PRINT_PREFIX
8833 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
8834 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
8836 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
8837 status
= SRB_STATUS_ERROR
;
8840 status
= SRB_STATUS_SUCCESS
;
8843 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
8844 if (tmpSrb
->SenseInfoBuffer
&&
8845 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
8847 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
8849 senseBuffer
->ErrorCode
= 0;
8850 senseBuffer
->Valid
= 1;
8851 senseBuffer
->AdditionalSenseLength
= 0xb;
8852 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
8853 senseBuffer
->AdditionalSenseCode
= 0;
8854 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8856 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
8858 AtapiDmaDBSync(chan
, tmpSrb
);
8859 UniataRemoveRequest(chan
, tmpSrb
);
8860 // Indicate command complete.
8861 ScsiPortNotification(RequestComplete
,
8864 status
= SRB_STATUS_SUCCESS
;
8868 // Abort function indicates that a request timed out.
8869 // Call reset routine. Card will only be reset if
8870 // status indicates something is wrong.
8871 // Fall through to reset code.
8873 case SRB_FUNCTION_RESET_DEVICE
:
8874 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
8876 // Reset single device.
8877 // For now we support only Lun=0
8879 // Note: reset is immediate command, it cannot be queued since it is usually used to
8880 // revert not-responding device to operational state
8881 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
8882 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
8883 status
= SRB_STATUS_SUCCESS
;
8886 case SRB_FUNCTION_RESET_BUS
:
8888 // Reset Atapi and SCSI bus.
8890 // Note: reset is immediate command, it cannot be queued since it is usually used to
8891 // revert not- responding device to operational state
8892 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
8893 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
8894 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
8895 // Log reset failure.
8896 KdPrint3((PRINT_PREFIX
8897 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
8898 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
8900 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
8901 status
= SRB_STATUS_ERROR
;
8904 status
= SRB_STATUS_SUCCESS
;
8909 case SRB_FUNCTION_SHUTDOWN
:
8911 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
8912 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8913 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
8916 // FLUSH ATAPI device - do nothing
8917 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
8919 // FLUSH IDE/ATA device
8920 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
8921 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8922 status
= AtaCommand(deviceExtension
, DeviceNumber
, GET_CHANNEL(Srb
),
8923 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
8924 // If supported & allowed, reset write cacheing
8925 if(LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
8927 // Disable write cache
8928 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8929 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8930 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
8931 // Check for errors.
8932 if (status
& IDE_STATUS_ERROR
) {
8933 KdPrint2((PRINT_PREFIX
8934 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
8937 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
8939 // Re-enable write cache
8940 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8941 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8942 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
8943 // Check for errors.
8944 if (status
& IDE_STATUS_ERROR
) {
8945 KdPrint2((PRINT_PREFIX
8946 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
8948 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
8950 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
8954 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8956 status
= SRB_STATUS_SUCCESS
;
8960 case SRB_FUNCTION_FLUSH
:
8962 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
8963 status
= SRB_STATUS_SUCCESS
;
8966 case SRB_FUNCTION_IO_CONTROL
: {
8970 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
8972 len
= Srb
->DataTransferLength
;
8974 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
8976 ULONG targetId
= (ULONG
)(-1);
8978 if(len
< sizeof(SRB_IO_CONTROL
)) {
8979 goto wrong_buffer_size
;
8982 // extract bogus bus address
8983 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
8984 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
8985 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
8987 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(GETVERSIONINPARAMS
)) {
8988 goto wrong_buffer_size
;
8991 targetId
= versionParameters
->bIDEDeviceMap
;
8992 KdPrint2((PRINT_PREFIX
"targetId (smart ver) %d\n", targetId
));
8994 case IOCTL_SCSI_MINIPORT_IDENTIFY
:
8995 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
8996 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
8997 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
8998 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
8999 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
9000 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
9001 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
9002 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
9003 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE
:
9004 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG
:
9005 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG
:
9007 PSENDCMDINPARAMS cmdInParameters
= (PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9009 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDINPARAMS
) - 1) {
9010 goto wrong_buffer_size
;
9013 targetId
= cmdInParameters
->bDriveNumber
;
9014 KdPrint2((PRINT_PREFIX
"targetId (smart/ident) %d\n", targetId
));
9018 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9019 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
9020 status
= SRB_STATUS_INVALID_REQUEST
;
9024 // adjust (if necessary) bus address
9025 if(targetId
!= (ULONG
)(-1)) {
9027 // This is done because of how the IOCTL_SCSI_MINIPORT
9028 // determines 'targetid's'. Disk.sys places the real target id value
9029 // in the DeviceMap field. Once we do some parameter checking, the value passed
9030 // back to the application will be determined.
9032 if (deviceExtension
->NumberChannels
== 1) {
9033 // do this for legacy controllers and legacy callers
9034 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call\n"));
9035 DeviceNumber
= (targetId
& 0x01);
9039 // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
9040 // due to DISK.SYS design bug, we have invalid SCSI address in SRB
9041 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call (2)\n"));
9042 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
9043 lChannel
= (UCHAR
)targetId
/ 2;
9046 lChannel
= (UCHAR
)(targetId
/ 2);
9047 DeviceNumber
= targetId
& 0x01;
9050 // otherwise assume lChannel and DeviceNumber from Srb are ok
9052 if(lChannel
>= deviceExtension
->NumberChannels
||
9053 DeviceNumber
>= deviceExtension
->NumberLuns
) {
9054 KdPrint2((PRINT_PREFIX
9055 "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
9057 // Indicate no device found at this address.
9060 targetId
= lChannel
*deviceExtension
->NumberLuns
+DeviceNumber
;
9061 chan
= &(deviceExtension
->chan
[lChannel
]);
9062 LunExt
= chan
->lun
[DeviceNumber
];
9066 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
9068 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9073 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9074 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9076 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9077 UCHAR deviceNumberMap
;
9079 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
9081 // Version and revision per SMART 1.03
9083 versionParameters
->bVersion
= 1;
9084 versionParameters
->bRevision
= 1;
9085 versionParameters
->bReserved
= 0;
9087 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
9088 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
9091 goto invalid_request
;
9094 // NOTE: This will only set the bit
9095 // corresponding to this drive's target id.
9096 // The bit mask is as follows:
9102 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
9103 deviceNumberMap
= 1 << lChannel
;
9106 if (deviceExtension
->NumberChannels
== 1) {
9107 if (chan
->PrimaryAddress
) {
9108 deviceNumberMap
= 1 << DeviceNumber
;
9110 deviceNumberMap
= 4 << DeviceNumber
;
9113 deviceNumberMap
= 1 << (DeviceNumber
+lChannel
*2);
9116 versionParameters
->bIDEDeviceMap
= deviceNumberMap
;
9118 status
= SRB_STATUS_SUCCESS
;
9122 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
9124 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9125 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9127 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
9128 // Extract the target.
9129 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
9131 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
9134 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
9135 goto invalid_request
;
9141 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
9142 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
9143 goto invalid_request
;
9146 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
9147 // Zero the output buffer
9148 RtlZeroMemory(cmdOutParameters
, len
);
9149 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
9150 ((PUCHAR)cmdOutParameters)[i] = 0;
9153 // Build status block.
9154 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
9155 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
9156 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
9158 // Extract the identify data from the device extension.
9159 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &(LunExt
->IdentifyData
),
9160 cmdOutParameters
->cBufferSize
);
9162 if((cmdOutParameters
->cBufferSize
== IDENTIFY_BUFFER_SIZE
) &&
9163 (LunExt
->IdentifyData
.ChecksumValid
== ATA_ChecksumValid
)) {
9164 // adjust checksum if it is possible
9168 for(i
=0; i
< IDENTIFY_BUFFER_SIZE
-1; i
++) {
9169 csum
+= (CHAR
)(cmdOutParameters
->bBuffer
[i
]);
9171 cmdOutParameters
->bBuffer
[i
] = -csum
;
9172 KdPrint2((PRINT_PREFIX
"AtapiStartIo: adjust checksum %d\n"));
9174 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
9176 status
= SRB_STATUS_SUCCESS
;
9180 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
9181 cmdInParameters
.irDriveRegs
.bCommandReg
));
9182 status
= SRB_STATUS_INVALID_REQUEST
;
9188 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9189 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9190 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9191 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9192 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9193 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9194 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9195 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9198 // *all* IOCTLs here are SMART
9200 KdPrint2((PRINT_PREFIX
9201 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
9204 goto invalid_request
;
9207 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9209 if(PostReq
|| TopLevel
) {
9210 UniataQueueRequest(chan
, Srb
);
9211 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9212 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9217 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
9218 status
= SRB_STATUS_PENDING
;
9220 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9223 status
= IdeSendSmartCommand(HwDeviceExtension
, Srb
, targetId
);
9227 // we should not get here, checked above
9229 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9230 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9231 status = SRB_STATUS_INVALID_REQUEST;
9236 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
9238 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
9239 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
9240 ULONG DeviceNumber
= AtaCtl
->addr
.TargetId
;
9244 pos
= FIELD_OFFSET(UNIATA_CTL
, RawData
);
9245 //chan = &(deviceExtension->chan[lChannel]);
9247 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9248 FIELD_OFFSET(UNIATA_CTL
, RawData
) ));
9249 goto wrong_buffer_size
;
9252 if(AtaCtl
->addr
.Lun
||
9253 AtaCtl
->addr
.TargetId
>= deviceExtension
->NumberLuns
||
9254 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
9262 lChannel
= AtaCtl
->addr
.PathId
;
9263 chan
= &(deviceExtension
->chan
[lChannel
]);
9264 LunExt
= chan
->lun
[DeviceNumber
];
9267 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl
->hdr
.ControlCode
, DeviceNumber
));
9269 /* check for valid LUN */
9270 switch (AtaCtl
->hdr
.ControlCode
) {
9271 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9272 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
9273 // this would be BUS reset
9275 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
9276 AtaCtl
->addr
.TargetId
!= 0xff ||
9277 AtaCtl
->addr
.Lun
!= 0
9279 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
9280 DeviceNumber
< deviceExtension
->NumberLuns
) { // AtaCtl->addr.TargetId != 0xff
9281 lChannel
= AtaCtl
->addr
.PathId
;
9282 chan
= &(deviceExtension
->chan
[lChannel
]);
9283 LunExt
= chan
->lun
[DeviceNumber
];
9286 goto handle_bad_ldev
;
9289 lChannel
= AtaCtl
->addr
.PathId
;
9290 chan
= &(deviceExtension
->chan
[lChannel
]);
9293 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
9294 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9295 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
9296 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9297 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
9300 KdPrint2((PRINT_PREFIX
9301 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
9302 // Indicate no device found at this address.
9307 /* check if queueing is necessary */
9308 switch (AtaCtl
->hdr
.ControlCode
) {
9309 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9310 if(!LunExt
->nBadBlocks
) {
9313 goto uata_ctl_queue
;
9314 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9315 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9316 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9317 pos
+sizeof(AtaCtl
->SetMode
) ));
9318 goto wrong_buffer_size
;
9320 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
9323 goto uata_ctl_queue
;
9324 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9325 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
9327 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
9328 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9330 if(PostReq
|| TopLevel
) {
9331 UniataQueueRequest(chan
, Srb
);
9332 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9333 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9336 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
9337 status
= SRB_STATUS_PENDING
;
9339 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9342 } // end switch (AtaCtl->hdr.ControlCode)
9344 /* process request */
9345 switch (AtaCtl
->hdr
.ControlCode
) {
9346 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9348 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
9350 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9351 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9352 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9353 goto wrong_buffer_size
;
9355 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
9356 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
9357 if(AtaCtl
->addr
.TargetId
!= 0xff) {
9358 LunExt
->DeviceFlags
&= ~DFLAGS_HIDDEN
;
9363 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9364 AtapiStallExecution(1000 * 1000);
9367 FindDevices(HwDeviceExtension
,
9368 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
9369 ? UNIATA_FIND_DEV_UNHIDE
: 0,
9370 AtaCtl
->addr
.PathId
);
9371 status
= SRB_STATUS_SUCCESS
;
9375 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
9377 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
9379 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9380 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9381 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9382 goto wrong_buffer_size
;
9384 LunExt
->DeviceFlags
= 0;
9385 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
9386 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
9387 //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
9388 UniataForgetDevice(LunExt
);
9391 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9392 AtapiStallExecution(1000 * 1000);
9395 status
= SRB_STATUS_SUCCESS
;
9398 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
9400 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
9402 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9403 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9404 pos
+sizeof(AtaCtl
->SetMode
) ));
9405 goto wrong_buffer_size
;
9407 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
9408 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
9410 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
9411 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
9412 if(LunExt
->LimitedTransferMode
>
9413 LunExt
->OrigTransferMode
) {
9414 // check for incorrect value
9415 LunExt
->LimitedTransferMode
=
9416 LunExt
->OrigTransferMode
;
9419 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
9421 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
9422 if(AtaCtl
->SetMode
.ApplyImmediately
) {
9423 AtapiDmaInit__(deviceExtension
, LunExt
);
9425 /* LunExt->TransferMode =
9426 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
9427 status
= SRB_STATUS_SUCCESS
;
9430 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
9432 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
9434 if(len
< pos
+sizeof(AtaCtl
->GetMode
)) {
9435 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9436 pos
+sizeof(AtaCtl
->GetMode
) ));
9437 goto wrong_buffer_size
;
9439 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
9440 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
9441 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
9442 AtaCtl
->GetMode
.PhyMode
= LunExt
->PhyTransferMode
;
9444 status
= SRB_STATUS_SUCCESS
;
9447 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION
: {
9449 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get version\n"));
9451 if(len
< pos
+sizeof(AtaCtl
->Version
)) {
9452 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9453 pos
+sizeof(AtaCtl
->Version
) ));
9454 goto wrong_buffer_size
;
9456 AtaCtl
->Version
.Length
= sizeof(GETDRVVERSION
);
9457 AtaCtl
->Version
.VersionMj
= UNIATA_VER_MJ
;
9458 AtaCtl
->Version
.VersionMn
= UNIATA_VER_MN
;
9459 AtaCtl
->Version
.SubVerMj
= UNIATA_VER_SUB_MJ
;
9460 AtaCtl
->Version
.SubVerMn
= UNIATA_VER_SUB_MN
;
9462 status
= SRB_STATUS_SUCCESS
;
9465 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
9467 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
9469 if(len
< pos
+sizeof(AtaCtl
->AdapterInfo
)) {
9470 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9471 pos
+sizeof(AtaCtl
->AdapterInfo
) ));
9472 goto wrong_buffer_size
;
9474 AtaCtl
->AdapterInfo
.HeaderLength
= sizeof(ADAPTERINFO
);
9476 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
9477 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
9478 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
9479 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
9480 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
9481 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
9482 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
9483 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
9484 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
9485 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
9486 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
9487 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
9488 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
9489 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
9490 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
9491 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
9492 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
9493 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
9494 AtaCtl
->AdapterInfo
.NumberLuns
= (UCHAR
)deviceExtension
->NumberLuns
;
9495 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
9496 if(deviceExtension
->FullDevName
) {
9497 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
9499 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
9500 AtaCtl
->AdapterInfo
.LunInfoValid
= FALSE
;
9501 AtaCtl
->AdapterInfo
.ChanHeaderLengthValid
= TRUE
;
9503 pos
+= AtaCtl
->AdapterInfo
.HeaderLength
;
9506 RtlZeroMemory(((PCHAR
)AtaCtl
)+pos
,
9509 if(len
>= pos
+AtaCtl
->AdapterInfo
.NumberChannels
*sizeof(CHANINFO
)) {
9510 PCHANINFO ChanInfo
= (PCHANINFO
)( ((PCHAR
)AtaCtl
)+pos
);
9511 PHW_CHANNEL cur_chan
;
9512 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Fill channel info\n"));
9513 for(i
=0;i
<AtaCtl
->AdapterInfo
.NumberChannels
;i
++) {
9514 KdPrint2((PRINT_PREFIX
"chan[%d] %x\n", i
, cur_chan
));
9515 cur_chan
= &(deviceExtension
->chan
[i
]);
9516 ChanInfo
->MaxTransferMode
= cur_chan
->MaxTransferMode
;
9517 ChanInfo
->ChannelCtrlFlags
= cur_chan
->ChannelCtrlFlags
;
9518 RtlCopyMemory(&(ChanInfo
->QueueStat
), &(cur_chan
->QueueStat
), sizeof(ChanInfo
->QueueStat
));
9519 ChanInfo
->ReorderCount
= cur_chan
->ReorderCount
;
9520 ChanInfo
->IntersectCount
= cur_chan
->IntersectCount
;
9521 ChanInfo
->TryReorderCount
= cur_chan
->TryReorderCount
;
9522 ChanInfo
->TryReorderHeadCount
= cur_chan
->TryReorderHeadCount
;
9523 ChanInfo
->TryReorderTailCount
= cur_chan
->TryReorderTailCount
;
9524 //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
9527 AtaCtl
->AdapterInfo
.ChanInfoValid
= TRUE
;
9528 AtaCtl
->AdapterInfo
.ChanHeaderLength
= sizeof(*ChanInfo
);
9531 status
= SRB_STATUS_SUCCESS
;
9534 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
9536 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
9538 ForgetBadBlocks(LunExt
);
9540 status
= SRB_STATUS_SUCCESS
;
9543 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
9545 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
9550 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
);
9553 status
= SRB_STATUS_SUCCESS
;
9557 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
9558 AtaCtl
->hdr
.ControlCode
));
9559 status
= SRB_STATUS_INVALID_REQUEST
;
9564 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
9565 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
9566 "SCSIDISK", "-UNIATA-"));
9568 status
= SRB_STATUS_INVALID_REQUEST
;
9573 } // end SRB_FUNCTION_IO_CONTROL
9576 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
9577 // Indicate unsupported command.
9578 status
= SRB_STATUS_INVALID_REQUEST
;
9586 PathId
= Srb
->PathId
;
9587 TargetId
= Srb
->TargetId
;
9590 if (status
!= SRB_STATUS_PENDING
) {
9592 KdPrint2((PRINT_PREFIX
9593 "AtapiStartIo: Srb %#x complete with status %#x\n",
9597 // Set status in SRB.
9598 Srb
->SrbStatus
= (UCHAR
)status
;
9601 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan
, Srb
));
9602 AtapiDmaDBSync(chan
, Srb
);
9604 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan
, Srb
));
9605 UniataRemoveRequest(chan
, Srb
);
9606 // Indicate command complete.
9607 KdPrint2((PRINT_PREFIX
"AtapiStartIo: ScsiPortNotification\n"));
9608 ScsiPortNotification(RequestComplete
,
9612 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataGetCurRequest\n"));
9613 // Remove current Srb & get next one
9614 if((Srb
= UniataGetCurRequest(chan
))) {
9615 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9616 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
9617 // current request is under precessing, thus
9618 // we should do nothing here
9622 KdPrint2((PRINT_PREFIX
"AtapiStartIo: chan %x, Src %x\n", chan
, Srb
));
9627 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
9629 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
9631 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
9632 // Indicate ready for next request.
9633 ScsiPortNotification(NextRequest
,
9637 ScsiPortNotification(NextLuRequest
,
9645 } // end AtapiStartIo__()
9650 UniataInitAtaCommands()
9656 KdPrint2((PRINT_PREFIX
"UniataInitAtaCommands:\n"));
9658 for(i
=0; i
<256; i
++) {
9663 //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
9666 case IDE_COMMAND_READ_DMA48
:
9667 case IDE_COMMAND_READ_DMA_Q48
:
9668 case IDE_COMMAND_READ_STREAM_DMA48
:
9669 case IDE_COMMAND_READ_STREAM48
:
9670 case IDE_COMMAND_WRITE_DMA48
:
9671 case IDE_COMMAND_WRITE_DMA_Q48
:
9672 case IDE_COMMAND_READ_DMA_Q
:
9673 case IDE_COMMAND_READ_DMA
:
9674 case IDE_COMMAND_WRITE_DMA
:
9675 case IDE_COMMAND_WRITE_DMA_Q
:
9676 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9677 case IDE_COMMAND_WRITE_STREAM48
:
9678 case IDE_COMMAND_WRITE_FUA_DMA48
:
9679 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9680 case IDE_COMMAND_READ_LOG_DMA48
:
9681 case IDE_COMMAND_WRITE_LOG_DMA48
:
9682 case IDE_COMMAND_TRUSTED_RCV_DMA
:
9683 case IDE_COMMAND_TRUSTED_SEND_DMA
:
9684 case IDE_COMMAND_DATA_SET_MGMT
:
9685 //KdPrint2((PRINT_PREFIX "DMA "));
9686 flags
|= ATA_CMD_FLAG_DMA
;
9690 case IDE_COMMAND_WRITE_FUA_DMA48
:
9691 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9692 case IDE_COMMAND_WRITE_MUL_FUA48
:
9694 flags
|= ATA_CMD_FLAG_FUA
;
9697 case IDE_COMMAND_READ48
:
9698 case IDE_COMMAND_READ_DMA48
:
9699 case IDE_COMMAND_READ_DMA_Q48
:
9700 case IDE_COMMAND_READ_MUL48
:
9701 case IDE_COMMAND_READ_STREAM_DMA48
:
9702 case IDE_COMMAND_READ_STREAM48
:
9703 case IDE_COMMAND_WRITE48
:
9704 case IDE_COMMAND_WRITE_DMA48
:
9705 case IDE_COMMAND_WRITE_DMA_Q48
:
9706 case IDE_COMMAND_WRITE_MUL48
:
9707 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9708 case IDE_COMMAND_WRITE_STREAM48
:
9709 case IDE_COMMAND_FLUSH_CACHE48
:
9710 case IDE_COMMAND_VERIFY48
:
9712 //KdPrint2((PRINT_PREFIX "48 "));
9713 flags
|= ATA_CMD_FLAG_48
;
9716 case IDE_COMMAND_READ
:
9717 case IDE_COMMAND_READ_MULTIPLE
:
9718 case IDE_COMMAND_READ_DMA
:
9719 case IDE_COMMAND_READ_DMA_Q
:
9720 case IDE_COMMAND_WRITE
:
9721 case IDE_COMMAND_WRITE_MULTIPLE
:
9722 case IDE_COMMAND_WRITE_DMA
:
9723 case IDE_COMMAND_WRITE_DMA_Q
:
9724 case IDE_COMMAND_FLUSH_CACHE
:
9725 case IDE_COMMAND_VERIFY
:
9727 //KdPrint2((PRINT_PREFIX "LBA "));
9728 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
9732 case IDE_COMMAND_READ_NATIVE_SIZE48
:
9733 case IDE_COMMAND_SET_NATIVE_SIZE48
:
9734 // we cannot set LBA flag for these commands to avoid BadBlock handling
9735 //flags |= ATA_CMD_FLAG_LBAIOsupp;
9736 flags
|= ATA_CMD_FLAG_48
;
9738 case IDE_COMMAND_READ_NATIVE_SIZE
:
9739 case IDE_COMMAND_SET_NATIVE_SIZE
:
9741 flags
|= ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_FUA
;
9744 flags
|= ATA_CMD_FLAG_48supp
;
9747 case IDE_COMMAND_READ
:
9748 command
= IDE_COMMAND_READ48
; break;
9749 case IDE_COMMAND_READ_MULTIPLE
:
9750 command
= IDE_COMMAND_READ_MUL48
; break;
9751 case IDE_COMMAND_READ_DMA
:
9752 command
= IDE_COMMAND_READ_DMA48
; break;
9753 case IDE_COMMAND_READ_DMA_Q
:
9754 command
= IDE_COMMAND_READ_DMA_Q48
; break;
9755 case IDE_COMMAND_WRITE
:
9756 command
= IDE_COMMAND_WRITE48
; break;
9757 case IDE_COMMAND_WRITE_MULTIPLE
:
9758 command
= IDE_COMMAND_WRITE_MUL48
; break;
9759 case IDE_COMMAND_WRITE_DMA
:
9760 command
= IDE_COMMAND_WRITE_DMA48
; break;
9761 case IDE_COMMAND_WRITE_DMA_Q
:
9762 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
9763 case IDE_COMMAND_FLUSH_CACHE
:
9764 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
9765 // case IDE_COMMAND_READ_NATIVE_SIZE:
9766 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
9767 case IDE_COMMAND_SET_NATIVE_SIZE
:
9768 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
9769 case IDE_COMMAND_VERIFY
:
9770 command
= IDE_COMMAND_VERIFY48
; break;
9772 //KdPrint2((PRINT_PREFIX "!28->48 "));
9773 flags
&= ~ATA_CMD_FLAG_48supp
;
9777 case IDE_COMMAND_READ
:
9778 case IDE_COMMAND_READ_MULTIPLE
:
9779 case IDE_COMMAND_READ_DMA48
:
9780 case IDE_COMMAND_READ_DMA_Q48
:
9781 case IDE_COMMAND_READ_STREAM_DMA48
:
9782 case IDE_COMMAND_READ_STREAM48
:
9783 case IDE_COMMAND_READ_DMA_Q
:
9784 case IDE_COMMAND_READ_DMA
:
9785 case IDE_COMMAND_READ_LOG_DMA48
:
9786 case IDE_COMMAND_TRUSTED_RCV_DMA
:
9787 case IDE_COMMAND_IDENTIFY
:
9788 case IDE_COMMAND_ATAPI_IDENTIFY
:
9789 //KdPrint2((PRINT_PREFIX "RD "));
9790 flags
|= ATA_CMD_FLAG_In
;
9792 case IDE_COMMAND_WRITE
:
9793 case IDE_COMMAND_WRITE_MULTIPLE
:
9794 case IDE_COMMAND_WRITE_DMA48
:
9795 case IDE_COMMAND_WRITE_DMA_Q48
:
9796 case IDE_COMMAND_WRITE_DMA
:
9797 case IDE_COMMAND_WRITE_DMA_Q
:
9798 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9799 case IDE_COMMAND_WRITE_STREAM48
:
9800 case IDE_COMMAND_WRITE_FUA_DMA48
:
9801 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9802 //KdPrint2((PRINT_PREFIX "WR "));
9803 flags
|= ATA_CMD_FLAG_Out
;
9807 //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
9808 AtaCommands48
[i
] = command
;
9809 AtaCommandFlags
[i
] = flags
;
9811 } // end UniataInitAtaCommands()
9815 Routine Description:
9817 Installable driver initialization entry point for system.
9825 Status from ScsiPortInitialize()
9832 IN PVOID DriverObject
,
9836 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
9839 ULONG statusToReturn
, newStatus
;
9840 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
9841 BOOLEAN ReEnter
= FALSE
;
9843 #ifndef USE_REACTOS_DDK
9847 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
9848 BOOLEAN PrimaryClaimed
= FALSE
;
9849 BOOLEAN SecondaryClaimed
= FALSE
;
9851 LARGE_INTEGER t0
, t1
;
9854 KdPrint2((PRINT_PREFIX
"%s", (PCCHAR
)ver_string
));
9855 a
= (WCHAR
)strlen(ver_string
);
9857 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
9859 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
9862 if(!SavedDriverObject
) {
9863 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
9864 #ifdef USE_REACTOS_DDK
9865 KdPrint(("UniATA Init: OS should be ReactOS\n"));
9870 // we are here for the 1st time
9871 // init CrossNT and get OS version
9872 if(!NT_SUCCESS(status
= CrNtInit(SavedDriverObject
, RegistryPath
))) {
9873 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status
));
9874 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
9877 #endif // USE_REACTOS_DDK
9878 KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion
, MinorVersion
, BuildNumber
, KeNumberProcessors
));
9880 KeQuerySystemTime(&t0
);
9882 KeQuerySystemTime(&t1
);
9883 } while(t0
.QuadPart
== t1
.QuadPart
);
9887 KeQuerySystemTime(&t1
);
9889 } while(t0
.QuadPart
== t1
.QuadPart
);
9890 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
9891 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
9893 KdPrint(("UniATA Init: ReEnter\n"));
9897 // (re)read bad block list
9898 InitBadBlocks(NULL
);
9901 // init ATA command translation table
9902 UniataInitAtaCommands();
9903 // get registry path to settings
9904 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
9905 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
9906 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
9907 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
9908 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
9909 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
9912 if(WinVer_Id() >= WinVer_2k
) {
9913 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
9914 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
9915 WinVer_WDM_Model
= TRUE
;
9917 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
9918 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
9919 WinVer_WDM_Model
= TRUE
;
9923 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
9924 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
9926 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
9929 statusToReturn
= 0xffffffff;
9931 // Zero out structure.
9932 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
9934 // Set size of hwInitializationData.
9935 hwInitializationData
.comm
.HwInitializationDataSize
=
9936 sizeof(hwInitializationData
.comm
) +
9937 // sizeof(hwInitializationData.nt4) +
9938 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
9939 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
9941 // Set entry points.
9942 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
9943 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
9944 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
9945 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
9947 // Specify size of extensions.
9948 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
9949 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
9950 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
9952 // Indicate PIO device.
9953 hwInitializationData
.comm
.MapBuffers
= TRUE
;
9954 // Set PnP-specific API
9955 if(WinVer_Id() > WinVer_NT
) {
9956 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
9957 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
9958 KdPrint(("set AtapiAdapterControl() ptr\n"));
9959 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
9962 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE enum supported BusMaster Devices\n"));
9966 g_opt_VirtualMachine
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualMachineType", g_opt_VirtualMachine
);
9967 if(g_opt_VirtualMachine
> VM_MAX_KNOWN
) {
9968 g_opt_VirtualMachine
= 0;
9970 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualBox", (g_opt_VirtualMachine
== VM_VBOX
))) {
9971 g_opt_VirtualMachine
= VM_VBOX
;
9973 // Pre-scan PCI bus, also check if we are under VM
9974 UniataEnumBusMasterController(DriverObject
, Argument2
);
9976 switch(g_opt_VirtualMachine
) {
9978 KdPrint2((PRINT_PREFIX
"adjust options for VirtualBox\n"));
9979 // adjust options for VirtualBox
9980 g_opt_WaitBusyCount
= 20000;
9981 g_opt_WaitBusyDelay
= 150;
9982 g_opt_WaitDrqDelay
= 100;
9983 g_opt_WaitBusyLongCount
= 20000;
9984 g_opt_MaxIsrWait
= 200;
9985 g_opt_AtapiSendDisableIntr
= 0;
9986 g_opt_AtapiDmaRawRead
= FALSE
;
9991 KdPrint2((PRINT_PREFIX
"old slow machine, adjust timings\n"));
9992 // old slow machine, adjust timings
9993 g_opt_WaitBusyCount
= 20000;
9994 g_opt_WaitBusyDelay
= 150;
9995 g_opt_WaitDrqDelay
= 100;
9996 g_opt_WaitBusyLongCount
= 20000;
9997 g_opt_MaxIsrWait
= 200;
10000 g_opt_WaitBusyCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyCount", g_opt_WaitBusyCount
); // 200 vs 20000
10001 g_opt_WaitBusyDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyDelay", g_opt_WaitBusyDelay
); // 10 vs 150
10002 g_opt_WaitDrqDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitDrqDelay", g_opt_WaitDrqDelay
); // 10 vs 100
10003 g_opt_WaitBusyLongCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongCount", g_opt_WaitBusyLongCount
); // 2000 vs 20000
10004 g_opt_WaitBusyLongDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongDelay", g_opt_WaitBusyLongDelay
); // 250 vs 250
10005 g_opt_AtapiSendDisableIntr
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr
); // 1 vs 0
10006 g_opt_AtapiDmaRawRead
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiDmaRawRead", g_opt_AtapiDmaRawRead
); // 1 vs 0
10007 g_opt_MaxIsrWait
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"MaxIsrWait", g_opt_MaxIsrWait
); // 40 vs xxx
10010 // Look for legacy ISA-bridged PCI IDE controller (onboard)
10011 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
10012 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
10013 for (i
=0; i
<BMListLen
; i
++) {
10015 if(!BMList
[i
].MasterDev
) {
10016 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
10019 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10023 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
10024 if(BMList
[i
].ChanInitOk
& 0x03) {
10025 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
10027 newStatus
= STATUS_SUCCESS
;
10031 //BMList[i].AltInitMasterDev = (UCHAR)0xff;
10033 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
10034 PrimaryClaimed
= TRUE
;
10035 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
10036 SecondaryClaimed
= TRUE
;
10038 if(!WinVer_WDM_Model
&& !PrimaryClaimed
&& !SecondaryClaimed
&&
10039 !(BMList
[i
].ChanInitOk
& 0x80)) {
10040 newStatus
= UniataClaimLegacyPCIIDE(i
);
10041 if(newStatus
!= STATUS_SUCCESS
) {
10042 KdPrint2((PRINT_PREFIX
"Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
10047 if(g_opt_Verbose
) {
10048 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
10052 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
10054 for(c
=0; c
<2; c
++) {
10056 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10060 if(PrimaryClaimed
) {
10061 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
10066 if(SecondaryClaimed
) {
10067 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
10072 if((WinVer_Id() < WinVer_2k
)) {
10073 // do not even try if already claimed
10075 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
10078 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
10081 if(!WinVer_WDM_Model
) {
10082 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10084 // in WDM model things are different....
10085 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
10086 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
10088 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10089 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10091 if(!WinVer_WDM_Model
) {
10092 BMList
[i
].channel
= (UCHAR
)c
;
10095 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
10096 newStatus
= ScsiPortInitialize(DriverObject
,
10098 &hwInitializationData
.comm
,
10099 (PVOID
)(i
| (alt
? 0x80000000 : 0)));
10100 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10101 if (newStatus
< statusToReturn
) {
10102 statusToReturn
= newStatus
;
10104 if (newStatus
== STATUS_SUCCESS
) {
10105 if(WinVer_Id() < WinVer_2k
) {
10106 // This should be done in HwInitialize under w2k+ to ensure that
10107 // channel is actually initialized
10108 BMList
[i
].ChanInitOk
|= 0x01 << c
;
10110 if(BMList
[i
].ChanInitOk
& (0x01 << c
)) {
10111 KdPrint2((PRINT_PREFIX
"HwInit passed\n"));
10115 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
10116 c = 1; // this will break our for()
10117 BMList[i].ChanInitOk |= 0x01 << c;
10122 /* if(WinVer_Id() >= WinVer_2k) {
10123 // the following didn't work under higher OSes,
10124 // until we move setting of FLAGS to HwInit
10125 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
10128 if(BMList
[i
].ChanInitOk
& 0x03) {
10129 // Under NT we receive status immediately, so
10130 // we can omit alternative init method if STATUS_SUCCESS returned.
10131 // Under w2k+ we relay on flags, set in HwInitialize.
10132 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
10135 if(WinVer_Id() >= WinVer_2k
) {
10136 // try AltInit if HwInit was not called immediately under w2k+
10137 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10139 // if (WinVer_Id() == WinVer_NT) and some error occured
10140 // try alternative init method
10141 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10144 if(g_opt_Verbose
) {
10145 if(BMList
[i
].ChanInitOk
& 0x03) {
10146 _PrintNtConsole(" OK\n");
10148 _PrintNtConsole(" failed\n");
10154 /* KeBugCheckEx(0xc000000e,
10155 (i << 16) | BMList[0].ChanInitOk,
10157 newStatus, statusToReturn);*/
10159 // Look for PCI IDE controller
10160 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
10161 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
10162 for (; i
<BMListLen
; i
++) {
10164 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", 0)) {
10167 /* if(BMList[i].MasterDev)
10169 if(g_opt_Verbose
) {
10170 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
10171 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
10172 BMList
[i
].busNumber
,
10173 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
10174 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
10177 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10178 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10179 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
10181 hwInitializationData
.comm
.VendorId
= (PVOID
)BMList
[i
].VendorId
;
10182 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
10183 hwInitializationData
.comm
.DeviceId
= (PVOID
)BMList
[i
].DeviceId
;
10184 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
10186 BMList
[i
].channel
= 0/*(UCHAR)c*/;
10188 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
10189 hwInitializationData
.comm
.VendorId
,
10190 hwInitializationData
.comm
.DeviceId
));
10191 newStatus
= ScsiPortInitialize(DriverObject
,
10193 &hwInitializationData
.comm
,
10195 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10196 if(newStatus
== (ULONG
)STATUS_DEVICE_DOES_NOT_EXIST
&& BMList
[i
].NeedAltInit
) {
10197 // Note: this is actually a BUG in scsiport.sys
10198 // It stops scanning PCI bus when reaches empty PCI Function inside Slot
10199 // However, this PCI Slot may have higher non-empty Functions
10200 // UniATA will perform all staff instead of ScsiPort under NT,
10201 // but for ReactOS it is better to patch ScsiPort.
10202 KdPrint2((PRINT_PREFIX
"STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
10203 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10204 newStatus
= ScsiPortInitialize(DriverObject
,
10206 &hwInitializationData
.comm
,
10207 (PVOID
)(i
| 0x80000000));
10208 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x (2)\n", newStatus
));
10210 if (newStatus
< statusToReturn
)
10211 statusToReturn
= newStatus
;
10213 if(g_opt_Verbose
) {
10214 if(newStatus
== STATUS_SUCCESS
) {
10215 _PrintNtConsole(" OK\n");
10217 _PrintNtConsole(" failed\n");
10223 /* KeBugCheckEx(0xc000000e,
10226 newStatus, statusToReturn);*/
10230 hwInitializationData
.comm
.VendorId
= 0;
10231 hwInitializationData
.comm
.VendorIdLength
= 0;
10232 hwInitializationData
.comm
.DeviceId
= 0;
10233 hwInitializationData
.comm
.DeviceIdLength
= 0;
10236 hwInitializationData
.comm
.SrbExtensionSize
= //FIELD_OFFSET(ATA_REQ, ata);
10238 KdPrint2((PRINT_PREFIX
"using AtaReq sz %x\n", hwInitializationData
.comm
.SrbExtensionSize
));
10241 // The adapter count is used by the find adapter routine to track how
10242 // which adapter addresses have been tested.
10244 // Indicate 2 access ranges and reset FindAdapter.
10245 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
10246 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindController
;
10248 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
10249 // Indicate ISA bustype.
10250 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10253 // Call initialization for ISA bustype.
10254 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
10255 newStatus
= ScsiPortInitialize(DriverObject
,
10257 &hwInitializationData
.comm
,
10259 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10260 if (newStatus
< statusToReturn
)
10261 statusToReturn
= newStatus
;
10263 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
10265 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
10266 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
10269 newStatus
= ScsiPortInitialize(DriverObject
,
10271 &hwInitializationData
.comm
,
10273 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10274 if (newStatus
< statusToReturn
)
10275 statusToReturn
= newStatus
;
10277 InDriverEntry
= FALSE
;
10279 KdPrint2((PRINT_PREFIX
"\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn
));
10281 return statusToReturn
;
10283 } // end DriverEntry()
10286 PSCSI_REQUEST_BLOCK
10288 BuildMechanismStatusSrb(
10289 IN PVOID HwDeviceExtension
,
10290 IN PSCSI_REQUEST_BLOCK Srb
10293 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10294 PSCSI_REQUEST_BLOCK srb
;
10296 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10298 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10300 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10302 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10303 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10304 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10305 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10307 // Set flags to disable synchronous negociation.
10308 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10310 // Set timeout to 4 seconds.
10311 srb
->TimeOutValue
= 4;
10313 srb
->CdbLength
= 6;
10314 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
10315 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10316 srb
->SrbExtension
= AtaReq
;
10318 // Set CDB operation code.
10319 cdb
= (PCDB
)srb
->Cdb
;
10320 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
10321 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10323 KdPrint2((PRINT_PREFIX
" MechanismStatusSrb %#x\n", srb
));
10326 } // end BuildMechanismStatusSrb()
10328 #endif //UNIATA_CORE
10330 PSCSI_REQUEST_BLOCK
10332 BuildRequestSenseSrb (
10333 IN PVOID HwDeviceExtension
,
10334 IN PSCSI_REQUEST_BLOCK Srb
10337 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10338 PSCSI_REQUEST_BLOCK srb
;
10340 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10342 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10344 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10346 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10347 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10348 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10349 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10351 // Set flags to disable synchronous negociation.
10352 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10354 // Set timeout to 2 seconds.
10355 srb
->TimeOutValue
= 4;
10357 srb
->CdbLength
= 6;
10358 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
10359 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
10360 srb
->SrbExtension
= AtaReq
;
10362 // Set CDB operation code.
10363 cdb
= (PCDB
)srb
->Cdb
;
10364 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
10365 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
10367 KdPrint2((PRINT_PREFIX
" RequestSenseSrb %#x\n", srb
));
10370 } // end BuildRequestSenseSrb()
10372 #ifndef UNIATA_CORE
10376 AtapiRegCheckDevLunValue(
10377 IN PVOID HwDeviceExtension
,
10378 IN PCWCH NamePrefix
,
10386 ULONG val
= Default
;
10388 val
= AtapiRegCheckParameterValue(
10389 HwDeviceExtension
, NamePrefix
, Name
, val
);
10391 if(chan
!= CHAN_NOT_SPECIFIED
) {
10392 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
10393 val
= AtapiRegCheckParameterValue(
10394 HwDeviceExtension
, namex
, Name
, val
);
10395 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
10396 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
10397 val
= AtapiRegCheckParameterValue(
10398 HwDeviceExtension
, namex
, Name
, val
);
10402 } // end AtapiRegCheckDevLunValue()
10415 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
10434 swprintf(Buffer
+j
, L
"%2.2x", a
);
10442 } // end EncodeVendorStr()
10446 AtapiRegCheckDevValue(
10447 IN PVOID HwDeviceExtension
,
10454 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10455 // WCHAR name0[11];
10456 // WCHAR name1[11+4+5];
10457 // WCHAR name2[11+4+4+10];
10458 // WCHAR name3[11+4+4+5+20];
10459 // WCHAR name3[11+4+4+5+20+1];
10468 IN ULONG SlotNumber
;
10470 ULONG val
= Default
;
10472 KdPrint(( " Parameter %ws\n", Name
));
10474 if(deviceExtension
) {
10475 VendorID
= deviceExtension
->DevID
& 0xffff;
10476 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
10477 SlotNumber
= deviceExtension
->slotNumber
;
10481 SlotNumber
= 0xffffffff;
10484 val
= AtapiRegCheckDevLunValue(
10485 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
10487 if(deviceExtension
) {
10488 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
10490 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
10491 swprintf(namex
, L
"Parameters%s", namev
);
10492 val
= AtapiRegCheckDevLunValue(
10493 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10496 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
10497 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
10498 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
10500 swprintf(namex
, L
"Parameters%s", namev
);
10501 val
= AtapiRegCheckDevLunValue(
10502 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10504 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
10505 val
= AtapiRegCheckDevLunValue(
10506 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10508 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
10509 val
= AtapiRegCheckDevLunValue(
10510 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10512 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
10514 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
10515 swprintf(namex
, L
"Parameters%s", namev
);
10516 val
= AtapiRegCheckDevLunValue(
10517 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10519 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
10520 swprintf(namex
, L
"Parameters%s", namev
);
10521 val
= AtapiRegCheckDevLunValue(
10522 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10525 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
10527 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
10528 swprintf(namex
, L
"Parameters%s", namev
);
10529 val
= AtapiRegCheckDevLunValue(
10530 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10532 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
10533 swprintf(namex
, L
"Parameters%s", namev
);
10534 val
= AtapiRegCheckDevLunValue(
10535 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10540 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
10543 } // end AtapiRegCheckDevValue()
10546 The user must specify that Xxx is to run on the platform
10547 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
10548 Services\UniATA\Xxx:REG_DWORD:Zzz.
10550 The user can override the global setting to enable or disable Xxx on a
10551 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
10552 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
10554 If this registry value does not exist or contains the value zero then
10555 the timer to check for media change does not run.
10559 RegistryPath - pointer to the unicode string inside
10560 ...\CurrentControlSet\Services\UniATA
10561 DeviceNumber - The number of the HBA device object
10563 Returns: Registry Key value
10567 AtapiRegCheckParameterValue(
10568 IN PVOID HwDeviceExtension
,
10569 IN PCWSTR PathSuffix
,
10574 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
10576 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10578 LONG zero
= Default
;
10580 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
10583 LONG doRun
= Default
;
10585 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
10587 UNICODE_STRING paramPath
;
10589 // <SavedRegPath>\<PathSuffix> -> <Name>
10590 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
10591 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
10593 paramPath
.Length
= 0;
10594 paramPath
.MaximumLength
= RegistryPath
->Length
+
10595 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
10596 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
10597 if(!paramPath
.Buffer
) {
10598 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
10602 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
10603 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
10604 RtlAppendUnicodeToString(¶mPath
, L
"\\");
10605 RtlAppendUnicodeToString(¶mPath
, REGRTL_STR_PTYPE PathSuffix
);
10607 // Check for the Xxx value.
10608 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
10610 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
10611 parameters
[0].Name
= REGRTL_STR_PTYPE Name
;
10612 parameters
[0].EntryContext
= &doRun
;
10613 parameters
[0].DefaultType
= REG_DWORD
;
10614 parameters
[0].DefaultData
= &zero
;
10615 parameters
[0].DefaultLength
= sizeof(ULONG
);
10617 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
10618 paramPath
.Buffer
, parameters
, NULL
, NULL
);
10619 if(NT_SUCCESS(status
)) {
10620 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix
, Name
, doRun
));
10623 ExFreePool(paramPath
.Buffer
);
10625 if(!NT_SUCCESS(status
)) {
10631 #undef ITEMS_TO_QUERY
10633 } // end AtapiRegCheckParameterValue()
10636 SCSI_ADAPTER_CONTROL_STATUS
10638 AtapiAdapterControl(
10639 IN PVOID HwDeviceExtension
,
10640 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
10641 IN PVOID Parameters
10644 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10645 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
10646 ULONG numberChannels
= deviceExtension
->NumberChannels
;
10650 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
10652 switch(ControlType
) {
10653 case ScsiQuerySupportedControlTypes
: {
10654 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
10655 TRUE
, // ScsiQuerySupportedControlTypes
10656 TRUE
, // ScsiStopAdapter
10657 TRUE
, // ScsiRestartAdapter
10658 FALSE
, // ScsiSetBootConfig
10659 FALSE
// ScsiSetRunningConfig
10662 ULONG lim
= ScsiAdapterControlMax
;
10665 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
10667 if(pControlTypeList
->MaxControlType
< lim
) {
10668 lim
= pControlTypeList
->MaxControlType
;
10671 for(i
= 0; i
< lim
; i
++) {
10672 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
10678 case ScsiStopAdapter
: {
10680 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
10681 // Shut down all interrupts on the adapter. They'll get re-enabled
10682 // by the initialization routines.
10683 for (c
= 0; c
< numberChannels
; c
++) {
10684 AtapiResetController(deviceExtension
, c
);
10685 AtapiDisableInterrupts(deviceExtension
, c
);
10687 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
10688 // we must never get here for non-PCI
10689 status
= UniataDisconnectIntr2(HwDeviceExtension
);
10690 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
10694 case ScsiRestartAdapter
: {
10696 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
10697 // Enable all the interrupts on the adapter while port driver call
10698 // for power up an HBA that was shut down for power management
10700 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
10701 status
= UniataConnectIntr2(HwDeviceExtension
);
10702 for (c
= 0; c
< numberChannels
; c
++) {
10703 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
10704 FindDevices(HwDeviceExtension
, 0, c
);
10705 AtapiEnableInterrupts(deviceExtension
, c
);
10706 AtapiHwInitialize__(deviceExtension
, c
);
10708 if(deviceExtension
->Isr2DevObj
) {
10709 // we must never get here for non-PCI
10710 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
10717 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
10718 return ScsiAdapterControlUnsuccessful
;
10722 return ScsiAdapterControlSuccess
;
10723 } // end AtapiAdapterControl()
10725 #endif //UNIATA_CORE
10744 UCHAR dbg_print_tmp_buff
[512];
10745 // UNICODE_STRING msgBuff;
10747 va_start(ap
, DebugMessage
);
10749 len
= _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], 511, DebugMessage
, ap
);
10751 dbg_print_tmp_buff
[511] = 0;
10753 KdPrint(((PCHAR
)&(dbg_print_tmp_buff
[0])));
10754 HalDisplayString(dbg_print_tmp_buff
);
10758 } // end PrintNtConsole()