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_AHCI
) {
6980 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: force use dma (ahci)\n"));
6984 /* if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) {
6985 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n"));
6989 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
6990 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
6992 if(AtaReq
->TransferLength
) {
6994 switch(Srb
->Cdb
[0]) {
6996 case SCSIOP_WRITE12
:
6997 case SCSIOP_WRITE16
:
6999 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
7002 case SCSIOP_RECEIVE
:
7007 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
7009 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7010 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7013 if(AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7014 (PUCHAR
)(AtaReq
->DataBuffer
),
7015 Srb
->DataTransferLength
7016 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
7018 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7023 case SCSIOP_READ_CD
:
7024 if(deviceExtension
->opt_AtapiDmaRawRead
)
7025 goto call_dma_setup
;
7029 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
7030 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7035 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
7036 KdPrint2((PRINT_PREFIX
"dma RO\n"));
7048 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7049 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7052 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7053 (PUCHAR
)(AtaReq
->DataBuffer
),
7054 Srb
->DataTransferLength
)) {
7055 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
7058 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7062 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer, no DMA setup\n"));
7066 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7068 UniataAhciSetupCmdPtr(AtaReq
);
7070 if(!Srb
->DataTransferLength
) {
7071 KdPrint2((PRINT_PREFIX
"zero-transfer\n"));
7074 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7075 (PUCHAR
)(AtaReq
->DataBuffer
),
7076 Srb
->DataTransferLength
)) {
7077 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no AHCI dma!\n"));
7078 return SRB_STATUS_ERROR
;
7081 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7083 FeatureReg
|= ATA_F_DMA
;
7084 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7085 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7086 FeatureReg
|= ATA_F_DMAREAD
;
7090 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: setup AHCI FIS\n"));
7091 // this is done in UniataAhciSetupFIS_H2D()
7092 //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
7093 RtlCopyMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), Srb
->Cdb
, Srb
->CdbLength
);
7095 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
7096 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
7097 IDE_COMMAND_ATAPI_PACKET
/* command */,
7099 (Srb
->DataTransferLength
>= 0x10000) ? (USHORT
)(0xffff) : (USHORT
)(Srb
->DataTransferLength
),
7100 FeatureReg
/* feature */
7104 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AHCI !FIS\n"));
7105 return SRB_STATUS_ERROR
;
7108 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0,
7109 ((Srb
->DataTransferLength
&& (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) ? ATA_AHCI_CMD_WRITE
: 0) |
7110 (ATA_AHCI_CMD_ATAPI
| ATA_AHCI_CMD_PREFETCH
),
7111 fis_size
, DeviceNumber
);
7113 KdPrint2((PRINT_PREFIX
"AtapiSendCommand ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
7117 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7118 // if this is queued request, reinit DMA and check
7119 // if DMA mode is still available
7120 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
7121 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7122 if (/*EnableDma &&*/
7123 (LunExt
->TransferMode
>= ATA_DMA
)) {
7124 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
7127 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7128 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
7131 dma_reinited
= TRUE
;
7135 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
7136 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
7137 return SRB_STATUS_PENDING
;
7139 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma
, Srb
->Cdb
[0]));
7140 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7141 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7144 if((Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) && !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7145 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
7147 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7148 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7149 } if(AtaReq
->TransferLength
) {
7151 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
7152 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7153 if (/*EnableDma &&*/
7154 (LunExt
->TransferMode
>= ATA_DMA
)) {
7157 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7162 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
7164 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7165 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7166 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
7167 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7170 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
7171 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7172 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7175 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
7177 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
7178 &(Srb
->Cdb
), Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
7180 // Make sure command is to ATAPI device.
7181 flags
= LunExt
->DeviceFlags
;
7182 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7183 if((Srb
->Lun
) > (LunExt
->DiscsPresent
- 1)) {
7185 // Indicate no device found at this address.
7186 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7187 return SRB_STATUS_SELECTION_TIMEOUT
;
7189 } else if(Srb
->Lun
> 0) {
7190 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7191 return SRB_STATUS_SELECTION_TIMEOUT
;
7194 if(!(flags
& DFLAGS_ATAPI_DEVICE
)) {
7195 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7196 return SRB_STATUS_SELECTION_TIMEOUT
;
7199 // Select device 0 or 1. Or more for PM
7200 SelectDrive(chan
, DeviceNumber
);
7202 // Verify that controller is ready for next command.
7203 GetStatus(chan
, statusByte
);
7204 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
7206 if(statusByte
== IDE_STATUS_WRONG
) {
7207 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
7210 if(statusByte
& IDE_STATUS_BUSY
) {
7211 if(statusByte
& IDE_STATUS_DSC
) {
7212 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
7214 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
7215 // We have to make reset here, since we are expecting device to be available
7216 //return SRB_STATUS_BUSY; // this cause queue freeze
7220 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7222 // Check if command list is free
7223 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
7225 // controller is busy, however we expect it to be free
7226 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI
));
7230 if(statusByte
& IDE_STATUS_ERROR
) {
7231 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
7233 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
7234 // Read the error reg. to clear it and fail this request.
7235 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7236 return MapError(deviceExtension
, Srb
);
7238 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
7241 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
7242 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
7243 if((!(statusByte
& IDE_STATUS_DSC
)) &&
7244 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
7246 AtapiStallExecution(200);
7247 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
7248 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7249 return SRB_STATUS_PENDING
;
7252 if(IS_RDP(Srb
->Cdb
[0])) {
7254 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
7258 if(statusByte
& IDE_STATUS_DRQ
) {
7260 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
7262 // Try to drain the data that one preliminary device thinks that it has
7263 // to transfer. Hopefully this random assertion of DRQ will not be present
7264 // in production devices.
7265 statusByte
= AtapiSuckPort2(chan
);
7267 for (i = 0; i < 0x10000; i++) {
7268 GetStatus(chan, statusByte);
7269 if(statusByte & IDE_STATUS_DRQ) {
7270 AtapiReadPort2(chan, IDX_IO1_i_Data);
7276 if (statusByte
& IDE_STATUS_DRQ
) {
7278 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte
));
7280 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7282 AtapiSoftReset(chan
, DeviceNumber
);
7284 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
7285 // Re-initialize Atapi device.
7286 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), DeviceNumber
, TRUE
);
7288 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
7289 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
7291 // Inform the port driver that the bus has been reset.
7292 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
7293 // Clean up device extension fields that AtapiStartIo won't.
7294 UniataExpectChannelInterrupt(chan
, FALSE
);
7296 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
7299 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7301 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7302 return SRB_STATUS_BUS_RESET;
7305 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
7309 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
7310 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7311 return SRB_STATUS_SELECTION_TIMEOUT
;
7315 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7316 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
7317 Srb
->Cdb
[1] &= ~0xE0;
7318 if((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
7319 // Torisan changer. TUR's are overloaded to be platter switches.
7320 Srb
->Cdb
[7] = Srb
->Lun
;
7327 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
7329 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
7332 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7333 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AHCI, begin transaction\n"));
7334 //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
7335 UniataExpectChannelInterrupt(chan
, TRUE
);
7336 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
7337 return SRB_STATUS_PENDING
;
7340 statusByte
= WaitOnBusy(chan
);
7341 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
7345 FeatureReg
|= ATA_F_DMA
;
7346 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7347 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7348 FeatureReg
|= ATA_F_DMAREAD
;
7352 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, FeatureReg
);
7354 // Write transfer byte count to registers.
7355 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
7356 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
7358 if (Srb
->DataTransferLength
>= 0x10000) {
7359 byteCountLow
= byteCountHigh
= 0xFF;
7362 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
7363 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
7365 if (flags
& DFLAGS_INT_DRQ
) {
7367 // This device interrupts when ready to receive the packet.
7369 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
7372 UniataExpectChannelInterrupt(chan
, TRUE
);
7373 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
7374 InterlockedExchange(&(chan
->CheckIntr
),
7377 // Write ATAPI packet command.
7378 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7380 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
7381 return SRB_STATUS_PENDING
;
7385 // This device quickly sets DRQ when ready to receive the packet.
7387 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
7390 UniataExpectChannelInterrupt(chan
, TRUE
);
7391 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
7392 InterlockedExchange(&(chan
->CheckIntr
),
7395 if(g_opt_AtapiSendDisableIntr
) {
7396 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7399 // Write ATAPI packet command.
7400 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7404 statusByte
= WaitForDrq(chan
);
7406 // Need to read status register and clear interrupt (if any)
7407 GetBaseStatus(chan
, statusByte
);
7409 if (!(statusByte
& IDE_STATUS_DRQ
)) {
7411 if(g_opt_AtapiSendDisableIntr
) {
7412 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7414 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte
));
7415 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7416 return SRB_STATUS_ERROR
;
7419 GetStatus(chan
, statusByte
);
7420 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
7422 // Send CDB to device.
7423 statusByte
= WaitOnBaseBusy(chan
);
7425 // Indicate expecting an interrupt and wait for it.
7426 UniataExpectChannelInterrupt(chan
, TRUE
);
7427 InterlockedExchange(&(chan
->CheckIntr
),
7429 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
7431 GetBaseStatus(chan
, statusByte
);
7433 if(g_opt_AtapiSendDisableIntr
) {
7434 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7439 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
7442 GetStatus(chan
, statusByte
);
7443 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: cmd status (%#x)\n", statusByte
));
7445 if(statusByte
& IDE_STATUS_ERROR
) {
7446 GetBaseStatus(chan
, statusByte
);
7447 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on cmd: (%#x)\n", statusByte
));
7448 // Read the error reg. to clear it and fail this request.
7449 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7450 return MapError(deviceExtension
, Srb
);
7452 /* if(statusByte & IDE_STATUS_DSC) {
7453 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DSC on cmd: (%#x)\n", statusByte));
7454 // Read the error reg. to clear it and fail this request.
7455 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7456 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte));
7457 if(statusByte >> 4) {
7458 GetBaseStatus(chan, statusByte);
7459 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7460 return MapError(deviceExtension, Srb);
7464 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
7465 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
7468 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
7470 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
7471 return SRB_STATUS_PENDING
;
7473 } // end AtapiSendCommand()
7480 Routine Description:
7481 Program ATA registers for IDE disk transfer.
7484 HwDeviceExtension - ATAPI driver storage.
7485 Srb - System request block.
7488 SRB status (pending if all goes well).
7493 ULONG check_point
= 0;
7494 #define SetCheckPoint(cp) { check_point = (cp) ; }
7496 #define SetCheckPoint(cp)
7502 IN PVOID HwDeviceExtension
,
7503 IN PSCSI_REQUEST_BLOCK Srb
,
7508 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
7511 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7516 PHW_LU_EXTENSION LunExt
;
7520 UCHAR statusByte
,errorByte
;
7521 ULONG status
= SRB_STATUS_INVALID_REQUEST
;
7524 PMODE_PARAMETER_HEADER modeData
;
7531 //ULONG __ebp__ = 0;
7533 SetCheckPoint(0x20);
7534 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
7539 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
7540 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
7541 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
7542 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
7543 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
7545 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
7546 Srb->SrbExtension));
7547 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
7550 SetCheckPoint(0x30);
7551 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7553 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
7555 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
7557 KdPrint2((PRINT_PREFIX
"** --- **\n"));
7559 lChannel
= GET_CHANNEL(Srb
);
7560 chan
= &(deviceExtension
->chan
[lChannel
]);
7561 //ldev = GET_LDEV(Srb);
7562 DeviceNumber
= GET_CDEV(Srb
);
7563 LunExt
= chan
->lun
[DeviceNumber
];
7565 SetCheckPoint(0x40);
7566 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
7567 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
7569 cdb
= (PCDB
)(Srb
->Cdb
);
7571 if(CmdAction
== CMD_ACTION_PREPARE
) {
7572 switch (Srb
->Cdb
[0]) {
7573 case SCSIOP_SERVICE_ACTION16
:
7574 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
7577 goto default_no_prep
;
7580 case SCSIOP_INQUIRY
: // now it requires device access
7582 case SCSIOP_READ_CAPACITY
:
7586 case SCSIOP_WRITE12
:
7588 case SCSIOP_WRITE16
:
7589 case SCSIOP_REQUEST_SENSE
:
7591 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
7597 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
7598 return SRB_STATUS_BUSY
;
7602 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
7603 switch (Srb
->Cdb
[0]) {
7604 case SCSIOP_INQUIRY
:
7606 KdPrint2((PRINT_PREFIX
7607 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
7608 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7609 // Filter out wrong TIDs.
7610 if ((Srb
->Lun
!= 0) ||
7611 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
7612 (Srb
->TargetId
>= deviceExtension
->NumberLuns
)) {
7614 KdPrint2((PRINT_PREFIX
7615 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
7616 // Indicate no device found at this address.
7617 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7622 KdPrint2((PRINT_PREFIX
7623 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
7624 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
7625 PIDENTIFY_DATA2 identifyData
= &(LunExt
->IdentifyData
);
7627 if (!(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7629 if(!CheckDevice(HwDeviceExtension
, lChannel
, DeviceNumber
, FALSE
)) {
7630 KdPrint2((PRINT_PREFIX
7631 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
7632 // Indicate no device found at this address.
7634 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7638 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, DeviceNumber
)) {
7639 KdPrint2((PRINT_PREFIX
7640 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
7641 // Indicate no device found at this address.
7642 UniataForgetDevice(chan
->lun
[DeviceNumber
]);
7644 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7649 // Zero INQUIRY data structure.
7650 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
7652 // Standard IDE interface only supports disks.
7653 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
7655 // Set the removable bit, if applicable.
7656 if (LunExt
->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
7657 KdPrint2((PRINT_PREFIX
7658 "RemovableMedia\n"));
7659 inquiryData
->RemovableMedia
= 1;
7661 // Set the Relative Addressing (LBA) bit, if applicable.
7662 if (LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
7663 inquiryData
->RelativeAddressing
= 1;
7664 KdPrint2((PRINT_PREFIX
7665 "RelativeAddressing\n"));
7667 // Set the CommandQueue bit
7668 inquiryData
->CommandQueue
= 1;
7670 // Fill in vendor identification fields.
7671 for (i
= 0; i
< 24; i
+= 2) {
7672 MOV_DW_SWP(inquiryData
->DeviceIdentificationString
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
7675 // Initialize unused portion of product id.
7676 for (i = 0; i < 4; i++) {
7677 inquiryData->ProductId[12+i] = ' ';
7680 // Move firmware revision from IDENTIFY data to
7681 // product revision in INQUIRY data.
7682 for (i
= 0; i
< 4; i
+= 2) {
7683 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
7686 status
= SRB_STATUS_SUCCESS
;
7691 case SCSIOP_REPORT_LUNS
: {
7694 PREPORT_LUNS_INFO_HDR LunInfo
;
7696 KdPrint2((PRINT_PREFIX
7697 "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
7698 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7700 MOV_DD_SWP(alen
, cdb
->REPORT_LUNS
.AllocationLength
);
7707 LunInfo
= (PREPORT_LUNS_INFO_HDR
)(Srb
->DataBuffer
);
7708 RtlZeroMemory(LunInfo
, 16);
7710 MOV_DD_SWP( LunInfo
->ListLength
, alen
);
7711 Srb
->DataTransferLength
= 16;
7712 status
= SRB_STATUS_SUCCESS
;
7716 case SCSIOP_MODE_SENSE
:
7718 KdPrint2((PRINT_PREFIX
7719 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
7720 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7722 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_POWER_CONDITION
) {
7723 PMODE_POWER_CONDITION_PAGE modeData
;
7725 KdPrint2((PRINT_PREFIX
"MODE_PAGE_POWER_CONDITION\n"));
7726 modeData
= (PMODE_POWER_CONDITION_PAGE
)(Srb
->DataBuffer
);
7727 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_POWER_CONDITION_PAGE
)) {
7728 status
= SRB_STATUS_DATA_OVERRUN
;
7730 RtlZeroMemory(modeData
, sizeof(MODE_POWER_CONDITION_PAGE
));
7731 modeData
->PageCode
= MODE_PAGE_POWER_CONDITION
;
7732 modeData
->PageLength
= sizeof(MODE_PAGE_POWER_CONDITION
)-sizeof(MODE_PARAMETER_HEADER
);
7733 modeData
->Byte3
.Fields
.Idle
= LunExt
->PowerState
<= StartStop_Power_Idle
;
7734 modeData
->Byte3
.Fields
.Standby
= LunExt
->PowerState
== StartStop_Power_Standby
;
7735 Srb
->DataTransferLength
= sizeof(MODE_POWER_CONDITION_PAGE
);
7736 status
= SRB_STATUS_SUCCESS
;
7739 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_CACHING
) {
7740 PMODE_CACHING_PAGE modeData
;
7742 KdPrint2((PRINT_PREFIX
"MODE_PAGE_CACHING\n"));
7743 modeData
= (PMODE_CACHING_PAGE
)(Srb
->DataBuffer
);
7744 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_CACHING_PAGE
)) {
7745 status
= SRB_STATUS_DATA_OVERRUN
;
7747 RtlZeroMemory(modeData
, sizeof(MODE_CACHING_PAGE
));
7748 modeData
->PageCode
= MODE_PAGE_CACHING
;
7749 modeData
->PageLength
= sizeof(MODE_CACHING_PAGE
)-sizeof(MODE_PARAMETER_HEADER
);
7750 modeData
->ReadDisableCache
= (LunExt
->DeviceFlags
& DFLAGS_RCACHE_ENABLED
) ? 0 : 1;
7751 modeData
->WriteCacheEnable
= (LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) ? 1 : 0;
7752 Srb
->DataTransferLength
= sizeof(MODE_CACHING_PAGE
);
7753 status
= SRB_STATUS_SUCCESS
;
7756 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
7758 // This is used to determine if the media is write-protected.
7759 // Since IDE does not support mode sense then we will modify just the portion we need
7760 // so the higher level driver can determine if media is protected.
7762 //SelectDrive(chan, DeviceNumber);
7763 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7764 //statusByte = WaitOnBusy(chan);
7765 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
7767 if (!(statusByte
& IDE_STATUS_ERROR
)) {
7769 // no error occured return success, media is not protected
7770 UniataExpectChannelInterrupt(chan
, FALSE
);
7771 InterlockedExchange(&(chan
->CheckIntr
),
7773 status
= SRB_STATUS_SUCCESS
;
7777 // error occured, handle it locally, clear interrupt
7778 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7780 GetBaseStatus(chan
, statusByte
);
7781 UniataExpectChannelInterrupt(chan
, FALSE
);
7782 InterlockedExchange(&(chan
->CheckIntr
),
7784 status
= SRB_STATUS_SUCCESS
;
7786 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
7788 //media is write-protected, set bit in mode sense buffer
7789 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
7791 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
7792 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
7795 status
= SRB_STATUS_SUCCESS
;
7797 status
= SRB_STATUS_INVALID_REQUEST
;
7801 case SCSIOP_TEST_UNIT_READY
:
7803 KdPrint2((PRINT_PREFIX
7804 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
7805 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7806 if (chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
7808 // Select device 0 or 1.
7809 //SelectDrive(chan, DeviceNumber);
7810 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7811 // Wait for busy. If media has not changed, return success
7812 //statusByte = WaitOnBusy(chan);
7813 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
7815 if (!(statusByte
& IDE_STATUS_ERROR
)){
7816 UniataExpectChannelInterrupt(chan
, FALSE
);
7817 InterlockedExchange(&(chan
->CheckIntr
),
7819 status
= SRB_STATUS_SUCCESS
;
7821 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7822 if (errorByte
== IDE_ERROR_DATA_ERROR
){
7824 // Special case: If current media is write-protected,
7825 // the 0xDA command will always fail since the write-protect bit
7826 // is sticky,so we can ignore this error
7827 GetBaseStatus(chan
, statusByte
);
7828 UniataExpectChannelInterrupt(chan
, FALSE
);
7829 InterlockedExchange(&(chan
->CheckIntr
),
7831 status
= SRB_STATUS_SUCCESS
;
7835 // Request sense buffer to be build
7836 UniataExpectChannelInterrupt(chan
, TRUE
);
7837 InterlockedExchange(&(chan
->CheckIntr
),
7839 status
= SRB_STATUS_PENDING
;
7843 status
= SRB_STATUS_SUCCESS
;
7848 case SCSIOP_READ_CAPACITY
:
7850 KdPrint2((PRINT_PREFIX
7851 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7852 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7853 // Claim 512 byte blocks (big-endian).
7854 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7856 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY_DATA
));
7857 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
7859 // Calculate last sector.
7860 if(!(i
= (ULONG
)LunExt
->NumOfSectors
)) {
7861 i
= LunExt
->IdentifyData
.SectorsPerTrack
*
7862 LunExt
->IdentifyData
.NumberOfHeads
*
7863 LunExt
->IdentifyData
.NumberOfCylinders
;
7867 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
7868 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
7869 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
7871 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
7873 KdPrint2((PRINT_PREFIX
7874 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
7876 LunExt
->IdentifyData
.SectorsPerTrack
,
7877 LunExt
->IdentifyData
.NumberOfHeads
,
7878 LunExt
->IdentifyData
.NumberOfCylinders
));
7881 status
= SRB_STATUS_SUCCESS
;
7884 case SCSIOP_SERVICE_ACTION16
:
7886 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
7887 KdPrint2((PRINT_PREFIX
7888 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7889 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7890 // Claim 512 byte blocks (big-endian).
7891 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7893 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY16_DATA
));
7894 MOV_DD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
7896 // Calculate last sector.
7897 if(!(lba
= LunExt
->NumOfSectors
)) {
7898 lba
= LunExt
->IdentifyData
.SectorsPerTrack
*
7899 LunExt
->IdentifyData
.NumberOfHeads
*
7900 LunExt
->IdentifyData
.NumberOfCylinders
;
7903 MOV_QD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, lba
);
7905 KdPrint2((PRINT_PREFIX
7906 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n",
7908 LunExt
->IdentifyData
.SectorsPerTrack
,
7909 LunExt
->IdentifyData
.NumberOfHeads
,
7910 LunExt
->IdentifyData
.NumberOfCylinders
));
7912 status
= SRB_STATUS_SUCCESS
;
7919 case SCSIOP_VERIFY12
:
7920 case SCSIOP_VERIFY16
:
7922 KdPrint2((PRINT_PREFIX
7923 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
7924 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7925 status
= IdeVerify(HwDeviceExtension
,Srb
);
7932 case SCSIOP_WRITE12
:
7934 case SCSIOP_WRITE16
:
7936 KdPrint2((PRINT_PREFIX
7937 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
7938 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
7939 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7940 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7941 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
7942 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
7943 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
7944 status
= IdeReadWrite(HwDeviceExtension
,
7948 case SCSIOP_START_STOP_UNIT
:
7950 KdPrint2((PRINT_PREFIX
7951 "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
7952 cdb
->START_STOP
.Immediate
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7953 //Determine what type of operation we should perform
7957 if(cdb
->START_STOP
.FL
||
7958 cdb
->START_STOP
.FormatLayerNumber
||
7959 cdb
->START_STOP
.Reserved2
||
7960 cdb
->START_STOP
.Reserved2_2
||
7961 cdb
->START_STOP
.Reserved3
||
7966 if (cdb
->START_STOP
.PowerConditions
) {
7967 KdPrint2((PRINT_PREFIX
"START_STOP Power %d\n", cdb
->START_STOP
.PowerConditions
));
7968 switch(cdb
->START_STOP
.PowerConditions
) {
7969 case StartStop_Power_Idle
:
7970 command
= IDE_COMMAND_IDLE_IMMED
;
7972 case StartStop_Power_Standby
:
7973 command
= IDE_COMMAND_STANDBY_IMMED
;
7975 case StartStop_Power_Sleep
:
7976 // TODO: we should save power state in order to know
7977 // that RESET sould be issued to revert device into
7980 command
= IDE_COMMAND_SLEEP
;
7985 LunExt
->PowerState
= cdb
->START_STOP
.PowerConditions
;
7987 if (cdb
->START_STOP
.LoadEject
== 1) {
7988 KdPrint2((PRINT_PREFIX
"START_STOP eject\n"));
7990 // first select device 0 or 1.
7991 //SelectDrive(chan, DeviceNumber);
7992 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
7993 command
= IDE_COMMAND_MEDIA_EJECT
;
7995 if (cdb
->START_STOP
.Start
== 0) {
7996 KdPrint2((PRINT_PREFIX
"START_STOP standby\n"));
7997 command
= IDE_COMMAND_STANDBY_IMMED
;
7999 // TODO: we may need to perform hard reset (after sleep) or
8000 // issue IDE_COMMAND_IDLE_IMMED in order to activate device
8001 KdPrint2((PRINT_PREFIX
"START_STOP activate\n"));
8003 if(LunExt
->PowerState
== StartStop_Power_Sleep
) {
8004 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
8005 status
= SRB_STATUS_SUCCESS
;
8008 if(LunExt
->PowerState
> StartStop_Power_Idle
) {
8009 KdPrint2((PRINT_PREFIX
" issue IDLE\n"));
8010 command
= IDE_COMMAND_IDLE_IMMED
;
8012 KdPrint2((PRINT_PREFIX
" do nothing\n"));
8013 status
= SRB_STATUS_SUCCESS
;
8018 statusByte
= WaitOnBaseBusy(chan
);
8019 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, command
, 0, 0, 0, 0, 0,
8020 cdb
->START_STOP
.Immediate
? ATA_IMMEDIATE
: ATA_WAIT_READY
);
8021 status
= (statusByte
& IDE_STATUS_ERROR
) ? SRB_STATUS_ERROR
: SRB_STATUS_SUCCESS
;
8022 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
8026 KdPrint2((PRINT_PREFIX
"START_STOP invalid\n"));
8027 if (Srb
->SenseInfoBuffer
) {
8029 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8031 senseBuffer
->ErrorCode
= 0x70;
8032 senseBuffer
->Valid
= 1;
8033 senseBuffer
->AdditionalSenseLength
= 0xb;
8034 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
8035 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_CDB
;
8036 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8038 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8039 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8041 status
= SRB_STATUS_ERROR
;
8045 case SCSIOP_MEDIUM_REMOVAL
:
8047 cdb
= (PCDB
)Srb
->Cdb
;
8049 if(LunExt
->IdentifyData
.Removable
) {
8050 statusByte
= WaitOnBaseBusy(chan
);
8052 //SelectDrive(chan, DeviceNumber);
8053 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
8054 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
8055 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_LOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8057 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
8058 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_UNLOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8060 status
= SRB_STATUS_SUCCESS
;
8062 status
= SRB_STATUS_INVALID_REQUEST
;
8067 // Note: I don't implement this, because NTFS driver too often issues this command
8068 // It causes awful performance degrade. However, if somebody wants, I will implement
8069 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
8070 case SCSIOP_FLUSH_BUFFER
:
8071 case SCSIOP_SYNCHRONIZE_CACHE
:
8073 SelectDrive(chan
, DeviceNumber
);
8074 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
8075 status
= SRB_STATUS_SUCCESS
;
8076 // status = SRB_STATUS_PENDING;
8077 statusByte
= WaitOnBusy(chan
);
8081 case SCSIOP_REQUEST_SENSE
:
8082 // this function makes sense buffers to report the results
8083 // of the original GET_MEDIA_STATUS command
8085 KdPrint2((PRINT_PREFIX
8086 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8087 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8088 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8089 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
8092 status
= SRB_STATUS_INVALID_REQUEST
;
8096 case SCSIOP_ATA_PASSTHROUGH
:
8099 BOOLEAN use_dma
= FALSE
;
8102 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
8104 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
8105 //lChannel = Srb->TargetId >> 1;
8107 DeviceNumber
= max(DeviceNumber
, 1);
8108 regs
->bDriveHeadReg
&= 0x0f;
8109 regs
->bDriveHeadReg
|= (UCHAR
) (((DeviceNumber
& 0x1) << 4) | 0xA0);
8112 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
8114 KdPrint2((PRINT_PREFIX
8115 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
8116 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8118 if((regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) == UNIATA_SPTI_EX_SPEC_TO
) {
8119 to_lim
= Srb
->TimeOutValue
;
8121 if(Srb
->TimeOutValue
<= 2) {
8122 to_lim
= Srb
->TimeOutValue
*900;
8124 to_lim
= (Srb
->TimeOutValue
*999) - 500;
8128 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8130 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
8132 statusByte
= UniataAhciSendPIOCommandDirect(
8141 if(statusByte
== IDE_STATUS_WRONG
) {
8142 goto passthrough_err
;
8144 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8145 UniataAhciAbortOperation(chan
);
8146 goto passthrough_err
;
8148 goto passthrough_done
;
8152 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
8153 if((chan
->lun
[DeviceNumber
]->LimitedTransferMode
>= ATA_DMA
)) {
8155 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
8156 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
8157 (PUCHAR
)(Srb
->DataBuffer
),
8158 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
8164 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
8165 AtapiStallExecution(10);
8167 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
8168 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8169 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8170 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8171 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8172 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8174 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
8175 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8176 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
8177 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8178 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
8179 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8180 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
8181 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8182 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
8183 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8185 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
8188 GetBaseStatus(chan
, statusByte
);
8189 if(statusByte
& IDE_STATUS_ERROR
) {
8190 goto passthrough_err
;
8192 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
8195 ScsiPortStallExecution(1); // wait for busy to be set
8197 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
8198 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
8199 GetBaseStatus(chan
, statusByte
);
8200 if(statusByte
& IDE_STATUS_ERROR
) {
8203 if(!(statusByte
& IDE_STATUS_BUSY
)) {
8208 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
8210 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8211 goto passthrough_err
;
8215 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
8217 AtapiDmaDone(deviceExtension
, DeviceNumber
, lChannel
, NULL
);
8218 GetBaseStatus(chan
, statusByte
);
8220 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8221 AtapiSuckPort2(chan
);
8223 if (Srb
->SenseInfoBuffer
) {
8225 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8227 senseBuffer
->ErrorCode
= 0x70;
8228 senseBuffer
->Valid
= 1;
8229 senseBuffer
->AdditionalSenseLength
= 0xb;
8230 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
8231 senseBuffer
->AdditionalSenseCode
= 0;
8232 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8234 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8235 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8237 status
= SRB_STATUS_ERROR
;
8241 if (statusByte
& IDE_STATUS_DRQ
) {
8242 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
8244 (PUSHORT
) Srb
->DataBuffer
,
8245 Srb
->DataTransferLength
/ 2,
8247 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
8249 (PUSHORT
) Srb
->DataBuffer
,
8250 Srb
->DataTransferLength
/ 2,
8255 status
= SRB_STATUS_SUCCESS
;
8258 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8260 } else { // read task register
8263 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
8265 KdPrint2((PRINT_PREFIX
8266 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
8267 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8269 if((Srb
->DataTransferLength
>= sizeof(IDEREGS_EX
)) &&
8270 (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
)) {
8273 if(Srb
->DataTransferLength
>= sizeof(IDEREGS
)) {
8276 KdPrint2((PRINT_PREFIX
" buffer too small \n"));
8277 status
= SRB_STATUS_DATA_OVERRUN
;
8280 RtlZeroMemory(regs
, use48
? sizeof(IDEREGS_EX
) : sizeof(IDEREGS
));
8281 regs
->bOpFlags
= use48
? ATA_FLAGS_48BIT_COMMAND
: 0;
8282 UniataSnapAtaRegs(chan
, 0, regs
);
8284 status
= SRB_STATUS_SUCCESS
;
8291 KdPrint2((PRINT_PREFIX
8292 "IdeSendCommand: Unsupported command %#x\n",
8295 status
= SRB_STATUS_INVALID_REQUEST
;
8299 if(status
== SRB_STATUS_PENDING
) {
8300 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
8301 if(CmdAction
& CMD_ACTION_EXEC
) {
8302 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
8303 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
8306 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
8307 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8312 } // end IdeSendCommand()
8317 Routine Description:
8318 Enables disables media status notification
8321 HwDeviceExtension - ATAPI driver storage.
8328 IN PVOID HwDeviceExtension
,
8330 IN ULONG DeviceNumber
8333 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8335 UCHAR statusByte
,errorByte
;
8337 chan
= &(deviceExtension
->chan
[lChannel
]);
8338 SelectDrive(chan
, DeviceNumber
);
8340 if (EnableMSN
== TRUE
){
8342 // If supported enable Media Status Notification support
8343 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
8346 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8347 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8348 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8350 if (statusByte
& IDE_STATUS_ERROR
) {
8351 // Read the error register.
8352 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8354 KdPrint2((PRINT_PREFIX
8355 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
8359 chan
->lun
[DeviceNumber
]->DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
8360 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
8361 chan
->ReturningMediaStatus
= 0;
8366 } else { // end if EnableMSN == TRUE
8368 // disable if previously enabled
8369 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
8371 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8372 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8373 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8374 chan
->lun
[DeviceNumber
]->DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
8381 } // end IdeMediaStatus()
8386 Routine Description:
8388 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
8389 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
8392 HwDeviceExtension - ATAPI driver storage.
8393 Srb - System request block.
8397 SRB status (ALWAYS SUCCESS).
8402 IdeBuildSenseBuffer(
8403 IN PVOID HwDeviceExtension
,
8404 IN PSCSI_REQUEST_BLOCK Srb
8407 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8409 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
8410 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
8414 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
8416 senseBuffer
->ErrorCode
= 0x70;
8417 senseBuffer
->Valid
= 1;
8418 senseBuffer
->AdditionalSenseLength
= 0xb;
8419 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8420 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8421 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8422 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
8424 senseBuffer
->ErrorCode
= 0x70;
8425 senseBuffer
->Valid
= 1;
8426 senseBuffer
->AdditionalSenseLength
= 0xb;
8427 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8428 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8429 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8430 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
8432 senseBuffer
->ErrorCode
= 0x70;
8433 senseBuffer
->Valid
= 1;
8434 senseBuffer
->AdditionalSenseLength
= 0xb;
8435 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
8436 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
8437 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8438 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
8440 senseBuffer
->ErrorCode
= 0x70;
8441 senseBuffer
->Valid
= 1;
8442 senseBuffer
->AdditionalSenseLength
= 0xb;
8443 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
8444 senseBuffer
->AdditionalSenseCode
= 0;
8445 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8447 return SRB_STATUS_SUCCESS
;
8449 return SRB_STATUS_ERROR
;
8451 }// End of IdeBuildSenseBuffer
8455 UniataUserDeviceReset(
8456 PHW_DEVICE_EXTENSION deviceExtension
,
8457 PHW_LU_EXTENSION LunExt
,
8462 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8463 if ((LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
8464 (LunExt
->PowerState
!= StartStop_Power_Sleep
)) {
8465 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
8466 AtapiSoftReset(&(deviceExtension
->chan
[lChannel
]), LunExt
->Lun
);
8468 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
8469 AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8470 for(i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
8471 deviceExtension
->chan
[lChannel
].lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
8474 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
8475 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8477 } // end UniataUserDeviceReset()
8482 PHW_DEVICE_EXTENSION deviceExtension
,
8487 BOOLEAN PostReq
= FALSE
;
8489 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
8490 if(chan
->queue_depth
> 0) {
8493 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
8494 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
8495 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
8497 status
= SRB_STATUS_BUSY
;
8506 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
8510 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
8513 } // end UniataNeedQueueing()
8517 Routine Description:
8519 This routine is called from the SCSI port driver synchronized
8520 with the kernel to start an IO request.
8525 HwDeviceExtension - HBA miniport driver's adapter data storage
8526 Srb - IO request packet
8536 IN PVOID HwDeviceExtension
,
8537 IN PSCSI_REQUEST_BLOCK Srb
8540 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
8541 } // end AtapiStartIo()
8546 IN PVOID HwDeviceExtension
,
8547 IN PSCSI_REQUEST_BLOCK Srb
,
8551 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8554 PHW_LU_EXTENSION LunExt
;
8562 PSCSI_REQUEST_BLOCK tmpSrb
;
8563 BOOLEAN PostReq
= FALSE
;
8565 BOOLEAN commPort
= FALSE
;
8567 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
8568 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
8569 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
8570 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
8572 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
8574 /* KeBugCheckEx(0xc000000e,
8575 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8577 TopLevel, 0x80000001);
8579 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
8580 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
8581 //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
8582 UniAtaClearAtaReq(Srb
->SrbExtension
);
8585 do { // fetch all queued commands for the channel (if valid)
8587 lChannel
= GET_CHANNEL(Srb
);
8588 //ldev = GET_LDEV(Srb);
8591 DeviceNumber
= GET_CDEV(Srb
);
8594 //ASSERT(deviceExtension);
8597 KdPrint2((PRINT_PREFIX
8598 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8599 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8600 KdPrint2((PRINT_PREFIX
" VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
8602 if(lChannel
== deviceExtension
->NumberChannels
&&
8603 !Srb
->Lun
&& !Srb
->TargetId
&&
8604 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
8605 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
8607 // This is our virtual device
8608 KdPrint2((PRINT_PREFIX
8609 "AtapiStartIo: Communication port\n"));
8610 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
8612 if(Srb
->DataTransferLength
< sizeof(PINQUIRYDATA
)) {
8613 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", Srb
->DataTransferLength
,
8614 sizeof(PINQUIRYDATA
) ));
8616 status
= SRB_STATUS_DATA_OVERRUN
;
8620 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
8622 KdPrint2((PRINT_PREFIX
8624 // Zero INQUIRY data structure.
8625 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
8627 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
8629 // Fill in vendor identification fields.
8630 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
8632 status
= SRB_STATUS_SUCCESS
;
8636 /* Pass IOCTL request down */
8638 if(lChannel
>= deviceExtension
->NumberChannels
||
8639 Srb
->TargetId
/*DeviceNumber*/ >= deviceExtension
->NumberLuns
||
8642 if(lChannel
>= deviceExtension
->NumberChannels
) {
8647 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8648 KdPrint3((PRINT_PREFIX
8649 "AtapiStartIo: SRB rejected\n"));
8650 // Indicate no device found at this address.
8651 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
8652 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8656 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
8657 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
8662 chan
= &(deviceExtension
->chan
[lChannel
]);
8663 LunExt
= chan
->lun
[DeviceNumber
];
8667 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
8673 if(!commPort
&& !LunExt
) {
8675 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
8678 deviceExtension
->NumberChannels
);
8679 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
8680 lChannel
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
8681 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8682 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
8686 for(i=0; i<1000; i++) {
8687 AtapiStallExecution(3*1000);
8694 // Determine which function.
8695 switch (Srb
->Function
) {
8697 case SRB_FUNCTION_EXECUTE_SCSI
:
8699 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8700 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
8701 // let passthrough go
8703 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
8707 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8708 KdPrint2((PRINT_PREFIX
8709 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
8710 // Indicate no device found at this address.
8711 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
8712 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8717 KdPrint2((PRINT_PREFIX
8718 " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb
, &(Srb
->Cdb
), Srb
->SrbExtension
, Srb
->Cdb
[0]));
8722 if(Srb->DataTransferLength) {
8724 a = ((PUCHAR)(Srb->DataBuffer))[0];
8727 } __except(EXCEPTION_EXECUTE_HANDLER) {
8728 KdPrint3((PRINT_PREFIX
8729 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
8730 // Indicate no device found at this address.
8731 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
8732 status = SRB_STATUS_ERROR;
8733 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
8738 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
8742 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
8744 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
8745 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
8747 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
8749 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
8750 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
8752 /*KeBugCheckEx(0xc000000e,
8753 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8755 status, 0x80000001);*/
8756 if(status
== SRB_STATUS_BUSY
)
8757 status
= SRB_STATUS_PENDING
;
8758 // Insert requests AFTER they have been initialized on
8759 // CMD_ACTION_PREPARE stage
8760 // we should not check TopLevel here (it is always TRUE)
8761 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8762 UniataQueueRequest(chan
, Srb
);
8764 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
8768 // Send command to device.
8769 KdPrint2((PRINT_PREFIX
"Send to device %x\n", Srb
->Cdb
[0]));
8771 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
8772 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8773 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
8774 //ASSERT(!AtaReq->Flags);
8775 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8776 UniataQueueRequest(chan
, Srb
);
8777 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
8778 //ASSERT(!AtaReq->Flags);
8779 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
8780 //ASSERT(!AtaReq->Flags);
8784 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8788 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
8789 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, DeviceNumber
)) {
8790 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, DeviceNumber
, TRUE
)) {
8794 if(!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8798 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
8807 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)/* &&
8808 (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
8809 KdPrint3((PRINT_PREFIX
"Try ATAPI send %x\n", Srb
->Cdb
[0]));
8810 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
8812 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
8817 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
8824 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
8826 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
8828 /* KeBugCheckEx(0xc000000e,
8829 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8831 status, 0x80000002);*/
8839 case SRB_FUNCTION_ABORT_COMMAND
:
8841 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
8843 // Verify that SRB to abort is still outstanding.
8844 if((tmpSrb
!= Srb
->NextSrb
) ||
8845 !chan
->queue_depth
) {
8847 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
8849 // Complete abort SRB.
8850 status
= SRB_STATUS_ABORT_FAILED
;
8854 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
8855 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
8856 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
8857 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
8858 // Log reset failure.
8859 KdPrint3((PRINT_PREFIX
8860 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
8861 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
8863 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
8864 status
= SRB_STATUS_ERROR
;
8867 status
= SRB_STATUS_SUCCESS
;
8870 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
8871 if (tmpSrb
->SenseInfoBuffer
&&
8872 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
8874 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
8876 senseBuffer
->ErrorCode
= 0;
8877 senseBuffer
->Valid
= 1;
8878 senseBuffer
->AdditionalSenseLength
= 0xb;
8879 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
8880 senseBuffer
->AdditionalSenseCode
= 0;
8881 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8883 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
8885 AtapiDmaDBSync(chan
, tmpSrb
);
8886 UniataRemoveRequest(chan
, tmpSrb
);
8887 // Indicate command complete.
8888 ScsiPortNotification(RequestComplete
,
8891 status
= SRB_STATUS_SUCCESS
;
8895 // Abort function indicates that a request timed out.
8896 // Call reset routine. Card will only be reset if
8897 // status indicates something is wrong.
8898 // Fall through to reset code.
8900 case SRB_FUNCTION_RESET_DEVICE
:
8901 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
8903 // Reset single device.
8904 // For now we support only Lun=0
8906 // Note: reset is immediate command, it cannot be queued since it is usually used to
8907 // revert not-responding device to operational state
8908 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
8909 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
8910 status
= SRB_STATUS_SUCCESS
;
8913 case SRB_FUNCTION_RESET_BUS
:
8915 // Reset Atapi and SCSI bus.
8917 // Note: reset is immediate command, it cannot be queued since it is usually used to
8918 // revert not- responding device to operational state
8919 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
8920 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
8921 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
8922 // Log reset failure.
8923 KdPrint3((PRINT_PREFIX
8924 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
8925 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
8927 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
8928 status
= SRB_STATUS_ERROR
;
8931 status
= SRB_STATUS_SUCCESS
;
8936 case SRB_FUNCTION_SHUTDOWN
:
8938 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
8939 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8940 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
8943 // FLUSH ATAPI device - do nothing
8944 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
8946 // FLUSH IDE/ATA device
8947 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
8948 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8949 status
= AtaCommand(deviceExtension
, DeviceNumber
, GET_CHANNEL(Srb
),
8950 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
8951 // If supported & allowed, reset write cacheing
8952 if(LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
8954 // Disable write cache
8955 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8956 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8957 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
8958 // Check for errors.
8959 if (status
& IDE_STATUS_ERROR
) {
8960 KdPrint2((PRINT_PREFIX
8961 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
8964 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
8966 // Re-enable write cache
8967 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8968 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8969 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
8970 // Check for errors.
8971 if (status
& IDE_STATUS_ERROR
) {
8972 KdPrint2((PRINT_PREFIX
8973 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
8975 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
8977 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
8981 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8983 status
= SRB_STATUS_SUCCESS
;
8987 case SRB_FUNCTION_FLUSH
:
8989 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
8990 status
= SRB_STATUS_SUCCESS
;
8993 case SRB_FUNCTION_IO_CONTROL
: {
8997 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
8999 len
= Srb
->DataTransferLength
;
9001 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
9003 ULONG targetId
= (ULONG
)(-1);
9005 if(len
< sizeof(SRB_IO_CONTROL
)) {
9006 goto wrong_buffer_size
;
9009 // extract bogus bus address
9010 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9011 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9012 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9014 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(GETVERSIONINPARAMS
)) {
9015 goto wrong_buffer_size
;
9018 targetId
= versionParameters
->bIDEDeviceMap
;
9019 KdPrint2((PRINT_PREFIX
"targetId (smart ver) %d\n", targetId
));
9021 case IOCTL_SCSI_MINIPORT_IDENTIFY
:
9022 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
9023 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
9024 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
9025 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
9026 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
9027 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
9028 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
9029 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
9030 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE
:
9031 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG
:
9032 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG
:
9034 PSENDCMDINPARAMS cmdInParameters
= (PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9036 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDINPARAMS
) - 1) {
9037 goto wrong_buffer_size
;
9040 targetId
= cmdInParameters
->bDriveNumber
;
9041 KdPrint2((PRINT_PREFIX
"targetId (smart/ident) %d\n", targetId
));
9045 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9046 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
9047 status
= SRB_STATUS_INVALID_REQUEST
;
9051 // adjust (if necessary) bus address
9052 if(targetId
!= (ULONG
)(-1)) {
9054 // This is done because of how the IOCTL_SCSI_MINIPORT
9055 // determines 'targetid's'. Disk.sys places the real target id value
9056 // in the DeviceMap field. Once we do some parameter checking, the value passed
9057 // back to the application will be determined.
9059 if (deviceExtension
->NumberChannels
== 1) {
9060 // do this for legacy controllers and legacy callers
9061 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call\n"));
9062 DeviceNumber
= (targetId
& 0x01);
9066 // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
9067 // due to DISK.SYS design bug, we have invalid SCSI address in SRB
9068 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call (2)\n"));
9069 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
9070 lChannel
= (UCHAR
)targetId
/ 2;
9073 lChannel
= (UCHAR
)(targetId
/ 2);
9074 DeviceNumber
= targetId
& 0x01;
9077 // otherwise assume lChannel and DeviceNumber from Srb are ok
9079 if(lChannel
>= deviceExtension
->NumberChannels
||
9080 DeviceNumber
>= deviceExtension
->NumberLuns
) {
9081 KdPrint2((PRINT_PREFIX
9082 "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
9084 // Indicate no device found at this address.
9087 targetId
= lChannel
*deviceExtension
->NumberLuns
+DeviceNumber
;
9088 chan
= &(deviceExtension
->chan
[lChannel
]);
9089 LunExt
= chan
->lun
[DeviceNumber
];
9093 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
9095 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9100 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9101 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9103 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9104 UCHAR deviceNumberMap
;
9106 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
9108 // Version and revision per SMART 1.03
9110 versionParameters
->bVersion
= 1;
9111 versionParameters
->bRevision
= 1;
9112 versionParameters
->bReserved
= 0;
9114 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
9115 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
9118 goto invalid_request
;
9121 // NOTE: This will only set the bit
9122 // corresponding to this drive's target id.
9123 // The bit mask is as follows:
9129 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
9130 deviceNumberMap
= 1 << lChannel
;
9133 if (deviceExtension
->NumberChannels
== 1) {
9134 if (chan
->PrimaryAddress
) {
9135 deviceNumberMap
= 1 << DeviceNumber
;
9137 deviceNumberMap
= 4 << DeviceNumber
;
9140 deviceNumberMap
= 1 << (DeviceNumber
+lChannel
*2);
9143 versionParameters
->bIDEDeviceMap
= deviceNumberMap
;
9145 status
= SRB_STATUS_SUCCESS
;
9149 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
9151 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9152 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9154 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
9155 // Extract the target.
9156 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
9158 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
9161 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
9162 goto invalid_request
;
9168 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
9169 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
9170 goto invalid_request
;
9173 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
9174 // Zero the output buffer
9175 RtlZeroMemory(cmdOutParameters
, len
);
9176 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
9177 ((PUCHAR)cmdOutParameters)[i] = 0;
9180 // Build status block.
9181 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
9182 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
9183 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
9185 // Extract the identify data from the device extension.
9186 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &(LunExt
->IdentifyData
),
9187 cmdOutParameters
->cBufferSize
);
9189 if((cmdOutParameters
->cBufferSize
== IDENTIFY_BUFFER_SIZE
) &&
9190 (LunExt
->IdentifyData
.ChecksumValid
== ATA_ChecksumValid
)) {
9191 // adjust checksum if it is possible
9195 for(i
=0; i
< IDENTIFY_BUFFER_SIZE
-1; i
++) {
9196 csum
+= (CHAR
)(cmdOutParameters
->bBuffer
[i
]);
9198 cmdOutParameters
->bBuffer
[i
] = -csum
;
9199 KdPrint2((PRINT_PREFIX
"AtapiStartIo: adjust checksum %d\n"));
9201 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
9203 status
= SRB_STATUS_SUCCESS
;
9207 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
9208 cmdInParameters
.irDriveRegs
.bCommandReg
));
9209 status
= SRB_STATUS_INVALID_REQUEST
;
9215 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9216 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9217 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9218 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9219 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9220 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9221 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9222 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9225 // *all* IOCTLs here are SMART
9227 KdPrint2((PRINT_PREFIX
9228 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
9231 goto invalid_request
;
9234 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9236 if(PostReq
|| TopLevel
) {
9237 UniataQueueRequest(chan
, Srb
);
9238 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9239 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9244 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
9245 status
= SRB_STATUS_PENDING
;
9247 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9250 status
= IdeSendSmartCommand(HwDeviceExtension
, Srb
, targetId
);
9254 // we should not get here, checked above
9256 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9257 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9258 status = SRB_STATUS_INVALID_REQUEST;
9263 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
9265 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
9266 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
9267 ULONG DeviceNumber
= AtaCtl
->addr
.TargetId
;
9271 pos
= FIELD_OFFSET(UNIATA_CTL
, RawData
);
9272 //chan = &(deviceExtension->chan[lChannel]);
9274 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9275 FIELD_OFFSET(UNIATA_CTL
, RawData
) ));
9276 goto wrong_buffer_size
;
9279 if(AtaCtl
->addr
.Lun
||
9280 AtaCtl
->addr
.TargetId
>= deviceExtension
->NumberLuns
||
9281 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
9289 lChannel
= AtaCtl
->addr
.PathId
;
9290 chan
= &(deviceExtension
->chan
[lChannel
]);
9291 LunExt
= chan
->lun
[DeviceNumber
];
9294 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl
->hdr
.ControlCode
, DeviceNumber
));
9296 /* check for valid LUN */
9297 switch (AtaCtl
->hdr
.ControlCode
) {
9298 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9299 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
9300 // this would be BUS reset
9302 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
9303 AtaCtl
->addr
.TargetId
!= 0xff ||
9304 AtaCtl
->addr
.Lun
!= 0
9306 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
9307 DeviceNumber
< deviceExtension
->NumberLuns
) { // AtaCtl->addr.TargetId != 0xff
9308 lChannel
= AtaCtl
->addr
.PathId
;
9309 chan
= &(deviceExtension
->chan
[lChannel
]);
9310 LunExt
= chan
->lun
[DeviceNumber
];
9313 goto handle_bad_ldev
;
9316 lChannel
= AtaCtl
->addr
.PathId
;
9317 chan
= &(deviceExtension
->chan
[lChannel
]);
9320 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
9321 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9322 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
9323 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9324 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
9327 KdPrint2((PRINT_PREFIX
9328 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
9329 // Indicate no device found at this address.
9334 /* check if queueing is necessary */
9335 switch (AtaCtl
->hdr
.ControlCode
) {
9336 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9337 if(!LunExt
->nBadBlocks
) {
9340 goto uata_ctl_queue
;
9341 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9342 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9343 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9344 pos
+sizeof(AtaCtl
->SetMode
) ));
9345 goto wrong_buffer_size
;
9347 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
9350 goto uata_ctl_queue
;
9351 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9352 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
9354 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
9355 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9357 if(PostReq
|| TopLevel
) {
9358 UniataQueueRequest(chan
, Srb
);
9359 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9360 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9363 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
9364 status
= SRB_STATUS_PENDING
;
9366 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9369 } // end switch (AtaCtl->hdr.ControlCode)
9371 /* process request */
9372 switch (AtaCtl
->hdr
.ControlCode
) {
9373 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9375 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
9377 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9378 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9379 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9380 goto wrong_buffer_size
;
9382 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
9383 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
9384 if(AtaCtl
->addr
.TargetId
!= 0xff) {
9385 LunExt
->DeviceFlags
&= ~DFLAGS_HIDDEN
;
9390 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9391 AtapiStallExecution(1000 * 1000);
9394 FindDevices(HwDeviceExtension
,
9395 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
9396 ? UNIATA_FIND_DEV_UNHIDE
: 0,
9397 AtaCtl
->addr
.PathId
);
9398 status
= SRB_STATUS_SUCCESS
;
9402 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
9404 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
9406 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9407 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9408 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9409 goto wrong_buffer_size
;
9411 LunExt
->DeviceFlags
= 0;
9412 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
9413 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
9414 //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
9415 UniataForgetDevice(LunExt
);
9418 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9419 AtapiStallExecution(1000 * 1000);
9422 status
= SRB_STATUS_SUCCESS
;
9425 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
9427 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
9429 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9430 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9431 pos
+sizeof(AtaCtl
->SetMode
) ));
9432 goto wrong_buffer_size
;
9434 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
9435 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
9437 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
9438 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
9439 if(LunExt
->LimitedTransferMode
>
9440 LunExt
->OrigTransferMode
) {
9441 // check for incorrect value
9442 LunExt
->LimitedTransferMode
=
9443 LunExt
->OrigTransferMode
;
9446 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
9448 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
9449 if(AtaCtl
->SetMode
.ApplyImmediately
) {
9450 AtapiDmaInit__(deviceExtension
, LunExt
);
9452 /* LunExt->TransferMode =
9453 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
9454 status
= SRB_STATUS_SUCCESS
;
9457 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
9459 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
9461 if(len
< pos
+sizeof(AtaCtl
->GetMode
)) {
9462 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9463 pos
+sizeof(AtaCtl
->GetMode
) ));
9464 goto wrong_buffer_size
;
9466 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
9467 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
9468 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
9469 AtaCtl
->GetMode
.PhyMode
= LunExt
->PhyTransferMode
;
9471 status
= SRB_STATUS_SUCCESS
;
9474 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION
: {
9476 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get version\n"));
9478 if(len
< pos
+sizeof(AtaCtl
->Version
)) {
9479 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9480 pos
+sizeof(AtaCtl
->Version
) ));
9481 goto wrong_buffer_size
;
9483 AtaCtl
->Version
.Length
= sizeof(GETDRVVERSION
);
9484 AtaCtl
->Version
.VersionMj
= UNIATA_VER_MJ
;
9485 AtaCtl
->Version
.VersionMn
= UNIATA_VER_MN
;
9486 AtaCtl
->Version
.SubVerMj
= UNIATA_VER_SUB_MJ
;
9487 AtaCtl
->Version
.SubVerMn
= UNIATA_VER_SUB_MN
;
9489 status
= SRB_STATUS_SUCCESS
;
9492 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
9494 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
9496 if(len
< pos
+sizeof(AtaCtl
->AdapterInfo
)) {
9497 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9498 pos
+sizeof(AtaCtl
->AdapterInfo
) ));
9499 goto wrong_buffer_size
;
9501 AtaCtl
->AdapterInfo
.HeaderLength
= sizeof(ADAPTERINFO
);
9503 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
9504 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
9505 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
9506 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
9507 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
9508 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
9509 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
9510 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
9511 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
9512 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
9513 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
9514 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
9515 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
9516 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
9517 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
9518 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
9519 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
9520 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
9521 AtaCtl
->AdapterInfo
.NumberLuns
= (UCHAR
)deviceExtension
->NumberLuns
;
9522 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
9523 if(deviceExtension
->FullDevName
) {
9524 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
9526 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
9527 AtaCtl
->AdapterInfo
.LunInfoValid
= FALSE
;
9528 AtaCtl
->AdapterInfo
.ChanHeaderLengthValid
= TRUE
;
9530 pos
+= AtaCtl
->AdapterInfo
.HeaderLength
;
9533 RtlZeroMemory(((PCHAR
)AtaCtl
)+pos
,
9536 if(len
>= pos
+AtaCtl
->AdapterInfo
.NumberChannels
*sizeof(CHANINFO
)) {
9537 PCHANINFO ChanInfo
= (PCHANINFO
)( ((PCHAR
)AtaCtl
)+pos
);
9538 PHW_CHANNEL cur_chan
;
9539 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Fill channel info\n"));
9540 for(i
=0;i
<AtaCtl
->AdapterInfo
.NumberChannels
;i
++) {
9541 KdPrint2((PRINT_PREFIX
"chan[%d] %x\n", i
, cur_chan
));
9542 cur_chan
= &(deviceExtension
->chan
[i
]);
9543 ChanInfo
->MaxTransferMode
= cur_chan
->MaxTransferMode
;
9544 ChanInfo
->ChannelCtrlFlags
= cur_chan
->ChannelCtrlFlags
;
9545 RtlCopyMemory(&(ChanInfo
->QueueStat
), &(cur_chan
->QueueStat
), sizeof(ChanInfo
->QueueStat
));
9546 ChanInfo
->ReorderCount
= cur_chan
->ReorderCount
;
9547 ChanInfo
->IntersectCount
= cur_chan
->IntersectCount
;
9548 ChanInfo
->TryReorderCount
= cur_chan
->TryReorderCount
;
9549 ChanInfo
->TryReorderHeadCount
= cur_chan
->TryReorderHeadCount
;
9550 ChanInfo
->TryReorderTailCount
= cur_chan
->TryReorderTailCount
;
9551 //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
9554 AtaCtl
->AdapterInfo
.ChanInfoValid
= TRUE
;
9555 AtaCtl
->AdapterInfo
.ChanHeaderLength
= sizeof(*ChanInfo
);
9558 status
= SRB_STATUS_SUCCESS
;
9561 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
9563 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
9565 ForgetBadBlocks(LunExt
);
9567 status
= SRB_STATUS_SUCCESS
;
9570 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
9572 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
9577 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
);
9580 status
= SRB_STATUS_SUCCESS
;
9584 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
9585 AtaCtl
->hdr
.ControlCode
));
9586 status
= SRB_STATUS_INVALID_REQUEST
;
9591 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
9592 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
9593 "SCSIDISK", "-UNIATA-"));
9595 status
= SRB_STATUS_INVALID_REQUEST
;
9600 } // end SRB_FUNCTION_IO_CONTROL
9603 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
9604 // Indicate unsupported command.
9605 status
= SRB_STATUS_INVALID_REQUEST
;
9613 PathId
= Srb
->PathId
;
9614 TargetId
= Srb
->TargetId
;
9617 if (status
!= SRB_STATUS_PENDING
) {
9619 KdPrint2((PRINT_PREFIX
9620 "AtapiStartIo: Srb %#x complete with status %#x\n",
9624 // Set status in SRB.
9625 Srb
->SrbStatus
= (UCHAR
)status
;
9628 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan
, Srb
));
9629 AtapiDmaDBSync(chan
, Srb
);
9631 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan
, Srb
));
9632 UniataRemoveRequest(chan
, Srb
);
9633 // Indicate command complete.
9634 KdPrint2((PRINT_PREFIX
"AtapiStartIo: ScsiPortNotification\n"));
9635 ScsiPortNotification(RequestComplete
,
9639 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataGetCurRequest\n"));
9640 // Remove current Srb & get next one
9641 if((Srb
= UniataGetCurRequest(chan
))) {
9642 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9643 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
9644 // current request is under precessing, thus
9645 // we should do nothing here
9649 KdPrint2((PRINT_PREFIX
"AtapiStartIo: chan %x, Src %x\n", chan
, Srb
));
9654 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
9656 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
9658 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
9659 // Indicate ready for next request.
9660 ScsiPortNotification(NextRequest
,
9664 ScsiPortNotification(NextLuRequest
,
9672 } // end AtapiStartIo__()
9677 UniataInitAtaCommands()
9683 KdPrint2((PRINT_PREFIX
"UniataInitAtaCommands:\n"));
9685 for(i
=0; i
<256; i
++) {
9690 //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
9693 case IDE_COMMAND_READ_DMA48
:
9694 case IDE_COMMAND_READ_DMA_Q48
:
9695 case IDE_COMMAND_READ_STREAM_DMA48
:
9696 case IDE_COMMAND_READ_STREAM48
:
9697 case IDE_COMMAND_WRITE_DMA48
:
9698 case IDE_COMMAND_WRITE_DMA_Q48
:
9699 case IDE_COMMAND_READ_DMA_Q
:
9700 case IDE_COMMAND_READ_DMA
:
9701 case IDE_COMMAND_WRITE_DMA
:
9702 case IDE_COMMAND_WRITE_DMA_Q
:
9703 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9704 case IDE_COMMAND_WRITE_STREAM48
:
9705 case IDE_COMMAND_WRITE_FUA_DMA48
:
9706 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9707 case IDE_COMMAND_READ_LOG_DMA48
:
9708 case IDE_COMMAND_WRITE_LOG_DMA48
:
9709 case IDE_COMMAND_TRUSTED_RCV_DMA
:
9710 case IDE_COMMAND_TRUSTED_SEND_DMA
:
9711 case IDE_COMMAND_DATA_SET_MGMT
:
9712 //KdPrint2((PRINT_PREFIX "DMA "));
9713 flags
|= ATA_CMD_FLAG_DMA
;
9717 case IDE_COMMAND_WRITE_FUA_DMA48
:
9718 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9719 case IDE_COMMAND_WRITE_MUL_FUA48
:
9721 flags
|= ATA_CMD_FLAG_FUA
;
9724 case IDE_COMMAND_READ48
:
9725 case IDE_COMMAND_READ_DMA48
:
9726 case IDE_COMMAND_READ_DMA_Q48
:
9727 case IDE_COMMAND_READ_MUL48
:
9728 case IDE_COMMAND_READ_STREAM_DMA48
:
9729 case IDE_COMMAND_READ_STREAM48
:
9730 case IDE_COMMAND_WRITE48
:
9731 case IDE_COMMAND_WRITE_DMA48
:
9732 case IDE_COMMAND_WRITE_DMA_Q48
:
9733 case IDE_COMMAND_WRITE_MUL48
:
9734 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9735 case IDE_COMMAND_WRITE_STREAM48
:
9736 case IDE_COMMAND_FLUSH_CACHE48
:
9737 case IDE_COMMAND_VERIFY48
:
9739 //KdPrint2((PRINT_PREFIX "48 "));
9740 flags
|= ATA_CMD_FLAG_48
;
9743 case IDE_COMMAND_READ
:
9744 case IDE_COMMAND_READ_MULTIPLE
:
9745 case IDE_COMMAND_READ_DMA
:
9746 case IDE_COMMAND_READ_DMA_Q
:
9747 case IDE_COMMAND_WRITE
:
9748 case IDE_COMMAND_WRITE_MULTIPLE
:
9749 case IDE_COMMAND_WRITE_DMA
:
9750 case IDE_COMMAND_WRITE_DMA_Q
:
9751 case IDE_COMMAND_FLUSH_CACHE
:
9752 case IDE_COMMAND_VERIFY
:
9754 //KdPrint2((PRINT_PREFIX "LBA "));
9755 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
9759 case IDE_COMMAND_READ_NATIVE_SIZE48
:
9760 case IDE_COMMAND_SET_NATIVE_SIZE48
:
9761 // we cannot set LBA flag for these commands to avoid BadBlock handling
9762 //flags |= ATA_CMD_FLAG_LBAIOsupp;
9763 flags
|= ATA_CMD_FLAG_48
;
9765 case IDE_COMMAND_READ_NATIVE_SIZE
:
9766 case IDE_COMMAND_SET_NATIVE_SIZE
:
9768 flags
|= ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_FUA
;
9771 flags
|= ATA_CMD_FLAG_48supp
;
9774 case IDE_COMMAND_READ
:
9775 command
= IDE_COMMAND_READ48
; break;
9776 case IDE_COMMAND_READ_MULTIPLE
:
9777 command
= IDE_COMMAND_READ_MUL48
; break;
9778 case IDE_COMMAND_READ_DMA
:
9779 command
= IDE_COMMAND_READ_DMA48
; break;
9780 case IDE_COMMAND_READ_DMA_Q
:
9781 command
= IDE_COMMAND_READ_DMA_Q48
; break;
9782 case IDE_COMMAND_WRITE
:
9783 command
= IDE_COMMAND_WRITE48
; break;
9784 case IDE_COMMAND_WRITE_MULTIPLE
:
9785 command
= IDE_COMMAND_WRITE_MUL48
; break;
9786 case IDE_COMMAND_WRITE_DMA
:
9787 command
= IDE_COMMAND_WRITE_DMA48
; break;
9788 case IDE_COMMAND_WRITE_DMA_Q
:
9789 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
9790 case IDE_COMMAND_FLUSH_CACHE
:
9791 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
9792 // case IDE_COMMAND_READ_NATIVE_SIZE:
9793 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
9794 case IDE_COMMAND_SET_NATIVE_SIZE
:
9795 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
9796 case IDE_COMMAND_VERIFY
:
9797 command
= IDE_COMMAND_VERIFY48
; break;
9799 //KdPrint2((PRINT_PREFIX "!28->48 "));
9800 flags
&= ~ATA_CMD_FLAG_48supp
;
9804 case IDE_COMMAND_READ
:
9805 case IDE_COMMAND_READ_MULTIPLE
:
9806 case IDE_COMMAND_READ_DMA48
:
9807 case IDE_COMMAND_READ_DMA_Q48
:
9808 case IDE_COMMAND_READ_STREAM_DMA48
:
9809 case IDE_COMMAND_READ_STREAM48
:
9810 case IDE_COMMAND_READ_DMA_Q
:
9811 case IDE_COMMAND_READ_DMA
:
9812 case IDE_COMMAND_READ_LOG_DMA48
:
9813 case IDE_COMMAND_TRUSTED_RCV_DMA
:
9814 case IDE_COMMAND_IDENTIFY
:
9815 case IDE_COMMAND_ATAPI_IDENTIFY
:
9816 //KdPrint2((PRINT_PREFIX "RD "));
9817 flags
|= ATA_CMD_FLAG_In
;
9819 case IDE_COMMAND_WRITE
:
9820 case IDE_COMMAND_WRITE_MULTIPLE
:
9821 case IDE_COMMAND_WRITE_DMA48
:
9822 case IDE_COMMAND_WRITE_DMA_Q48
:
9823 case IDE_COMMAND_WRITE_DMA
:
9824 case IDE_COMMAND_WRITE_DMA_Q
:
9825 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9826 case IDE_COMMAND_WRITE_STREAM48
:
9827 case IDE_COMMAND_WRITE_FUA_DMA48
:
9828 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9829 //KdPrint2((PRINT_PREFIX "WR "));
9830 flags
|= ATA_CMD_FLAG_Out
;
9834 //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
9835 AtaCommands48
[i
] = command
;
9836 AtaCommandFlags
[i
] = flags
;
9838 } // end UniataInitAtaCommands()
9842 Routine Description:
9844 Installable driver initialization entry point for system.
9852 Status from ScsiPortInitialize()
9859 IN PVOID DriverObject
,
9863 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
9866 ULONG statusToReturn
, newStatus
;
9867 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
9868 BOOLEAN ReEnter
= FALSE
;
9870 #ifndef USE_REACTOS_DDK
9874 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
9875 BOOLEAN PrimaryClaimed
= FALSE
;
9876 BOOLEAN SecondaryClaimed
= FALSE
;
9878 LARGE_INTEGER t0
, t1
;
9881 KdPrint2((PRINT_PREFIX
"%s", (PCCHAR
)ver_string
));
9882 a
= (WCHAR
)strlen(ver_string
);
9884 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
9886 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
9889 if(!SavedDriverObject
) {
9890 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
9891 #ifdef USE_REACTOS_DDK
9892 KdPrint(("UniATA Init: OS should be ReactOS\n"));
9897 // we are here for the 1st time
9898 // init CrossNT and get OS version
9899 if(!NT_SUCCESS(status
= CrNtInit(SavedDriverObject
, RegistryPath
))) {
9900 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status
));
9901 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
9904 #endif // USE_REACTOS_DDK
9905 KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion
, MinorVersion
, BuildNumber
, KeNumberProcessors
));
9907 KeQuerySystemTime(&t0
);
9909 KeQuerySystemTime(&t1
);
9910 } while(t0
.QuadPart
== t1
.QuadPart
);
9914 KeQuerySystemTime(&t1
);
9916 } while(t0
.QuadPart
== t1
.QuadPart
);
9917 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
9918 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
9920 KdPrint(("UniATA Init: ReEnter\n"));
9924 // (re)read bad block list
9925 InitBadBlocks(NULL
);
9928 // init ATA command translation table
9929 UniataInitAtaCommands();
9930 // get registry path to settings
9931 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
9932 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
9933 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
9934 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
9935 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
9936 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
9939 if(WinVer_Id() >= WinVer_2k
) {
9940 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
9941 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
9942 WinVer_WDM_Model
= TRUE
;
9944 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
9945 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
9946 WinVer_WDM_Model
= TRUE
;
9950 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
9951 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
9953 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
9956 statusToReturn
= 0xffffffff;
9958 // Zero out structure.
9959 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
9961 // Set size of hwInitializationData.
9962 hwInitializationData
.comm
.HwInitializationDataSize
=
9963 sizeof(hwInitializationData
.comm
) +
9964 // sizeof(hwInitializationData.nt4) +
9965 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
9966 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
9968 // Set entry points.
9969 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
9970 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
9971 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
9972 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
9974 // Specify size of extensions.
9975 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
9976 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
9977 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
9979 // Indicate PIO device.
9980 hwInitializationData
.comm
.MapBuffers
= TRUE
;
9981 // Set PnP-specific API
9982 if(WinVer_Id() > WinVer_NT
) {
9983 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
9984 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
9985 KdPrint(("set AtapiAdapterControl() ptr\n"));
9986 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
9989 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE enum supported BusMaster Devices\n"));
9993 g_opt_VirtualMachine
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualMachineType", g_opt_VirtualMachine
);
9994 if(g_opt_VirtualMachine
> VM_MAX_KNOWN
) {
9995 g_opt_VirtualMachine
= 0;
9997 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualBox", (g_opt_VirtualMachine
== VM_VBOX
))) {
9998 g_opt_VirtualMachine
= VM_VBOX
;
10000 // Pre-scan PCI bus, also check if we are under VM
10001 UniataEnumBusMasterController(DriverObject
, Argument2
);
10003 switch(g_opt_VirtualMachine
) {
10005 KdPrint2((PRINT_PREFIX
"adjust options for VirtualBox\n"));
10006 // adjust options for VirtualBox
10007 g_opt_WaitBusyCount
= 20000;
10008 g_opt_WaitBusyDelay
= 150;
10009 g_opt_WaitDrqDelay
= 100;
10010 g_opt_WaitBusyLongCount
= 20000;
10011 g_opt_MaxIsrWait
= 200;
10012 g_opt_AtapiSendDisableIntr
= 0;
10013 g_opt_AtapiDmaRawRead
= FALSE
;
10018 KdPrint2((PRINT_PREFIX
"old slow machine, adjust timings\n"));
10019 // old slow machine, adjust timings
10020 g_opt_WaitBusyCount
= 20000;
10021 g_opt_WaitBusyDelay
= 150;
10022 g_opt_WaitDrqDelay
= 100;
10023 g_opt_WaitBusyLongCount
= 20000;
10024 g_opt_MaxIsrWait
= 200;
10027 g_opt_WaitBusyCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyCount", g_opt_WaitBusyCount
); // 200 vs 20000
10028 g_opt_WaitBusyDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyDelay", g_opt_WaitBusyDelay
); // 10 vs 150
10029 g_opt_WaitDrqDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitDrqDelay", g_opt_WaitDrqDelay
); // 10 vs 100
10030 g_opt_WaitBusyLongCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongCount", g_opt_WaitBusyLongCount
); // 2000 vs 20000
10031 g_opt_WaitBusyLongDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongDelay", g_opt_WaitBusyLongDelay
); // 250 vs 250
10032 g_opt_AtapiSendDisableIntr
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr
); // 1 vs 0
10033 g_opt_AtapiDmaRawRead
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiDmaRawRead", g_opt_AtapiDmaRawRead
); // 1 vs 0
10034 g_opt_MaxIsrWait
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"MaxIsrWait", g_opt_MaxIsrWait
); // 40 vs xxx
10037 // Look for legacy ISA-bridged PCI IDE controller (onboard)
10038 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
10039 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
10040 for (i
=0; i
<BMListLen
; i
++) {
10042 if(!BMList
[i
].MasterDev
) {
10043 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
10046 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10050 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
10051 if(BMList
[i
].ChanInitOk
& 0x03) {
10052 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
10054 newStatus
= STATUS_SUCCESS
;
10058 //BMList[i].AltInitMasterDev = (UCHAR)0xff;
10060 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
10061 PrimaryClaimed
= TRUE
;
10062 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
10063 SecondaryClaimed
= TRUE
;
10065 if(!WinVer_WDM_Model
&& !PrimaryClaimed
&& !SecondaryClaimed
&&
10066 !(BMList
[i
].ChanInitOk
& 0x80)) {
10067 newStatus
= UniataClaimLegacyPCIIDE(i
);
10068 if(newStatus
!= STATUS_SUCCESS
) {
10069 KdPrint2((PRINT_PREFIX
"Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
10074 if(g_opt_Verbose
) {
10075 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
10079 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
10081 for(c
=0; c
<2; c
++) {
10083 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10087 if(PrimaryClaimed
) {
10088 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
10093 if(SecondaryClaimed
) {
10094 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
10099 if((WinVer_Id() < WinVer_2k
)) {
10100 // do not even try if already claimed
10102 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
10105 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
10108 if(!WinVer_WDM_Model
) {
10109 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10111 // in WDM model things are different....
10112 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
10113 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
10115 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10116 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10118 if(!WinVer_WDM_Model
) {
10119 BMList
[i
].channel
= (UCHAR
)c
;
10122 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
10123 newStatus
= ScsiPortInitialize(DriverObject
,
10125 &hwInitializationData
.comm
,
10126 (PVOID
)(i
| (alt
? 0x80000000 : 0)));
10127 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10128 if (newStatus
< statusToReturn
) {
10129 statusToReturn
= newStatus
;
10131 if (newStatus
== STATUS_SUCCESS
) {
10132 if(WinVer_Id() < WinVer_2k
) {
10133 // This should be done in HwInitialize under w2k+ to ensure that
10134 // channel is actually initialized
10135 BMList
[i
].ChanInitOk
|= 0x01 << c
;
10137 if(BMList
[i
].ChanInitOk
& (0x01 << c
)) {
10138 KdPrint2((PRINT_PREFIX
"HwInit passed\n"));
10142 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
10143 c = 1; // this will break our for()
10144 BMList[i].ChanInitOk |= 0x01 << c;
10149 /* if(WinVer_Id() >= WinVer_2k) {
10150 // the following didn't work under higher OSes,
10151 // until we move setting of FLAGS to HwInit
10152 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
10155 if(BMList
[i
].ChanInitOk
& 0x03) {
10156 // Under NT we receive status immediately, so
10157 // we can omit alternative init method if STATUS_SUCCESS returned.
10158 // Under w2k+ we relay on flags, set in HwInitialize.
10159 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
10162 if(WinVer_Id() >= WinVer_2k
) {
10163 // try AltInit if HwInit was not called immediately under w2k+
10164 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10166 // if (WinVer_Id() == WinVer_NT) and some error occured
10167 // try alternative init method
10168 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10171 if(g_opt_Verbose
) {
10172 if(BMList
[i
].ChanInitOk
& 0x03) {
10173 _PrintNtConsole(" OK\n");
10175 _PrintNtConsole(" failed\n");
10181 /* KeBugCheckEx(0xc000000e,
10182 (i << 16) | BMList[0].ChanInitOk,
10184 newStatus, statusToReturn);*/
10186 // Look for PCI IDE controller
10187 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
10188 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
10189 for (; i
<BMListLen
; i
++) {
10191 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", 0)) {
10194 /* if(BMList[i].MasterDev)
10196 if(g_opt_Verbose
) {
10197 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
10198 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
10199 BMList
[i
].busNumber
,
10200 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
10201 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
10204 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10205 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10206 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
10208 hwInitializationData
.comm
.VendorId
= (PVOID
)BMList
[i
].VendorId
;
10209 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
10210 hwInitializationData
.comm
.DeviceId
= (PVOID
)BMList
[i
].DeviceId
;
10211 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
10213 BMList
[i
].channel
= 0/*(UCHAR)c*/;
10215 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
10216 hwInitializationData
.comm
.VendorId
,
10217 hwInitializationData
.comm
.DeviceId
));
10218 newStatus
= ScsiPortInitialize(DriverObject
,
10220 &hwInitializationData
.comm
,
10222 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10223 if(newStatus
== (ULONG
)STATUS_DEVICE_DOES_NOT_EXIST
&& BMList
[i
].NeedAltInit
) {
10224 // Note: this is actually a BUG in scsiport.sys
10225 // It stops scanning PCI bus when reaches empty PCI Function inside Slot
10226 // However, this PCI Slot may have higher non-empty Functions
10227 // UniATA will perform all staff instead of ScsiPort under NT,
10228 // but for ReactOS it is better to patch ScsiPort.
10229 KdPrint2((PRINT_PREFIX
"STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
10230 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10231 newStatus
= ScsiPortInitialize(DriverObject
,
10233 &hwInitializationData
.comm
,
10234 (PVOID
)(i
| 0x80000000));
10235 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x (2)\n", newStatus
));
10237 if (newStatus
< statusToReturn
)
10238 statusToReturn
= newStatus
;
10240 if(g_opt_Verbose
) {
10241 if(newStatus
== STATUS_SUCCESS
) {
10242 _PrintNtConsole(" OK\n");
10244 _PrintNtConsole(" failed\n");
10250 /* KeBugCheckEx(0xc000000e,
10253 newStatus, statusToReturn);*/
10257 hwInitializationData
.comm
.VendorId
= 0;
10258 hwInitializationData
.comm
.VendorIdLength
= 0;
10259 hwInitializationData
.comm
.DeviceId
= 0;
10260 hwInitializationData
.comm
.DeviceIdLength
= 0;
10263 hwInitializationData
.comm
.SrbExtensionSize
= //FIELD_OFFSET(ATA_REQ, ata);
10265 KdPrint2((PRINT_PREFIX
"using AtaReq sz %x\n", hwInitializationData
.comm
.SrbExtensionSize
));
10268 // The adapter count is used by the find adapter routine to track how
10269 // which adapter addresses have been tested.
10271 // Indicate 2 access ranges and reset FindAdapter.
10272 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
10273 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindController
;
10275 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
10276 // Indicate ISA bustype.
10277 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10280 // Call initialization for ISA bustype.
10281 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
10282 newStatus
= ScsiPortInitialize(DriverObject
,
10284 &hwInitializationData
.comm
,
10286 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10287 if (newStatus
< statusToReturn
)
10288 statusToReturn
= newStatus
;
10290 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
10292 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
10293 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
10296 newStatus
= ScsiPortInitialize(DriverObject
,
10298 &hwInitializationData
.comm
,
10300 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10301 if (newStatus
< statusToReturn
)
10302 statusToReturn
= newStatus
;
10304 InDriverEntry
= FALSE
;
10306 KdPrint2((PRINT_PREFIX
"\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn
));
10308 return statusToReturn
;
10310 } // end DriverEntry()
10313 PSCSI_REQUEST_BLOCK
10315 BuildMechanismStatusSrb(
10316 IN PVOID HwDeviceExtension
,
10317 IN PSCSI_REQUEST_BLOCK Srb
10320 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10321 PSCSI_REQUEST_BLOCK srb
;
10323 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10325 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10327 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10329 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10330 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10331 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10332 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10334 // Set flags to disable synchronous negociation.
10335 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10337 // Set timeout to 4 seconds.
10338 srb
->TimeOutValue
= 4;
10340 srb
->CdbLength
= 6;
10341 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
10342 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10343 srb
->SrbExtension
= AtaReq
;
10345 // Set CDB operation code.
10346 cdb
= (PCDB
)srb
->Cdb
;
10347 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
10348 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10350 KdPrint2((PRINT_PREFIX
" MechanismStatusSrb %#x\n", srb
));
10353 } // end BuildMechanismStatusSrb()
10355 #endif //UNIATA_CORE
10357 PSCSI_REQUEST_BLOCK
10359 BuildRequestSenseSrb (
10360 IN PVOID HwDeviceExtension
,
10361 IN PSCSI_REQUEST_BLOCK Srb
10364 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10365 PSCSI_REQUEST_BLOCK srb
;
10367 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10369 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10371 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10373 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10374 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10375 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10376 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10378 // Set flags to disable synchronous negociation.
10379 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10381 // Set timeout to 2 seconds.
10382 srb
->TimeOutValue
= 4;
10384 srb
->CdbLength
= 6;
10385 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
10386 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
10387 srb
->SrbExtension
= AtaReq
;
10389 // Set CDB operation code.
10390 cdb
= (PCDB
)srb
->Cdb
;
10391 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
10392 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
10394 KdPrint2((PRINT_PREFIX
" RequestSenseSrb %#x\n", srb
));
10397 } // end BuildRequestSenseSrb()
10399 #ifndef UNIATA_CORE
10403 AtapiRegCheckDevLunValue(
10404 IN PVOID HwDeviceExtension
,
10405 IN PCWCH NamePrefix
,
10413 ULONG val
= Default
;
10415 val
= AtapiRegCheckParameterValue(
10416 HwDeviceExtension
, NamePrefix
, Name
, val
);
10418 if(chan
!= CHAN_NOT_SPECIFIED
) {
10419 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
10420 val
= AtapiRegCheckParameterValue(
10421 HwDeviceExtension
, namex
, Name
, val
);
10422 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
10423 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
10424 val
= AtapiRegCheckParameterValue(
10425 HwDeviceExtension
, namex
, Name
, val
);
10429 } // end AtapiRegCheckDevLunValue()
10442 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
10461 swprintf(Buffer
+j
, L
"%2.2x", a
);
10469 } // end EncodeVendorStr()
10473 AtapiRegCheckDevValue(
10474 IN PVOID HwDeviceExtension
,
10481 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10482 // WCHAR name0[11];
10483 // WCHAR name1[11+4+5];
10484 // WCHAR name2[11+4+4+10];
10485 // WCHAR name3[11+4+4+5+20];
10486 // WCHAR name3[11+4+4+5+20+1];
10495 IN ULONG SlotNumber
;
10497 ULONG val
= Default
;
10499 KdPrint(( " Parameter %ws\n", Name
));
10501 if(deviceExtension
) {
10502 VendorID
= deviceExtension
->DevID
& 0xffff;
10503 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
10504 SlotNumber
= deviceExtension
->slotNumber
;
10508 SlotNumber
= 0xffffffff;
10511 val
= AtapiRegCheckDevLunValue(
10512 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
10514 if(deviceExtension
) {
10515 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
10517 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
10518 swprintf(namex
, L
"Parameters%s", namev
);
10519 val
= AtapiRegCheckDevLunValue(
10520 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10523 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
10524 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
10525 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
10527 swprintf(namex
, L
"Parameters%s", namev
);
10528 val
= AtapiRegCheckDevLunValue(
10529 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10531 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
10532 val
= AtapiRegCheckDevLunValue(
10533 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10535 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
10536 val
= AtapiRegCheckDevLunValue(
10537 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10539 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
10541 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
10542 swprintf(namex
, L
"Parameters%s", namev
);
10543 val
= AtapiRegCheckDevLunValue(
10544 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10546 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
10547 swprintf(namex
, L
"Parameters%s", namev
);
10548 val
= AtapiRegCheckDevLunValue(
10549 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10552 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
10554 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
10555 swprintf(namex
, L
"Parameters%s", namev
);
10556 val
= AtapiRegCheckDevLunValue(
10557 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10559 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
10560 swprintf(namex
, L
"Parameters%s", namev
);
10561 val
= AtapiRegCheckDevLunValue(
10562 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10567 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
10570 } // end AtapiRegCheckDevValue()
10573 The user must specify that Xxx is to run on the platform
10574 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
10575 Services\UniATA\Xxx:REG_DWORD:Zzz.
10577 The user can override the global setting to enable or disable Xxx on a
10578 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
10579 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
10581 If this registry value does not exist or contains the value zero then
10582 the timer to check for media change does not run.
10586 RegistryPath - pointer to the unicode string inside
10587 ...\CurrentControlSet\Services\UniATA
10588 DeviceNumber - The number of the HBA device object
10590 Returns: Registry Key value
10594 AtapiRegCheckParameterValue(
10595 IN PVOID HwDeviceExtension
,
10596 IN PCWSTR PathSuffix
,
10601 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
10603 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10605 LONG zero
= Default
;
10607 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
10610 LONG doRun
= Default
;
10612 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
10614 UNICODE_STRING paramPath
;
10616 // <SavedRegPath>\<PathSuffix> -> <Name>
10617 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
10618 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
10620 paramPath
.Length
= 0;
10621 paramPath
.MaximumLength
= RegistryPath
->Length
+
10622 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
10623 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
10624 if(!paramPath
.Buffer
) {
10625 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
10629 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
10630 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
10631 RtlAppendUnicodeToString(¶mPath
, L
"\\");
10632 RtlAppendUnicodeToString(¶mPath
, REGRTL_STR_PTYPE PathSuffix
);
10634 // Check for the Xxx value.
10635 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
10637 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
10638 parameters
[0].Name
= REGRTL_STR_PTYPE Name
;
10639 parameters
[0].EntryContext
= &doRun
;
10640 parameters
[0].DefaultType
= REG_DWORD
;
10641 parameters
[0].DefaultData
= &zero
;
10642 parameters
[0].DefaultLength
= sizeof(ULONG
);
10644 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
10645 paramPath
.Buffer
, parameters
, NULL
, NULL
);
10646 if(NT_SUCCESS(status
)) {
10647 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix
, Name
, doRun
));
10650 ExFreePool(paramPath
.Buffer
);
10652 if(!NT_SUCCESS(status
)) {
10658 #undef ITEMS_TO_QUERY
10660 } // end AtapiRegCheckParameterValue()
10663 SCSI_ADAPTER_CONTROL_STATUS
10665 AtapiAdapterControl(
10666 IN PVOID HwDeviceExtension
,
10667 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
10668 IN PVOID Parameters
10671 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10672 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
10673 ULONG numberChannels
= deviceExtension
->NumberChannels
;
10677 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
10679 switch(ControlType
) {
10680 case ScsiQuerySupportedControlTypes
: {
10681 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
10682 TRUE
, // ScsiQuerySupportedControlTypes
10683 TRUE
, // ScsiStopAdapter
10684 TRUE
, // ScsiRestartAdapter
10685 FALSE
, // ScsiSetBootConfig
10686 FALSE
// ScsiSetRunningConfig
10689 ULONG lim
= ScsiAdapterControlMax
;
10692 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
10694 if(pControlTypeList
->MaxControlType
< lim
) {
10695 lim
= pControlTypeList
->MaxControlType
;
10698 for(i
= 0; i
< lim
; i
++) {
10699 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
10705 case ScsiStopAdapter
: {
10707 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
10708 // Shut down all interrupts on the adapter. They'll get re-enabled
10709 // by the initialization routines.
10710 for (c
= 0; c
< numberChannels
; c
++) {
10711 AtapiResetController(deviceExtension
, c
);
10712 AtapiDisableInterrupts(deviceExtension
, c
);
10714 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
10715 // we must never get here for non-PCI
10716 status
= UniataDisconnectIntr2(HwDeviceExtension
);
10717 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
10721 case ScsiRestartAdapter
: {
10723 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
10724 // Enable all the interrupts on the adapter while port driver call
10725 // for power up an HBA that was shut down for power management
10727 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
10728 status
= UniataConnectIntr2(HwDeviceExtension
);
10729 for (c
= 0; c
< numberChannels
; c
++) {
10730 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
10731 FindDevices(HwDeviceExtension
, 0, c
);
10732 AtapiEnableInterrupts(deviceExtension
, c
);
10733 AtapiHwInitialize__(deviceExtension
, c
);
10735 if(deviceExtension
->Isr2DevObj
) {
10736 // we must never get here for non-PCI
10737 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
10744 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
10745 return ScsiAdapterControlUnsuccessful
;
10749 return ScsiAdapterControlSuccess
;
10750 } // end AtapiAdapterControl()
10752 #endif //UNIATA_CORE
10762 #define DEBUG_MSG_BUFFER_SIZE 512
10773 UCHAR dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
];
10774 // UNICODE_STRING msgBuff;
10776 va_start(ap
, DebugMessage
);
10778 len
= _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], DEBUG_MSG_BUFFER_SIZE
-1, DebugMessage
, ap
);
10780 dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
-1] = 0;
10782 //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro
10783 HalDisplayString(dbg_print_tmp_buff
);
10786 if(g_LogToDisplay
> 1) {
10787 AtapiStallExecution(g_LogToDisplay
*1000);
10793 } // end PrintNtConsole()