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 GetBaseStatus(chan
, statusByte2
);
729 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_RESET
);
731 // Do not wait for BUSY assertion if it was initially set, jump to
732 // BUSY release wait loop
733 if(!(statusByte2
& IDE_STATUS_BUSY
)) {
734 // Wait for BUSY assertion, in some cases delay may occure
735 // 100ms should be enough
737 while (!(AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
740 AtapiStallExecution(10);
745 // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
746 // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
747 // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
748 // implementation. (which is around 1 second)
749 while ((AtapiReadPort1(chan
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) &&
752 AtapiStallExecution(30);
756 SelectDrive(chan
, DeviceNumber
);
758 GetBaseStatus(chan
, statusByte2
);
759 AtapiStallExecution(500);
761 GetBaseStatus(chan
, statusByte2
);
762 if(chan
&& chan
->DeviceExtension
) {
763 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
764 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
766 KdPrint2((PRINT_PREFIX
" can't get DMA status\n"));
768 if(dma_status
& BM_STATUS_INTR
) {
769 // bullshit, we have DMA interrupt, but had never initiate DMA operation
770 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr on ATAPI reset\n"));
771 AtapiDmaDone(chan
->DeviceExtension
, DeviceNumber
, chan
->lChannel
, NULL
);
772 GetBaseStatus(chan
, statusByte2
);
774 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
775 UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, DeviceNumber
);
776 /* if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
777 UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1);
782 } // end AtapiSoftReset()
785 Send command to device.
786 Translate to 48-Lba form if required
791 IN PHW_DEVICE_EXTENSION deviceExtension
,
792 IN ULONG DeviceNumber
,
801 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
806 KdPrint2((PRINT_PREFIX
"AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
807 deviceExtension
->DevIndex
, deviceExtension
->Channel
, DeviceNumber
, command
, lba
, count
, feature
));
809 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
810 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
812 KdPrint3((" (ahci)\n"));
814 statusByte
= UniataAhciSendPIOCommand(deviceExtension
, lChannel
, DeviceNumber
,
815 (PSCSI_REQUEST_BLOCK
)NULL
,
823 1000 /* timeout 1 sec */
829 SelectDrive(chan
, DeviceNumber
);
831 statusByte
= WaitOnBusy(chan
);
833 /* ready to issue command ? */
834 if (statusByte
& IDE_STATUS_BUSY
) {
835 KdPrint2((PRINT_PREFIX
" Returning BUSY status\n"));
838 // !!! We should not check ERROR condition here
839 // ERROR bit may be asserted durring previous operation
840 // and not cleared after SELECT
842 //>>>>>> NV: 2006/08/03
843 if(((AtaCommandFlags
[command
] & (ATA_CMD_FLAG_LBAIOsupp
|ATA_CMD_FLAG_FUA
)) == ATA_CMD_FLAG_LBAIOsupp
) &&
844 CheckIfBadBlock(chan
->lun
[DeviceNumber
], lba
, count
)) {
845 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
846 return IDE_STATUS_ERROR
;
847 //return SRB_STATUS_ERROR;
849 //<<<<<< NV: 2006/08/03
851 /* only use 48bit addressing if needed because of the overhead */
852 if (UniAta_need_lba48(command
, lba
, count
,
853 chan
->lun
[DeviceNumber
]->IdentifyData
.FeaturesSupport
.Address48
)) {
855 KdPrint2((PRINT_PREFIX
" dev %#x USE_LBA_48\n", DeviceNumber
));
856 /* translate command into 48bit version */
857 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
858 command
= AtaCommands48
[command
];
860 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
864 chan
->ChannelCtrlFlags
|= CTRFLAGS_LBA48
;
867 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)(feature
>>8));
868 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
869 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)(count
>>8));
870 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
871 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[3]));
872 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)(plba
[0]));
873 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[4]));
874 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)(plba
[1]));
875 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[5]));
876 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)(plba
[2]));
878 //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber ));
879 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
) );
882 plba
= (PUCHAR
)&lba
; //ktp
883 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_LBA48
;
886 // (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
887 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, (UCHAR
)feature
);
889 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, (UCHAR
)count
);
890 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, (UCHAR
)plba
[0]);
891 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, (UCHAR
)plba
[1]);
892 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, (UCHAR
)plba
[2]);
893 if(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
894 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber ));
895 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
897 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber ));
898 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, (UCHAR
)(plba
[3] & 0xf) | (DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
) );
902 // write command code to device
903 AtapiWritePort1(chan
, IDX_IO1_o_Command
, command
);
905 switch (wait_flags
) {
908 // caller requested wait for interrupt
911 statusByte
= WaitForDrq(chan
);
912 if (statusByte
& IDE_STATUS_DRQ
)
914 AtapiStallExecution(500);
915 KdPrint2((PRINT_PREFIX
" retry waiting DRQ, status %#x\n", statusByte
));
922 // caller requested wait for entering Wait state
923 for (i
=0; i
<30 * 1000; i
++) {
925 GetStatus(chan
, statusByte
);
926 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
927 if(statusByte
== IDE_STATUS_WRONG
) {
931 if(statusByte
& IDE_STATUS_ERROR
) {
934 if(statusByte
& IDE_STATUS_BUSY
) {
935 AtapiStallExecution(100);
938 if(statusByte
== IDE_STATUS_IDLE
) {
941 //if(deviceExtension->HwFlags & UNIATA_SATA) {
942 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
945 AtapiStallExecution(100);
948 //statusByte |= IDE_STATUS_BUSY;
952 statusByte
= WaitOnBusyLong(chan
);
954 case ATA_WAIT_BASE_READY
:
955 statusByte
= WaitOnBaseBusyLong(chan
);
958 GetStatus(chan
, statusByte
);
959 if (statusByte
& IDE_STATUS_ERROR
) {
960 KdPrint2((PRINT_PREFIX
" Warning: Immed Status %#x :(\n", statusByte
));
961 if(statusByte
== (IDE_STATUS_IDLE
| IDE_STATUS_ERROR
)) {
964 KdPrint2((PRINT_PREFIX
" try to continue\n"));
965 statusByte
&= ~IDE_STATUS_ERROR
;
967 UniataExpectChannelInterrupt(chan
, TRUE
);
969 InterlockedExchange(&(chan
->CheckIntr
),
975 KdPrint2((PRINT_PREFIX
" Status %#x\n", statusByte
));
978 } // end AtaCommand48()
981 Send command to device.
982 This is simply wrapper for AtaCommand48()
987 IN PHW_DEVICE_EXTENSION deviceExtension
,
988 IN ULONG DeviceNumber
,
999 if(!(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
1000 return AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1002 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
1003 count
, feature
, wait_flags
);
1005 return UniataAhciSendPIOCommand(deviceExtension
, lChannel
, DeviceNumber
,
1006 (PSCSI_REQUEST_BLOCK
)NULL
,
1010 (ULONG
)sector
| ((ULONG
)cylinder
<< 8) | ((ULONG
)(head
& 0x0f) << 24),
1013 0 /* ahci flags */ ,
1015 1000 /* timeout 1 sec */
1019 } // end AtaCommand()
1023 AtaPio2Mode(LONG pio
)
1026 default: return ATA_PIO
;
1027 case 0: return ATA_PIO0
;
1028 case 1: return ATA_PIO1
;
1029 case 2: return ATA_PIO2
;
1030 case 3: return ATA_PIO3
;
1031 case 4: return ATA_PIO4
;
1032 case 5: return ATA_PIO5
;
1034 } // end AtaPio2Mode()
1038 AtaPioMode(PIDENTIFY_DATA2 ident
)
1040 if (ident
->PioTimingsValid
) {
1041 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_5
)
1043 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_4
)
1045 if (ident
->AdvancedPIOModes
& AdvancedPIOModes_3
)
1048 if (ident
->PioCycleTimingMode
== 2)
1050 if (ident
->PioCycleTimingMode
== 1)
1052 if (ident
->PioCycleTimingMode
== 0)
1054 return IOMODE_NOT_SPECIFIED
;
1055 } // end AtaPioMode()
1059 AtaWmode(PIDENTIFY_DATA2 ident
)
1061 if (ident
->MultiWordDMASupport
& 0x04)
1063 if (ident
->MultiWordDMASupport
& 0x02)
1065 if (ident
->MultiWordDMASupport
& 0x01)
1067 return IOMODE_NOT_SPECIFIED
;
1072 AtaUmode(PIDENTIFY_DATA2 ident
)
1074 if (!ident
->UdmaModesValid
)
1075 return IOMODE_NOT_SPECIFIED
;
1076 if (ident
->UltraDMASupport
& 0x40)
1078 if (ident
->UltraDMASupport
& 0x20)
1080 if (ident
->UltraDMASupport
& 0x10)
1082 if (ident
->UltraDMASupport
& 0x08)
1084 if (ident
->UltraDMASupport
& 0x04)
1086 if (ident
->UltraDMASupport
& 0x02)
1088 if (ident
->UltraDMASupport
& 0x01)
1090 return IOMODE_NOT_SPECIFIED
;
1095 AtaSAmode(PIDENTIFY_DATA2 ident
) {
1096 if(!ident
->SataCapabilities
||
1097 ident
->SataCapabilities
== 0xffff) {
1098 return IOMODE_NOT_SPECIFIED
;
1100 if(ident
->SataCapabilities
& ATA_SATA_GEN3
) {
1103 if(ident
->SataCapabilities
& ATA_SATA_GEN2
) {
1106 if(ident
->SataCapabilities
& ATA_SATA_GEN1
) {
1109 return IOMODE_NOT_SPECIFIED
;
1110 } // end AtaSAmode()
1117 IN PVOID HwDeviceExtension
1120 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1121 PHW_TIMER HwScsiTimer
;
1123 ULONG MiniportTimerValue
;
1124 BOOLEAN recall
= FALSE
;
1128 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc:\n"));
1130 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1131 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1132 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no items\n"));
1135 chan
= &(deviceExtension
->chan
[lChannel
]);
1139 HwScsiTimer
= chan
->HwScsiTimer
;
1140 chan
->HwScsiTimer
= NULL
;
1142 deviceExtension
->FirstDpcChan
= chan
->NextDpcChan
;
1143 if(deviceExtension
->FirstDpcChan
!= CHAN_NOT_SPECIFIED
) {
1147 HwScsiTimer(HwDeviceExtension
);
1149 chan
->NextDpcChan
= CHAN_NOT_SPECIFIED
;
1151 lChannel
= deviceExtension
->ActiveDpcChan
= deviceExtension
->FirstDpcChan
;
1152 if(lChannel
== CHAN_NOT_SPECIFIED
) {
1153 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: no more items\n"));
1154 deviceExtension
->FirstDpcChan
=
1155 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1159 KeQuerySystemTime(&time
);
1160 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1162 chan
= &deviceExtension
->chan
[lChannel
];
1163 if(time
.QuadPart
>= chan
->DpcTime
- 10) {
1165 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1166 (ULONG
)(chan
->DpcTime
>> 32), (ULONG
)(chan
->DpcTime
)));
1173 deviceExtension
->ActiveDpcChan
= CHAN_NOT_SPECIFIED
;
1174 MiniportTimerValue
= (ULONG
)(time
.QuadPart
- chan
->DpcTime
)/10;
1175 if(!MiniportTimerValue
)
1176 MiniportTimerValue
= 1;
1178 KdPrint2((PRINT_PREFIX
"AtapiTimerDpc: recall AtapiTimerDpc\n"));
1179 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1186 } // end AtapiTimerDpc()
1189 Wrapper for ScsiPort, that implements smart Dpc
1190 queueing. We need it to allow parallel functioning
1191 of IDE channles with shared interrupt. Standard Dpc mechanism
1192 cancels previous Dpc request (if any), but we need Dpc queue.
1197 IN PVOID HwDeviceExtension
,
1199 IN PHW_TIMER HwScsiTimer
,
1200 IN ULONG MiniportTimerValue
1203 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1205 LARGE_INTEGER time2
;
1207 PHW_CHANNEL prev_chan
;
1209 // BOOLEAN UseRequestTimerCall = TRUE;
1211 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1212 KeQuerySystemTime(&time
);
1214 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1215 time
.QuadPart
+= MiniportTimerValue
*10;
1216 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time
.HighPart
, time
.LowPart
));
1218 KdPrint2((PRINT_PREFIX
" ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension
->ActiveDpcChan
, deviceExtension
->FirstDpcChan
));
1220 i
= deviceExtension
->FirstDpcChan
;
1221 chan
= prev_chan
= NULL
;
1222 while(i
!= CHAN_NOT_SPECIFIED
) {
1224 chan
= &(deviceExtension
->chan
[i
]);
1225 if(chan
->DpcTime
> time
.QuadPart
) {
1228 i
= chan
->NextDpcChan
;
1230 chan
= &(deviceExtension
->chan
[lChannel
]);
1232 deviceExtension
->FirstDpcChan
= lChannel
;
1234 prev_chan
->NextDpcChan
= lChannel
;
1236 chan
->NextDpcChan
= i
;
1237 chan
->HwScsiTimer
= HwScsiTimer
;
1238 chan
->DpcTime
= time
.QuadPart
;
1240 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2
.HighPart
, time2
.LowPart
));
1241 if(time
.QuadPart
<= time2
.QuadPart
) {
1242 MiniportTimerValue
= 1;
1244 MiniportTimerValue
= (ULONG
)((time
.QuadPart
- time2
.QuadPart
) / 10);
1247 KdPrint2((PRINT_PREFIX
"AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue
, lChannel
));
1248 ScsiPortNotification(RequestTimerCall
, HwDeviceExtension
,
1250 MiniportTimerValue
);
1252 } // end AtapiQueueTimerDpc()
1254 #endif //UNIATA_CORE
1264 UCHAR statusByteAlt
;
1266 GetStatus(chan
, statusByteAlt
);
1267 KdPrint2((PRINT_PREFIX
" AltStatus (%#x)\n", statusByteAlt
));
1269 for(j
=1; j
<IDX_IO1_SZ
; j
++) {
1270 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1271 KdPrint2((PRINT_PREFIX
1272 " Reg_%#x (%#x) = %#x\n",
1274 chan
->RegTranslation
[IDX_IO1
+j
].Addr
,
1277 for(j
=0; j
<IDX_BM_IO_SZ
-1; j
++) {
1278 statusByteAlt
= AtapiReadPort1(chan
, IDX_BM_IO
+j
);
1279 KdPrint2((PRINT_PREFIX
1280 " BM_%#x (%#x) = %#x\n",
1282 chan
->RegTranslation
[IDX_BM_IO
+j
].Addr
,
1286 } // end UniataDumpATARegs()
1292 IN PHW_CHANNEL chan
,
1293 IN ULONG DeviceNumber
,
1294 IN OUT PIDEREGS_EX regs
1297 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
1299 UniataAhciSnapAtaRegs(chan
, DeviceNumber
, regs
);
1301 // SATA/PATA, assume drive is selected
1303 UCHAR statusByteAlt
;
1305 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) {
1306 for(j
=IDX_IO1_i_Error
; j
<=IDX_IO1_i_Status
; j
++) {
1307 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1308 ((PUCHAR
)regs
)[j
-1] = statusByteAlt
;
1312 regs
->bDriveHeadReg
= AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
);
1313 for(j
=IDX_IO1_i_Error
; j
<IDX_IO1_i_DriveSelect
; j
++) {
1314 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1315 ((PUCHAR
)regs
)[j
-1] = statusByteAlt
;
1316 statusByteAlt
= AtapiReadPort1(chan
, IDX_IO1
+j
);
1317 ((PUCHAR
)regs
)[j
+8-1] = statusByteAlt
;
1319 regs
->bCommandReg
= AtapiReadPort1(chan
, IDX_IO1_i_Status
);
1323 } // end UniataSnapAtaRegs()
1327 Routine Description:
1329 Issue IDENTIFY command to a device.
1333 HwDeviceExtension - HBA miniport driver's adapter data storage
1334 DeviceNumber - Indicates which device.
1335 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1339 TRUE if all goes well.
1345 IN PVOID HwDeviceExtension
,
1346 IN ULONG DeviceNumber
,
1352 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1353 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
1354 ULONG waitCount
= 50000;
1357 //UCHAR statusByte2;
1360 BOOLEAN atapiDev
= FALSE
;
1361 BOOLEAN use_ahci
= FALSE
;
1362 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
1364 use_ahci
= UniataIsSATARangeAvailable(deviceExtension
, lChannel
) &&
1365 (deviceExtension
->HwFlags
& UNIATA_AHCI
);
1367 if(chan
->ChannelCtrlFlags
& CTRFLAGS_AHCI_PM
) {
1368 if(chan
->PmLunMap
& (1 << DeviceNumber
)) {
1371 KdPrint2((PRINT_PREFIX
"IssueIdentify: PM empty port\n"));
1375 if(DeviceNumber
&& (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
1376 KdPrint2((PRINT_PREFIX
"IssueIdentify: NO SLAVE\n"));
1379 if(LunExt
->DeviceFlags
& DFLAGS_HIDDEN
) {
1380 KdPrint2((PRINT_PREFIX
"IssueIdentify: HIDDEN\n"));
1385 statusByte
= WaitOnBusyLong(chan
);
1387 if(!chan
->AhciInternalAtaReq
) {
1388 KdPrint2((PRINT_PREFIX
"!AhciInternalAtaReq\n"));
1392 SelectDrive(chan
, DeviceNumber
);
1393 AtapiStallExecution(10);
1394 statusByte
= WaitOnBusyLong(chan
);
1395 // Check that the status register makes sense.
1396 GetBaseStatus(chan
, statusByte
);
1399 if (Command
== IDE_COMMAND_IDENTIFY
) {
1400 // Mask status byte ERROR bits.
1401 statusByte
= UniataIsIdle(deviceExtension
, statusByte
& ~(IDE_STATUS_ERROR
| IDE_STATUS_INDEX
));
1402 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte
));
1403 // Check if register value is reasonable.
1405 if(statusByte
!= IDE_STATUS_IDLE
) {
1407 // No reset here !!!
1408 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1410 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1411 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1412 SelectDrive(chan
, DeviceNumber
);
1413 WaitOnBusyLong(chan
);
1415 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1416 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1418 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1419 signatureHigh
== ATAPI_MAGIC_MSB
) {
1421 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber
));
1425 // We really should wait up to 31 seconds
1426 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1427 // (30 seconds for device 1)
1429 // Wait for Busy to drop.
1430 AtapiStallExecution(100);
1431 GetStatus(chan
, statusByte
);
1432 if(statusByte
== IDE_STATUS_WRONG
) {
1433 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_WRONG (dev %d)\n", DeviceNumber
));
1437 } while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
--);
1438 GetBaseStatus(chan
, statusByte
);
1440 SelectDrive(chan
, DeviceNumber
);
1442 GetBaseStatus(chan
, statusByte
);
1444 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1446 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1447 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1449 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1450 signatureHigh
== ATAPI_MAGIC_MSB
) {
1451 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber
));
1456 statusByte
= UniataIsIdle(deviceExtension
, statusByte
) & ~IDE_STATUS_INDEX
;
1457 if (statusByte
!= IDE_STATUS_IDLE
) {
1459 KdPrint2((PRINT_PREFIX
"IssueIdentify: no dev (dev %d)\n", DeviceNumber
));
1464 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte
));
1465 if(statusByte
== IDE_STATUS_WRONG
) {
1468 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1469 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1470 statusByte
= WaitForIdleLong(chan
);
1471 KdPrint2((PRINT_PREFIX
"IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte
));
1476 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1478 statusByte
= UniataAhciSendPIOCommand(HwDeviceExtension
, lChannel
, DeviceNumber
,
1479 (PSCSI_REQUEST_BLOCK
)NULL
,
1480 (PUCHAR
)(&deviceExtension
->FullIdentifyData
),
1485 0 /* ahci flags */ ,
1487 1000 /* timeout 1 sec */
1489 j
= 9; // AHCI is rather different, skip loop at all
1491 if(LunExt
->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
1492 j
= 9; // don't send IDENTIFY, assume it is not supported
1493 KdPrint2((PRINT_PREFIX
"IssueIdentify: Manual CHS\n"));
1494 RtlZeroMemory(&(deviceExtension
->FullIdentifyData
), sizeof(deviceExtension
->FullIdentifyData
));
1495 RtlCopyMemory(&(deviceExtension
->FullIdentifyData
), &(LunExt
->IdentifyData
), sizeof(LunExt
->IdentifyData
));
1497 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
1498 j
= 4; // skip old-style checks
1502 for (; j
< 4*2; j
++) {
1503 // Send IDENTIFY command.
1505 // Load CylinderHigh and CylinderLow with number bytes to transfer for old devices, use 0 for newer.
1507 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, Command
, (j
< 4) ? DEV_BSIZE
: 0 /* cyl */, 0, 0, 0, 0, ATA_WAIT_INTR
);
1510 if (statusByte
& IDE_STATUS_DRQ
) {
1511 // Read status to acknowledge any interrupts generated.
1512 KdPrint2((PRINT_PREFIX
"IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte
));
1513 GetBaseStatus(chan
, statusByte
);
1514 // One last check for Atapi.
1515 if (Command
== IDE_COMMAND_IDENTIFY
) {
1516 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1517 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1519 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1520 signatureHigh
== ATAPI_MAGIC_MSB
) {
1521 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber
));
1528 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte
));
1529 if (Command
== IDE_COMMAND_IDENTIFY
) {
1530 // Check the signature. If DRQ didn't come up it's likely Atapi.
1531 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
1532 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
1534 if (signatureLow
== ATAPI_MAGIC_LSB
&&
1535 signatureHigh
== ATAPI_MAGIC_MSB
) {
1537 KdPrint2((PRINT_PREFIX
"IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber
));
1541 if(!(statusByte
& IDE_STATUS_ERROR
) && (statusByte
& IDE_STATUS_BUSY
)) {
1542 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n"));
1546 // Device didn't respond correctly. It will be given one more chance.
1547 KdPrint2((PRINT_PREFIX
"IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1548 statusByte
, AtapiReadPort1(chan
, IDX_IO1_i_Error
)));
1549 GetBaseStatus(chan
, statusByte
);
1550 AtapiSoftReset(chan
,DeviceNumber
);
1552 AtapiDisableInterrupts(deviceExtension
, lChannel
);
1553 AtapiEnableInterrupts(deviceExtension
, lChannel
);
1555 GetBaseStatus(chan
, statusByte
);
1556 //GetStatus(chan, statusByte);
1557 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after soft reset (%#x)\n", statusByte
));
1560 // Check for error on really stupid master devices that assert random
1561 // patterns of bits in the status register at the slave address.
1562 if ((Command
== IDE_COMMAND_IDENTIFY
) && (statusByte
& IDE_STATUS_ERROR
)) {
1563 KdPrint2((PRINT_PREFIX
"IssueIdentify: Exit on error (%#x)\n", statusByte
));
1568 // everything should already be done by controller
1570 if(LunExt
->DeviceFlags
& DFLAGS_MANUAL_CHS
) {
1571 j
= 9; // don't send IDENTIFY, assume it is not supported
1572 KdPrint2((PRINT_PREFIX
"IssueIdentify: Manual CHS (2)\n"));
1573 statusByte
= WaitForDrq(chan
);
1574 statusByte
= WaitOnBusyLong(chan
);
1575 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1576 GetBaseStatus(chan
, statusByte
);
1579 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status before read words %#x\n", statusByte
));
1580 // Suck out 256 words. After waiting for one model that asserts busy
1581 // after receiving the Packet Identify command.
1582 statusByte
= WaitForDrq(chan
);
1583 statusByte
= WaitOnBusyLong(chan
);
1584 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1586 if (!(statusByte
& IDE_STATUS_DRQ
)) {
1587 KdPrint2((PRINT_PREFIX
"IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte
));
1588 GetBaseStatus(chan
, statusByte
);
1591 GetBaseStatus(chan
, statusByte
);
1592 KdPrint2((PRINT_PREFIX
"IssueIdentify: BASE statusByte %#x\n", statusByte
));
1594 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
1596 KdPrint2((PRINT_PREFIX
" use 16bit IO\n"));
1598 // ATI/SII chipsets with memory-mapped IO hangs when
1599 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1600 // Unfortunately, I don't know yet how to workaround it except
1601 // spacifying manual delay in the way you see below.
1602 ReadBuffer(chan
, (PUSHORT
)&deviceExtension
->FullIdentifyData
, 256, PIO0_TIMING
);
1604 // Work around for some IDE and one model Atapi that will present more than
1605 // 256 bytes for the Identify data.
1606 KdPrint2((PRINT_PREFIX
"IssueIdentify: suck data port\n", statusByte
));
1607 statusByte
= AtapiSuckPort2(chan
);
1609 KdPrint2((PRINT_PREFIX
" use 32bit IO\n"));
1610 ReadBuffer2(chan
, (PULONG
)&deviceExtension
->FullIdentifyData
, 256/2, PIO0_TIMING
);
1613 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1614 statusByte
= WaitForDrq(chan
);
1615 KdPrint2((PRINT_PREFIX
"IssueIdentify: statusByte %#x\n", statusByte
));
1616 GetBaseStatus(chan
, statusByte
);
1618 KdPrint2((PRINT_PREFIX
"IssueIdentify: Status after read words %#x\n", statusByte
));
1621 KdPrint2((PRINT_PREFIX
"IssueIdentify: no setup, exiting\n"));
1625 KdPrint2((PRINT_PREFIX
"Model: %20.20s\n", deviceExtension
->FullIdentifyData
.ModelNumber
));
1626 KdPrint2((PRINT_PREFIX
"FW: %4.4s\n", deviceExtension
->FullIdentifyData
.FirmwareRevision
));
1627 KdPrint2((PRINT_PREFIX
"S/N: %20.20s\n", deviceExtension
->FullIdentifyData
.SerialNumber
));
1628 KdPrint2((PRINT_PREFIX
"Pio: %x\n", deviceExtension
->FullIdentifyData
.PioCycleTimingMode
));
1629 if(deviceExtension
->FullIdentifyData
.PioTimingsValid
) {
1630 KdPrint2((PRINT_PREFIX
"APio: %x\n", deviceExtension
->FullIdentifyData
.AdvancedPIOModes
));
1632 KdPrint2((PRINT_PREFIX
"SWDMA: %x\n", deviceExtension
->FullIdentifyData
.SingleWordDMAActive
));
1633 KdPrint2((PRINT_PREFIX
"MWDMA: %x\n", deviceExtension
->FullIdentifyData
.MultiWordDMAActive
));
1634 if(deviceExtension
->FullIdentifyData
.UdmaModesValid
) {
1635 KdPrint2((PRINT_PREFIX
"UDMA: %x/%x\n", deviceExtension
->FullIdentifyData
.UltraDMAActive
, deviceExtension
->FullIdentifyData
.UltraDMASupport
));
1637 KdPrint2((PRINT_PREFIX
"SATA: %x\n", deviceExtension
->FullIdentifyData
.SataEnable
));
1638 KdPrint2((PRINT_PREFIX
"SATA support: %x, CAPs %#x\n",
1639 deviceExtension
->FullIdentifyData
.SataSupport
,
1640 deviceExtension
->FullIdentifyData
.SataCapabilities
));
1642 LunExt
->LimitedTransferMode
=
1643 LunExt
->OrigTransferMode
=
1644 (UCHAR
)ata_cur_mode_from_ident(&(deviceExtension
->FullIdentifyData
), IDENT_MODE_MAX
);
1645 LunExt
->TransferMode
=
1646 (UCHAR
)ata_cur_mode_from_ident(&(deviceExtension
->FullIdentifyData
), IDENT_MODE_ACTIVE
);
1648 KdPrint2((PRINT_PREFIX
"OrigTransferMode: %x, Active: %x\n", LunExt
->OrigTransferMode
, LunExt
->TransferMode
));
1649 KdPrint2((PRINT_PREFIX
"Accoustic %d, cur %d\n",
1650 deviceExtension
->FullIdentifyData
.VendorAcoustic
,
1651 deviceExtension
->FullIdentifyData
.CurrentAcoustic
1653 KdPrint2((PRINT_PREFIX
"AdvPowerMode %d, cur %d\n",
1654 deviceExtension
->FullIdentifyData
.CfAdvPowerMode
1657 // Check out a few capabilities / limitations of the device.
1658 if (deviceExtension
->FullIdentifyData
.RemovableStatus
& 1) {
1659 // Determine if this drive supports the MSN functions.
1660 KdPrint2((PRINT_PREFIX
"IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1662 deviceExtension
->FullIdentifyData
.RemovableStatus
));
1663 LunExt
->DeviceFlags
|= DFLAGS_REMOVABLE_DRIVE
;
1666 // AHCI doesn't recommend using PIO and multiblock
1667 LunExt
->MaximumBlockXfer
= 0;
1669 if (deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
) {
1670 // Determine max. block transfer for this device.
1671 LunExt
->MaximumBlockXfer
=
1672 (UCHAR
)(deviceExtension
->FullIdentifyData
.MaximumBlockTransfer
& 0xFF);
1674 LunExt
->NumOfSectors
= 0;
1675 if (Command
== IDE_COMMAND_IDENTIFY
) {
1676 ULONGLONG NumOfSectors
=0;
1677 ULONGLONG NativeNumOfSectors
=0;
1678 ULONGLONG cylinders
=0;
1679 ULONGLONG tmp_cylinders
=0;
1680 // Read very-old-style drive geometry
1681 KdPrint2((PRINT_PREFIX
"CHS %#x:%#x:%#x\n",
1682 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1683 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1684 deviceExtension
->FullIdentifyData
.SectorsPerTrack
1686 NumOfSectors
= deviceExtension
->FullIdentifyData
.NumberOfCylinders
*
1687 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1688 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1689 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1690 // Check for HDDs > 8Gb
1691 if ((deviceExtension
->FullIdentifyData
.NumberOfCylinders
== 0x3fff) &&
1692 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1693 (NumOfSectors
< deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1694 KdPrint2((PRINT_PREFIX
"NumberOfCylinders == 0x3fff\n"));
1696 (deviceExtension
->FullIdentifyData
.UserAddressableSectors
/
1697 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1698 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1700 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1702 NumOfSectors
= cylinders
*
1703 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1704 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1706 KdPrint2((PRINT_PREFIX
"NumOfSectors %#I64x\n", NumOfSectors
));
1710 // Check for LBA mode
1711 KdPrint2((PRINT_PREFIX
"SupportLba flag %#x\n", deviceExtension
->FullIdentifyData
.SupportLba
));
1712 KdPrint2((PRINT_PREFIX
"MajorRevision %#x\n", deviceExtension
->FullIdentifyData
.MajorRevision
));
1713 KdPrint2((PRINT_PREFIX
"UserAddressableSectors %#x\n", deviceExtension
->FullIdentifyData
.UserAddressableSectors
));
1714 if ( deviceExtension
->FullIdentifyData
.SupportLba
1716 (deviceExtension
->FullIdentifyData
.MajorRevision
&&
1717 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1718 deviceExtension
->FullIdentifyData
.UserAddressableSectors
)) {
1719 KdPrint2((PRINT_PREFIX
"LBA mode\n"));
1720 LunExt
->DeviceFlags
|= DFLAGS_LBA_ENABLED
;
1722 KdPrint2((PRINT_PREFIX
"Keep orig geometry\n"));
1723 LunExt
->DeviceFlags
|= DFLAGS_ORIG_GEOMETRY
;
1724 goto skip_lba_staff
;
1726 // Check for LBA48 support
1727 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
1728 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
&&
1729 deviceExtension
->FullIdentifyData
.FeaturesEnabled
.Address48
&&
1730 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
> NumOfSectors
)
1732 KdPrint2((PRINT_PREFIX
"LBA48\n"));
1734 (deviceExtension
->FullIdentifyData
.UserAddressableSectors48
/
1735 (deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1736 deviceExtension
->FullIdentifyData
.SectorsPerTrack
));
1738 KdPrint2((PRINT_PREFIX
"cylinders %#I64x\n", cylinders
));
1740 NativeNumOfSectors
= cylinders
*
1741 deviceExtension
->FullIdentifyData
.NumberOfHeads
*
1742 deviceExtension
->FullIdentifyData
.SectorsPerTrack
;
1744 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1746 if(NativeNumOfSectors
> NumOfSectors
) {
1747 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1748 NumOfSectors
= NativeNumOfSectors
;
1752 // Check drive capacity report for LBA48-capable drives.
1753 if(deviceExtension
->FullIdentifyData
.FeaturesSupport
.Address48
) {
1754 ULONG hNativeNumOfSectors
;
1755 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1757 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1758 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1760 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1762 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1764 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1765 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1766 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) ;
1768 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
1771 KdPrint2((PRINT_PREFIX
"Read high order bytes\n"));
1772 NativeNumOfSectors
|=
1773 (ULONG
)((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24 );
1774 hNativeNumOfSectors
=
1775 (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) |
1776 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 8) ;
1777 ((PULONG
)&NativeNumOfSectors
)[1] = hNativeNumOfSectors
;
1779 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1781 // Some drives report LBA48 capability while has capacity below 128Gb
1782 // Probably they support large block-counters.
1783 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
1784 // Here we check this
1785 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1786 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!!\n"));
1788 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1789 IDE_COMMAND_READ_NATIVE_SIZE48
, 0, 0, 0, ATA_WAIT_READY
);
1791 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1793 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1795 NativeNumOfSectors
= (ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1796 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) << 24) |
1797 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8 ) |
1798 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 32) |
1799 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1800 ((ULONGLONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 40)
1805 if((NativeNumOfSectors
& 0xffffff) == ((NativeNumOfSectors
>> 24) & 0xffffff)) {
1806 KdPrint2((PRINT_PREFIX
"High-order bytes == Low-order bytes !!! (2)\n"));
1807 NativeNumOfSectors
= 0;
1811 if(NumOfSectors
<= ATA_MAX_LBA28
&&
1812 NativeNumOfSectors
> NumOfSectors
) {
1814 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
1815 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1817 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1818 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1819 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1820 NumOfSectors
= NativeNumOfSectors
;
1826 if(NumOfSectors
< 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
1827 // check for native LBA size
1828 // some drives report ~32Gb in Identify Block
1829 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
1831 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_READ_NATIVE_SIZE
,
1832 0, IDE_USE_LBA
, 0, 0, 0, ATA_WAIT_READY
);
1834 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1836 NativeNumOfSectors
= chan
->AhciInternalAtaReq
->ahci
.in_lba
;
1838 NativeNumOfSectors
= (ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
) |
1839 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
) << 8) |
1840 ((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
) << 16) |
1841 (((ULONG
)AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
) & 0xf) << 24);
1843 KdPrint2((PRINT_PREFIX
"NativeNumOfSectors %#I64x\n", NativeNumOfSectors
));
1845 if(NativeNumOfSectors
> NumOfSectors
) {
1847 KdPrint2((PRINT_PREFIX
"Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
1848 KdPrint2((PRINT_PREFIX
"Update NumOfSectors to %#I64x\n", NativeNumOfSectors
));
1850 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
1851 IDE_COMMAND_SET_NATIVE_SIZE
, NativeNumOfSectors
, 0, 0, ATA_WAIT_READY
);
1852 if(!(statusByte
& IDE_STATUS_ERROR
)) {
1853 NumOfSectors
= NativeNumOfSectors
;
1859 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
1861 // fill IdentifyData with bogus geometry
1862 KdPrint2((PRINT_PREFIX
"requested LunExt->GeomType=%x\n", LunExt
->opt_GeomType
));
1863 tmp_cylinders
= NumOfSectors
/ (deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*
1864 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
);
1865 KdPrint2((PRINT_PREFIX
"tmp_cylinders = %#I64x\n", tmp_cylinders
));
1866 if((tmp_cylinders
< 0xffff) || (LunExt
->opt_GeomType
== GEOM_ORIG
)) {
1867 // ok, we can keep original values
1868 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1869 LunExt
->opt_GeomType
= GEOM_ORIG
;
1872 tmp_cylinders
= NumOfSectors
/ (255*63);
1873 if(tmp_cylinders
< 0xffff) {
1874 // we can use generic values for H/S for generic geometry approach
1875 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1876 LunExt
->opt_GeomType
= GEOM_STD
;
1879 // we should use UNIATA geometry approach
1880 if(LunExt
->opt_GeomType
== GEOM_AUTO
) {
1881 LunExt
->opt_GeomType
= GEOM_UNIATA
;
1886 if(LunExt
->opt_GeomType
== GEOM_STD
) {
1887 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
=
1888 deviceExtension
->FullIdentifyData
.SectorsPerTrack
= 63;
1890 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
=
1891 deviceExtension
->FullIdentifyData
.NumberOfHeads
= 255;
1893 cylinders
= NumOfSectors
/ (255*63);
1894 KdPrint2((PRINT_PREFIX
"Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders
, 255, 63));
1896 if(LunExt
->opt_GeomType
== GEOM_UNIATA
) {
1897 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x80)) {
1899 KdPrint2((PRINT_PREFIX
"cylinders /= 2\n"));
1900 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1901 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1903 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x80)) {
1905 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (2)\n"));
1906 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1907 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1909 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.SectorsPerTrack
< 0x8000)) {
1911 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (3)\n"));
1912 deviceExtension
->FullIdentifyData
.SectorsPerTrack
*= 2;
1913 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
*= 2;
1915 while ((cylinders
> 0xffff) && (deviceExtension
->FullIdentifyData
.NumberOfHeads
< 0x8000)) {
1917 KdPrint2((PRINT_PREFIX
"cylinders /= 2 (4)\n"));
1918 deviceExtension
->FullIdentifyData
.NumberOfHeads
*= 2;
1919 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
*= 2;
1921 KdPrint2((PRINT_PREFIX
"Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders
,
1922 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
,
1923 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
));
1926 KdPrint2((PRINT_PREFIX
"cylinders = tmp_cylinders (%x = %x)\n", cylinders
, tmp_cylinders
));
1927 cylinders
= tmp_cylinders
;
1929 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
=
1930 deviceExtension
->FullIdentifyData
.NumberOfCylinders
= (USHORT
)cylinders
;
1934 KdPrint2((PRINT_PREFIX
"Geometry: C %#x (%#x)\n",
1935 deviceExtension
->FullIdentifyData
.NumberOfCylinders
,
1936 deviceExtension
->FullIdentifyData
.NumberOfCurrentCylinders
1938 KdPrint2((PRINT_PREFIX
"Geometry: H %#x (%#x)\n",
1939 deviceExtension
->FullIdentifyData
.NumberOfHeads
,
1940 deviceExtension
->FullIdentifyData
.NumberOfCurrentHeads
1942 KdPrint2((PRINT_PREFIX
"Geometry: S %#x (%#x)\n",
1943 deviceExtension
->FullIdentifyData
.SectorsPerTrack
,
1944 deviceExtension
->FullIdentifyData
.CurrentSectorsPerTrack
1948 LunExt
->NumOfSectors
= NumOfSectors
;
1949 /* if(deviceExtension->FullIdentifyData.MajorRevision &&
1950 deviceExtension->FullIdentifyData.DoubleWordIo) {
1951 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
1955 ScsiPortMoveMemory(&LunExt
->IdentifyData
,
1956 &deviceExtension
->FullIdentifyData
,sizeof(IDENTIFY_DATA2
));
1958 InitBadBlocks(LunExt
);
1960 if ((LunExt
->IdentifyData
.DrqType
& ATAPI_DRQT_INTR
) &&
1961 (Command
!= IDE_COMMAND_IDENTIFY
)) {
1963 // This device interrupts with the assertion of DRQ after receiving
1964 // Atapi Packet Command
1965 LunExt
->DeviceFlags
|= DFLAGS_INT_DRQ
;
1966 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device interrupts on assertion of DRQ.\n"));
1969 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
1972 if(Command
!= IDE_COMMAND_IDENTIFY
) {
1974 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_TAPE
) {
1976 LunExt
->DeviceFlags
|= DFLAGS_TAPE_DEVICE
;
1977 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is a tape drive.\n"));
1979 if(LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
||
1980 LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_OPTICAL
) {
1981 KdPrint2((PRINT_PREFIX
"IssueIdentify: Device is CD/Optical drive.\n"));
1982 // set CD default costs
1983 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_CD
;
1984 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_CD
;
1985 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_CD
;
1986 statusByte
= WaitForDrq(chan
);
1988 KdPrint2((PRINT_PREFIX
"IssueIdentify: ATAPI drive type %#x.\n",
1989 LunExt
->IdentifyData
.DeviceType
));
1992 KdPrint2((PRINT_PREFIX
"IssueIdentify: hard drive.\n"));
1995 GetBaseStatus(chan
, statusByte
);
1996 KdPrint2((PRINT_PREFIX
"IssueIdentify: final Status on exit (%#x)\n", statusByte
));
1999 } // end IssueIdentify()
2004 Routine Description:
2005 Set drive parameters using the IDENTIFY data.
2008 HwDeviceExtension - HBA miniport driver's adapter data storage
2009 DeviceNumber - Indicates which device.
2012 TRUE if all goes well.
2018 IN PVOID HwDeviceExtension
,
2019 IN ULONG DeviceNumber
,
2023 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2024 PIDENTIFY_DATA2 identifyData
;
2025 PHW_LU_EXTENSION LunExt
;
2030 LunExt
= deviceExtension
->chan
[lChannel
].lun
[DeviceNumber
];
2031 identifyData
= &(LunExt
->IdentifyData
);
2033 if(LunExt
->DeviceFlags
&
2034 (DFLAGS_LBA_ENABLED
| DFLAGS_ORIG_GEOMETRY
))
2037 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Number of heads %#x\n", identifyData
->NumberOfHeads
));
2038 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Sectors per track %#x\n", identifyData
->SectorsPerTrack
));
2040 // Send SET PARAMETER command.
2041 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
2042 IDE_COMMAND_SET_DRIVE_PARAMETERS
, 0,
2043 (identifyData
->NumberOfHeads
- 1), 0,
2044 (UCHAR
)identifyData
->SectorsPerTrack
, 0, ATA_WAIT_IDLE
);
2046 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2047 if(statusByte
& IDE_STATUS_ERROR
) {
2048 errorByte
= AtapiReadPort1(&deviceExtension
->chan
[lChannel
], IDX_IO1_i_Error
);
2049 KdPrint2((PRINT_PREFIX
"SetDriveParameters: Error bit set. Status %#x, error %#x\n",
2050 errorByte
, statusByte
));
2054 if(statusByte
== IDE_STATUS_IDLE
) {
2060 } // end SetDriveParameters()
2065 PHW_LU_EXTENSION LunExt
2068 // keep only DFLAGS_HIDDEN flag
2069 LunExt
->DeviceFlags
&= DFLAGS_HIDDEN
;
2070 LunExt
->AtapiReadyWaitDelay
= 0;
2071 } // end UniataForgetDevice()
2076 Routine Description:
2077 Reset IDE controller and/or Atapi device.
2081 HwDeviceExtension - HBA miniport driver's adapter data storage
2090 AtapiResetController(
2091 IN PVOID HwDeviceExtension
,
2095 KdPrint2((PRINT_PREFIX
"AtapiResetController(%x)\n", PathId
));
2096 return AtapiResetController__(HwDeviceExtension
, PathId
, RESET_COMPLETE_ALL
);
2097 } // end AtapiResetController()
2101 AtapiResetController__(
2102 IN PVOID HwDeviceExtension
,
2104 IN BOOLEAN CompleteType
2107 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2108 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2109 PHW_CHANNEL chan
= NULL
;
2113 PSCSI_REQUEST_BLOCK CurSrb
;
2114 ULONG ChannelCtrlFlags
;
2115 UCHAR dma_status
= 0;
2117 ULONG slotNumber
= deviceExtension
->slotNumber
;
2118 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
2119 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
2121 ULONG DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
2123 //ULONG RevID = deviceExtension->RevID;
2124 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
2128 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID
, DeviceID
, slotNumber
));
2129 KdPrint2((PRINT_PREFIX
"simplexOnly %d\n", deviceExtension
->simplexOnly
));
2131 if(!deviceExtension
->simplexOnly
&& (PathId
!= CHAN_NOT_SPECIFIED
)) {
2132 // we shall reset both channels on SimplexOnly devices,
2133 // It's not worth doing so on normal controllers
2135 numberChannels
= min(j
+1, deviceExtension
->NumberChannels
);
2138 numberChannels
= deviceExtension
->NumberChannels
;
2141 for (; j
< numberChannels
; j
++) {
2143 KdPrint2((PRINT_PREFIX
"AtapiResetController: Reset channel %d\n", j
));
2144 chan
= &(deviceExtension
->chan
[j
]);
2145 MaxLuns
= chan
->NumberLuns
;
2146 KdPrint2((PRINT_PREFIX
" CompleteType %#x, Luns %d, chan %#x, sptr %#x\n", CompleteType
, MaxLuns
, chan
, &chan
));
2147 //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
2148 if(CompleteType
!= RESET_COMPLETE_NONE
) {
2150 while((CurSrb
= UniataGetCurRequest(chan
))) {
2152 PATA_REQ AtaReq
= (PATA_REQ
)(CurSrb
->SrbExtension
);
2154 KdPrint2((PRINT_PREFIX
"AtapiResetController: pending SRB %#x, chan %#x\n", CurSrb
, chan
));
2155 // Check and see if we are processing an internal srb
2156 if (AtaReq
->OriginalSrb
) {
2157 KdPrint2((PRINT_PREFIX
" restore original SRB %#x\n", AtaReq
->OriginalSrb
));
2158 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
2159 CurSrb
->SrbExtension
= NULL
;
2160 AtaReq
->OriginalSrb
= NULL
;
2161 // NOTE: internal SRB doesn't get to SRB queue !!!
2162 CurSrb
= AtaReq
->Srb
;
2165 // Remove current request from queue
2166 UniataRemoveRequest(chan
, CurSrb
);
2168 // Check if request is in progress.
2169 ASSERT(AtaReq
->Srb
== CurSrb
);
2171 // Complete outstanding request with SRB_STATUS_BUS_RESET.
2172 UCHAR PathId
= CurSrb
->PathId
;
2173 UCHAR TargetId
= CurSrb
->TargetId
;
2174 UCHAR Lun
= CurSrb
->Lun
;
2176 CurSrb
->SrbStatus
= ((CompleteType
== RESET_COMPLETE_ALL
) ? SRB_STATUS_BUS_RESET
: SRB_STATUS_ABORTED
) | SRB_STATUS_AUTOSENSE_VALID
;
2177 CurSrb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
2179 if (CurSrb
->SenseInfoBuffer
) {
2181 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)CurSrb
->SenseInfoBuffer
;
2182 KdPrint2((PRINT_PREFIX
" senseBuffer %#x, chan %#x\n", senseBuffer
, chan
));
2184 senseBuffer
->ErrorCode
= 0x70;
2185 senseBuffer
->Valid
= 1;
2186 senseBuffer
->AdditionalSenseLength
= 0xb;
2187 if(CompleteType
== RESET_COMPLETE_ALL
) {
2188 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
2189 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2190 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_BUS_RESET
;
2191 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_SCSI_BUS
;
2193 KdPrint2((PRINT_PREFIX
"AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
2194 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2195 senseBuffer
->AdditionalSenseCode
= 0;
2196 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2200 // Clear request tracking fields.
2201 AtaReq
->WordsLeft
= 0;
2202 AtaReq
->DataBuffer
= NULL
;
2203 AtaReq
->TransferLength
= 0;
2204 KdPrint2((PRINT_PREFIX
"chan %#x\n", chan
));
2206 ScsiPortNotification(RequestComplete
,
2210 // Indicate ready for next request.
2211 ScsiPortNotification(NextLuRequest
,
2217 if(CompleteType
!= RESET_COMPLETE_ALL
)
2220 #endif //UNIATA_CORE
2221 } // end if (!CompleteType != RESET_COMPLETE_NONE)
2223 // Save control flags
2224 ChannelCtrlFlags
= chan
->ChannelCtrlFlags
;
2225 // Clear expecting interrupt flag.
2226 UniataExpectChannelInterrupt(chan
, FALSE
);
2228 chan
->ChannelCtrlFlags
= 0;
2229 InterlockedExchange(&(chan
->CheckIntr
),
2232 for (i
= 0; i
< MaxLuns
; i
++) {
2233 chan
->lun
[i
]->PowerState
= 0;
2236 if(ChipFlags
& UNIATA_AHCI
) {
2237 KdPrint2((PRINT_PREFIX
" AHCI path\n"));
2238 if(UniataAhciChanImplemented(deviceExtension
, j
)) {
2240 UniataDumpAhciPortRegs(chan
);
2242 AtapiDisableInterrupts(deviceExtension
, j
);
2243 UniataAhciReset(HwDeviceExtension
, j
);
2245 KdPrint2((PRINT_PREFIX
" skip not implemented\n"));
2248 KdPrint2((PRINT_PREFIX
" ATA path, chan %#x\n", chan
));
2249 KdPrint2((PRINT_PREFIX
" disable intr (0)\n"));
2250 AtapiDisableInterrupts(deviceExtension
, j
);
2251 KdPrint2((PRINT_PREFIX
" done\n"));
2253 case ATA_INTEL_ID
: {
2257 if(!(ChipFlags
& UNIATA_SATA
)) {
2260 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2265 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2266 if(ChipFlags
& UNIATA_AHCI
) {
2269 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2270 GetPciConfig1(0x90, tmp8
);
2278 mask
= 1 << chan
->lun
[0]->SATA_lun_map
;
2280 mask
|= (1 << chan
->lun
[1]->SATA_lun_map
);
2283 ChangePciConfig2(0x92, a
& ~mask
);
2284 AtapiStallExecution(10);
2285 ChangePciConfig2(0x92, a
| mask
);
2288 /* Wait up to 1 sec for "connect well". */
2289 if (ChipFlags
& (I6CH
| I6CH2
)) {
2295 GetPciConfig2(0x92, tmp16
);
2296 if (((tmp16
>> pshift
) & mask
) == mask
) {
2297 GetBaseStatus(chan
, statusByte
);
2298 if(statusByte
!= IDE_STATUS_WRONG
) {
2302 AtapiStallExecution(10000);
2306 case ATA_NVIDIA_ID
: {
2307 KdPrint2((PRINT_PREFIX
" SIS/nVidia\n"));
2308 if(!(ChipFlags
& UNIATA_SATA
))
2311 case ATA_SILICON_IMAGE_ID
: {
2313 ULONG Channel
= deviceExtension
->Channel
+ j
;
2314 if(!(ChipFlags
& UNIATA_SATA
))
2316 offset
= ((Channel
& 1) << 7) + ((Channel
& 2) << 8);
2317 /* disable PHY state change interrupt */
2318 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x148 + offset
, 0);
2320 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2322 /* reset controller part for this channel */
2323 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2324 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) | (0xc0 >> Channel
));
2325 AtapiStallExecution(1000);
2326 AtapiWritePortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48,
2327 AtapiReadPortEx4(NULL
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
), 0x48) & ~(0xc0 >> Channel
));
2331 case ATA_PROMISE_ID
: {
2334 if(ChipFlags
& UNIATA_SATA
) {
2335 KdPrint2((PRINT_PREFIX
" SATA generic reset\n"));
2336 UniataSataClearErr(HwDeviceExtension
, j
, UNIATA_SATA_IGNORE_CONNECT
, 0);
2339 KdPrint2((PRINT_PREFIX
" send reset\n"));
2340 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
|
2341 IDE_DC_RESET_CONTROLLER
);
2342 KdPrint2((PRINT_PREFIX
" wait a little\n"));
2343 AtapiStallExecution(10000);
2344 // Disable interrupts
2345 KdPrint2((PRINT_PREFIX
" disable intr\n"));
2346 AtapiDisableInterrupts(deviceExtension
, j
);
2347 AtapiStallExecution(100);
2348 KdPrint2((PRINT_PREFIX
" re-enable intr\n"));
2349 AtapiEnableInterrupts(deviceExtension
, j
);
2350 KdPrint2((PRINT_PREFIX
" wait a little (2)\n"));
2351 AtapiStallExecution(100000);
2352 KdPrint2((PRINT_PREFIX
" done\n"));
2357 //if(!(ChipFlags & UNIATA_SATA)) {}
2358 if(!UniataIsSATARangeAvailable(deviceExtension
, j
)) {
2359 // Reset DMA engine if active
2360 KdPrint2((PRINT_PREFIX
" check DMA engine\n"));
2361 dma_status
= GetDmaStatus(chan
->DeviceExtension
, chan
->lChannel
);
2362 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
2363 if((ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
2364 (dma_status
& BM_STATUS_INTR
)) {
2365 AtapiDmaDone(HwDeviceExtension
, 0, j
, NULL
);
2370 // all these shall be performed inside AtapiHwInitialize__() ?
2372 KdPrint2((PRINT_PREFIX
" process connected devices 0 - %d\n", MaxLuns
-1));
2373 // Do special processing for ATAPI and IDE disk devices.
2374 for (i
= 0; i
< MaxLuns
; i
++) {
2376 // Check if device present.
2377 KdPrint2((PRINT_PREFIX
" Chan %#x\n", chan
));
2378 KdPrint2((PRINT_PREFIX
" Lun %#x\n", i
));
2379 KdPrint2((PRINT_PREFIX
" Lun ptr %#x\n", chan
->lun
[i
]));
2380 if (!(chan
->lun
[i
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2381 if(ChipFlags
& UNIATA_AHCI
) {
2382 // everything is done in UniataAhciReset()
2383 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2389 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2390 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2393 if(!CheckDevice(HwDeviceExtension
, j
, i
, TRUE
)) {
2397 if(ChipFlags
& UNIATA_AHCI
) {
2398 // everything is done in UniataAhciReset()
2399 KdPrint2((PRINT_PREFIX
" found some device\n"));
2401 if(!IssueIdentify(HwDeviceExtension
,
2403 ATAPI_DEVICE(chan
, i
) ?
2404 IDE_COMMAND_ATAPI_IDENTIFY
: IDE_COMMAND_IDENTIFY
,
2406 KdPrint2((PRINT_PREFIX
" identify failed !\n"));
2407 UniataForgetDevice(chan
->lun
[i
]);
2411 if(!UniataAnybodyHome(HwDeviceExtension
, j
, i
)) {
2412 KdPrint2((PRINT_PREFIX
" device have gone\n"));
2413 UniataForgetDevice(chan
->lun
[i
]);
2418 SelectDrive(chan
, i
);
2419 AtapiStallExecution(10);
2420 statusByte
= WaitOnBusyLong(chan
);
2421 statusByte
= UniataIsIdle(deviceExtension
, statusByte
);
2422 if(statusByte
== IDE_STATUS_WRONG
) {
2423 KdPrint2((PRINT_PREFIX
2424 "no drive, status %#x\n",
2426 UniataForgetDevice(chan
->lun
[i
]);
2428 // Check for ATAPI disk.
2429 if (ATAPI_DEVICE(chan
, i
)) {
2430 // Issue soft reset and issue identify.
2431 GetStatus(chan
, statusByte
);
2432 KdPrint2((PRINT_PREFIX
"AtapiResetController: Status before Atapi reset (%#x).\n",
2435 AtapiDisableInterrupts(deviceExtension
, j
);
2436 AtapiSoftReset(chan
, i
);
2437 AtapiEnableInterrupts(deviceExtension
, j
);
2439 GetStatus(chan
, statusByte
);
2441 if(statusByte
== IDE_STATUS_SUCCESS
) {
2443 IssueIdentify(HwDeviceExtension
,
2445 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
);
2448 KdPrint2((PRINT_PREFIX
2449 "AtapiResetController: Status after soft reset %#x\n",
2452 GetBaseStatus(chan
, statusByte
);
2455 // Issue identify and reinit after channel reset.
2457 if (statusByte
!= IDE_STATUS_IDLE
&&
2458 statusByte
!= IDE_STATUS_SUCCESS
&&
2459 statusByte
!= IDE_STATUS_DRDY
) {
2461 KdPrint2((PRINT_PREFIX
"AtapiResetController: IdeHardReset failed\n"));
2463 if(!IssueIdentify(HwDeviceExtension
,
2465 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2467 KdPrint2((PRINT_PREFIX
"AtapiResetController: IDE IssueIdentify failed\n"));
2469 // Set disk geometry parameters.
2470 if (!SetDriveParameters(HwDeviceExtension
, i
, j
)) {
2471 KdPrint2((PRINT_PREFIX
"AtapiResetController: SetDriveParameters failed\n"));
2473 GetBaseStatus(chan
, statusByte
);
2475 // force DMA mode reinit
2476 chan
->lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
2480 // Enable interrupts, note, we can have here recursive disable
2481 AtapiStallExecution(10);
2482 KdPrint2((PRINT_PREFIX
"AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2484 chan
->DisableIntr
));
2485 AtapiEnableInterrupts(deviceExtension
, j
);
2487 // Call the HwInitialize routine to setup multi-block.
2488 AtapiHwInitialize__(deviceExtension
, j
);
2490 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
2494 } // end AtapiResetController__()
2499 Routine Description:
2500 This routine maps ATAPI and IDE errors to specific SRB statuses.
2503 HwDeviceExtension - HBA miniport driver's adapter data storage
2504 Srb - IO request packet
2513 IN PVOID HwDeviceExtension
,
2514 IN PSCSI_REQUEST_BLOCK Srb
2517 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2518 ULONG lChannel
= GET_CHANNEL(Srb
);
2519 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2521 UCHAR errorByte
= 0;
2522 UCHAR srbStatus
= SRB_STATUS_SUCCESS
;
2524 ULONG DeviceNumber
= GET_CDEV(Srb
);
2525 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
2527 // Read the error register.
2529 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
2530 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
2532 errorByte
= AtaReq
->ahci
.in_error
;
2536 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2538 KdPrint2((PRINT_PREFIX
2539 "MapError: Error register is %#x\n",
2542 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
2544 switch (errorByte
>> 4) {
2545 case SCSI_SENSE_NO_SENSE
:
2547 KdPrint2((PRINT_PREFIX
2548 "ATAPI: No sense information\n"));
2549 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2550 srbStatus
= SRB_STATUS_ERROR
;
2553 case SCSI_SENSE_RECOVERED_ERROR
:
2555 KdPrint2((PRINT_PREFIX
2556 "ATAPI: Recovered error\n"));
2558 srbStatus
= SRB_STATUS_SUCCESS
;
2561 case SCSI_SENSE_NOT_READY
:
2563 KdPrint2((PRINT_PREFIX
2564 "ATAPI: Device not ready\n"));
2565 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2566 srbStatus
= SRB_STATUS_ERROR
;
2569 case SCSI_SENSE_MEDIUM_ERROR
:
2571 KdPrint2((PRINT_PREFIX
2572 "ATAPI: Media error\n"));
2573 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2574 srbStatus
= SRB_STATUS_ERROR
;
2577 case SCSI_SENSE_HARDWARE_ERROR
:
2579 KdPrint2((PRINT_PREFIX
2580 "ATAPI: Hardware error\n"));
2581 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2582 srbStatus
= SRB_STATUS_ERROR
;
2585 case SCSI_SENSE_ILLEGAL_REQUEST
:
2587 KdPrint2((PRINT_PREFIX
2588 "ATAPI: Illegal request\n"));
2589 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2590 srbStatus
= SRB_STATUS_ERROR
;
2593 case SCSI_SENSE_UNIT_ATTENTION
:
2595 KdPrint2((PRINT_PREFIX
2596 "ATAPI: Unit attention\n"));
2597 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2598 srbStatus
= SRB_STATUS_ERROR
;
2601 case SCSI_SENSE_DATA_PROTECT
:
2603 KdPrint2((PRINT_PREFIX
2604 "ATAPI: Data protect\n"));
2605 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2606 srbStatus
= SRB_STATUS_ERROR
;
2609 case SCSI_SENSE_BLANK_CHECK
:
2611 KdPrint2((PRINT_PREFIX
2612 "ATAPI: Blank check\n"));
2613 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2614 srbStatus
= SRB_STATUS_ERROR
;
2617 case SCSI_SENSE_ABORTED_COMMAND
:
2618 KdPrint2((PRINT_PREFIX
2619 "Atapi: Command Aborted\n"));
2620 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2621 srbStatus
= SRB_STATUS_ERROR
;
2626 KdPrint2((PRINT_PREFIX
2627 "ATAPI: Invalid sense information\n"));
2629 srbStatus
= SRB_STATUS_ERROR
;
2637 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
2638 chan
->ReturningMediaStatus
= errorByte
;
2640 if (errorByte
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
2641 KdPrint2((PRINT_PREFIX
2642 "IDE: Media change\n"));
2643 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2644 srbStatus
= SRB_STATUS_ERROR
;
2646 if (Srb
->SenseInfoBuffer
) {
2648 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2650 senseBuffer
->ErrorCode
= 0x70;
2651 senseBuffer
->Valid
= 1;
2652 senseBuffer
->AdditionalSenseLength
= 0xb;
2653 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2654 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2655 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2657 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2660 } else if (errorByte
& IDE_ERROR_COMMAND_ABORTED
) {
2661 KdPrint2((PRINT_PREFIX
2662 "IDE: Command abort\n"));
2663 srbStatus
= SRB_STATUS_ABORTED
;
2664 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2666 if (Srb
->SenseInfoBuffer
) {
2668 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2670 senseBuffer
->ErrorCode
= 0x70;
2671 senseBuffer
->Valid
= 1;
2672 senseBuffer
->AdditionalSenseLength
= 0xb;
2673 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
2674 senseBuffer
->AdditionalSenseCode
= 0;
2675 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2677 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2680 LunExt
->ErrorCount
++;
2682 } else if (errorByte
& IDE_ERROR_END_OF_MEDIA
) {
2684 KdPrint2((PRINT_PREFIX
2685 "IDE: End of media\n"));
2686 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2687 srbStatus
= SRB_STATUS_ERROR
;
2689 if (Srb
->SenseInfoBuffer
) {
2691 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2693 senseBuffer
->ErrorCode
= 0x70;
2694 senseBuffer
->Valid
= 1;
2695 senseBuffer
->AdditionalSenseLength
= 0xb;
2696 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2697 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIA_STATE
;
2698 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_END_OF_MEDIUM
;
2699 senseBuffer
->EndOfMedia
= 1;
2701 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2704 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2705 LunExt
->ErrorCount
++;
2708 } else if (errorByte
& IDE_ERROR_ILLEGAL_LENGTH
) {
2710 KdPrint2((PRINT_PREFIX
2711 "IDE: Illegal length\n"));
2712 srbStatus
= SRB_STATUS_INVALID_REQUEST
;
2714 if (Srb
->SenseInfoBuffer
) {
2716 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2718 senseBuffer
->ErrorCode
= 0x70;
2719 senseBuffer
->Valid
= 1;
2720 senseBuffer
->AdditionalSenseLength
= 0xb;
2721 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
2722 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_VALUE
;
2723 senseBuffer
->AdditionalSenseCodeQualifier
= SCSI_SENSEQ_PARAM_INVALID_VALUE
;
2724 senseBuffer
->IncorrectLength
= 1;
2726 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2729 } else if (errorByte
& IDE_ERROR_BAD_BLOCK
) {
2731 KdPrint2((PRINT_PREFIX
2732 "IDE: Bad block\n"));
2733 srbStatus
= SRB_STATUS_ERROR
;
2734 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2735 if (Srb
->SenseInfoBuffer
) {
2737 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2739 senseBuffer
->ErrorCode
= 0x70;
2740 senseBuffer
->Valid
= 1;
2741 senseBuffer
->AdditionalSenseLength
= 0xb;
2742 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2743 senseBuffer
->AdditionalSenseCode
= 0;
2744 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2746 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2749 } else if (errorByte
& IDE_ERROR_ID_NOT_FOUND
) {
2751 KdPrint2((PRINT_PREFIX
2752 "IDE: Id not found\n"));
2753 srbStatus
= SRB_STATUS_ERROR
;
2754 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2756 if (Srb
->SenseInfoBuffer
) {
2758 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2760 senseBuffer
->ErrorCode
= 0x70;
2761 senseBuffer
->Valid
= 1;
2762 senseBuffer
->AdditionalSenseLength
= 0xb;
2763 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2764 senseBuffer
->AdditionalSenseCode
= 0;
2765 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2767 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2770 LunExt
->ErrorCount
++;
2772 } else if (errorByte
& IDE_ERROR_MEDIA_CHANGE
) {
2774 KdPrint2((PRINT_PREFIX
2775 "IDE: Media change\n"));
2776 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2777 srbStatus
= SRB_STATUS_ERROR
;
2779 if (Srb
->SenseInfoBuffer
) {
2781 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2783 senseBuffer
->ErrorCode
= 0x70;
2784 senseBuffer
->Valid
= 1;
2785 senseBuffer
->AdditionalSenseLength
= 0xb;
2786 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
2787 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
2788 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2790 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2793 } else if (errorByte
& IDE_ERROR_DATA_ERROR
) {
2795 KdPrint2((PRINT_PREFIX
2796 "IDE: Data error\n"));
2797 scsiStatus
= SCSISTAT_CHECK_CONDITION
;
2798 srbStatus
= SRB_STATUS_ERROR
;
2800 if (!(LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)){
2801 LunExt
->ErrorCount
++;
2804 // Build sense buffer
2805 if (Srb
->SenseInfoBuffer
) {
2807 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
2809 senseBuffer
->ErrorCode
= 0x70;
2810 senseBuffer
->Valid
= 1;
2811 senseBuffer
->AdditionalSenseLength
= 0xb;
2812 senseBuffer
->SenseKey
= SCSI_SENSE_MEDIUM_ERROR
;
2813 senseBuffer
->AdditionalSenseCode
= 0;
2814 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
2816 srbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2820 if (LunExt
->ErrorCount
>= MAX_ERRORS
) {
2821 // deviceExtension->DWordIO = FALSE;
2823 KdPrint2((PRINT_PREFIX
2824 "MapError: ErrorCount >= MAX_ERRORS\n"));
2826 LunExt
->DeviceFlags
&= ~DFLAGS_DWORDIO_ENABLED
;
2827 LunExt
->MaximumBlockXfer
= 0;
2830 KdPrint2((PRINT_PREFIX
2831 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
2834 KdPrint2((PRINT_PREFIX
2835 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
2844 ScsiPortLogError( HwDeviceExtension
,
2852 // Reprogram to not use Multi-sector.
2855 if (LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
&&
2856 !(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
2858 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY
);
2860 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2861 // command was aborted.
2862 if (statusByte
& IDE_STATUS_ERROR
) {
2864 // Read the error register.
2865 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2867 KdPrint2((PRINT_PREFIX
"MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
2871 // Adjust the devExt. value, if necessary.
2872 LunExt
->MaximumBlockXfer
= 0;
2880 // Set SCSI status to indicate a check condition.
2881 Srb
->ScsiStatus
= scsiStatus
;
2890 Routine Description:
2893 HwDeviceExtension - HBA miniport driver's adapter data storage
2897 TRUE - if initialization successful.
2898 FALSE - if initialization unsuccessful.
2904 IN PVOID HwDeviceExtension
2907 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2908 ULONG numberChannels
= deviceExtension
->NumberChannels
;
2911 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base)\n"));
2913 if(WinVer_WDM_Model
) {
2914 AtapiResetController__(HwDeviceExtension
, CHAN_NOT_SPECIFIED
, RESET_COMPLETE_ALL
);
2916 if(deviceExtension
->MasterDev
) {
2917 KdPrint2((PRINT_PREFIX
" mark chan %d of master controller [%x] as inited\n",
2918 deviceExtension
->Channel
, deviceExtension
->DevIndex
));
2919 BMList
[deviceExtension
->DevIndex
].ChanInitOk
|= 0x01 << deviceExtension
->Channel
;
2922 /* do extra chipset specific setups */
2923 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
2925 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
2926 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
2927 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
2930 for (c
= 0; c
< numberChannels
; c
++) {
2931 AtapiHwInitialize__(deviceExtension
, c
);
2933 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: (base) done\n"));
2935 } // end AtapiHwInitialize()
2939 AtapiHwInitialize__(
2940 IN PHW_DEVICE_EXTENSION deviceExtension
,
2945 UCHAR statusByte
, errorByte
;
2946 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2947 PHW_LU_EXTENSION LunExt
;
2949 ULONG PreferedMode
= 0xffffffff;
2951 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
2952 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
2956 AtapiChipInit(deviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
);
2957 FindDevices(deviceExtension
, 0, lChannel
);
2959 for (i
= 0; i
< chan
->NumberLuns
; i
++) {
2961 KdPrint3((PRINT_PREFIX
"AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel
, i
));
2963 LunExt
= chan
->lun
[i
];
2965 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
2969 AtapiDisableInterrupts(deviceExtension
, lChannel
);
2970 AtapiStallExecution(1);
2972 if (!(LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_MANUAL_CHS
))) {
2974 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: IDE branch\n"));
2975 // Enable media status notification
2976 IdeMediaStatus(TRUE
,deviceExtension
,lChannel
,(UCHAR
)i
);
2978 // If supported, setup Multi-block transfers.
2979 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
2980 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2981 LunExt
->MaximumBlockXfer
, 0, ATA_WAIT_BASE_READY
);
2983 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2984 // command was aborted.
2985 if (statusByte
& IDE_STATUS_ERROR
) {
2987 // Read the error register.
2988 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
2990 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
2994 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
2995 IDE_COMMAND_SET_MULTIPLE
, 0, 0, 0,
2996 0, 0, ATA_WAIT_BASE_READY
);
2998 if (statusByte
& IDE_STATUS_ERROR
) {
2999 // Read the error register.
3000 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
3002 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
3006 // Adjust the devExt. value, if necessary.
3007 LunExt
->MaximumBlockXfer
= 0;
3010 KdPrint2((PRINT_PREFIX
3011 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
3013 LunExt
->MaximumBlockXfer
));
3016 if(LunExt
->IdentifyData
.MajorRevision
) {
3018 if(LunExt
->opt_ReadCacheEnable
) {
3019 KdPrint2((PRINT_PREFIX
" Try Enable Read Cache\n"));
3020 // If supported, setup read/write cacheing
3021 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3022 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3023 0, ATA_C_F_ENAB_RCACHE
, ATA_WAIT_BASE_READY
);
3025 // Check for errors.
3026 if (statusByte
& IDE_STATUS_ERROR
) {
3027 KdPrint2((PRINT_PREFIX
3028 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
3030 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3032 LunExt
->DeviceFlags
|= DFLAGS_RCACHE_ENABLED
;
3035 KdPrint2((PRINT_PREFIX
" Disable Read Cache\n"));
3036 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3037 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3038 0, ATA_C_F_DIS_RCACHE
, ATA_WAIT_BASE_READY
);
3039 LunExt
->DeviceFlags
&= ~DFLAGS_RCACHE_ENABLED
;
3041 if(LunExt
->opt_WriteCacheEnable
) {
3042 KdPrint2((PRINT_PREFIX
" Try Enable Write Cache\n"));
3043 // If supported & allowed, setup write cacheing
3044 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3045 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3046 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
3047 // Check for errors.
3048 if (statusByte
& IDE_STATUS_ERROR
) {
3049 KdPrint2((PRINT_PREFIX
3050 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
3052 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3054 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
3057 KdPrint2((PRINT_PREFIX
" Disable Write Cache\n"));
3058 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3059 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3060 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
3061 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
3064 if(LunExt
->IdentifyData
.FeaturesSupport
.PowerMngt
||
3065 LunExt
->IdentifyData
.FeaturesSupport
.APM
) {
3067 if(LunExt
->opt_AdvPowerMode
) {
3068 KdPrint2((PRINT_PREFIX
" Try Enable Adv. Power Mgmt\n"));
3070 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3071 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3072 LunExt
->opt_AdvPowerMode
, ATA_C_F_ENAB_APM
, ATA_WAIT_BASE_READY
);
3073 // Check for errors.
3074 if (statusByte
& IDE_STATUS_ERROR
) {
3075 KdPrint2((PRINT_PREFIX
3076 "AtapiHwInitialize: Enable APM on Device %d failed\n",
3080 KdPrint2((PRINT_PREFIX
" Disable Adv. Power Mgmt\n"));
3081 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3082 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3083 0, ATA_C_F_DIS_APM
, ATA_WAIT_BASE_READY
);
3086 if(LunExt
->IdentifyData
.FeaturesSupport
.AutoAcoustic
) {
3087 if(LunExt
->opt_AcousticMode
) {
3088 KdPrint2((PRINT_PREFIX
" Try Enable Acoustic Mgmt\n"));
3089 // setup acoustic mgmt
3090 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3091 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3092 LunExt
->opt_AcousticMode
, ATA_C_F_ENAB_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3093 // Check for errors.
3094 if (statusByte
& IDE_STATUS_ERROR
) {
3095 KdPrint2((PRINT_PREFIX
3096 "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n",
3100 KdPrint2((PRINT_PREFIX
" Disable Acoustic Mgmt\n"));
3101 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3102 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
3103 0, ATA_C_F_DIS_ACOUSTIC
, ATA_WAIT_BASE_READY
);
3106 if(LunExt
->IdentifyData
.FeaturesSupport
.Standby
) {
3107 KdPrint2((PRINT_PREFIX
" Try init standby timer: %d\n"));
3108 // setup standby timer
3109 statusByte
= AtaCommand(deviceExtension
, i
, lChannel
,
3110 IDE_COMMAND_IDLE
, 0, 0, 0,
3111 LunExt
->opt_StandbyTimer
, 0, ATA_WAIT_BASE_READY
);
3112 // Check for errors.
3113 if (statusByte
& IDE_STATUS_ERROR
) {
3114 KdPrint2((PRINT_PREFIX
3115 "AtapiHwInitialize: standby timer on Device %d failed\n",
3121 } else if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
)){
3124 //BOOLEAN isSanyo = FALSE;
3127 KdPrint2((PRINT_PREFIX
"AtapiHwInitialize: ATAPI/Changer branch\n"));
3129 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
3130 for (j
= 0; j
< 26; j
+= 2) {
3132 // Build a buffer based on the identify data.
3133 MOV_DW_SWP(vendorId
[j
], ((PUCHAR
)LunExt
->IdentifyData
.ModelNumber
)[j
]);
3136 if (!AtapiStringCmp (vendorId
, "CD-ROM CDR", 11)) {
3138 // Inquiry string for older model had a '-', newer is '_'
3139 if (vendorId
[12] == 'C') {
3141 // Torisan changer. Set the bit. This will be used in several places
3142 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
3143 LunExt
->DeviceFlags
|= (DFLAGS_CHANGER_INITED
| DFLAGS_SANYO_ATAPI_CHANGER
);
3144 LunExt
->DiscsPresent
= 3;
3150 PreferedMode
= LunExt
->opt_MaxTransferMode
;
3151 if((PreferedMode
== 0xffffffff) || (PreferedMode
> chan
->MaxTransferMode
)) {
3152 KdPrint2((PRINT_PREFIX
"MaxTransferMode (overriden): %#x\n", chan
->MaxTransferMode
));
3153 PreferedMode
= chan
->MaxTransferMode
;
3156 if(LunExt
->opt_PreferedTransferMode
!= 0xffffffff) {
3157 KdPrint2((PRINT_PREFIX
"PreferedTransferMode: %#x\n", PreferedMode
));
3158 PreferedMode
= min(LunExt
->opt_PreferedTransferMode
, PreferedMode
);
3161 KdPrint2((PRINT_PREFIX
" try mode %#x\n", PreferedMode
));
3162 LunExt
->LimitedTransferMode
=
3163 LunExt
->TransferMode
=
3166 AtapiDmaInit__(deviceExtension
, LunExt
);
3168 LunExt
->LimitedTransferMode
=
3169 LunExt
->TransferMode
;
3170 KdPrint2((PRINT_PREFIX
"Using %#x mode\n", LunExt
->TransferMode
));
3172 // We need to get our device ready for action before
3173 // returning from this function
3175 // According to the atapi spec 2.5 or 2.6, an atapi device
3176 // clears its status BSY bit when it is ready for atapi commands.
3177 // However, some devices (Panasonic SQ-TC500N) are still
3178 // not ready even when the status BSY is clear. They don't react
3179 // to atapi commands.
3181 // Since there is really no other indication that tells us
3182 // the drive is really ready for action. We are going to check BSY
3183 // is clear and then just wait for an arbitrary amount of time!
3185 if (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
3188 // have to get out of the loop sometime!
3189 // 10000 * 100us = 1000,000us = 1000ms = 1s
3191 GetStatus(chan
, statusByte
);
3192 if(statusByte
== IDE_STATUS_WRONG
) {
3195 while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
) {
3197 KdPrint2((PRINT_PREFIX
"Wait for ATAPI (status %x)\n", statusByte
));
3198 // Wait for Busy to drop.
3199 AtapiStallExecution(100);
3200 GetStatus(chan
, statusByte
);
3204 // 5000 * 100us = 500,000us = 500ms = 0.5s
3205 if(statusByte
!= IDE_STATUS_WRONG
) {
3208 AtapiStallExecution(100);
3209 } while (waitCount
--);
3212 GetBaseStatus(chan
, statusByte
);
3213 AtapiEnableInterrupts(deviceExtension
, lChannel
);
3214 AtapiStallExecution(10);
3219 } // end AtapiHwInitialize__()
3226 AtapiHwInitializeChanger(
3227 IN PVOID HwDeviceExtension
,
3228 IN PSCSI_REQUEST_BLOCK Srb
,
3229 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus
)
3231 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3232 ULONG lChannel
= GET_CHANNEL(Srb
);
3233 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3234 ULONG DeviceNumber
= GET_CDEV(Srb
);
3235 PHW_LU_EXTENSION LunExt
= chan
->lun
[DeviceNumber
];
3237 if (MechanismStatus
) {
3238 LunExt
->DiscsPresent
= MechanismStatus
->NumberAvailableSlots
;
3239 if (LunExt
->DiscsPresent
> 1) {
3240 LunExt
->DeviceFlags
|= DFLAGS_ATAPI_CHANGER
;
3244 } // end AtapiHwInitializeChanger()
3249 Routine Description:
3250 This routine will parse the string for a match on the keyword, then
3251 calculate the value for the keyword and return it to the caller.
3254 String - The ASCII string to parse.
3255 KeyWord - The keyword for the value desired.
3258 Zero if value not found
3259 Value converted from ASCII to binary.
3264 AtapiParseArgumentString(
3272 ULONG stringLength
= 0;
3273 ULONG keyWordLength
= 0;
3283 // Calculate the string length and lower case all characters.
3289 // Calculate the keyword length.
3295 if (keyWordLength
> stringLength
) {
3297 // Can't possibly have a match.
3301 // Now setup and start the compare.
3306 // The input string may start with white space. Skip it.
3307 while (*cptr
== ' ' || *cptr
== '\t') {
3311 if (*cptr
== '\0') {
3317 while ((*cptr
== *kptr
) ||
3318 (*cptr
>= 'A' && *cptr
<= 'Z' && *cptr
+ ('a' - 'A') == *kptr
) ||
3319 (*cptr
>= 'a' && *cptr
<= 'z' && *cptr
- ('a' - 'A') == *kptr
)) {
3323 if (*cptr
== '\0') {
3329 if (*kptr
== '\0') {
3331 // May have a match backup and check for blank or equals.
3332 while (*cptr
== ' ' || *cptr
== '\t') {
3336 // Found a match. Make sure there is an equals.
3339 // Not a match so move to the next semicolon.
3341 if (*cptr
++ == ';') {
3342 goto ContinueSearch
;
3347 // Skip the equals sign.
3350 // Skip white space.
3351 while ((*cptr
== ' ') || (*cptr
== '\t')) {
3355 if (*cptr
== '\0') {
3356 // Early end of string, return not found
3361 // This isn't it either.
3363 goto ContinueSearch
;
3367 if ((*cptr
== '0') && ((*(cptr
+ 1) == 'x') || (*(cptr
+ 1) == 'X'))) {
3368 // Value is in Hex. Skip the "0x"
3370 for (index
= 0; *(cptr
+ index
); index
++) {
3372 if (*(cptr
+ index
) == ' ' ||
3373 *(cptr
+ index
) == '\t' ||
3374 *(cptr
+ index
) == ';') {
3378 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3379 value
= (16 * value
) + (*(cptr
+ index
) - '0');
3381 if ((*(cptr
+ index
) >= 'a') && (*(cptr
+ index
) <= 'f')) {
3382 value
= (16 * value
) + (*(cptr
+ index
) - 'a' + 10);
3383 } else if ((*(cptr
+ index
) >= 'A') && (*(cptr
+ index
) <= 'F')) {
3384 value
= (16 * value
) + (*(cptr
+ index
) - 'A' + 10);
3386 // Syntax error, return not found.
3393 // Value is in Decimal.
3394 for (index
= 0; *(cptr
+ index
); index
++) {
3396 if (*(cptr
+ index
) == ' ' ||
3397 *(cptr
+ index
) == '\t' ||
3398 *(cptr
+ index
) == ';') {
3402 if ((*(cptr
+ index
) >= '0') && (*(cptr
+ index
) <= '9')) {
3403 value
= (10 * value
) + (*(cptr
+ index
) - '0');
3406 // Syntax error return not found.
3415 // Not a match check for ';' to continue search.
3417 if (*cptr
++ == ';') {
3418 goto ContinueSearch
;
3424 } // end AtapiParseArgumentString()_
3432 IN PVOID HwDeviceExtension
,
3437 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3438 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
3441 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
3444 KdPrint2((PRINT_PREFIX
"AtapiCallBack:\n"));
3445 // If the last command was DSC restrictive, see if it's set. If so, the device is
3446 // ready for a new request. Otherwise, reset the timer and come back to here later.
3448 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3449 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3450 // we shall have no problem with interrupt handler.
3451 if (!srb
|| chan
->ExpectingInterrupt
) {
3452 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Calling ISR directly due to BUSY\n"));
3453 chan
->DpcState
= DPC_STATE_TIMER
;
3454 if(!AtapiInterrupt__(HwDeviceExtension
, lChannel
)) {
3455 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3456 KdPrint2((PRINT_PREFIX
"AtapiCallBack: What's fucking this ???\n"));
3458 goto ReturnCallback
;
3462 if (!IS_RDP((srb
->Cdb
[0]))) {
3463 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb
->Cdb
[0]));
3467 goto ReturnEnableIntr
;
3469 GetStatus(chan
, statusByte
);
3470 if (statusByte
& IDE_STATUS_DSC
) {
3472 UCHAR PathId
= srb
->PathId
;
3473 UCHAR TargetId
= srb
->TargetId
;
3474 UCHAR Lun
= srb
->Lun
;
3476 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Found DSC for RDP - %#x\n", srb
->Cdb
[0]));
3477 AtapiDmaDBSync(chan
, srb
);
3478 UniataRemoveRequest(chan
, srb
);
3479 ScsiPortNotification(RequestComplete
, deviceExtension
, srb
);
3480 // Clear current SRB.
3481 if(!deviceExtension
->simplexOnly
) {
3482 srb
= UniataGetCurRequest(chan
);
3488 // Ask for next request.
3489 ScsiPortNotification(NextLuRequest
,
3494 ScsiPortNotification(NextRequest
, deviceExtension
, NULL
);
3497 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3501 KdPrint2((PRINT_PREFIX
"AtapiCallBack: Requesting another timer for Op %#x\n",
3504 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3508 goto ReturnCallback
;
3513 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
3514 KdPrint2((PRINT_PREFIX
"AtapiCallBack: CallDisableInterrupts\n"));
3515 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3516 #ifdef UNIATA_USE_XXableInterrupts
3517 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
3518 // must be called on DISPATCH_LEVEL
3519 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
3520 AtapiEnableInterrupts__
);
3522 AtapiEnableInterrupts(HwDeviceExtension
, lChannel
);
3523 InterlockedExchange(&(chan
->CheckIntr
),
3525 // Will raise IRQL to DIRQL
3526 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
3527 AtapiEnableInterrupts__
,
3529 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
3530 #endif // UNIATA_USE_XXableInterrupts
3532 //ASSERT(!deviceExtension->simplexOnly);
3537 // Check other channel
3538 // In simplex mode no interrupts must appear on other channels
3539 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3540 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3546 chan
= &(deviceExtension
->chan
[c
]);
3548 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
3549 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3550 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) == CHECK_INTR_DETECTED
)
3552 //ASSERT(!deviceExtension->simplexOnly);
3553 chan
->DpcState
= DPC_STATE_ISR
;
3554 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3555 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3559 KdPrint2((PRINT_PREFIX
"AtapiCallBack: return\n"));
3562 } // end AtapiCallBack__()
3567 IN PVOID HwDeviceExtension
3570 AtapiCallBack__(HwDeviceExtension
, (UCHAR
)((PHW_DEVICE_EXTENSION
)HwDeviceExtension
)->ActiveDpcChan
);
3571 } // end AtapiCallBack_X()
3573 #endif //UNIATA_CORE
3577 Routine Description:
3579 This is the interrupt service routine for ATAPI IDE miniport driver.
3583 HwDeviceExtension - HBA miniport driver's adapter data storage
3587 TRUE if expecting an interrupt.
3593 IN PVOID HwDeviceExtension
3596 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3598 BOOLEAN status
= FALSE
;
3602 //BOOLEAN checked[AHCI_MAX_PORT];
3606 KdPrint2((PRINT_PREFIX
"Intr: VendorID+DeviceID/Rev %#x/%#x (ex %d)\n",
3607 deviceExtension
->DevID
, deviceExtension
->RevID
, deviceExtension
->ExpectingInterrupt
));
3609 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3610 // AHCI may generate state change notification, never skip this check
3611 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
3612 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3616 // assume all non-interrupted ports to be already checked
3618 // assume all not implemented ports to be already checked
3619 checked
|= ~deviceExtension
->AHCI_PI
;
3621 checked
= 0; // assume all ports are not checked
3624 if(!deviceExtension
->ExpectingInterrupt
) {
3625 // if we do not expect interrupt, exit now,
3626 // but keep in mind that it can be unexpected one
3627 // Note: this is just a hint, not exact counter
3628 KdPrint2((PRINT_PREFIX
"unexpected, 1st chance\n"));
3629 //deviceExtension->ExpectingInterrupt++;
3632 // clear this flag now, it can be set again in sub-calls
3633 deviceExtension
->ExpectingInterrupt
=0;
3636 // for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
3637 // checked[_c] = (UCHAR)((hIS >> _c) & 0x01);
3641 for(pass
=0; pass
<2; pass
++) {
3642 //KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): pass %d\n", pass));
3643 if(status
&& pass
) {
3644 // we catched some expected interrupts now.
3645 // do not touch unexpected until next ISR call
3648 for(_c
=0; _c
<deviceExtension
->NumberChannels
; _c
++) {
3650 c
= (_c
+deviceExtension
->FirstChannelToCheck
) % deviceExtension
->NumberChannels
;
3652 if((checked
>>c
) & 0x01)
3655 // check non-empty and expecting interrupt channels first
3656 if(!pass
&& !deviceExtension
->chan
[c
].ExpectingInterrupt
)
3659 checked
|= (ULONG
)1 << c
;
3661 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3663 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3664 // we get here on idle channels or when ISR is posted to DPC
3665 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): disabled INTR on ch %d\n", c
));
3668 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
3670 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): try lock\n"));
3671 // c_state = deviceExtension->chan[c].CheckIntr;
3672 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
3673 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
3676 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3677 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3678 CRNT_ILK_TYPE CHECK_INTR_DETECTED
);
3679 if(c_state
== CHECK_INTR_IDLE
) {
3680 // c_state = deviceExtension->chan[c].CheckIntr;
3681 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
3682 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
3685 (ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3686 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3687 CRNT_ILK_TYPE CHECK_INTR_IDLE
);
3689 } while(c_state
== CHECK_INTR_CHECK
);
3690 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): locked\n"));
3691 // check if already serviced
3692 if(c_state
== CHECK_INTR_ACTIVE
) {
3693 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
3697 if((c_state
== CHECK_INTR_DETECTED
) ||
3698 (i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3700 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
3701 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): Catch unexpected\n"));
3702 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3707 // disable interrupts on other channel of legacy mode
3708 // ISA-bridged onboard controller
3709 if(deviceExtension
->simplexOnly
/*||
3710 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3711 AtapiDisableInterrupts(deviceExtension
, !c
);
3714 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_ISR
;
3715 if(AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3716 deviceExtension
->LastInterruptedChannel
= (UCHAR
)c
;
3717 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): return status TRUE\n"));
3720 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
3721 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3724 // re-enable interrupts on other channel
3725 if(deviceExtension
->simplexOnly
/*||
3726 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3727 AtapiEnableInterrupts(deviceExtension
, !c
);
3731 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
3732 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3737 KdPrint2((PRINT_PREFIX
"AtapiInterrupt(base): exit with status %#x\n", status
));
3739 deviceExtension
->FirstChannelToCheck
++;
3740 if(deviceExtension
->FirstChannelToCheck
>= deviceExtension
->NumberChannels
)
3741 deviceExtension
->FirstChannelToCheck
= 0;
3744 } // end AtapiInterrupt()
3752 IN PKINTERRUPT Interrupt
,
3753 IN PVOID Isr2HwDeviceExtension
3756 // This ISR is intended to catch interrupts when we are already in other ISR instance
3757 // for the same device. This may happen when we have multiple channels,
3758 // especially on SMP machines
3760 PISR2_DEVICE_EXTENSION Isr2DeviceExtension
= (PISR2_DEVICE_EXTENSION
)Isr2HwDeviceExtension
;
3761 PHW_DEVICE_EXTENSION deviceExtension
= Isr2DeviceExtension
->HwDeviceExtension
;
3763 BOOLEAN status
= FALSE
;
3769 // we should never get here for ISA/MCA
3770 if(!BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
3771 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3775 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3776 // AHCI may generate state change notification, never skip this check
3777 hIS
= UniataAhciReadHostPort4(deviceExtension
, IDX_AHCI_IS
);
3778 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS
, deviceExtension
->DevIndex
, deviceExtension
->Channel
));
3782 // assume all non-interrupted ports to be already checked
3784 // assume all not implemented ports to be already checked
3785 checked
|= ~deviceExtension
->AHCI_PI
;
3788 checked
= 0; // assume all ports are not checked
3790 if(!deviceExtension
->ExpectingInterrupt
) {
3791 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !deviceExtension->ExpectingInterrupt\n"));
3792 deviceExtension
->ExpectingInterrupt
++;
3795 //deviceExtension->ExpectingInterrupt = 0;
3797 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3798 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension
->DevIndex
, c
));
3800 if((checked
>>c
) & 0x01)
3803 checked
|= (ULONG
)1 << c
;
3805 if(CrNtInterlockedExchangeAdd(&(deviceExtension
->chan
[c
].DisableIntr
), 0)) {
3806 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: disabled INTR\n"));
3810 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3811 CRNT_ILK_TYPE CHECK_INTR_CHECK
,
3812 CRNT_ILK_TYPE CHECK_INTR_IDLE
) != CHECK_INTR_IDLE
)
3814 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
3815 // hunt on unexpected intr (Some devices generate double interrupts,
3816 // some controllers (at least CMD649) interrupt twice with small delay.
3817 // If interrupts are disabled, they queue interrupt and re-issue it later,
3818 // when we do not expect it.
3823 if((i_res
= AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)c
))) {
3825 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: intr\n"));
3826 if(i_res
== INTERRUPT_REASON_UNEXPECTED
) {
3827 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: Catch unexpected\n"));
3828 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3833 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_DETECTED
);
3835 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3838 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: status %d, c_count %d\n", status
, c_count
));
3839 if(status
&& (c_count
!= deviceExtension
->NumberChannels
)) {
3840 // there is an active ISR/DPC for one channel, but
3841 // we have an interrupt from another one
3842 // Lets inform current ISR/DPC about new interrupt
3843 InterlockedExchange(&(deviceExtension
->ReCheckIntr
), CHECK_INTR_DETECTED
);
3847 KdPrint2((PRINT_PREFIX
"AtapiInterrupt2: return %d\n", status
));
3850 } // end AtapiInterrupt2()
3852 RETTYPE_XXableInterrupts
3855 IN PVOID HwDeviceExtension
3858 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3861 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3862 KdPrint2((PRINT_PREFIX
"AtapiInterruptDpc: %#x\n",c
));
3864 if(!(deviceExtension
->chan
[c
].ChannelCtrlFlags
& CTRFLAGS_DPC_REQ
)) {
3866 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(deviceExtension
->chan
[c
].CheckIntr
),
3867 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3868 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
)
3874 deviceExtension
->chan
[c
].ChannelCtrlFlags
&= ~CTRFLAGS_DPC_REQ
;
3877 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
3878 AtapiDisableInterrupts(deviceExtension, lChannel);
3881 deviceExtension
->chan
[c
].DpcState
= DPC_STATE_DPC
;
3882 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3883 InterlockedExchange(&(deviceExtension
->chan
[c
].CheckIntr
), CHECK_INTR_IDLE
);
3886 return RETVAL_XXableInterrupts
;
3887 } // end AtapiInterruptDpc()
3890 RETTYPE_XXableInterrupts
3892 AtapiEnableInterrupts__(
3893 IN PVOID HwDeviceExtension
3896 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3897 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__():\n"));
3899 PHW_CHANNEL chan
= NULL
;
3901 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
3902 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts__(2): %#x\n",c
));
3903 chan
= &(deviceExtension
->chan
[c
]);
3905 if(chan
->ChannelCtrlFlags
& CTRFLAGS_ENABLE_INTR_REQ
) {
3906 // enable intrs on requested channel
3907 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_ENABLE_INTR_REQ
;
3908 AtapiEnableInterrupts(HwDeviceExtension
, c
);
3909 InterlockedExchange(&(chan
->CheckIntr
),
3912 // check if current or other channel(s) interrupted
3913 //AtapiInterrupt(HwDeviceExtension);
3915 if(deviceExtension
->simplexOnly
) {
3919 // check if other channel(s) interrupted
3920 // must do nothing in simplex mode
3921 if((ULONG
)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE
&(chan
->CheckIntr
),
3922 CRNT_ILK_TYPE CHECK_INTR_ACTIVE
,
3923 CRNT_ILK_TYPE CHECK_INTR_DETECTED
) != CHECK_INTR_DETECTED
) {
3926 //ASSERT(!deviceExtension->simplexOnly);
3927 chan
->DpcState
= DPC_STATE_ISR
;
3928 if(!AtapiInterrupt__(HwDeviceExtension
, (UCHAR
)c
)) {
3929 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
3933 // In simplex mode next command must be sent to device here
3934 if(deviceExtension
->simplexOnly
&& chan
) {
3935 PSCSI_REQUEST_BLOCK srb
;
3936 chan
= UniataGetNextChannel(chan
);
3938 srb
= UniataGetCurRequest(chan
);
3943 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
3947 return RETVAL_XXableInterrupts
;
3949 } // end AtapiEnableInterrupts__()
3951 #endif //UNIATA_CORE
3956 AtapiEnableInterrupts(
3957 IN PVOID HwDeviceExtension
,
3961 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
3965 if(c
>= deviceExtension
->NumberChannels
) {
3966 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c
));
3969 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
3970 !UniataAhciChanImplemented(deviceExtension
, c
)) {
3971 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c
));
3975 chan
= &(deviceExtension
->chan
[c
]);
3976 KdPrint2((PRINT_PREFIX
"AtapiEnableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
3977 if(!InterlockedDecrement(&chan
->DisableIntr
)) {
3978 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
3979 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
,
3980 (ATA_AHCI_P_IX_CPD
| ATA_AHCI_P_IX_TFE
| ATA_AHCI_P_IX_HBF
|
3981 ATA_AHCI_P_IX_HBD
| ATA_AHCI_P_IX_INF
| ATA_AHCI_P_IX_IF
| ATA_AHCI_P_IX_OF
|
3982 ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
: 0) |
3983 ATA_AHCI_P_IX_PRC
| ATA_AHCI_P_IX_PC
| /* DEBUG */
3985 ATA_AHCI_P_IX_DP
| ATA_AHCI_P_IX_UF
| ATA_AHCI_P_IX_SDB
|
3986 ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DHR
)
3989 //SelectDrive(chan, 0);
3990 //GetBaseStatus(chan, statusByte);
3991 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
3993 //if(chan->NumberLuns) {
3994 // SelectDrive(chan, 1);
3995 // GetBaseStatus(chan, statusByte);
3996 // AtapiWritePort1(chan, IDX_IO2_o_Control,
3998 // SelectDrive(chan, chan->cur_cdev);
4001 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_INTR_DISABLED
;
4003 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4004 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4007 } // end AtapiEnableInterrupts()
4011 AtapiDisableInterrupts(
4012 IN PVOID HwDeviceExtension
,
4016 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4018 if(c
>= deviceExtension
->NumberChannels
) {
4019 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c
));
4022 chan
= &(deviceExtension
->chan
[c
]);
4023 KdPrint2((PRINT_PREFIX
"AtapiDisableInterrupts_%d: %d\n",c
, chan
->DisableIntr
));
4024 // mark channel as busy
4025 if(InterlockedIncrement(&chan
->DisableIntr
)) {
4026 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4027 UniataAhciWriteChannelPort4(chan
, IDX_AHCI_P_IE
, 0);
4029 //SelectDrive(chan, 0);
4030 AtapiWritePort1(chan
, IDX_IO2_o_Control
,
4031 IDE_DC_DISABLE_INTERRUPTS
/*| IDE_DC_A_4BIT*/ );
4032 //if(chan->NumberLuns) {
4033 // SelectDrive(chan, 1);
4034 // AtapiWritePort1(chan, IDX_IO2_o_Control,
4035 // IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4036 // SelectDrive(chan, chan->cur_cdev);
4039 chan
->ChannelCtrlFlags
|= CTRFLAGS_INTR_DISABLED
;
4043 } // end AtapiDisableInterrupts()
4046 UniataExpectChannelInterrupt(
4047 IN
struct _HW_CHANNEL
* chan
,
4048 IN BOOLEAN Expecting
4051 chan
->ExpectingInterrupt
= Expecting
;
4053 chan
->DeviceExtension
->ExpectingInterrupt
++;
4055 if(chan
->DeviceExtension
->ExpectingInterrupt
) {
4056 chan
->DeviceExtension
->ExpectingInterrupt
--;
4059 } // end UniataExpectChannelInterrupt()
4062 Check hardware for interrupt state
4066 AtapiCheckInterrupt__(
4067 IN PVOID HwDeviceExtension
,
4068 IN UCHAR c
// logical channel
4071 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4072 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4073 PHW_LU_EXTENSION LunExt
;
4075 ULONG VendorID
= deviceExtension
->DevID
& 0xffff;
4076 ULONG ChipType
= deviceExtension
->HwFlags
& CHIPTYPE_MASK
;
4079 ULONG pr_status
= 0;
4080 UCHAR dma_status
= 0;
4083 UCHAR statusByte
= 0;
4084 ULONG slotNumber
= deviceExtension
->slotNumber
;
4085 ULONG SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
4086 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
4089 BOOLEAN DmaTransfer
= FALSE
;
4090 BOOLEAN OurInterrupt
= FALSE
;
4091 BOOLEAN StatusValid
= FALSE
;
4093 UCHAR interruptReason
;
4094 BOOLEAN EarlyIntr
= FALSE
;
4095 BOOLEAN SingleBlockIntr
= FALSE
;
4097 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__:\n"));
4100 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4101 LunExt
= chan
->lun
[chan
->cur_cdev
];
4103 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ chan %#x:\n", chan));
4104 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ (%d/%d):\n", Channel, chan->cur_cdev));
4106 if((ChipFlags
& UNIATA_AHCI
) &&
4107 UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4109 if(!UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
4110 return OurInterrupt
;
4113 OurInterrupt
= UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
4114 if((OurInterrupt
== INTERRUPT_REASON_UNEXPECTED
) &&
4115 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
)) {
4116 UniataAhciWaitCommandReady(chan
, 2 /* ms */ );
4117 statusByte
= (UCHAR
)UniataAhciWaitReady(chan
, 0 /* immediate */);
4118 if(!(statusByte
& (IDE_STATUS_BUSY
)) ) {
4119 KdPrint2((PRINT_PREFIX
"ATAPI special case READY\n"));
4120 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
4121 OurInterrupt
= INTERRUPT_REASON_OUR
;
4123 if((statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
)) == (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
) ) {
4124 KdPrint2((PRINT_PREFIX
"ATAPI special case pre ERR-READY\n"));
4125 OurInterrupt
= INTERRUPT_REASON_OUR
;
4127 if(statusByte
& IDE_STATUS_ERROR
) {
4128 KdPrint2((PRINT_PREFIX
"ATAPI special case ERR-READY\n"));
4129 OurInterrupt
= INTERRUPT_REASON_OUR
;
4131 KdPrint2((PRINT_PREFIX
"ATAPI special case ? %x\n", statusByte
));
4132 OurInterrupt
= INTERRUPT_REASON_OUR
;
4135 return OurInterrupt
;
4138 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4140 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension
->DevIndex
,
4141 deviceExtension
->Channel
+ c
, c
));
4143 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension
->DevIndex
,
4144 deviceExtension
->Channel
+ c
, c
));
4145 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4146 KdPrint2((PRINT_PREFIX
" DMA status %#x\n", dma_status
));
4149 // do controller-specific interrupt servicing staff
4150 if(deviceExtension
->UnknownDev
) {
4151 KdPrint2((PRINT_PREFIX
" UnknownDev\n"));
4156 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
4157 // Such behavior was observed with Intel ICH-xxx chips
4158 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
4162 case ATA_PROMISE_ID
: {
4166 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x1c);
4170 ((Channel
) ? 0x00004000 : 0x00000400))) {
4171 KdPrint2((PRINT_PREFIX
" Promise old/new unexpected\n"));
4172 return INTERRUPT_REASON_IGNORE
;
4176 AtapiWritePort1(chan
, IDX_BM_DeviceSpecific0
, 0x0b);
4177 status
= AtapiReadPort1(chan
, IDX_BM_DeviceSpecific1
);
4180 if(!(status
& 0x20)) {
4181 KdPrint2((PRINT_PREFIX
" Promise tx unexpected\n"));
4182 return INTERRUPT_REASON_IGNORE
;
4186 status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x0040);
4187 if(ChipFlags
& PRSATA
) {
4188 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c);
4189 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressBM_0
),0x006c, pr_status
& 0x000000ff);
4191 if(pr_status
& (0x11 << Channel
)) {
4192 // TODO: reset channel
4193 KdPrint2((PRINT_PREFIX
" Promise mio unexpected + reset req\n"));
4194 return INTERRUPT_REASON_IGNORE
;
4196 if(!(status
& (0x01 << Channel
))) {
4197 KdPrint2((PRINT_PREFIX
" Promise mio unexpected\n"));
4198 return INTERRUPT_REASON_IGNORE
;
4200 AtapiWritePort4(chan
, IDX_BM_DeviceSpecific0
, 0x00000001);
4204 case ATA_NVIDIA_ID
: {
4205 if(!(ChipFlags
& UNIATA_SATA
))
4208 KdPrint2((PRINT_PREFIX
"NVIDIA\n"));
4210 ULONG offs
= (ChipFlags
& NV4OFF
) ? 0x0440 : 0x0010;
4211 ULONG shift
= Channel
<< ((ChipFlags
& NVQ
) ? 4 : 2);
4213 /* get and clear interrupt status */
4214 if(ChipFlags
& NVQ
) {
4215 pr_status
= AtapiReadPortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4216 AtapiWritePortEx4(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0fUL
<< shift
) | 0x00f000f0);
4218 pr_status
= AtapiReadPortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
);
4219 AtapiWritePortEx1(chan
, (ULONGIO_PTR
)(&deviceExtension
->BaseIoAddressSATA_0
),offs
, (0x0f << shift
));
4221 KdPrint2((PRINT_PREFIX
" pr_status %x\n", pr_status
));
4223 /* check for and handle connect events */
4224 if(((pr_status
& (0x0cUL
<< shift
)) == (0x04UL
<< shift
)) ) {
4225 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
, 0);
4227 /* check for and handle disconnect events */
4228 if((pr_status
& (0x08UL
<< shift
)) &&
4229 !((pr_status
& (0x04UL
<< shift
) &&
4230 UniataSataReadPort4(chan
, IDX_SATA_SStatus
, 0))) ) {
4231 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
, 0);
4233 /* do we have any device action ? */
4234 if(!(pr_status
& (0x01UL
<< shift
))) {
4235 KdPrint2((PRINT_PREFIX
" nVidia unexpected\n"));
4236 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4237 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4239 return INTERRUPT_REASON_IGNORE
;
4245 KdPrint2((PRINT_PREFIX
"ATI\n"));
4246 if(ChipType
== SIIMIO
) {
4251 case ATA_SILICON_IMAGE_ID
:
4253 if(ChipType
== SIIMIO
) {
4255 reg32
= AtapiReadPort4(chan
, IDX_BM_DeviceSpecific0
);
4256 KdPrint2((PRINT_PREFIX
" Sii DS0 %x\n", reg32
));
4257 if(reg32
== 0xffffffff) {
4258 KdPrint2((PRINT_PREFIX
" Sii mio unexpected\n"));
4259 return INTERRUPT_REASON_IGNORE
;
4261 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
))) {
4262 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (2)\n"));
4263 return INTERRUPT_REASON_IGNORE
;
4266 if(ChipFlags
& UNIATA_SATA
) {
4267 if(reg32
& (BM_DS0_SII_DMA_SATA_IRQ
| BM_DS0_SII_IRQ
)) {
4269 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
4270 * controllers continue to assert IRQ as long as
4271 * SError bits are pending. Clear SError immediately.
4273 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4274 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4281 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4282 KdPrint2((PRINT_PREFIX
" Sii mio unexpected (3)\n"));
4283 return OurInterrupt
;
4285 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
& ~BM_STATUS_ERR
);
4286 goto skip_dma_stat_check
;
4289 if(!(deviceExtension
->HwFlags
& SIIINTR
))
4291 GetPciConfig1(0x71, reg8
);
4292 KdPrint2((PRINT_PREFIX
" 0x71 = %#x\n", reg8
));
4294 (Channel
? 0x08 : 0x04))) {
4295 return INTERRUPT_REASON_IGNORE
;
4298 KdPrint2((PRINT_PREFIX
" cmd our\n"));
4299 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4301 SetPciConfig1(0x71, (Channel
? 0x08 : 0x04));
4308 //dma_status = GetDmaStatus(deviceExtension, lChannel);
4309 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4310 KdPrint2((PRINT_PREFIX
" Acard unexpected\n"));
4311 return INTERRUPT_REASON_IGNORE
;
4313 AtapiWritePort1(chan
, IDX_BM_Status
, dma_status
| BM_STATUS_INTR
);
4314 AtapiStallExecution(1);
4315 AtapiWritePort1(chan
, IDX_BM_Command
,
4316 AtapiReadPort1(chan
, IDX_BM_Command
) & ~BM_COMMAND_START_STOP
);
4317 goto skip_dma_stat_check
;
4319 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4320 if(ChipFlags
& UNIATA_AHCI
) {
4323 if(ChipFlags
& UNIATA_SATA
) {
4324 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4325 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4327 if(!(chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
)) {
4328 if(UniataSataClearErr(chan
->DeviceExtension
, chan
->lChannel
, UNIATA_SATA_IGNORE_CONNECT
, 1)) {
4329 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4336 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
4337 if(ChipFlags
& UNIATA_AHCI
) {
4340 if(ChipFlags
& UNIATA_SATA
) {
4341 if(UniataSataClearErr(HwDeviceExtension
, c
, UNIATA_SATA_DO_CONNECT
, 0)) {
4342 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4348 KdPrint2((PRINT_PREFIX
" perform generic check\n"));
4350 if (!((dma_status
= GetDmaStatus(deviceExtension
, lChannel
)) & BM_STATUS_INTR
)) {
4351 KdPrint2((PRINT_PREFIX
" DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status
));
4352 if(dma_status
& BM_STATUS_ERR
) {
4353 KdPrint2((PRINT_PREFIX
" DmaTransfer + BM_STATUS_ERR -> our\n"));
4354 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4356 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4357 GetStatus(chan
, statusByte
);
4359 KdPrint2((PRINT_PREFIX
" status %#x\n", statusByte
));
4360 if(statusByte
& IDE_STATUS_ERROR
) {
4361 KdPrint2((PRINT_PREFIX
" IDE_STATUS_ERROR -> our\n", statusByte
));
4362 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4364 if ((statusByte
& IDE_STATUS_DSC
) &&
4365 (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
4366 (dma_status
== BM_STATUS_ACTIVE
)) {
4367 KdPrint2((PRINT_PREFIX
" special case DMA + ATAPI + IDE_STATUS_DSC -> our\n", statusByte
));
4368 // some devices interrupts on each block transfer even in DMA mode
4369 if(LunExt
->TransferMode
>= ATA_SDMA
&& LunExt
->TransferMode
<= ATA_WDMA2
) {
4370 KdPrint2((PRINT_PREFIX
" wait for completion\n"));
4371 ///* clear interrupt and get status */
4372 //GetBaseStatus(chan, statusByte);
4373 //return INTERRUPT_REASON_IGNORE;
4374 SingleBlockIntr
= TRUE
;
4377 return INTERRUPT_REASON_IGNORE
;
4382 if(dma_status
& BM_STATUS_INTR
) {
4383 // bullshit, we have DMA interrupt, but had never initiate DMA operation
4384 KdPrint2((PRINT_PREFIX
" clear unexpected DMA intr\n"));
4385 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4387 OurInterrupt
= INTERRUPT_REASON_UNEXPECTED
;
4390 skip_dma_stat_check
:
4391 if(!(ChipFlags
& UNIATA_SATA
) && chan
->ExpectingInterrupt
) {
4392 AtapiStallExecution(1);
4395 /* if drive is busy it didn't interrupt */
4396 /* the exception is DCS + BSY state of ATAPI devices */
4398 KdPrint2((PRINT_PREFIX
" getting status...\n"));
4399 GetStatus(chan
, statusByte
);
4401 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4402 KdPrint3((PRINT_PREFIX
" ATAPI status %#x\n", statusByte
));
4404 KdPrint2((PRINT_PREFIX
" IDE status %#x\n", statusByte
));
4406 if (statusByte
== IDE_STATUS_WRONG
) {
4407 // interrupt from empty controller ?
4409 if (statusByte
& IDE_STATUS_BUSY
) {
4410 if(!chan
->ExpectingInterrupt
) {
4411 KdPrint3((PRINT_PREFIX
" unexpected intr + BUSY\n"));
4412 return OurInterrupt
;
4415 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4416 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4418 KdPrint2((PRINT_PREFIX
" expecting intr + BUSY (3), non ATAPI\n"));
4419 return INTERRUPT_REASON_IGNORE
;
4421 if((statusByte
& ~IDE_STATUS_DRQ
) != (IDE_STATUS_BUSY
| IDE_STATUS_DRDY
| IDE_STATUS_DSC
)) {
4422 KdPrint3((PRINT_PREFIX
" unexpected status, seems it is not our\n"));
4423 return INTERRUPT_REASON_IGNORE
;
4425 if(!(LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
) && (statusByte
& IDE_STATUS_DRQ
)) {
4426 KdPrint3((PRINT_PREFIX
" unexpected DRQ, seems it is not our\n"));
4427 return INTERRUPT_REASON_IGNORE
;
4432 if(dma_status
& BM_STATUS_INTR
) {
4433 KdPrint3((PRINT_PREFIX
" our interrupt with BSY set, try wait in ISR or post to DPC\n"));
4434 /* clear interrupt and get status */
4435 GetBaseStatus(chan
, statusByte
);
4436 if(!(dma_status
& BM_STATUS_ACTIVE
)) {
4437 AtapiDmaDone(deviceExtension
, DEVNUM_NOT_SPECIFIED
,lChannel
, NULL
);
4439 KdPrint3((PRINT_PREFIX
" base status %#x (+BM_STATUS_INTR)\n", statusByte
));
4440 return INTERRUPT_REASON_OUR
;
4443 if(g_WaitBusyInISR
) {
4444 GetStatus(chan
, statusByte
);
4445 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4446 reg8
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4447 KdPrint2((PRINT_PREFIX
" Error reg (%#x)\n", reg8
));
4448 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4449 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4451 if (statusByte
& IDE_STATUS_BUSY
) {
4452 KdPrint2((PRINT_PREFIX
" still BUSY, seems it is not our\n"));
4453 return INTERRUPT_REASON_IGNORE
;
4459 /* clear interrupt and get status */
4460 GetBaseStatus(chan
, statusByte
);
4461 KdPrint2((PRINT_PREFIX
" base status %#x\n", statusByte
));
4462 if (statusByte
== IDE_STATUS_WRONG
) {
4463 // interrupt from empty controller ?
4465 if(!(statusByte
& (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
))) {
4466 KdPrint2((PRINT_PREFIX
" no DRQ/DRDY set\n"));
4467 return OurInterrupt
;
4470 #ifndef UNIATA_PIO_ONLY
4472 if(!SingleBlockIntr
&& (!EarlyIntr
|| g_WaitBusyInISR
)) {
4473 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4475 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4476 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4480 if(SingleBlockIntr
) {
4481 KdPrint2((PRINT_PREFIX
" set REQ_STATE_ATAPI_EXPECTING_DATA_INTR2.\n"));
4483 KdPrint2((PRINT_PREFIX
" set REQ_STATE_EARLY_INTR.\n"));
4486 AtaReq
->ReqState
= SingleBlockIntr
? REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
: REQ_STATE_EARLY_INTR
;
4492 if (!(chan
->ExpectingInterrupt
)) {
4494 KdPrint2((PRINT_PREFIX
" Unexpected interrupt.\n"));
4496 if(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) {
4497 KdPrint2((PRINT_PREFIX
" ATAPI additional check\n"));
4499 KdPrint2((PRINT_PREFIX
" OurInterrupt = %d\n", OurInterrupt
));
4500 return OurInterrupt
;
4502 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
4503 KdPrint3((PRINT_PREFIX
"AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason
));
4504 return OurInterrupt
;
4506 //ASSERT(!chan->queue_depth || chan->cur_req);
4508 KdPrint2((PRINT_PREFIX
"AtapiCheckInterrupt__: exit with TRUE\n"));
4509 return INTERRUPT_REASON_OUR
;
4511 } // end AtapiCheckInterrupt__()
4517 IN PVOID HwDeviceExtension
,
4521 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
4522 PHW_CHANNEL chan
= &(deviceExtension
->chan
[c
]);
4524 PSCSI_REQUEST_BLOCK srb
= UniataGetCurRequest(chan
);
4525 PATA_REQ AtaReq
= srb
? (PATA_REQ
)(srb
->SrbExtension
) : NULL
;
4527 ULONG wordCount
= 0, wordsThisInterrupt
= DEV_BSIZE
/2;
4528 ULONG status
= SRB_STATUS_SUCCESS
;
4529 UCHAR dma_status
= 0;
4532 UCHAR statusByte
= 0,interruptReason
;
4534 BOOLEAN atapiDev
= FALSE
;
4541 BOOLEAN DmaTransfer
= FALSE
;
4543 ULONG TimerValue
= 1000;
4544 ULONG TotalTimerValue
= 0;
4545 #ifdef UNIATA_USE_XXableInterrupts
4546 BOOLEAN InDpc
= (KeGetCurrentIrql() == DISPATCH_LEVEL
);
4548 BOOLEAN InDpc
= (chan
->DpcState
!= DPC_STATE_ISR
);
4549 #endif // UNIATA_USE_XXableInterrupts
4550 BOOLEAN UseDpc
= deviceExtension
->UseDpc
;
4551 // BOOLEAN RestoreUseDpc = FALSE;
4552 BOOLEAN DataOverrun
= FALSE
;
4553 BOOLEAN NoStartIo
= TRUE
;
4555 KdPrint2((PRINT_PREFIX
"AtapiInterrupt:\n"));
4557 KdPrint2((PRINT_PREFIX
" InDpc = TRUE\n"));
4558 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
4564 UCHAR OldReqState
= REQ_STATE_NONE
;
4566 PHW_LU_EXTENSION LunExt
;
4571 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4573 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension
->DevIndex
, Channel
, KeGetCurrentIrql(), c
));
4576 if((chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
4577 (AtaReq
&& (AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
)) ||
4578 (deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
4580 KdPrint2((PRINT_PREFIX
" DmaTransfer = TRUE\n"));
4584 PathId
= srb
->PathId
;
4585 TargetId
= srb
->TargetId
;
4591 goto enqueue_next_req
;
4594 //ldev = GET_LDEV2(PathId, TargetId, Lun);
4595 DeviceNumber
= (UCHAR
)(TargetId
);
4596 LunExt
= chan
->lun
[DeviceNumber
];
4597 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
4598 KdPrint2((PRINT_PREFIX
" dev_type %s\n", atapiDev
? "ATAPI" : "IDE"));
4600 // check if we are in ISR DPC
4602 KdPrint2((PRINT_PREFIX
" InDpc -> CTRFLAGS_INTR_DISABLED\n"));
4603 goto ServiceInterrupt
;
4607 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4610 if (!(chan
->ExpectingInterrupt
)) {
4612 KdPrint2((PRINT_PREFIX
" Unexpected interrupt for this channel.\n"));
4616 // change request state
4618 OldReqState
= AtaReq
->ReqState
;
4619 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4620 KdPrint2((PRINT_PREFIX
" OldReqState = %x\n", OldReqState
));
4623 // We don't want using DPC for fast operations, like
4624 // DMA completion, sending CDB, short ATAPI transfers, etc.
4626 // We MUST use DPC, because of interprocessor synchronization
4627 // on multiprocessor platforms
4630 goto ServiceInterrupt
;
4632 switch(OldReqState
) {
4633 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR
:
4634 KdPrint3((PRINT_PREFIX
" EXPECTING_CMD_INTR\n"));
4635 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR
:
4636 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
:
4637 case REQ_STATE_DPC_WAIT_BUSY0
:
4638 case REQ_STATE_DPC_WAIT_BUSY1
:
4639 KdPrint2((PRINT_PREFIX
" continue service interrupt\n"));
4640 goto ServiceInterrupt
;
4641 case REQ_STATE_ATAPI_DO_NOTHING_INTR
:
4642 KdPrint2((PRINT_PREFIX
" do nothing on interrupt\n"));
4646 if(!DmaTransfer
&& !atapiDev
) {
4647 KdPrint2((PRINT_PREFIX
" service PIO HDD\n"));
4654 goto ServiceInterrupt
;
4656 #ifdef UNIATA_USE_XXableInterrupts
4658 KdPrint2((PRINT_PREFIX
" Unexpected InDpc\n"));
4660 // shall never get here
4665 KdPrint2((PRINT_PREFIX
" this is direct DPC call on DRQL\n"));
4667 AtaReq
->ReqState
= REQ_STATE_DPC_INTR_REQ
;
4668 KdPrint2((PRINT_PREFIX
" ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
4670 KdPrint2((PRINT_PREFIX
" DPC without AtaReq!!!\n"));
4673 KdPrint2((PRINT_PREFIX
"call service interrupt\n"));
4674 goto ServiceInterrupt
;
4675 #endif // UNIATA_USE_XXableInterrupts
4680 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
4681 // We always get here when are called from timer callback, which is invoked on DRQL.
4682 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
4684 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: start DPC init...\n"));
4685 // disable interrupts for this channel,
4686 // but avoid recursion and double-disable
4687 if(OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4688 UniataExpectChannelInterrupt(chan
, FALSE
);
4689 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4692 chan
->ChannelCtrlFlags
|= CTRFLAGS_DPC_REQ
;
4694 #ifdef UNIATA_USE_XXableInterrupts
4695 // Will lower IRQL to DISPATCH_LEVEL
4696 ScsiPortNotification(CallEnableInterrupts
, HwDeviceExtension
,
4697 /*c ?*/ AtapiInterruptDpc
/*_1 : AtapiInterruptDpc_0*/);
4698 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DPC inited\n"));
4700 // Will raise IRQL to DIRQL
4701 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4704 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
4705 #endif // UNIATA_USE_XXableInterrupts
4710 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4712 if(!InDpc
&& OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4713 // we must block interrupts from this channel
4714 // If device generate new interrupt before we get to DPC,
4715 // ISR will assume, that it is NOT our interrupt
4716 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4717 // We should not clean ExpectingInterrupt flag on channel, since it is used in DPC
4719 // Will raise IRQL to DIRQL
4720 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4724 #endif //UNIATA_CORE
4728 if(AtaReq
&& InDpc
) {
4729 switch(AtaReq
->ReqState
) {
4730 case REQ_STATE_DPC_WAIT_DRQ0
:
4732 case REQ_STATE_DPC_WAIT_BUSY
:
4734 case REQ_STATE_DPC_WAIT_DRQ
:
4736 case REQ_STATE_DPC_WAIT_DRQ_ERR
:
4738 case REQ_STATE_DPC_WAIT_BUSY0
:
4739 case REQ_STATE_DPC_WAIT_BUSY1
:
4740 // continue normal execution
4746 #endif //UNIATA_CORE
4748 // make additional delay for old devices (if we are not in DPC)
4749 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
4753 !(deviceExtension->HwFlags & UNIATA_SATA)
4755 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
4756 AtapiStallExecution(10);
4760 /* clear interrupt and get status */
4761 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4762 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, srb
);
4763 statusByte
= (UCHAR
)(AtaReq
->ahci
.in_status
& IDE_STATUS_MASK
);
4765 if(chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
)) {
4766 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
)));
4767 if(chan
->AhciLastIS
& ~ATA_AHCI_P_IX_OF
) {
4768 //KdPrint3((PRINT_PREFIX "Err mask (%#x)\n", chan->AhciLastIS & ~ATA_AHCI_P_IX_OF));
4769 // We have some other error except Overflow
4770 // Just signal ERROR, operation will be aborted in ERROR branch.
4771 statusByte
|= IDE_STATUS_ERROR
;
4773 // We have only Overflow. Abort operation and continue
4775 UniataDumpAhciPortRegs(chan
);
4777 if(!UniataAhciAbortOperation(chan
)) {
4778 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
4781 UniataDumpAhciPortRegs(chan
);
4783 UniataAhciWaitCommandReady(chan
, 10);
4788 GetBaseStatus(chan
, statusByte
);
4791 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte
));
4793 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Entered with status (%#x)\n", statusByte
));
4797 KdPrint2((PRINT_PREFIX
" operate like in DPC\n"));
4803 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4804 KdPrint3((PRINT_PREFIX
" AHCI branch (IDE)\n"));
4806 if (statusByte
& IDE_STATUS_BUSY
) {
4807 if (deviceExtension
->DriverMustPoll
) {
4808 // Crashdump is polling and we got caught with busy asserted.
4809 // Just go away, and we will be polled again shortly.
4810 KdPrint2((PRINT_PREFIX
" Hit BUSY while polling during crashdump.\n"));
4811 goto ReturnEnableIntr
;
4814 // Ensure BUSY is non-asserted.
4815 // make a very small idle before falling to DPC
4816 k
= (InDpc
&& UseDpc
) ? 1000 : 2;
4818 for (i
= 0; i
< k
; i
++) {
4820 GetBaseStatus(chan
, statusByte
);
4821 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4824 AtapiStallExecution(10);
4827 if (!InDpc
&& UseDpc
&& i
== 2) {
4829 KdPrint2((PRINT_PREFIX
" BUSY on entry. Status %#x, Base IO %#x\n", statusByte
));
4832 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4837 AtapiStallExecution(TimerValue
);
4838 goto ServiceInterrupt
;
4839 #endif //UNIATA_CORE
4841 if (InDpc
&& i
== k
) {
4842 // reset the controller.
4843 KdPrint2((PRINT_PREFIX
4844 " Resetting due to BUSY on entry - %#x.\n",
4846 goto IntrPrepareResetController
;
4851 if(!LunExt
->IdentifyData
.MajorRevision
&&
4854 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
4856 //KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n"));
4857 //AtapiStallExecution(10);
4859 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4860 KdPrint3((PRINT_PREFIX
" AHCI branch (ATAPI)\n"));
4862 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
4863 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
4866 if (statusByte
& IDE_STATUS_BUSY
) {
4867 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
4870 // This is just workaround
4871 // We should DISABLE interrupts before entering WAIT state
4872 UniataExpectChannelInterrupt(chan, TRUE);
4873 #endif //UNIATA_CORE
4875 KdPrint3((PRINT_PREFIX
" BUSY on ATAPI device, waiting %d us\n", LunExt
->AtapiReadyWaitDelay
));
4877 if(LunExt
->AtapiReadyWaitDelay
&& (LunExt
->AtapiReadyWaitDelay
> g_opt_MaxIsrWait
) && !InDpc
&& UseDpc
) {
4878 TimerValue
= LunExt
->AtapiReadyWaitDelay
;
4879 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC (0)\n"));
4880 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4883 #endif //UNIATA_CORE
4886 GetBaseStatus(chan
, statusByte
);
4887 KdPrint3((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4888 KdPrint3((PRINT_PREFIX
" Error reg (%#x)\n",
4889 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Error
)));
4890 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4891 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4894 TotalTimerValue
+= TimerValue
;
4896 KdPrint3((PRINT_PREFIX
" too long wait -> DPC\n"));
4898 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC\n"));
4900 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4902 KdPrint2((PRINT_PREFIX
" too long wait: DPC -> DPC\n"));
4904 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY1
;
4908 if(!LunExt
->AtapiReadyWaitDelay
) {
4909 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
4913 #endif //UNIATA_CORE
4916 AtapiStallExecution(TimerValue
);
4919 if(!LunExt
->AtapiReadyWaitDelay
) {
4920 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
4921 KdPrint2((PRINT_PREFIX
" store AtapiReadyWaitDelay: %d\n", LunExt
->AtapiReadyWaitDelay
));
4923 if (statusByte
& IDE_STATUS_BUSY
) {
4924 KdPrint3((PRINT_PREFIX
" expecting intr + BUSY (2), try DPC wait\n"));
4930 if(AtaReq
&& DmaTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
4931 switch(OldReqState
) {
4932 case REQ_STATE_EARLY_INTR
:
4933 case REQ_STATE_DPC_WAIT_BUSY0
:
4935 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4936 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DMA still active\n"));
4937 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4944 // Check for error conditions.
4945 if ((statusByte
& IDE_STATUS_ERROR
) ||
4946 (dma_status
& BM_STATUS_ERR
)) {
4948 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4949 error
= AtaReq
->ahci
.in_error
;
4952 UniataDumpAhciPortRegs(chan
);
4954 if(!UniataAhciAbortOperation(chan
)) {
4955 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
4957 // clear interrupts again
4958 UniataAhciWaitCommandReady(chan
, 10);
4960 UniataDumpAhciPortRegs(chan
);
4962 UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
4964 UniataDumpAhciPortRegs(chan
);
4967 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4969 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error %#x\n", error
));
4971 if(error & IDE_STATUS_CORRECTED_ERROR) {
4972 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
4973 statusByte &= ~IDE_STATUS_ERROR;
4978 KdPrint2((PRINT_PREFIX
" Bad Lba %#I64x\n", AtaReq
->lba
));
4980 KdPrint2((PRINT_PREFIX
" Bad Lba unknown\n"));
4985 KdPrint2((PRINT_PREFIX
" wait 100 ready after IDE error\n"));
4986 AtapiStallExecution(100);
4988 KdPrint2((PRINT_PREFIX
" wait 10 ready after ATAPI error\n"));
4989 AtapiStallExecution(10);
4993 KdPrint3((PRINT_PREFIX
" Intr on DRQ %x\n",
4994 LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
));
4996 for (k
= atapiDev
? 0 : 200; k
; k
--) {
4997 GetBaseStatus(chan
, statusByte
);
4998 if (!(statusByte
& IDE_STATUS_DRQ
)) {
4999 AtapiStallExecution(50);
5006 /* if this is a UDMA CRC error, reinject request */
5009 if(AtaReq
->retry
< MAX_RETRIES
) {
5010 #ifdef IO_STATISTICS
5011 chan
->lun
[DeviceNumber
]->ModeErrorCount
[AtaReq
->retry
]++;
5012 #endif //IO_STATISTICS
5014 (error & IDE_ERROR_ICRC)*/) {
5015 if(AtaReq
->retry
< MAX_RETRIES
) {
5017 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5018 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5019 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5020 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5024 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5027 KdPrint2((PRINT_PREFIX
"Errors in PIO mode\n"));
5031 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5032 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason
));
5034 if(DmaTransfer
&& (chan
->lun
[DeviceNumber
]->TransferMode
> ATA_UDMA2
) &&
5035 ((error
>> 4) == SCSI_SENSE_HARDWARE_ERROR
)) {
5036 if(AtaReq
->retry
< MAX_RETRIES
) {
5038 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5039 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5040 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5041 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5045 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5048 KdPrint3((PRINT_PREFIX
"Errors in PIO mode\n"));
5052 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error\n"));
5053 if (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
5054 // Fail this request.
5055 status
= SRB_STATUS_ERROR
;
5056 goto CompleteRequest
;
5058 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n"));
5061 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE_LBA48
) {
5062 KdPrint2((PRINT_PREFIX
"DMA doesn't work right with LBA48\n"));
5063 deviceExtension
->HbaCtrlFlags
|= HBAFLAGS_DMA_DISABLED_LBA48
;
5065 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
) {
5066 #ifdef IO_STATISTICS
5067 KdPrint2((PRINT_PREFIX
"Some higher mode doesn't work right :((\n"));
5068 KdPrint2((PRINT_PREFIX
"Recovery stats[%d]: %d vs %d\n",
5070 LunExt
->RecoverCount
[AtaReq
->retry
],
5071 LunExt
->BlockIoCount
5073 LunExt
->RecoverCount
[AtaReq
->retry
]++;
5074 if(LunExt
->RecoverCount
[AtaReq
->retry
] >= chan
->lun
[DeviceNumber
]->BlockIoCount
/3 ||
5075 (deviceExtension
->HwFlags
& UNIATA_NO80CHK
)
5078 if(deviceExtension
->HwFlags
& UNIATA_NO80CHK
) {
5079 #endif //IO_STATISTICS
5080 KdPrint2((PRINT_PREFIX
"Limit transfer rate to %x\n", LunExt
->TransferMode
));
5081 LunExt
->LimitedTransferMode
=
5082 LunExt
->TransferMode
;
5085 #ifdef IO_STATISTICS
5086 if(AtaReq
->bcount
) {
5087 // we need stats for Read/Write operations
5088 LunExt
->BlockIoCount
++;
5091 #endif //IO_STATISTICS
5095 // check reason for this interrupt.
5098 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI branch\n"));
5101 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5102 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
5104 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5106 wordsThisInterrupt
= DEV_BSIZE
/2;
5114 // simulate DRQ for DMA transfers
5115 statusByte
|= IDE_STATUS_DRQ
;
5117 if (statusByte
& IDE_STATUS_DRQ
) {
5120 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5122 if (LunExt
->MaximumBlockXfer
) {
5123 wordsThisInterrupt
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5126 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5128 interruptReason
= ATAPI_IR_IO_toHost
;
5130 } else if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5131 interruptReason
= ATAPI_IR_IO_toDev
;
5134 status
= SRB_STATUS_ERROR
;
5135 goto CompleteRequest
;
5138 } else if (statusByte
& IDE_STATUS_BUSY
) {
5140 //AtapiEnableInterrupts(deviceExtension, lChannel);
5141 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
5146 if (AtaReq
->WordsLeft
) {
5148 // Funky behaviour seen with PCI IDE (not all, just one).
5150 // The ISR hits with DRQ low, but comes up later.
5151 for (k
= 0; k
< 5000; k
++) {
5152 GetBaseStatus(chan
, statusByte
);
5153 if (statusByte
& IDE_STATUS_DRQ
) {
5158 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ0
;
5160 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq0)\n"));
5164 AtapiStallExecution(TimerValue
);
5165 goto ServiceInterrupt
;
5166 #endif //UNIATA_CORE
5168 AtapiStallExecution(100);
5171 // reset the controller.
5172 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
5174 IntrPrepareResetController
:
5175 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
);
5176 goto ReturnEnableIntr
;
5179 interruptReason
= (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? ATAPI_IR_IO_toHost
: ATAPI_IR_IO_toDev
;
5183 // Command complete - verify, write, or the SMART enable/disable.
5184 // Also get_media_status
5185 interruptReason
= ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
;
5190 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason
, statusByte
));
5191 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5192 KdPrint2((PRINT_PREFIX
" AHCI path, WordsTransfered %x, WordsLeft %x\n", AtaReq
->WordsTransfered
, AtaReq
->WordsLeft
));
5193 /* if(chan->AhciLastIS & ATA_AHCI_P_IX_OF) {
5194 //status = SRB_STATUS_DATA_OVERRUN;
5197 status = SRB_STATUS_SUCCESS;
5199 if(AtaReq
->WordsTransfered
>= AtaReq
->WordsLeft
) {
5200 AtaReq
->WordsLeft
= 0;
5202 AtaReq
->WordsLeft
-= AtaReq
->WordsTransfered
;
5204 //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
5205 // status = SRB_STATUS_DATA_OVERRUN;
5207 status
= SRB_STATUS_SUCCESS
;
5208 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5209 goto CompleteRequest
;
5211 if (interruptReason
== ATAPI_IR_COD_Cmd
&& (statusByte
& IDE_STATUS_DRQ
)) {
5212 // Write the packet.
5213 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Writing Atapi packet.\n"));
5214 // Send CDB to device.
5215 WriteBuffer(chan
, (PUSHORT
)srb
->Cdb
,
5216 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
5218 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5220 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
5221 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: AtapiDmaStart().\n"));
5222 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, srb
);
5225 goto ReturnEnableIntr
;
5227 } else if (interruptReason
== ATAPI_IR_IO_toDev
&& (statusByte
& IDE_STATUS_DRQ
)) {
5232 // Pick up bytes to transfer and convert to words.
5234 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
5237 (USHORT
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
5239 // Covert bytes to words.
5241 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get W wordCount %#x\n", wordCount
));
5243 if (wordCount
!= AtaReq
->WordsLeft
) {
5244 KdPrint2((PRINT_PREFIX
5245 "AtapiInterrupt: %d words requested; %d words xferred\n",
5250 // Verify this makes sense.
5251 if (wordCount
> AtaReq
->WordsLeft
) {
5252 wordCount
= AtaReq
->WordsLeft
;
5253 KdPrint2((PRINT_PREFIX
5254 "AtapiInterrupt: Write underrun\n"));
5260 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
5261 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5262 // Transfer only words requested.
5263 wordCount
= AtaReq
->WordsLeft
;
5265 // Transfer next block.
5266 wordCount
= wordsThisInterrupt
;
5271 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5272 //ASSERT(AtaReq->WordsLeft == wordCount);
5273 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5274 KdPrint2((PRINT_PREFIX
5275 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5276 if(AtaReq
->WordsLeft
> wordCount
) {
5277 AtaReq
->WordsLeft
-= wordCount
;
5278 AtaReq
->WordsTransfered
+= wordCount
;
5279 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5280 goto ReturnEnableIntr
;
5282 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5284 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5285 AtaReq
->WordsLeft
= 0;
5286 status
= SRB_STATUS_SUCCESS
;
5287 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5288 goto CompleteRequest
;
5291 // Ensure that this is a write command.
5292 if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5294 KdPrint2((PRINT_PREFIX
5295 "AtapiInterrupt: Write interrupt\n"));
5297 statusByte
= WaitOnBusy(chan
);
5299 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
5304 UniataGetPioTiming(LunExt
));
5308 (PULONG
)(AtaReq
->DataBuffer
),
5310 UniataGetPioTiming(LunExt
));
5314 KdPrint3((PRINT_PREFIX
5315 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5319 // Fail this request.
5320 status
= SRB_STATUS_ERROR
;
5321 goto CompleteRequest
;
5323 // Advance data buffer pointer and bytes left.
5324 AtaReq
->DataBuffer
+= wordCount
;
5325 AtaReq
->WordsLeft
-= wordCount
;
5326 AtaReq
->WordsTransfered
+= wordCount
;
5329 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5332 goto ReturnEnableIntr
;
5334 } else if (interruptReason
== ATAPI_IR_IO_toHost
&& (statusByte
& IDE_STATUS_DRQ
)) {
5339 // Pick up bytes to transfer and convert to words.
5341 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
) |
5342 (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8);
5344 // Convert bytes to words.
5346 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get R wordCount %#x\n", wordCount
));
5348 if (wordCount
!= AtaReq
->WordsLeft
) {
5349 KdPrint2((PRINT_PREFIX
5350 "AtapiInterrupt: %d words requested; %d words xferred\n",
5355 // Verify this makes sense.
5356 if (wordCount
> AtaReq
->WordsLeft
) {
5357 wordCount
= AtaReq
->WordsLeft
;
5363 // Check if words left is at least 256.
5364 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5365 // Transfer only words requested.
5366 wordCount
= AtaReq
->WordsLeft
;
5368 // Transfer next block.
5369 wordCount
= wordsThisInterrupt
;
5374 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5375 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5376 KdPrint2((PRINT_PREFIX
5377 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5378 if(AtaReq
->WordsLeft
> wordCount
) {
5379 AtaReq
->WordsLeft
-= wordCount
;
5380 AtaReq
->WordsTransfered
+= wordCount
;
5381 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5382 goto ReturnEnableIntr
;
5384 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5386 //ASSERT(AtaReq->WordsLeft == wordCount);
5387 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5388 AtaReq
->WordsLeft
= 0;
5389 status
= SRB_STATUS_SUCCESS
;
5390 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5391 goto CompleteRequest
;
5393 // Ensure that this is a read command.
5394 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5397 "AtapiInterrupt: Read interrupt\n"));*/
5399 statusByte
= WaitOnBusy(chan
);
5401 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
5402 KdPrint2((PRINT_PREFIX
5403 "IdeIntr: Read %#x words\n", wordCount
));
5408 UniataGetPioTiming(LunExt
));
5409 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)-1) ));
5410 //KdDump(AtaReq->DataBuffer, wordCount*2);
5411 if(srb
&& atapiDev
&& srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
5412 KdDump(AtaReq
->DataBuffer
, wordCount
*2);
5415 GetBaseStatus(chan
, statusByte
);
5416 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
5419 KdPrint2((PRINT_PREFIX
" DataOverrun\n"));
5420 AtapiSuckPort2(chan
);
5421 GetBaseStatus(chan
, statusByte
);
5424 if(statusByte
& IDE_STATUS_BUSY
) {
5425 for (i
= 0; i
< 2; i
++) {
5426 AtapiStallExecution(10);
5427 GetBaseStatus(chan
, statusByte
);
5428 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5435 KdPrint2((PRINT_PREFIX
5436 "IdeIntr: Read %#x Dwords\n", wordCount
/2));
5439 (PULONG
)(AtaReq
->DataBuffer
),
5441 UniataGetPioTiming(LunExt
));
5445 KdPrint3((PRINT_PREFIX
5446 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5450 // Fail this request.
5451 status
= SRB_STATUS_ERROR
;
5452 goto CompleteRequest
;
5455 // Advance data buffer pointer and bytes left.
5456 AtaReq
->DataBuffer
+= wordCount
;
5457 AtaReq
->WordsLeft
-= wordCount
;
5458 AtaReq
->WordsTransfered
+= wordCount
;
5460 // Check for read command complete.
5461 if (AtaReq
->WordsLeft
== 0) {
5463 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
5466 // Work around to make many atapi devices return correct sector size
5467 // of 2048. Also certain devices will have sector count == 0x00, check
5469 if ((srb
->Cdb
[0] == SCSIOP_READ_CAPACITY
) &&
5470 (LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
)) {
5472 AtaReq
->DataBuffer
-= wordCount
;
5473 if (AtaReq
->DataBuffer
[0] == 0x00) {
5475 *((ULONG
*) &(AtaReq
->DataBuffer
[0])) = 0xFFFFFF7F;
5479 *((ULONG
*) &(AtaReq
->DataBuffer
[2])) = 0x00080000;
5480 AtaReq
->DataBuffer
+= wordCount
;
5483 GetStatus(chan
, statusByte
);
5484 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5485 // Assume command is completed if BUSY is cleared
5486 // and all data read
5487 // Optionally, we may receive COMPLETE interrupt later and
5488 // treat it as unexpected
5489 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete ? status %x\n", statusByte
));
5491 status
= SRB_STATUS_SUCCESS
;
5492 goto CompleteRequest
;
5498 // Completion for IDE drives.
5499 if (AtaReq->WordsLeft) {
5500 status = SRB_STATUS_DATA_OVERRUN;
5502 status = SRB_STATUS_SUCCESS;
5505 goto CompleteRequest;
5507 status
= SRB_STATUS_SUCCESS
;
5508 goto CompleteRequest
;
5513 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5514 GetStatus(chan
, statusByte
);
5515 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5516 // Assume command is completed if BUSY is cleared
5517 // even if NOT all data read
5518 // Optionally, we may receive COMPLETE interrupt later and
5519 // treat it as unexpected
5520 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete + underrun ? status %x\n", statusByte
));
5522 status
= SRB_STATUS_SUCCESS
;
5523 goto CompleteRequest
;
5528 goto ReturnEnableIntr
;
5530 } else if (interruptReason
== (ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
) && !(statusByte
& IDE_STATUS_DRQ
)) {
5532 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: interruptReason = CompleteRequest\n"));
5533 // Command complete. We exactly know this because os IReason.
5536 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
5537 AtaReq
->WordsTransfered
+= AtaReq
->WordsLeft
;
5538 AtaReq
->WordsLeft
= 0;
5540 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was PIO\n"));
5542 wordCount
= AtaReq
->WordsLeft
;
5543 // Advance data buffer pointer and bytes left.
5544 AtaReq
->DataBuffer
+= wordCount
;
5545 AtaReq
->WordsLeft
-= wordCount
;
5546 AtaReq
->WordsTransfered
+= wordCount
;
5548 //if (AtaReq->WordsLeft) {
5549 // status = SRB_STATUS_DATA_OVERRUN;
5551 status
= SRB_STATUS_SUCCESS
;
5554 #ifdef UNIATA_DUMP_ATAPI
5556 srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5560 PCHAR ModeSelectData
;
5562 PSCSI_REQUEST_BLOCK Srb
= srb
;
5564 Cdb
= (PCDB
)(Srb
->Cdb
);
5565 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
5566 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
5567 CdbDataLen
= Srb
->DataTransferLength
;
5569 if(CdbDataLen
> 0x1000) {
5570 CdbDataLen
= 0x1000;
5574 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
5575 KdPrint2(("P:T:D=%d:%d:%d\n",
5579 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand
));
5582 if(ScsiCommand
== SCSIOP_MODE_SENSE
) {
5583 KdPrint(("ModeSense 6\n"));
5584 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5585 ModeSelectData
= CdbData
+4;
5586 KdDump(CdbData
, CdbDataLen
);
5588 if(ScsiCommand
== SCSIOP_MODE_SENSE10
) {
5589 KdPrint(("ModeSense 10\n"));
5590 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5591 ModeSelectData
= CdbData
+8;
5592 KdDump(CdbData
, CdbDataLen
);
5594 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5595 KdPrint(("Read buffer from device:\n"));
5596 KdDump(CdbData
, CdbDataLen
);
5601 #endif //UNIATA_DUMP_ATAPI
5605 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, srbstatus %x\n", status
));
5606 // Check and see if we are processing our secret (mechanism status/request sense) srb
5608 if(AtaReq
->WordsLeft
&& (status
== SRB_STATUS_SUCCESS
)) {
5609 KdPrint2((PRINT_PREFIX
"WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq
->WordsLeft
));
5610 status
= SRB_STATUS_DATA_OVERRUN
;
5613 if (AtaReq
->OriginalSrb
) {
5617 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: OriginalSrb != NULL\n"));
5618 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
5620 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
5621 if (status
== SRB_STATUS_SUCCESS
) {
5623 AtapiHwInitializeChanger (HwDeviceExtension
,
5625 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
5627 // Get ready to issue the original srb
5628 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5629 AtaReq
->OriginalSrb
= NULL
;
5632 // failed! Get the sense key and maybe try again
5633 srb
= AtaReq
->Srb
= BuildRequestSenseSrb (
5635 AtaReq
->OriginalSrb
);
5638 // do not enable interrupts in DPC, do not waste time, do it now!
5639 if(UseDpc && chan->DisableIntr) {
5640 AtapiEnableInterrupts(HwDeviceExtension, c);
5642 RestoreUseDpc = TRUE;
5645 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
5647 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
5649 if (srbStatus
== SRB_STATUS_PENDING
) {
5650 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
5651 goto ReturnEnableIntr
;
5655 // restore state on error
5657 AtapiDisableInterrupts(HwDeviceExtension, c);
5661 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
5663 PSENSE_DATA senseData
= (PSENSE_DATA
) srb
->DataBuffer
;
5665 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI command status %#x\n", status
));
5666 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5667 // Check to see if we at least get mininum number of bytes
5668 if ((srb
->DataTransferLength
- AtaReq
->WordsLeft
) >
5669 (FIELD_OFFSET (SENSE_DATA
, AdditionalSenseLength
) + sizeof(senseData
->AdditionalSenseLength
))) {
5670 status
= SRB_STATUS_SUCCESS
;
5674 if (status
== SRB_STATUS_SUCCESS
) {
5676 if ((senseData
->SenseKey
!= SCSI_SENSE_ILLEGAL_REQUEST
) &&
5677 chan
->MechStatusRetryCount
) {
5679 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: MechStatusRetryCount %#x\n", chan
->MechStatusRetryCount
));
5680 // The sense key doesn't say the last request is illegal, so try again
5681 chan
->MechStatusRetryCount
--;
5682 srb
= AtaReq
->Srb
= BuildMechanismStatusSrb (
5684 AtaReq
->OriginalSrb
);
5687 // last request was illegal. No point trying again.
5688 // Do-nothing call ?
5689 AtapiHwInitializeChanger (HwDeviceExtension
,
5691 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
5693 // Get ready to issue the original srb
5694 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5695 AtaReq
->OriginalSrb
= NULL
;
5697 #endif //UNIATA_CORE
5699 // do not enable interrupts in DPC, do not waste time, do it now!
5700 if(UseDpc && chan->DisableIntr) {
5701 AtapiEnableInterrupts(HwDeviceExtension, c);
5703 RestoreUseDpc = TRUE;
5706 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
5708 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan
->ExpectingInterrupt
));
5710 if (srbStatus
== SRB_STATUS_PENDING
) {
5711 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
5712 goto ReturnEnableIntr
;
5716 // restore state on error
5718 AtapiDisableInterrupts(HwDeviceExtension, c);
5724 // If we get here, it means AtapiSendCommand() has failed
5725 // Can't recover. Pretend the original srb has failed and complete it.
5727 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. complete OriginalSrb\n"));
5729 if (AtaReq
->OriginalSrb
) {
5730 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
5731 // Do-nothing call ?
5732 AtapiHwInitializeChanger (HwDeviceExtension
,
5734 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
5735 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5736 AtaReq
->OriginalSrb
= NULL
;
5739 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan
->ExpectingInterrupt
));
5741 // fake an error and read no data
5742 status
= SRB_STATUS_ERROR
;
5743 srb
->ScsiStatus
= 0;
5744 AtaReq
->DataBuffer
= (PUSHORT
)(srb
->DataBuffer
);
5745 AtaReq
->WordsLeft
= srb
->DataTransferLength
;
5748 } else if (status
== SRB_STATUS_ERROR
) {
5750 // Map error to specific SRB status and handle request sense.
5751 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. Begin mapping...\n"));
5752 status
= MapError(deviceExtension
,
5757 } else if(!DmaTransfer
) {
5759 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion\n"));
5760 // Command complete.
5762 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion, wait BUSY\n"));
5763 // Wait for busy to drop.
5764 for (i
= 0; i
< 5*30; i
++) {
5765 GetBaseStatus(chan
, statusByte
);
5766 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5771 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY
;
5773 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (busy)\n"));
5777 AtapiStallExecution(TimerValue
);
5778 goto ServiceInterrupt
;
5779 #endif //UNIATA_CORE
5781 AtapiStallExecution(100);
5786 // reset the controller.
5787 KdPrint2((PRINT_PREFIX
5788 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
5790 goto IntrPrepareResetController
;
5792 // Check to see if DRQ is still up.
5793 if(statusByte
& IDE_STATUS_DRQ
) {
5794 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DRQ...\n"));
5796 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5797 KdPrint2((PRINT_PREFIX
"srb %x data in\n", srb
));
5799 KdPrint2((PRINT_PREFIX
"srb %x data out\n", srb
));
5802 KdPrint2((PRINT_PREFIX
"srb NULL\n"));
5805 KdPrint2((PRINT_PREFIX
"AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq
, AtaReq
->WordsLeft
));
5807 KdPrint2((PRINT_PREFIX
"AtaReq NULL\n"));
5809 if(AtaReq
&& AtaReq
->WordsLeft
/*&&
5810 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
5811 KdPrint2((PRINT_PREFIX
"DRQ+AtaReq->WordsLeft -> next portion\n"));
5815 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
5816 //if ((statusByte & IDE_STATUS_DRQ)) {}
5817 if((statusByte
& IDE_STATUS_DRQ
) &&
5818 (LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_TAPE_DEVICE
| DFLAGS_LBA_ENABLED
)) ) {
5821 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO_wait_DRQ\n"));
5822 for (i
= 0; i
< 200; i
++) {
5823 GetBaseStatus(chan
, statusByte
);
5824 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5829 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq)\n"));
5830 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ
;
5835 AtapiStallExecution(TimerValue
);
5836 goto ServiceInterrupt
;
5837 #endif //UNIATA_CORE
5839 AtapiStallExecution(100);
5843 // reset the controller.
5844 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
5846 goto IntrPrepareResetController
;
5850 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
5851 AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)(-1)), srb
->DataTransferLength
));
5852 //KdDump(srb->DataBuffer, srb->DataTransferLength);
5854 if(!AtapiDmaPioSync(HwDeviceExtension
, srb
, (PUCHAR
)(srb
->DataBuffer
), srb
->DataTransferLength
)) {
5855 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
5859 // Clear interrupt expecting flag.
5860 UniataExpectChannelInterrupt(chan
, FALSE
);
5861 // clear this flag now, it can be set again in sub-calls
5862 InterlockedExchange(&(chan
->CheckIntr
),
5865 // Sanity check that there is a current request.
5867 // Set status in SRB.
5868 srb
->SrbStatus
= (UCHAR
)status
;
5870 // Check for underflow.
5871 if(AtaReq
->WordsLeft
) {
5873 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq
->WordsLeft
));
5874 // Subtract out residual words and update if filemark hit,
5875 // setmark hit , end of data, end of media...
5876 if (!(LunExt
->DeviceFlags
& DFLAGS_TAPE_DEVICE
)) {
5877 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5878 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5880 srb
->DataTransferLength
= 0;
5883 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5886 if(status
== SRB_STATUS_SUCCESS
) {
5887 //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) {
5888 // // This should be set in UniataAhciEndTransaction() for AHCI
5889 // AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
5892 AtaReq
->WordsTransfered
*2 < AtaReq
->TransferLength
) {
5893 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
5894 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5895 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5896 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_NEXT
;
5899 KdPrint2((PRINT_PREFIX
" Transfered %x, full size %x\n",
5900 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5904 if (srb
->Function
!= SRB_FUNCTION_IO_CONTROL
) {
5907 // Indicate command complete.
5909 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete\n"));
5912 if (status
== SRB_STATUS_SUCCESS
&&
5913 srb
->SenseInfoBuffer
&&
5914 srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
5916 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)srb
->SenseInfoBuffer
;
5918 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: set AutoSense\n"));
5919 senseBuffer
->ErrorCode
= 0;
5920 senseBuffer
->Valid
= 1;
5921 senseBuffer
->AdditionalSenseLength
= 0xb;
5922 senseBuffer
->SenseKey
= 0;
5923 senseBuffer
->AdditionalSenseCode
= 0;
5924 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
5926 srb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
5928 AtapiDmaDBSync(chan
, srb
);
5929 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove srb %#x, status %x\n", srb
, status
));
5930 UniataRemoveRequest(chan
, srb
);
5931 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete, srb %#x\n", srb
));
5932 ScsiPortNotification(RequestComplete
,
5938 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: IOCTL completion\n"));
5940 if (status
!= SRB_STATUS_SUCCESS
) {
5941 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5942 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: error %#x\n", error
));
5945 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
5947 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5948 // Build the SMART status block depending upon the completion status.
5949 cmdOutParameters
->cBufferSize
= wordCount
;
5950 cmdOutParameters
->DriverStatus
.bDriverError
= (error
) ? SMART_IDE_ERROR
: 0;
5951 cmdOutParameters
->DriverStatus
.bIDEError
= error
;
5953 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
5955 if (chan
->SmartCommand
== RETURN_SMART_STATUS
) {
5956 PIDEREGS_EX regs
= (PIDEREGS_EX
)&(cmdOutParameters
->bBuffer
);
5959 UniataSnapAtaRegs(chan
, 0, regs
);
5961 regs
->bCommandReg
= SMART_CMD
;
5962 regs
->bFeaturesReg
= RETURN_SMART_STATUS
;
5964 cmdOutParameters
->cBufferSize
= 8;
5966 chan
->SmartCommand
= 0; // cleanup after execution
5968 // Indicate command complete.
5969 goto IntrCompleteReq
;
5974 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: No SRB!\n"));
5979 for (i
= 0; i
< 5; i
++) {
5980 GetBaseStatus(chan
, statusByte
);
5981 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5982 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RDP + cleared BUSY\n"));
5986 if (statusByte
& IDE_STATUS_DSC
) {
5987 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Clear RDP\n"));
5991 AtapiStallExecution(50);
5994 // RDP can be cleared since previous check
5996 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestTimerCall 2000\n"));
6002 AtapiStallExecution(TimerValue
);
6003 goto ServiceInterrupt
;
6004 #endif //UNIATA_CORE
6007 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
6010 srb
= UniataGetCurRequest(chan
);
6015 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: NextRequest, srb=%#x\n",srb
));
6017 ScsiPortNotification(NextRequest
,
6021 ScsiPortNotification(NextLuRequest
,
6026 // in simplex mode next command must NOT be sent here
6027 if(!deviceExtension
->simplexOnly
) {
6028 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6031 // Try to get SRB fron any non-empty queue (later)
6032 if(deviceExtension
->simplexOnly
) {
6035 #endif //UNIATA_CORE
6037 goto ReturnEnableIntr
;
6041 // Unexpected int. Catch it
6042 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
6046 if(OldReqState
== REQ_STATE_DPC_WAIT_BUSY0
&&
6047 AtaReq
->WordsLeft
== 0) {
6048 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: pending WAIT_BUSY0. Complete.\n"));
6049 status
= SRB_STATUS_SUCCESS
;
6050 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6051 goto CompleteRequest
;
6057 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ReturnEnableIntr\n",srb
));
6058 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6059 deviceExtension
->ExpectingInterrupt
= TRUE
;
6061 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
6062 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
6063 #ifdef UNIATA_USE_XXableInterrupts
6064 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
6065 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
6066 // must be called on DISPATCH_LEVEL
6067 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
6068 AtapiEnableInterrupts__
);
6070 AtapiEnableInterrupts(HwDeviceExtension
, c
);
6071 InterlockedExchange(&(chan
->CheckIntr
),
6073 // Will raise IRQL to DIRQL
6075 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
6076 AtapiEnableInterrupts__
,
6078 #endif // UNIATA_CORE
6079 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
6080 #endif // UNIATA_USE_XXableInterrupts
6084 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
6085 // in simplex mode next command must be sent here if
6087 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc
, NoStartIo
));
6090 if(!UseDpc
&& /*deviceExtension->simplexOnly &&*/ !NoStartIo
) {
6091 chan
= UniataGetNextChannel(chan
);
6093 srb
= UniataGetCurRequest(chan
);
6097 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: run srb %x\n", srb
));
6099 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6102 #endif //UNIATA_CORE
6105 } // end AtapiInterrupt__()
6111 Routine Description:
6113 This routine handles SMART enable, disable, read attributes and threshold commands.
6117 HwDeviceExtension - HBA miniport driver's adapter data storage
6118 Srb - IO request packet
6127 IdeSendSmartCommand(
6128 IN PVOID HwDeviceExtension
,
6129 IN PSCSI_REQUEST_BLOCK Srb
,
6130 IN ULONG targetId
// assume it is always valid
6133 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6134 ULONG c
; // = GET_CHANNEL(Srb); may be invalid
6135 PHW_CHANNEL chan
; // = &(deviceExtension->chan[c]);
6136 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6137 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6138 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6139 PIDEREGS regs
= &cmdInParameters
.irDriveRegs
;
6144 if (regs
->bCommandReg
!= SMART_CMD
) {
6145 KdPrint2((PRINT_PREFIX
6146 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
6147 return SRB_STATUS_INVALID_REQUEST
;
6150 c
= targetId
/ deviceExtension
->NumberLuns
;
6151 DeviceNumber
= targetId
% deviceExtension
->NumberLuns
;
6152 KdPrint2((PRINT_PREFIX
" c %d, dev %d\n", c
, DeviceNumber
));
6154 chan
= &(deviceExtension
->chan
[c
]);
6156 chan
->SmartCommand
= regs
->bFeaturesReg
;
6158 // Determine which of the commands to carry out.
6159 switch(regs
->bFeaturesReg
) {
6160 case READ_ATTRIBUTES
:
6161 case READ_THRESHOLDS
:
6162 case READ_LOG_SECTOR
:
6163 case WRITE_LOG_SECTOR
:
6165 if(Srb
->DataTransferLength
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1) {
6166 KdPrint2((PRINT_PREFIX
6167 "IdeSendSmartCommand: wrong buffer size\n"));
6168 return SRB_STATUS_DATA_OVERRUN
;
6171 statusByte
= WaitOnBusy(chan
);
6173 if (statusByte
& IDE_STATUS_BUSY
) {
6174 KdPrint2((PRINT_PREFIX
6175 "IdeSendSmartCommand: Returning BUSY status\n"));
6176 return SRB_STATUS_BUSY
;
6179 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6180 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1);
6182 // Set data buffer pointer and words left.
6183 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6184 AtaReq
->WordsLeft
= READ_ATTRIBUTE_BUFFER_SIZE
/ 2;
6186 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6188 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6190 regs
->bSectorNumberReg
,
6191 regs
->bSectorCountReg
,
6195 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6196 // Wait for interrupt.
6197 return SRB_STATUS_PENDING
;
6199 return SRB_STATUS_ERROR
;
6203 case RETURN_SMART_STATUS
:
6204 case ENABLE_DISABLE_AUTOSAVE
:
6205 case EXECUTE_OFFLINE_DIAGS
:
6206 case SAVE_ATTRIBUTE_VALUES
:
6209 statusByte
= WaitOnBusy(chan
);
6211 if (statusByte
& IDE_STATUS_BUSY
) {
6212 KdPrint2((PRINT_PREFIX
6213 "IdeSendSmartCommand: Returning BUSY status\n"));
6214 return SRB_STATUS_BUSY
;
6217 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6218 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) - 1);
6220 // Set data buffer pointer and indicate no data transfer.
6221 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6222 AtaReq
->WordsLeft
= 0;
6224 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6226 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6228 regs
->bSectorNumberReg
,
6229 regs
->bSectorCountReg
,
6233 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6234 // Wait for interrupt.
6235 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6236 return SRB_STATUS_PENDING
;
6238 return SRB_STATUS_ERROR
;
6239 } // end switch(regs->bFeaturesReg)
6241 return SRB_STATUS_INVALID_REQUEST
;
6243 } // end IdeSendSmartCommand()
6245 #endif //UNIATA_CORE
6249 UniAtaCalculateLBARegs(
6250 PHW_LU_EXTENSION LunExt
,
6251 ULONGLONG startingSector
,
6255 UCHAR drvSelect
,sectorNumber
;
6259 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6260 if(LunExt
->LimitedTransferMode
>= ATA_DMA
) {
6261 if(LunExt
->DeviceExtension
) {
6262 (*max_bcount
) = LunExt
->DeviceExtension
->MaximumDmaTransferLength
/ DEV_BSIZE
;
6265 return startingSector
;
6267 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6268 LunExt
->IdentifyData
.NumberOfHeads
;
6270 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
6274 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
;
6276 cylinder
= (USHORT
)(startingSector
/ tmp
);
6277 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
6278 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
6279 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
- sectorNumber
+ 1;
6280 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
6281 cylinder
, drvSelect
, sectorNumber
, (*max_bcount
)));
6285 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
6286 } // end UniAtaCalculateLBARegs()
6290 UniAtaCalculateLBARegsBack(
6291 PHW_LU_EXTENSION LunExt
,
6295 ULONG drvSelect
,sectorNumber
;
6299 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6302 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6303 LunExt
->IdentifyData
.NumberOfHeads
;
6305 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
6306 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
6307 sectorNumber
= (UCHAR
)(lba
& 0xff);
6309 lba
= sectorNumber
-1 +
6310 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
6314 } // end UniAtaCalculateLBARegsBack()
6319 Routine Description:
6321 This routine handles IDE read and writes.
6325 HwDeviceExtension - HBA miniport driver's adapter data storage
6326 Srb - IO request packet
6336 IN PVOID HwDeviceExtension
,
6337 IN PSCSI_REQUEST_BLOCK Srb
,
6341 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6342 UCHAR lChannel
= GET_CHANNEL(Srb
);
6343 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6344 PHW_LU_EXTENSION LunExt
;
6345 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6346 //ULONG ldev = GET_LDEV(Srb);
6347 UCHAR DeviceNumber
= GET_CDEV(Srb
);;
6348 ULONGLONG startingSector
=0;
6350 ULONG wordCount
= 0;
6351 UCHAR statusByte
,statusByte2
;
6354 BOOLEAN use_dma
= FALSE
;
6357 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6358 LunExt
= chan
->lun
[DeviceNumber
];
6360 if((CmdAction
& CMD_ACTION_PREPARE
) &&
6361 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
6363 if(LunExt
->opt_ReadOnly
&&
6364 (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) {
6365 if(LunExt
->opt_ReadOnly
== 1) {
6366 KdPrint2((PRINT_PREFIX
"Abort WRITE (Soft R/O)\n"));
6367 return SRB_STATUS_ERROR
;
6369 KdPrint2((PRINT_PREFIX
"Ignore WRITE (Soft R/O)\n"));
6370 return SRB_STATUS_SUCCESS
;
6374 // Set data buffer pointer and words left.
6375 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6377 if(AtaReq
->WordsTransfered
) {
6378 AtaReq
->DataBuffer
= ((PUSHORT
)(Srb
->DataBuffer
)) + AtaReq
->WordsTransfered
;
6379 startingSector
= (UniAtaCalculateLBARegsBack(LunExt
, AtaReq
->lba
)) /* latest lba */ + AtaReq
->bcount
/* previous bcount */;
6380 AtaReq
->bcount
= (AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2 + DEV_BSIZE
-1) / DEV_BSIZE
;
6381 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Chained REQ): Starting sector %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
6383 AtaReq
->TransferLength
/2,
6384 AtaReq
->WordsTransfered
,
6387 AtaReq
->DataBuffer
= (PUSHORT
)(Srb
->DataBuffer
);
6388 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
6389 // Set up 1st block.
6390 switch(Srb
->Cdb
[0]) {
6393 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6394 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6397 case SCSIOP_WRITE12
:
6398 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
6399 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6402 case SCSIOP_WRITE16
:
6403 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6404 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6407 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Orig REQ): Starting sector %I64x, OrigWordsRequested %#x, DevSize %#x\n",
6409 AtaReq
->TransferLength
/2,
6412 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6415 AtaReq
->bcount
= min(AtaReq
->bcount
, max_bcount
);
6417 AtaReq
->WordsLeft
= min(AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2,
6418 AtaReq
->bcount
* DEV_BSIZE
) / 2;
6420 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n",
6427 // assume best case here
6428 // we cannot reinit Dma until previous request is completed
6429 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6430 UniataAhciSetupCmdPtr(AtaReq
);
6431 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6432 (PUCHAR
)(AtaReq
->DataBuffer
),
6433 AtaReq
->bcount
* DEV_BSIZE
)) {
6434 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !DMA\n"));
6435 return SRB_STATUS_ERROR
;
6438 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
6440 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6441 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6442 (PUCHAR
)(AtaReq
->DataBuffer
),
6443 AtaReq
->bcount
* DEV_BSIZE
)) {
6448 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6449 KdPrint2((PRINT_PREFIX
"IdeReadWrite: setup AHCI FIS\n"));
6450 RtlZeroMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
), sizeof(AtaReq
->ahci_cmd0
.cfis
));
6452 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
6453 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
6454 (AtaReq
->Flags
& REQ_FLAG_READ
) ? IDE_COMMAND_READ_DMA
: IDE_COMMAND_WRITE_DMA
,
6456 (USHORT
)(AtaReq
->bcount
),
6458 /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/
6462 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !FIS\n"));
6463 return SRB_STATUS_ERROR
;
6466 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0, (AtaReq
->Flags
& REQ_FLAG_READ
) ? 0 : ATA_AHCI_CMD_WRITE
, fis_size
, DeviceNumber
);
6467 KdPrint2((PRINT_PREFIX
"IdeReadWrite ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
6470 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
6472 } else { // exec_only
6473 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
6476 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6480 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
6482 return SRB_STATUS_PENDING
;
6485 // if this is queued request, reinit DMA and check
6486 // if DMA mode is still available
6487 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
6488 if (/*EnableDma &&*/
6489 (LunExt
->TransferMode
>= ATA_DMA
)) {
6492 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6496 // Check if write request.
6497 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6499 // Prepare read command.
6501 cmd
= IDE_COMMAND_READ_DMA
;
6503 if(LunExt
->MaximumBlockXfer
) {
6504 cmd
= IDE_COMMAND_READ_MULTIPLE
;
6506 cmd
= IDE_COMMAND_READ
;
6510 // Prepare write command.
6512 wordCount
= AtaReq
->bcount
*DEV_BSIZE
/2;
6513 cmd
= IDE_COMMAND_WRITE_DMA
;
6515 if (LunExt
->MaximumBlockXfer
) {
6516 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
6518 if (AtaReq
->WordsLeft
< wordCount
) {
6519 // Transfer only words requested.
6520 wordCount
= AtaReq
->WordsLeft
;
6522 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
6525 wordCount
= DEV_BSIZE
/2;
6526 cmd
= IDE_COMMAND_WRITE
;
6531 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
6532 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
6534 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
6536 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6539 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6540 // AHCI doesn't distinguish DMA and PIO
6541 //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
6542 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
6543 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6544 InterlockedExchange(&(chan
->CheckIntr
),
6546 return SRB_STATUS_PENDING
;
6549 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
6551 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
6553 (USHORT
)(AtaReq
->bcount
),
6554 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6556 if(statusByte2
!= IDE_STATUS_WRONG
) {
6557 GetStatus(chan
, statusByte2
);
6559 if(statusByte2
& IDE_STATUS_ERROR
) {
6560 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6561 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
6562 return SRB_STATUS_ERROR
;
6565 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
6567 return SRB_STATUS_PENDING
;
6570 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
6572 (USHORT
)(AtaReq
->bcount
),
6573 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6576 if (!(statusByte
& IDE_STATUS_DRQ
) ||
6577 statusByte
== IDE_STATUS_WRONG
) {
6579 if(statusByte
== IDE_STATUS_WRONG
) {
6580 KdPrint2((PRINT_PREFIX
6581 "IdeReadWrite: error sending command (%#x)\n",
6584 KdPrint2((PRINT_PREFIX
6585 "IdeReadWrite: DRQ never asserted (%#x)\n",
6589 AtaReq
->WordsLeft
= 0;
6591 // Clear interrupt expecting flag.
6592 UniataExpectChannelInterrupt(chan
, FALSE
);
6593 InterlockedExchange(&(chan
->CheckIntr
),
6596 // Clear current SRB.
6597 UniataRemoveRequest(chan
, Srb
);
6599 return (statusByte
== IDE_STATUS_WRONG
) ? SRB_STATUS_ERROR
: SRB_STATUS_TIMEOUT
;
6602 UniataExpectChannelInterrupt(chan
, TRUE
);
6603 InterlockedExchange(&(chan
->CheckIntr
),
6606 // Write next DEV_BSIZE/2*N words.
6607 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
)) {
6608 KdPrint2((PRINT_PREFIX
6609 "IdeReadWrite: Write %#x words\n", wordCount
));
6614 UniataGetPioTiming(LunExt
));
6618 KdPrint2((PRINT_PREFIX
6619 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
6622 (PULONG
)(AtaReq
->DataBuffer
),
6624 UniataGetPioTiming(LunExt
));
6627 // Adjust buffer address and words left count.
6628 AtaReq
->WordsLeft
-= wordCount
;
6629 AtaReq
->DataBuffer
+= wordCount
;
6631 // Wait for interrupt.
6632 return SRB_STATUS_PENDING
;
6634 } // end IdeReadWrite()
6640 Routine Description:
6641 This routine handles IDE Verify.
6644 HwDeviceExtension - HBA miniport driver's adapter data storage
6645 Srb - IO request packet
6654 IN PVOID HwDeviceExtension
,
6655 IN PSCSI_REQUEST_BLOCK Srb
6658 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6659 UCHAR lChannel
= GET_CHANNEL(Srb
);
6660 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6661 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6662 PHW_LU_EXTENSION LunExt
;
6663 //ULONG ldev = GET_LDEV(Srb);
6664 ULONG DeviceNumber
= GET_CDEV(Srb
);
6666 ULONGLONG startingSector
=0;
6669 ULONGLONG endSector
;
6670 ULONG sectorCount
=0;
6673 LunExt
= chan
->lun
[DeviceNumber
];
6674 // Drive has these number sectors.
6675 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
6676 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
6677 LunExt
->IdentifyData
.NumberOfHeads
*
6678 LunExt
->IdentifyData
.NumberOfCylinders
;
6681 KdPrint2((PRINT_PREFIX
6682 "IdeVerify: Total sectors %#x\n",
6685 // Get starting sector number from CDB.
6686 switch(Srb
->Cdb
[0]) {
6688 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6689 MOV_SWP_DW2DD(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6691 case SCSIOP_VERIFY12
:
6692 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
6693 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6695 case SCSIOP_VERIFY16
:
6696 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6697 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6701 KdPrint2((PRINT_PREFIX
6702 "IdeVerify: Starting sector %#I64x. Number of blocks %#x\n",
6706 endSector
= startingSector
+ sectorCount
;
6708 KdPrint2((PRINT_PREFIX
6709 "IdeVerify: Ending sector %#I64x\n",
6712 if (endSector
> sectors
) {
6714 // Too big, round down.
6715 KdPrint2((PRINT_PREFIX
6716 "IdeVerify: Truncating request to %#x blocks\n",
6717 sectors
- startingSector
- 1));
6719 sectorCount
= (ULONG
)(sectors
- startingSector
- 1);
6723 // Set up sector count register. Round up to next block.
6724 if (sectorCount
> 0xFF) {
6725 sectorCount
= (USHORT
)0xFF;
6729 // Set data buffer pointer and words left.
6730 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
6731 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
6733 // Indicate expecting an interrupt.
6734 InterlockedExchange(&(chan
->CheckIntr
),
6737 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6739 statusByte
= AtaCommand48(deviceExtension
, LunExt
->Lun
, GET_CHANNEL(Srb
),
6740 IDE_COMMAND_VERIFY
, lba
,
6741 (USHORT
)sectorCount
,
6744 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6745 // Wait for interrupt.
6746 return SRB_STATUS_PENDING
;
6748 return SRB_STATUS_ERROR
;
6750 } // end IdeVerify()
6752 #endif //UNIATA_CORE
6756 Routine Description:
6757 Send ATAPI packet command to device.
6760 HwDeviceExtension - HBA miniport driver's adapter data storage
6761 Srb - IO request packet
6769 IN PVOID HwDeviceExtension
,
6770 IN PSCSI_REQUEST_BLOCK Srb
,
6774 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6775 UCHAR lChannel
= GET_CHANNEL(Srb
);
6776 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6777 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6778 PHW_LU_EXTENSION LunExt
;
6779 //ULONG ldev = GET_LDEV(Srb);
6780 ULONG DeviceNumber
= GET_CDEV(Srb
);
6782 UCHAR statusByte
,statusByte0
,byteCountLow
,byteCountHigh
;
6783 BOOLEAN use_dma
= FALSE
;
6784 BOOLEAN dma_reinited
= FALSE
;
6785 BOOLEAN retried
= FALSE
;
6789 LunExt
= chan
->lun
[DeviceNumber
];
6791 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: req state %#x, Action %x\n", AtaReq
->ReqState
, CmdAction
));
6792 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
6793 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
6796 #ifdef UNIATA_DUMP_ATAPI
6797 if(CmdAction
& CMD_ACTION_PREPARE
) {
6801 PCHAR ModeSelectData
;
6804 Cdb
= (PCDB
)(Srb
->Cdb
);
6805 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
6806 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
6807 CdbDataLen
= Srb
->DataTransferLength
;
6809 if(CdbDataLen
> 0x1000) {
6810 CdbDataLen
= 0x1000;
6814 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
6815 KdPrint2(("P:T:D=%d:%d:%d\n",
6819 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
6822 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
6823 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
6824 Cdb
->WRITE_CD
.LBA
[0],
6825 Cdb
->WRITE_CD
.LBA
[1],
6826 Cdb
->WRITE_CD
.LBA
[2],
6827 Cdb
->WRITE_CD
.LBA
[3]
6830 if(ScsiCommand
== SCSIOP_WRITE12
) {
6831 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
6832 Cdb
->CDB12READWRITE
.LBA
[0],
6833 Cdb
->CDB12READWRITE
.LBA
[1],
6834 Cdb
->CDB12READWRITE
.LBA
[2],
6835 Cdb
->CDB12READWRITE
.LBA
[3]
6838 if(ScsiCommand
== SCSIOP_WRITE16
) {
6839 KdPrint(("Write16, LBA %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
6840 Cdb
->CDB16READWRITE
.LBA
[0],
6841 Cdb
->CDB16READWRITE
.LBA
[1],
6842 Cdb
->CDB16READWRITE
.LBA
[2],
6843 Cdb
->CDB16READWRITE
.LBA
[3],
6844 Cdb
->CDB16READWRITE
.LBA
[4],
6845 Cdb
->CDB16READWRITE
.LBA
[5],
6846 Cdb
->CDB16READWRITE
.LBA
[6],
6847 Cdb
->CDB16READWRITE
.LBA
[7]
6850 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
6851 KdPrint(("ModeSelect 6\n"));
6852 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6853 ModeSelectData
= CdbData
+4;
6854 KdDump(CdbData
, CdbDataLen
);
6856 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
6857 KdPrint(("ModeSelect 10\n"));
6858 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6859 ModeSelectData
= CdbData
+8;
6860 KdDump(CdbData
, CdbDataLen
);
6862 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
6863 KdPrint(("Send buffer to device:\n"));
6864 KdDump(CdbData
, CdbDataLen
);
6869 #endif //UNIATA_DUMP_ATAPI
6872 if(CmdAction
== CMD_ACTION_PREPARE
) {
6873 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb
->Cdb
)));
6875 switch (Srb
->Cdb
[0]) {
6876 case SCSIOP_RECEIVE
:
6881 case SCSIOP_WRITE12
:
6883 case SCSIOP_WRITE16
:
6887 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
6888 return SRB_STATUS_BUSY
;
6891 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6892 !AtaReq
->OriginalSrb
) {
6893 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
6894 return SRB_STATUS_BUSY
;
6899 // We need to know how many platters our atapi cd-rom device might have.
6900 // Before anyone tries to send a srb to our target for the first time,
6901 // we must "secretly" send down a separate mechanism status srb in order to
6902 // initialize our device extension changer data. That's how we know how
6903 // many platters our target has.
6905 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6906 !AtaReq
->OriginalSrb
) {
6910 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
6911 // Set this flag now. If the device hangs on the mech. status
6912 // command, we will not have the chance to set it.
6913 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
6915 chan
->MechStatusRetryCount
= 3;
6916 AtaReq
->OriginalSrb
= Srb
;
6917 AtaReq
->Srb
= BuildMechanismStatusSrb (
6921 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
6922 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
6923 if (srbStatus
== SRB_STATUS_PENDING
) {
6924 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
6928 // failed! Get the sense key and maybe try again
6929 AtaReq
->Srb
= BuildRequestSenseSrb ( HwDeviceExtension
,
6930 AtaReq
->OriginalSrb
);
6932 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
6934 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
6936 if (srbStatus
== SRB_STATUS_PENDING
) {
6937 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n"));
6941 // failed again ? should not get here
6943 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6944 AtaReq
->OriginalSrb
= NULL
;
6946 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiHwInitializeChanger()\n"));
6947 // Do-nothing call ?
6948 AtapiHwInitializeChanger (HwDeviceExtension
, Srb
,
6949 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
6953 #endif //UNIATA_CORE
6955 if((CmdAction
& CMD_ACTION_PREPARE
) &&
6956 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
6958 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb
->Cdb
[0], &(Srb
->Cdb
)));
6960 if(!LunExt
->IdentifyData
.AtapiCmdSize
&&
6961 (Srb
->CdbLength
> 12)) {
6962 KdPrint2((PRINT_PREFIX
"Cdb16 not supported\n"));
6963 return SRB_STATUS_INVALID_REQUEST
;
6966 // Set data buffer pointer and words left.
6967 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
6968 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
6969 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
6970 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6971 // reset this to force PRD init. May be already setup by recursive SRB
6972 AtaReq
->dma_entries
= 0;
6974 // check if reorderable
6975 switch(Srb
->Cdb
[0]) {
6977 case SCSIOP_WRITE16
:
6979 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6980 MOV_QD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6984 case SCSIOP_WRITE12
:
6986 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6992 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6994 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6996 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6997 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6998 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
6999 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
7000 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ?
7001 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
7004 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7005 if(!AtaReq
->TransferLength
) {
7006 KdPrint((" assume 0-transfer\n"));
7008 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
7009 KdPrint((" assume OUT\n"));
7010 AtaReq
->Flags
|= REQ_FLAG_WRITE
;
7012 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7013 KdPrint((" assume IN\n"));
7014 AtaReq
->Flags
|= REQ_FLAG_READ
;
7019 // check if DMA read/write
7020 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7021 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: force use dma (ahci)\n"));
7025 /* if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) {
7026 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n"));
7030 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
7031 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
7033 if(AtaReq
->TransferLength
) {
7035 switch(Srb
->Cdb
[0]) {
7037 case SCSIOP_WRITE12
:
7038 case SCSIOP_WRITE16
:
7040 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
7043 case SCSIOP_RECEIVE
:
7048 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
7050 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7051 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7054 if(AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7055 (PUCHAR
)(AtaReq
->DataBuffer
),
7056 Srb
->DataTransferLength
7057 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
7059 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7064 case SCSIOP_READ_CD
:
7065 if(deviceExtension
->opt_AtapiDmaRawRead
)
7066 goto call_dma_setup
;
7070 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
7071 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7076 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
7077 KdPrint2((PRINT_PREFIX
"dma RO\n"));
7089 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7090 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7093 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7094 (PUCHAR
)(AtaReq
->DataBuffer
),
7095 Srb
->DataTransferLength
)) {
7096 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
7099 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7103 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer, no DMA setup\n"));
7107 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7109 UniataAhciSetupCmdPtr(AtaReq
);
7111 if(!Srb
->DataTransferLength
) {
7112 KdPrint2((PRINT_PREFIX
"zero-transfer\n"));
7115 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7116 (PUCHAR
)(AtaReq
->DataBuffer
),
7117 Srb
->DataTransferLength
)) {
7118 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no AHCI dma!\n"));
7119 return SRB_STATUS_ERROR
;
7122 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7124 FeatureReg
|= ATA_F_DMA
;
7125 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7126 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7127 FeatureReg
|= ATA_F_DMAREAD
;
7131 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: setup AHCI FIS\n"));
7132 // this is done in UniataAhciSetupFIS_H2D()
7133 //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
7134 RtlCopyMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), Srb
->Cdb
, Srb
->CdbLength
);
7136 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
7137 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
7138 IDE_COMMAND_ATAPI_PACKET
/* command */,
7140 (Srb
->DataTransferLength
>= 0x10000) ? (USHORT
)(0xffff) : (USHORT
)(Srb
->DataTransferLength
),
7141 FeatureReg
/* feature */
7145 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AHCI !FIS\n"));
7146 return SRB_STATUS_ERROR
;
7149 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0,
7150 ((Srb
->DataTransferLength
&& (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) ? ATA_AHCI_CMD_WRITE
: 0) |
7151 (ATA_AHCI_CMD_ATAPI
| ATA_AHCI_CMD_PREFETCH
),
7152 fis_size
, DeviceNumber
);
7154 KdPrint2((PRINT_PREFIX
"AtapiSendCommand ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
7158 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7159 // if this is queued request, reinit DMA and check
7160 // if DMA mode is still available
7161 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
7162 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7163 if (/*EnableDma &&*/
7164 (LunExt
->TransferMode
>= ATA_DMA
)) {
7165 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
7168 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7169 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
7172 dma_reinited
= TRUE
;
7176 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
7177 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
7178 return SRB_STATUS_PENDING
;
7180 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma
, Srb
->Cdb
[0]));
7181 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7182 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7185 if((Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) && !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7186 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
7188 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7189 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7190 } if(AtaReq
->TransferLength
) {
7192 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
7193 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7194 if (/*EnableDma &&*/
7195 (LunExt
->TransferMode
>= ATA_DMA
)) {
7198 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7203 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
7205 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7206 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7207 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
7208 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7211 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
7212 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7213 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7216 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
7218 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
7219 &(Srb
->Cdb
), Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
7221 // Make sure command is to ATAPI device.
7222 flags
= LunExt
->DeviceFlags
;
7223 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7224 if((Srb
->Lun
) > (LunExt
->DiscsPresent
- 1)) {
7226 // Indicate no device found at this address.
7227 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7228 return SRB_STATUS_SELECTION_TIMEOUT
;
7230 } else if(Srb
->Lun
> 0) {
7231 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7232 return SRB_STATUS_SELECTION_TIMEOUT
;
7235 if(!(flags
& DFLAGS_ATAPI_DEVICE
)) {
7236 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7237 return SRB_STATUS_SELECTION_TIMEOUT
;
7240 // Select device 0 or 1. Or more for PM
7241 SelectDrive(chan
, DeviceNumber
);
7243 // Verify that controller is ready for next command.
7244 GetStatus(chan
, statusByte
);
7245 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
7247 if(statusByte
== IDE_STATUS_WRONG
) {
7248 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
7251 if(statusByte
& IDE_STATUS_BUSY
) {
7252 if(statusByte
& IDE_STATUS_DSC
) {
7253 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
7255 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
7256 // We have to make reset here, since we are expecting device to be available
7257 //return SRB_STATUS_BUSY; // this cause queue freeze
7261 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7263 // Check if command list is free
7264 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
7266 // controller is busy, however we expect it to be free
7267 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI
));
7271 if(statusByte
& IDE_STATUS_ERROR
) {
7272 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
7274 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
7275 // Read the error reg. to clear it and fail this request.
7276 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7277 return MapError(deviceExtension
, Srb
);
7279 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
7282 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
7283 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
7284 if((!(statusByte
& IDE_STATUS_DSC
)) &&
7285 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
7287 AtapiStallExecution(200);
7288 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
7289 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7290 return SRB_STATUS_PENDING
;
7293 if(IS_RDP(Srb
->Cdb
[0])) {
7295 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
7299 if(statusByte
& IDE_STATUS_DRQ
) {
7301 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
7303 // Try to drain the data that one preliminary device thinks that it has
7304 // to transfer. Hopefully this random assertion of DRQ will not be present
7305 // in production devices.
7306 statusByte
= AtapiSuckPort2(chan
);
7308 for (i = 0; i < 0x10000; i++) {
7309 GetStatus(chan, statusByte);
7310 if(statusByte & IDE_STATUS_DRQ) {
7311 AtapiReadPort2(chan, IDX_IO1_i_Data);
7317 if (statusByte
& IDE_STATUS_DRQ
) {
7319 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte
));
7321 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7323 AtapiSoftReset(chan
, DeviceNumber
);
7325 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
7326 // Re-initialize Atapi device.
7327 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), DeviceNumber
, TRUE
);
7329 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
7330 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
7332 // Inform the port driver that the bus has been reset.
7333 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
7334 // Clean up device extension fields that AtapiStartIo won't.
7335 UniataExpectChannelInterrupt(chan
, FALSE
);
7337 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
7340 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7342 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7343 return SRB_STATUS_BUS_RESET;
7346 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
7350 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
7351 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7352 return SRB_STATUS_SELECTION_TIMEOUT
;
7356 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7357 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
7358 Srb
->Cdb
[1] &= ~0xE0;
7359 if((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
7360 // Torisan changer. TUR's are overloaded to be platter switches.
7361 Srb
->Cdb
[7] = Srb
->Lun
;
7368 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
7370 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
7373 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7374 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AHCI, begin transaction\n"));
7375 //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
7376 UniataExpectChannelInterrupt(chan
, TRUE
);
7377 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
7378 return SRB_STATUS_PENDING
;
7381 statusByte
= WaitOnBusy(chan
);
7382 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
7386 FeatureReg
|= ATA_F_DMA
;
7387 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7388 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7389 FeatureReg
|= ATA_F_DMAREAD
;
7393 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, FeatureReg
);
7395 // Write transfer byte count to registers.
7396 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
7397 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
7399 if (Srb
->DataTransferLength
>= 0x10000) {
7400 byteCountLow
= byteCountHigh
= 0xFF;
7403 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
7404 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
7406 if (flags
& DFLAGS_INT_DRQ
) {
7408 // This device interrupts when ready to receive the packet.
7410 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
7413 UniataExpectChannelInterrupt(chan
, TRUE
);
7414 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
7415 InterlockedExchange(&(chan
->CheckIntr
),
7418 // Write ATAPI packet command.
7419 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7421 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
7422 return SRB_STATUS_PENDING
;
7426 // This device quickly sets DRQ when ready to receive the packet.
7428 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
7431 UniataExpectChannelInterrupt(chan
, TRUE
);
7432 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
7433 InterlockedExchange(&(chan
->CheckIntr
),
7436 if(g_opt_AtapiSendDisableIntr
) {
7437 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7439 // remember status. Later we may check if error appeared after cmd packet
7440 statusByte0
= statusByte
;
7442 // Write ATAPI packet command.
7443 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7447 statusByte
= WaitForDrq(chan
);
7449 // Need to read status register and clear interrupt (if any)
7450 GetBaseStatus(chan
, statusByte
);
7452 if (!(statusByte
& IDE_STATUS_DRQ
)) {
7454 if(g_opt_AtapiSendDisableIntr
) {
7455 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7457 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte
));
7458 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7459 return SRB_STATUS_ERROR
;
7462 GetStatus(chan
, statusByte
);
7463 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
7465 // Send CDB to device.
7466 statusByte
= WaitOnBaseBusy(chan
);
7468 // Indicate expecting an interrupt and wait for it.
7469 UniataExpectChannelInterrupt(chan
, TRUE
);
7470 InterlockedExchange(&(chan
->CheckIntr
),
7472 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
7474 GetBaseStatus(chan
, statusByte
);
7476 if(g_opt_AtapiSendDisableIntr
) {
7477 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7482 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
7485 GetStatus(chan
, statusByte
);
7486 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: cmd status (%#x)\n", statusByte
));
7488 // When we operate in DMA mode, we should not start transfer when there is an error on entry
7489 // Interrupt may never come in such case.
7490 if(statusByte
& IDE_STATUS_ERROR
) {
7491 UCHAR interruptReason
;
7493 GetBaseStatus(chan
, statusByte
);
7494 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on cmd: (%#x)\n", statusByte
));
7496 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
7497 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: iReason %x\n", interruptReason
));
7499 // TODO: we should check interruptReason and decide what to do now
7501 // Read the error reg. to clear it and fail this request.
7502 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7503 return MapError(deviceExtension
, Srb
);
7505 /* if(statusByte & IDE_STATUS_DSC) {
7506 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DSC on cmd: (%#x)\n", statusByte));
7507 // Read the error reg. to clear it and fail this request.
7508 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7509 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte));
7510 if(statusByte >> 4) {
7511 GetBaseStatus(chan, statusByte);
7512 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7513 return MapError(deviceExtension, Srb);
7517 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
7518 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
7521 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
7523 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
7524 return SRB_STATUS_PENDING
;
7526 } // end AtapiSendCommand()
7533 Routine Description:
7534 Program ATA registers for IDE disk transfer.
7537 HwDeviceExtension - ATAPI driver storage.
7538 Srb - System request block.
7541 SRB status (pending if all goes well).
7546 ULONG check_point
= 0;
7547 #define SetCheckPoint(cp) { check_point = (cp) ; }
7549 #define SetCheckPoint(cp)
7555 IN PVOID HwDeviceExtension
,
7556 IN PSCSI_REQUEST_BLOCK Srb
,
7561 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
7564 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7569 PHW_LU_EXTENSION LunExt
;
7573 UCHAR statusByte
,errorByte
;
7574 ULONG status
= SRB_STATUS_INVALID_REQUEST
;
7577 PMODE_PARAMETER_HEADER modeData
;
7584 //ULONG __ebp__ = 0;
7586 SetCheckPoint(0x20);
7587 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
7592 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
7593 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
7594 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
7595 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
7596 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
7598 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
7599 Srb->SrbExtension));
7600 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
7603 SetCheckPoint(0x30);
7604 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7606 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
7608 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
7610 KdPrint2((PRINT_PREFIX
"** --- **\n"));
7612 lChannel
= GET_CHANNEL(Srb
);
7613 chan
= &(deviceExtension
->chan
[lChannel
]);
7614 //ldev = GET_LDEV(Srb);
7615 DeviceNumber
= GET_CDEV(Srb
);
7616 LunExt
= chan
->lun
[DeviceNumber
];
7618 SetCheckPoint(0x40);
7619 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
7620 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
7622 cdb
= (PCDB
)(Srb
->Cdb
);
7624 if(CmdAction
== CMD_ACTION_PREPARE
) {
7625 switch (Srb
->Cdb
[0]) {
7626 case SCSIOP_SERVICE_ACTION16
:
7627 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
7630 goto default_no_prep
;
7633 case SCSIOP_INQUIRY
: // now it requires device access
7635 case SCSIOP_READ_CAPACITY
:
7639 case SCSIOP_WRITE12
:
7641 case SCSIOP_WRITE16
:
7642 case SCSIOP_REQUEST_SENSE
:
7644 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
7650 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
7651 return SRB_STATUS_BUSY
;
7655 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
7656 switch (Srb
->Cdb
[0]) {
7657 case SCSIOP_INQUIRY
:
7659 KdPrint2((PRINT_PREFIX
7660 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
7661 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7662 // Filter out wrong TIDs.
7663 if ((Srb
->Lun
!= 0) ||
7664 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
7665 (Srb
->TargetId
>= deviceExtension
->NumberLuns
)) {
7667 KdPrint2((PRINT_PREFIX
7668 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
7669 // Indicate no device found at this address.
7670 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7675 KdPrint2((PRINT_PREFIX
7676 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
7677 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
7678 PIDENTIFY_DATA2 identifyData
= &(LunExt
->IdentifyData
);
7680 if (!(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7682 if(!CheckDevice(HwDeviceExtension
, lChannel
, DeviceNumber
, FALSE
)) {
7683 KdPrint2((PRINT_PREFIX
7684 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
7685 // Indicate no device found at this address.
7687 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7691 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, DeviceNumber
)) {
7692 KdPrint2((PRINT_PREFIX
7693 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
7694 // Indicate no device found at this address.
7695 UniataForgetDevice(chan
->lun
[DeviceNumber
]);
7697 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7702 // Zero INQUIRY data structure.
7703 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
7705 // Standard IDE interface only supports disks.
7706 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
7708 // Set the removable bit, if applicable.
7709 if (LunExt
->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
7710 KdPrint2((PRINT_PREFIX
7711 "RemovableMedia\n"));
7712 inquiryData
->RemovableMedia
= 1;
7714 // Set the Relative Addressing (LBA) bit, if applicable.
7715 if (LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
7716 inquiryData
->RelativeAddressing
= 1;
7717 KdPrint2((PRINT_PREFIX
7718 "RelativeAddressing\n"));
7720 // Set the CommandQueue bit
7721 inquiryData
->CommandQueue
= 1;
7723 // Fill in vendor identification fields.
7724 for (i
= 0; i
< 24; i
+= 2) {
7725 MOV_DW_SWP(inquiryData
->DeviceIdentificationString
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
7728 // Initialize unused portion of product id.
7729 for (i = 0; i < 4; i++) {
7730 inquiryData->ProductId[12+i] = ' ';
7733 // Move firmware revision from IDENTIFY data to
7734 // product revision in INQUIRY data.
7735 for (i
= 0; i
< 4; i
+= 2) {
7736 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
7739 status
= SRB_STATUS_SUCCESS
;
7744 case SCSIOP_REPORT_LUNS
: {
7747 PREPORT_LUNS_INFO_HDR LunInfo
;
7749 KdPrint2((PRINT_PREFIX
7750 "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
7751 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7753 MOV_DD_SWP(alen
, cdb
->REPORT_LUNS
.AllocationLength
);
7760 LunInfo
= (PREPORT_LUNS_INFO_HDR
)(Srb
->DataBuffer
);
7761 RtlZeroMemory(LunInfo
, 16);
7763 MOV_DD_SWP( LunInfo
->ListLength
, alen
);
7764 Srb
->DataTransferLength
= 16;
7765 status
= SRB_STATUS_SUCCESS
;
7769 case SCSIOP_MODE_SENSE
:
7771 KdPrint2((PRINT_PREFIX
7772 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
7773 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7775 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_POWER_CONDITION
) {
7776 PMODE_POWER_CONDITION_PAGE modeData
;
7778 KdPrint2((PRINT_PREFIX
"MODE_PAGE_POWER_CONDITION\n"));
7779 modeData
= (PMODE_POWER_CONDITION_PAGE
)(Srb
->DataBuffer
);
7780 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_POWER_CONDITION_PAGE
)) {
7781 status
= SRB_STATUS_DATA_OVERRUN
;
7783 RtlZeroMemory(modeData
, sizeof(MODE_POWER_CONDITION_PAGE
));
7784 modeData
->PageCode
= MODE_PAGE_POWER_CONDITION
;
7785 modeData
->PageLength
= sizeof(MODE_PAGE_POWER_CONDITION
)-sizeof(MODE_PARAMETER_HEADER
);
7786 modeData
->Byte3
.Fields
.Idle
= LunExt
->PowerState
<= StartStop_Power_Idle
;
7787 modeData
->Byte3
.Fields
.Standby
= LunExt
->PowerState
== StartStop_Power_Standby
;
7788 Srb
->DataTransferLength
= sizeof(MODE_POWER_CONDITION_PAGE
);
7789 status
= SRB_STATUS_SUCCESS
;
7792 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_CACHING
) {
7793 PMODE_CACHING_PAGE modeData
;
7795 KdPrint2((PRINT_PREFIX
"MODE_PAGE_CACHING\n"));
7796 modeData
= (PMODE_CACHING_PAGE
)(Srb
->DataBuffer
);
7797 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_CACHING_PAGE
)) {
7798 status
= SRB_STATUS_DATA_OVERRUN
;
7800 RtlZeroMemory(modeData
, sizeof(MODE_CACHING_PAGE
));
7801 modeData
->PageCode
= MODE_PAGE_CACHING
;
7802 modeData
->PageLength
= sizeof(MODE_CACHING_PAGE
)-sizeof(MODE_PARAMETER_HEADER
);
7803 modeData
->ReadDisableCache
= (LunExt
->DeviceFlags
& DFLAGS_RCACHE_ENABLED
) ? 0 : 1;
7804 modeData
->WriteCacheEnable
= (LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) ? 1 : 0;
7805 Srb
->DataTransferLength
= sizeof(MODE_CACHING_PAGE
);
7806 status
= SRB_STATUS_SUCCESS
;
7809 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
7811 // This is used to determine if the media is write-protected.
7812 // Since IDE does not support mode sense then we will modify just the portion we need
7813 // so the higher level driver can determine if media is protected.
7815 //SelectDrive(chan, DeviceNumber);
7816 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7817 //statusByte = WaitOnBusy(chan);
7818 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
7820 if (!(statusByte
& IDE_STATUS_ERROR
)) {
7822 // no error occured return success, media is not protected
7823 UniataExpectChannelInterrupt(chan
, FALSE
);
7824 InterlockedExchange(&(chan
->CheckIntr
),
7826 status
= SRB_STATUS_SUCCESS
;
7830 // error occured, handle it locally, clear interrupt
7831 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7833 GetBaseStatus(chan
, statusByte
);
7834 UniataExpectChannelInterrupt(chan
, FALSE
);
7835 InterlockedExchange(&(chan
->CheckIntr
),
7837 status
= SRB_STATUS_SUCCESS
;
7839 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
7841 //media is write-protected, set bit in mode sense buffer
7842 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
7844 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
7845 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
7848 status
= SRB_STATUS_SUCCESS
;
7850 status
= SRB_STATUS_INVALID_REQUEST
;
7854 case SCSIOP_TEST_UNIT_READY
:
7856 KdPrint2((PRINT_PREFIX
7857 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
7858 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7859 if (chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
7861 // Select device 0 or 1.
7862 //SelectDrive(chan, DeviceNumber);
7863 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7864 // Wait for busy. If media has not changed, return success
7865 //statusByte = WaitOnBusy(chan);
7866 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
7868 if (!(statusByte
& IDE_STATUS_ERROR
)){
7869 UniataExpectChannelInterrupt(chan
, FALSE
);
7870 InterlockedExchange(&(chan
->CheckIntr
),
7872 status
= SRB_STATUS_SUCCESS
;
7874 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7875 if (errorByte
== IDE_ERROR_DATA_ERROR
){
7877 // Special case: If current media is write-protected,
7878 // the 0xDA command will always fail since the write-protect bit
7879 // is sticky,so we can ignore this error
7880 GetBaseStatus(chan
, statusByte
);
7881 UniataExpectChannelInterrupt(chan
, FALSE
);
7882 InterlockedExchange(&(chan
->CheckIntr
),
7884 status
= SRB_STATUS_SUCCESS
;
7888 // Request sense buffer to be build
7889 UniataExpectChannelInterrupt(chan
, TRUE
);
7890 InterlockedExchange(&(chan
->CheckIntr
),
7892 status
= SRB_STATUS_PENDING
;
7896 status
= SRB_STATUS_SUCCESS
;
7901 case SCSIOP_READ_CAPACITY
:
7903 KdPrint2((PRINT_PREFIX
7904 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7905 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7906 // Claim 512 byte blocks (big-endian).
7907 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7909 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY_DATA
));
7910 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
7912 // Calculate last sector.
7913 if(!(i
= (ULONG
)LunExt
->NumOfSectors
)) {
7914 i
= LunExt
->IdentifyData
.SectorsPerTrack
*
7915 LunExt
->IdentifyData
.NumberOfHeads
*
7916 LunExt
->IdentifyData
.NumberOfCylinders
;
7920 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
7921 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
7922 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
7924 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
7926 KdPrint2((PRINT_PREFIX
7927 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
7929 LunExt
->IdentifyData
.SectorsPerTrack
,
7930 LunExt
->IdentifyData
.NumberOfHeads
,
7931 LunExt
->IdentifyData
.NumberOfCylinders
));
7934 status
= SRB_STATUS_SUCCESS
;
7937 case SCSIOP_SERVICE_ACTION16
:
7939 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
7940 KdPrint2((PRINT_PREFIX
7941 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7942 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7943 // Claim 512 byte blocks (big-endian).
7944 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7946 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY16_DATA
));
7947 MOV_DD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
7949 // Calculate last sector.
7950 if(!(lba
= LunExt
->NumOfSectors
)) {
7951 lba
= LunExt
->IdentifyData
.SectorsPerTrack
*
7952 LunExt
->IdentifyData
.NumberOfHeads
*
7953 LunExt
->IdentifyData
.NumberOfCylinders
;
7956 MOV_QD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, lba
);
7958 KdPrint2((PRINT_PREFIX
7959 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n",
7961 LunExt
->IdentifyData
.SectorsPerTrack
,
7962 LunExt
->IdentifyData
.NumberOfHeads
,
7963 LunExt
->IdentifyData
.NumberOfCylinders
));
7965 status
= SRB_STATUS_SUCCESS
;
7972 case SCSIOP_VERIFY12
:
7973 case SCSIOP_VERIFY16
:
7975 KdPrint2((PRINT_PREFIX
7976 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
7977 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7978 status
= IdeVerify(HwDeviceExtension
,Srb
);
7985 case SCSIOP_WRITE12
:
7987 case SCSIOP_WRITE16
:
7989 KdPrint2((PRINT_PREFIX
7990 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
7991 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
7992 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7993 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7994 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
7995 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
7996 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
7997 status
= IdeReadWrite(HwDeviceExtension
,
8001 case SCSIOP_START_STOP_UNIT
:
8003 KdPrint2((PRINT_PREFIX
8004 "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
8005 cdb
->START_STOP
.Immediate
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8006 //Determine what type of operation we should perform
8010 if(cdb
->START_STOP
.FL
||
8011 cdb
->START_STOP
.FormatLayerNumber
||
8012 cdb
->START_STOP
.Reserved2
||
8013 cdb
->START_STOP
.Reserved2_2
||
8014 cdb
->START_STOP
.Reserved3
||
8019 if (cdb
->START_STOP
.PowerConditions
) {
8020 KdPrint2((PRINT_PREFIX
"START_STOP Power %d\n", cdb
->START_STOP
.PowerConditions
));
8021 switch(cdb
->START_STOP
.PowerConditions
) {
8022 case StartStop_Power_Idle
:
8023 command
= IDE_COMMAND_IDLE_IMMED
;
8025 case StartStop_Power_Standby
:
8026 command
= IDE_COMMAND_STANDBY_IMMED
;
8028 case StartStop_Power_Sleep
:
8029 // TODO: we should save power state in order to know
8030 // that RESET sould be issued to revert device into
8033 command
= IDE_COMMAND_SLEEP
;
8038 LunExt
->PowerState
= cdb
->START_STOP
.PowerConditions
;
8040 if (cdb
->START_STOP
.LoadEject
== 1) {
8041 KdPrint2((PRINT_PREFIX
"START_STOP eject\n"));
8043 // first select device 0 or 1.
8044 //SelectDrive(chan, DeviceNumber);
8045 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
8046 command
= IDE_COMMAND_MEDIA_EJECT
;
8048 if (cdb
->START_STOP
.Start
== 0) {
8049 KdPrint2((PRINT_PREFIX
"START_STOP standby\n"));
8050 command
= IDE_COMMAND_STANDBY_IMMED
;
8052 // TODO: we may need to perform hard reset (after sleep) or
8053 // issue IDE_COMMAND_IDLE_IMMED in order to activate device
8054 KdPrint2((PRINT_PREFIX
"START_STOP activate\n"));
8056 if(LunExt
->PowerState
== StartStop_Power_Sleep
) {
8057 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
8058 status
= SRB_STATUS_SUCCESS
;
8061 if(LunExt
->PowerState
> StartStop_Power_Idle
) {
8062 KdPrint2((PRINT_PREFIX
" issue IDLE\n"));
8063 command
= IDE_COMMAND_IDLE_IMMED
;
8065 KdPrint2((PRINT_PREFIX
" do nothing\n"));
8066 status
= SRB_STATUS_SUCCESS
;
8071 statusByte
= WaitOnBaseBusy(chan
);
8072 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, command
, 0, 0, 0, 0, 0,
8073 cdb
->START_STOP
.Immediate
? ATA_IMMEDIATE
: ATA_WAIT_READY
);
8074 status
= (statusByte
& IDE_STATUS_ERROR
) ? SRB_STATUS_ERROR
: SRB_STATUS_SUCCESS
;
8075 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
8079 KdPrint2((PRINT_PREFIX
"START_STOP invalid\n"));
8080 if (Srb
->SenseInfoBuffer
) {
8082 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8084 senseBuffer
->ErrorCode
= 0x70;
8085 senseBuffer
->Valid
= 1;
8086 senseBuffer
->AdditionalSenseLength
= 0xb;
8087 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
8088 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_CDB
;
8089 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8091 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8092 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8094 status
= SRB_STATUS_ERROR
;
8098 case SCSIOP_MEDIUM_REMOVAL
:
8100 cdb
= (PCDB
)Srb
->Cdb
;
8102 if(LunExt
->IdentifyData
.Removable
) {
8103 statusByte
= WaitOnBaseBusy(chan
);
8105 //SelectDrive(chan, DeviceNumber);
8106 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
8107 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
8108 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_LOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8110 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
8111 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_UNLOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8113 status
= SRB_STATUS_SUCCESS
;
8115 status
= SRB_STATUS_INVALID_REQUEST
;
8120 // Note: I don't implement this, because NTFS driver too often issues this command
8121 // It causes awful performance degrade. However, if somebody wants, I will implement
8122 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
8123 case SCSIOP_FLUSH_BUFFER
:
8124 case SCSIOP_SYNCHRONIZE_CACHE
:
8126 SelectDrive(chan
, DeviceNumber
);
8127 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
8128 status
= SRB_STATUS_SUCCESS
;
8129 // status = SRB_STATUS_PENDING;
8130 statusByte
= WaitOnBusy(chan
);
8134 case SCSIOP_REQUEST_SENSE
:
8135 // this function makes sense buffers to report the results
8136 // of the original GET_MEDIA_STATUS command
8138 KdPrint2((PRINT_PREFIX
8139 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8140 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8141 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8142 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
8145 status
= SRB_STATUS_INVALID_REQUEST
;
8149 case SCSIOP_ATA_PASSTHROUGH
:
8152 BOOLEAN use_dma
= FALSE
;
8155 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
8157 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
8158 //lChannel = Srb->TargetId >> 1;
8160 DeviceNumber
= max(DeviceNumber
, 1);
8161 regs
->bDriveHeadReg
&= 0x0f;
8162 regs
->bDriveHeadReg
|= (UCHAR
) (((DeviceNumber
& 0x1) << 4) | 0xA0);
8165 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
8167 KdPrint2((PRINT_PREFIX
8168 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
8169 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8171 if((regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) == UNIATA_SPTI_EX_SPEC_TO
) {
8172 to_lim
= Srb
->TimeOutValue
;
8174 if(Srb
->TimeOutValue
<= 2) {
8175 to_lim
= Srb
->TimeOutValue
*900;
8177 to_lim
= (Srb
->TimeOutValue
*999) - 500;
8181 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8183 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
8185 statusByte
= UniataAhciSendPIOCommandDirect(
8194 if(statusByte
== IDE_STATUS_WRONG
) {
8195 goto passthrough_err
;
8197 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8198 UniataAhciAbortOperation(chan
);
8199 goto passthrough_err
;
8201 goto passthrough_done
;
8205 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
8206 if((chan
->lun
[DeviceNumber
]->LimitedTransferMode
>= ATA_DMA
)) {
8208 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
8209 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
8210 (PUCHAR
)(Srb
->DataBuffer
),
8211 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
8217 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
8218 AtapiStallExecution(10);
8220 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
8221 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8222 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8223 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8224 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8225 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8227 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
8228 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8229 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
8230 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8231 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
8232 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8233 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
8234 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8235 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
8236 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8238 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
8241 GetBaseStatus(chan
, statusByte
);
8242 if(statusByte
& IDE_STATUS_ERROR
) {
8243 goto passthrough_err
;
8245 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
8248 ScsiPortStallExecution(1); // wait for busy to be set
8250 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
8251 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
8252 GetBaseStatus(chan
, statusByte
);
8253 if(statusByte
& IDE_STATUS_ERROR
) {
8256 if(!(statusByte
& IDE_STATUS_BUSY
)) {
8261 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
8263 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8264 goto passthrough_err
;
8268 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
8270 AtapiDmaDone(deviceExtension
, DeviceNumber
, lChannel
, NULL
);
8271 GetBaseStatus(chan
, statusByte
);
8273 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8274 AtapiSuckPort2(chan
);
8276 if (Srb
->SenseInfoBuffer
) {
8278 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8280 senseBuffer
->ErrorCode
= 0x70;
8281 senseBuffer
->Valid
= 1;
8282 senseBuffer
->AdditionalSenseLength
= 0xb;
8283 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
8284 senseBuffer
->AdditionalSenseCode
= 0;
8285 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8287 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8288 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8290 status
= SRB_STATUS_ERROR
;
8294 if (statusByte
& IDE_STATUS_DRQ
) {
8295 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
8297 (PUSHORT
) Srb
->DataBuffer
,
8298 Srb
->DataTransferLength
/ 2,
8300 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
8302 (PUSHORT
) Srb
->DataBuffer
,
8303 Srb
->DataTransferLength
/ 2,
8308 status
= SRB_STATUS_SUCCESS
;
8311 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8313 } else { // read task register
8316 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
8318 KdPrint2((PRINT_PREFIX
8319 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
8320 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8322 if((Srb
->DataTransferLength
>= sizeof(IDEREGS_EX
)) &&
8323 (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
)) {
8326 if(Srb
->DataTransferLength
>= sizeof(IDEREGS
)) {
8329 KdPrint2((PRINT_PREFIX
" buffer too small \n"));
8330 status
= SRB_STATUS_DATA_OVERRUN
;
8333 RtlZeroMemory(regs
, use48
? sizeof(IDEREGS_EX
) : sizeof(IDEREGS
));
8334 regs
->bOpFlags
= use48
? ATA_FLAGS_48BIT_COMMAND
: 0;
8335 UniataSnapAtaRegs(chan
, 0, regs
);
8337 status
= SRB_STATUS_SUCCESS
;
8344 KdPrint2((PRINT_PREFIX
8345 "IdeSendCommand: Unsupported command %#x\n",
8348 status
= SRB_STATUS_INVALID_REQUEST
;
8352 if(status
== SRB_STATUS_PENDING
) {
8353 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
8354 if(CmdAction
& CMD_ACTION_EXEC
) {
8355 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
8356 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
8359 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
8360 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8365 } // end IdeSendCommand()
8370 Routine Description:
8371 Enables disables media status notification
8374 HwDeviceExtension - ATAPI driver storage.
8381 IN PVOID HwDeviceExtension
,
8383 IN ULONG DeviceNumber
8386 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8388 UCHAR statusByte
,errorByte
;
8390 chan
= &(deviceExtension
->chan
[lChannel
]);
8391 SelectDrive(chan
, DeviceNumber
);
8393 if (EnableMSN
== TRUE
){
8395 // If supported enable Media Status Notification support
8396 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
8399 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8400 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8401 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8403 if (statusByte
& IDE_STATUS_ERROR
) {
8404 // Read the error register.
8405 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8407 KdPrint2((PRINT_PREFIX
8408 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
8412 chan
->lun
[DeviceNumber
]->DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
8413 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
8414 chan
->ReturningMediaStatus
= 0;
8419 } else { // end if EnableMSN == TRUE
8421 // disable if previously enabled
8422 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
8424 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8425 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8426 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8427 chan
->lun
[DeviceNumber
]->DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
8434 } // end IdeMediaStatus()
8439 Routine Description:
8441 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
8442 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
8445 HwDeviceExtension - ATAPI driver storage.
8446 Srb - System request block.
8450 SRB status (ALWAYS SUCCESS).
8455 IdeBuildSenseBuffer(
8456 IN PVOID HwDeviceExtension
,
8457 IN PSCSI_REQUEST_BLOCK Srb
8460 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8462 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
8463 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
8467 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
8469 senseBuffer
->ErrorCode
= 0x70;
8470 senseBuffer
->Valid
= 1;
8471 senseBuffer
->AdditionalSenseLength
= 0xb;
8472 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8473 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8474 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8475 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
8477 senseBuffer
->ErrorCode
= 0x70;
8478 senseBuffer
->Valid
= 1;
8479 senseBuffer
->AdditionalSenseLength
= 0xb;
8480 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8481 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8482 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8483 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
8485 senseBuffer
->ErrorCode
= 0x70;
8486 senseBuffer
->Valid
= 1;
8487 senseBuffer
->AdditionalSenseLength
= 0xb;
8488 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
8489 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
8490 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8491 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
8493 senseBuffer
->ErrorCode
= 0x70;
8494 senseBuffer
->Valid
= 1;
8495 senseBuffer
->AdditionalSenseLength
= 0xb;
8496 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
8497 senseBuffer
->AdditionalSenseCode
= 0;
8498 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8500 return SRB_STATUS_SUCCESS
;
8502 return SRB_STATUS_ERROR
;
8504 }// End of IdeBuildSenseBuffer
8508 UniataUserDeviceReset(
8509 PHW_DEVICE_EXTENSION deviceExtension
,
8510 PHW_LU_EXTENSION LunExt
,
8515 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8516 if ((LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
8517 (LunExt
->PowerState
!= StartStop_Power_Sleep
)) {
8518 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
8519 AtapiSoftReset(&(deviceExtension
->chan
[lChannel
]), LunExt
->Lun
);
8521 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
8522 AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8523 for(i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
8524 deviceExtension
->chan
[lChannel
].lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
8527 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
8528 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8530 } // end UniataUserDeviceReset()
8535 PHW_DEVICE_EXTENSION deviceExtension
,
8540 BOOLEAN PostReq
= FALSE
;
8542 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
8543 if(chan
->queue_depth
> 0) {
8546 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
8547 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
8548 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
8550 status
= SRB_STATUS_BUSY
;
8559 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
8563 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
8566 } // end UniataNeedQueueing()
8570 Routine Description:
8572 This routine is called from the SCSI port driver synchronized
8573 with the kernel to start an IO request.
8578 HwDeviceExtension - HBA miniport driver's adapter data storage
8579 Srb - IO request packet
8589 IN PVOID HwDeviceExtension
,
8590 IN PSCSI_REQUEST_BLOCK Srb
8593 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
8594 } // end AtapiStartIo()
8599 IN PVOID HwDeviceExtension
,
8600 IN PSCSI_REQUEST_BLOCK Srb
,
8604 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8607 PHW_LU_EXTENSION LunExt
;
8615 PSCSI_REQUEST_BLOCK tmpSrb
;
8616 BOOLEAN PostReq
= FALSE
;
8618 BOOLEAN commPort
= FALSE
;
8620 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
8621 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
8622 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
8623 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
8625 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
8627 /* KeBugCheckEx(0xc000000e,
8628 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8630 TopLevel, 0x80000001);
8632 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
8633 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
8634 //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
8635 UniAtaClearAtaReq(Srb
->SrbExtension
);
8638 do { // fetch all queued commands for the channel (if valid)
8640 lChannel
= GET_CHANNEL(Srb
);
8641 //ldev = GET_LDEV(Srb);
8644 DeviceNumber
= GET_CDEV(Srb
);
8647 //ASSERT(deviceExtension);
8650 KdPrint2((PRINT_PREFIX
8651 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8652 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8653 KdPrint2((PRINT_PREFIX
" VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
8655 if(lChannel
== deviceExtension
->NumberChannels
&&
8656 !Srb
->Lun
&& !Srb
->TargetId
&&
8657 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
8658 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
8660 // This is our virtual device
8661 KdPrint2((PRINT_PREFIX
8662 "AtapiStartIo: Communication port\n"));
8663 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
8665 if(Srb
->DataTransferLength
< sizeof(PINQUIRYDATA
)) {
8666 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", Srb
->DataTransferLength
,
8667 sizeof(PINQUIRYDATA
) ));
8669 status
= SRB_STATUS_DATA_OVERRUN
;
8673 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
8675 KdPrint2((PRINT_PREFIX
8677 // Zero INQUIRY data structure.
8678 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
8680 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
8682 // Fill in vendor identification fields.
8683 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
8685 status
= SRB_STATUS_SUCCESS
;
8689 /* Pass IOCTL request down */
8691 if(lChannel
>= deviceExtension
->NumberChannels
||
8692 Srb
->TargetId
/*DeviceNumber*/ >= deviceExtension
->NumberLuns
||
8695 if(lChannel
>= deviceExtension
->NumberChannels
) {
8700 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8701 KdPrint3((PRINT_PREFIX
8702 "AtapiStartIo: SRB rejected\n"));
8703 // Indicate no device found at this address.
8704 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
8705 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8709 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
8710 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
8715 chan
= &(deviceExtension
->chan
[lChannel
]);
8716 LunExt
= chan
->lun
[DeviceNumber
];
8720 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
8726 if(!commPort
&& !LunExt
) {
8728 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
8731 deviceExtension
->NumberChannels
);
8732 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
8733 lChannel
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
8734 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8735 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
8739 for(i=0; i<1000; i++) {
8740 AtapiStallExecution(3*1000);
8747 // Determine which function.
8748 switch (Srb
->Function
) {
8750 case SRB_FUNCTION_EXECUTE_SCSI
:
8752 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8753 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
8754 // let passthrough go
8756 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
8760 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8761 KdPrint2((PRINT_PREFIX
8762 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
8763 // Indicate no device found at this address.
8764 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
8765 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8770 KdPrint2((PRINT_PREFIX
8771 " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb
, &(Srb
->Cdb
), Srb
->SrbExtension
, Srb
->Cdb
[0]));
8775 if(Srb->DataTransferLength) {
8777 a = ((PUCHAR)(Srb->DataBuffer))[0];
8780 } __except(EXCEPTION_EXECUTE_HANDLER) {
8781 KdPrint3((PRINT_PREFIX
8782 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
8783 // Indicate no device found at this address.
8784 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
8785 status = SRB_STATUS_ERROR;
8786 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
8791 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
8795 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
8797 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
8798 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
8800 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
8802 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
8803 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
8805 /*KeBugCheckEx(0xc000000e,
8806 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8808 status, 0x80000001);*/
8809 if(status
== SRB_STATUS_BUSY
)
8810 status
= SRB_STATUS_PENDING
;
8811 // Insert requests AFTER they have been initialized on
8812 // CMD_ACTION_PREPARE stage
8813 // we should not check TopLevel here (it is always TRUE)
8814 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8815 UniataQueueRequest(chan
, Srb
);
8817 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
8821 // Send command to device.
8822 KdPrint2((PRINT_PREFIX
"Send to device %x\n", Srb
->Cdb
[0]));
8824 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
8825 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8826 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
8827 //ASSERT(!AtaReq->Flags);
8828 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8829 UniataQueueRequest(chan
, Srb
);
8830 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
8831 //ASSERT(!AtaReq->Flags);
8832 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
8833 //ASSERT(!AtaReq->Flags);
8837 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8841 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
8842 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, DeviceNumber
)) {
8843 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, DeviceNumber
, TRUE
)) {
8847 if(!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8851 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
8860 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)/* &&
8861 (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
8862 KdPrint3((PRINT_PREFIX
"Try ATAPI send %x\n", Srb
->Cdb
[0]));
8863 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
8865 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
8870 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
8877 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
8879 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
8881 /* KeBugCheckEx(0xc000000e,
8882 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8884 status, 0x80000002);*/
8892 case SRB_FUNCTION_ABORT_COMMAND
:
8894 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
8896 // Verify that SRB to abort is still outstanding.
8897 if((tmpSrb
!= Srb
->NextSrb
) ||
8898 !chan
->queue_depth
) {
8900 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
8902 // Complete abort SRB.
8903 status
= SRB_STATUS_ABORT_FAILED
;
8907 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
8908 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
8909 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
8910 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
8911 // Log reset failure.
8912 KdPrint3((PRINT_PREFIX
8913 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
8914 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
8916 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
8917 status
= SRB_STATUS_ERROR
;
8920 status
= SRB_STATUS_SUCCESS
;
8923 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
8924 if (tmpSrb
->SenseInfoBuffer
&&
8925 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
8927 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
8929 senseBuffer
->ErrorCode
= 0;
8930 senseBuffer
->Valid
= 1;
8931 senseBuffer
->AdditionalSenseLength
= 0xb;
8932 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
8933 senseBuffer
->AdditionalSenseCode
= 0;
8934 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8936 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
8938 AtapiDmaDBSync(chan
, tmpSrb
);
8939 UniataRemoveRequest(chan
, tmpSrb
);
8940 // Indicate command complete.
8941 ScsiPortNotification(RequestComplete
,
8944 status
= SRB_STATUS_SUCCESS
;
8948 // Abort function indicates that a request timed out.
8949 // Call reset routine. Card will only be reset if
8950 // status indicates something is wrong.
8951 // Fall through to reset code.
8953 case SRB_FUNCTION_RESET_DEVICE
:
8954 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
8956 // Reset single device.
8957 // For now we support only Lun=0
8959 // Note: reset is immediate command, it cannot be queued since it is usually used to
8960 // revert not-responding device to operational state
8961 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
8962 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
8963 status
= SRB_STATUS_SUCCESS
;
8966 case SRB_FUNCTION_RESET_BUS
:
8968 // Reset Atapi and SCSI bus.
8970 // Note: reset is immediate command, it cannot be queued since it is usually used to
8971 // revert not- responding device to operational state
8972 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
8973 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
8974 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
8975 // Log reset failure.
8976 KdPrint3((PRINT_PREFIX
8977 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
8978 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
8980 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
8981 status
= SRB_STATUS_ERROR
;
8984 status
= SRB_STATUS_SUCCESS
;
8989 case SRB_FUNCTION_SHUTDOWN
:
8991 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
8992 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8993 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
8996 // FLUSH ATAPI device - do nothing
8997 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
8999 // FLUSH IDE/ATA device
9000 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
9001 AtapiDisableInterrupts(deviceExtension
, lChannel
);
9002 status
= AtaCommand(deviceExtension
, DeviceNumber
, GET_CHANNEL(Srb
),
9003 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
9004 // If supported & allowed, reset write cacheing
9005 if(LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
9007 // Disable write cache
9008 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9009 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9010 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
9011 // Check for errors.
9012 if (status
& IDE_STATUS_ERROR
) {
9013 KdPrint2((PRINT_PREFIX
9014 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
9017 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9019 // Re-enable write cache
9020 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9021 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9022 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
9023 // Check for errors.
9024 if (status
& IDE_STATUS_ERROR
) {
9025 KdPrint2((PRINT_PREFIX
9026 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
9028 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9030 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
9034 AtapiEnableInterrupts(deviceExtension
, lChannel
);
9036 status
= SRB_STATUS_SUCCESS
;
9040 case SRB_FUNCTION_FLUSH
:
9042 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
9043 status
= SRB_STATUS_SUCCESS
;
9046 case SRB_FUNCTION_IO_CONTROL
: {
9050 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
9052 len
= Srb
->DataTransferLength
;
9054 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
9056 ULONG targetId
= (ULONG
)(-1);
9058 if(len
< sizeof(SRB_IO_CONTROL
)) {
9059 goto wrong_buffer_size
;
9062 // extract bogus bus address
9063 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9064 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9065 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9067 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(GETVERSIONINPARAMS
)) {
9068 goto wrong_buffer_size
;
9071 targetId
= versionParameters
->bIDEDeviceMap
;
9072 KdPrint2((PRINT_PREFIX
"targetId (smart ver) %d\n", targetId
));
9074 case IOCTL_SCSI_MINIPORT_IDENTIFY
:
9075 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
9076 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
9077 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
9078 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
9079 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
9080 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
9081 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
9082 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
9083 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE
:
9084 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG
:
9085 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG
:
9087 PSENDCMDINPARAMS cmdInParameters
= (PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9089 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDINPARAMS
) - 1) {
9090 goto wrong_buffer_size
;
9093 targetId
= cmdInParameters
->bDriveNumber
;
9094 KdPrint2((PRINT_PREFIX
"targetId (smart/ident) %d\n", targetId
));
9098 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9099 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
9100 status
= SRB_STATUS_INVALID_REQUEST
;
9104 // adjust (if necessary) bus address
9105 if(targetId
!= (ULONG
)(-1)) {
9107 // This is done because of how the IOCTL_SCSI_MINIPORT
9108 // determines 'targetid's'. Disk.sys places the real target id value
9109 // in the DeviceMap field. Once we do some parameter checking, the value passed
9110 // back to the application will be determined.
9112 if (deviceExtension
->NumberChannels
== 1) {
9113 // do this for legacy controllers and legacy callers
9114 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call\n"));
9115 DeviceNumber
= (targetId
& 0x01);
9119 // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
9120 // due to DISK.SYS design bug, we have invalid SCSI address in SRB
9121 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call (2)\n"));
9122 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
9123 lChannel
= (UCHAR
)targetId
/ 2;
9126 lChannel
= (UCHAR
)(targetId
/ 2);
9127 DeviceNumber
= targetId
& 0x01;
9130 // otherwise assume lChannel and DeviceNumber from Srb are ok
9132 if(lChannel
>= deviceExtension
->NumberChannels
||
9133 DeviceNumber
>= deviceExtension
->NumberLuns
) {
9134 KdPrint2((PRINT_PREFIX
9135 "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
9137 // Indicate no device found at this address.
9140 targetId
= lChannel
*deviceExtension
->NumberLuns
+DeviceNumber
;
9141 chan
= &(deviceExtension
->chan
[lChannel
]);
9142 LunExt
= chan
->lun
[DeviceNumber
];
9146 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
9148 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9153 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9154 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9156 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9157 UCHAR deviceNumberMap
;
9159 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
9161 // Version and revision per SMART 1.03
9163 versionParameters
->bVersion
= 1;
9164 versionParameters
->bRevision
= 1;
9165 versionParameters
->bReserved
= 0;
9167 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
9168 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
9171 goto invalid_request
;
9174 // NOTE: This will only set the bit
9175 // corresponding to this drive's target id.
9176 // The bit mask is as follows:
9182 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
9183 deviceNumberMap
= 1 << lChannel
;
9186 if (deviceExtension
->NumberChannels
== 1) {
9187 if (chan
->PrimaryAddress
) {
9188 deviceNumberMap
= 1 << DeviceNumber
;
9190 deviceNumberMap
= 4 << DeviceNumber
;
9193 deviceNumberMap
= 1 << (DeviceNumber
+lChannel
*2);
9196 versionParameters
->bIDEDeviceMap
= deviceNumberMap
;
9198 status
= SRB_STATUS_SUCCESS
;
9202 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
9204 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9205 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9207 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
9208 // Extract the target.
9209 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
9211 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
9214 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
9215 goto invalid_request
;
9221 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
9222 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
9223 goto invalid_request
;
9226 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
9227 // Zero the output buffer
9228 RtlZeroMemory(cmdOutParameters
, len
);
9229 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
9230 ((PUCHAR)cmdOutParameters)[i] = 0;
9233 // Build status block.
9234 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
9235 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
9236 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
9238 // Extract the identify data from the device extension.
9239 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &(LunExt
->IdentifyData
),
9240 cmdOutParameters
->cBufferSize
);
9242 if((cmdOutParameters
->cBufferSize
== IDENTIFY_BUFFER_SIZE
) &&
9243 (LunExt
->IdentifyData
.ChecksumValid
== ATA_ChecksumValid
)) {
9244 // adjust checksum if it is possible
9248 for(i
=0; i
< IDENTIFY_BUFFER_SIZE
-1; i
++) {
9249 csum
+= (CHAR
)(cmdOutParameters
->bBuffer
[i
]);
9251 cmdOutParameters
->bBuffer
[i
] = -csum
;
9252 KdPrint2((PRINT_PREFIX
"AtapiStartIo: adjust checksum %d\n"));
9254 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
9256 status
= SRB_STATUS_SUCCESS
;
9260 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
9261 cmdInParameters
.irDriveRegs
.bCommandReg
));
9262 status
= SRB_STATUS_INVALID_REQUEST
;
9268 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9269 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9270 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9271 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9272 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9273 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9274 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9275 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9278 // *all* IOCTLs here are SMART
9280 KdPrint2((PRINT_PREFIX
9281 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
9284 goto invalid_request
;
9287 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9289 if(PostReq
|| TopLevel
) {
9290 UniataQueueRequest(chan
, Srb
);
9291 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9292 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9297 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
9298 status
= SRB_STATUS_PENDING
;
9300 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9303 status
= IdeSendSmartCommand(HwDeviceExtension
, Srb
, targetId
);
9307 // we should not get here, checked above
9309 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9310 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9311 status = SRB_STATUS_INVALID_REQUEST;
9316 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
9318 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
9319 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
9320 ULONG DeviceNumber
= AtaCtl
->addr
.TargetId
;
9324 pos
= FIELD_OFFSET(UNIATA_CTL
, RawData
);
9325 //chan = &(deviceExtension->chan[lChannel]);
9327 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9328 FIELD_OFFSET(UNIATA_CTL
, RawData
) ));
9329 goto wrong_buffer_size
;
9332 if(AtaCtl
->addr
.Lun
||
9333 AtaCtl
->addr
.TargetId
>= deviceExtension
->NumberLuns
||
9334 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
9342 lChannel
= AtaCtl
->addr
.PathId
;
9343 chan
= &(deviceExtension
->chan
[lChannel
]);
9344 LunExt
= chan
->lun
[DeviceNumber
];
9347 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl
->hdr
.ControlCode
, DeviceNumber
));
9349 /* check for valid LUN */
9350 switch (AtaCtl
->hdr
.ControlCode
) {
9351 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9352 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
9353 // this would be BUS reset
9355 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
9356 AtaCtl
->addr
.TargetId
!= 0xff ||
9357 AtaCtl
->addr
.Lun
!= 0
9359 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
9360 DeviceNumber
< deviceExtension
->NumberLuns
) { // AtaCtl->addr.TargetId != 0xff
9361 lChannel
= AtaCtl
->addr
.PathId
;
9362 chan
= &(deviceExtension
->chan
[lChannel
]);
9363 LunExt
= chan
->lun
[DeviceNumber
];
9366 goto handle_bad_ldev
;
9369 lChannel
= AtaCtl
->addr
.PathId
;
9370 chan
= &(deviceExtension
->chan
[lChannel
]);
9373 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
9374 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9375 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
9376 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9377 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
9380 KdPrint2((PRINT_PREFIX
9381 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
9382 // Indicate no device found at this address.
9387 /* check if queueing is necessary */
9388 switch (AtaCtl
->hdr
.ControlCode
) {
9389 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9390 if(!LunExt
->nBadBlocks
) {
9393 goto uata_ctl_queue
;
9394 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9395 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9396 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9397 pos
+sizeof(AtaCtl
->SetMode
) ));
9398 goto wrong_buffer_size
;
9400 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
9403 goto uata_ctl_queue
;
9404 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9405 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
9407 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
9408 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9410 if(PostReq
|| TopLevel
) {
9411 UniataQueueRequest(chan
, Srb
);
9412 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9413 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9416 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
9417 status
= SRB_STATUS_PENDING
;
9419 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9422 } // end switch (AtaCtl->hdr.ControlCode)
9424 /* process request */
9425 switch (AtaCtl
->hdr
.ControlCode
) {
9426 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9428 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
9430 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9431 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9432 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9433 goto wrong_buffer_size
;
9435 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
9436 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
9437 if(AtaCtl
->addr
.TargetId
!= 0xff) {
9438 LunExt
->DeviceFlags
&= ~DFLAGS_HIDDEN
;
9443 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9444 AtapiStallExecution(1000 * 1000);
9447 FindDevices(HwDeviceExtension
,
9448 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
9449 ? UNIATA_FIND_DEV_UNHIDE
: 0,
9450 AtaCtl
->addr
.PathId
);
9451 status
= SRB_STATUS_SUCCESS
;
9455 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
9457 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
9459 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9460 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9461 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9462 goto wrong_buffer_size
;
9464 LunExt
->DeviceFlags
= 0;
9465 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
9466 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
9467 //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
9468 UniataForgetDevice(LunExt
);
9471 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9472 AtapiStallExecution(1000 * 1000);
9475 status
= SRB_STATUS_SUCCESS
;
9478 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
9480 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
9482 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9483 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9484 pos
+sizeof(AtaCtl
->SetMode
) ));
9485 goto wrong_buffer_size
;
9487 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
9488 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
9490 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
9491 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
9492 if(LunExt
->LimitedTransferMode
>
9493 LunExt
->OrigTransferMode
) {
9494 // check for incorrect value
9495 LunExt
->LimitedTransferMode
=
9496 LunExt
->OrigTransferMode
;
9499 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
9501 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
9502 if(AtaCtl
->SetMode
.ApplyImmediately
) {
9503 AtapiDmaInit__(deviceExtension
, LunExt
);
9505 /* LunExt->TransferMode =
9506 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
9507 status
= SRB_STATUS_SUCCESS
;
9510 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
9512 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
9514 if(len
< pos
+sizeof(AtaCtl
->GetMode
)) {
9515 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9516 pos
+sizeof(AtaCtl
->GetMode
) ));
9517 goto wrong_buffer_size
;
9519 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
9520 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
9521 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
9522 AtaCtl
->GetMode
.PhyMode
= LunExt
->PhyTransferMode
;
9524 status
= SRB_STATUS_SUCCESS
;
9527 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION
: {
9529 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get version\n"));
9531 if(len
< pos
+sizeof(AtaCtl
->Version
)) {
9532 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9533 pos
+sizeof(AtaCtl
->Version
) ));
9534 goto wrong_buffer_size
;
9536 AtaCtl
->Version
.Length
= sizeof(GETDRVVERSION
);
9537 AtaCtl
->Version
.VersionMj
= UNIATA_VER_MJ
;
9538 AtaCtl
->Version
.VersionMn
= UNIATA_VER_MN
;
9539 AtaCtl
->Version
.SubVerMj
= UNIATA_VER_SUB_MJ
;
9540 AtaCtl
->Version
.SubVerMn
= UNIATA_VER_SUB_MN
;
9542 status
= SRB_STATUS_SUCCESS
;
9545 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
9547 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
9549 if(len
< pos
+sizeof(AtaCtl
->AdapterInfo
)) {
9550 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9551 pos
+sizeof(AtaCtl
->AdapterInfo
) ));
9552 goto wrong_buffer_size
;
9554 AtaCtl
->AdapterInfo
.HeaderLength
= sizeof(ADAPTERINFO
);
9556 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
9557 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
9558 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
9559 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
9560 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
9561 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
9562 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
9563 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
9564 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
9565 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
9566 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
9567 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
9568 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
9569 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
9570 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
9571 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
9572 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
9573 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
9574 AtaCtl
->AdapterInfo
.NumberLuns
= (UCHAR
)deviceExtension
->NumberLuns
;
9575 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
9576 if(deviceExtension
->FullDevName
) {
9577 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
9579 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
9580 AtaCtl
->AdapterInfo
.LunInfoValid
= FALSE
;
9581 AtaCtl
->AdapterInfo
.ChanHeaderLengthValid
= TRUE
;
9583 pos
+= AtaCtl
->AdapterInfo
.HeaderLength
;
9586 RtlZeroMemory(((PCHAR
)AtaCtl
)+pos
,
9589 if(len
>= pos
+AtaCtl
->AdapterInfo
.NumberChannels
*sizeof(CHANINFO
)) {
9590 PCHANINFO ChanInfo
= (PCHANINFO
)( ((PCHAR
)AtaCtl
)+pos
);
9591 PHW_CHANNEL cur_chan
;
9592 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Fill channel info\n"));
9593 for(i
=0;i
<AtaCtl
->AdapterInfo
.NumberChannels
;i
++) {
9594 KdPrint2((PRINT_PREFIX
"chan[%d] %x\n", i
, cur_chan
));
9595 cur_chan
= &(deviceExtension
->chan
[i
]);
9596 ChanInfo
->MaxTransferMode
= cur_chan
->MaxTransferMode
;
9597 ChanInfo
->ChannelCtrlFlags
= cur_chan
->ChannelCtrlFlags
;
9598 RtlCopyMemory(&(ChanInfo
->QueueStat
), &(cur_chan
->QueueStat
), sizeof(ChanInfo
->QueueStat
));
9599 ChanInfo
->ReorderCount
= cur_chan
->ReorderCount
;
9600 ChanInfo
->IntersectCount
= cur_chan
->IntersectCount
;
9601 ChanInfo
->TryReorderCount
= cur_chan
->TryReorderCount
;
9602 ChanInfo
->TryReorderHeadCount
= cur_chan
->TryReorderHeadCount
;
9603 ChanInfo
->TryReorderTailCount
= cur_chan
->TryReorderTailCount
;
9604 //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
9607 AtaCtl
->AdapterInfo
.ChanInfoValid
= TRUE
;
9608 AtaCtl
->AdapterInfo
.ChanHeaderLength
= sizeof(*ChanInfo
);
9611 status
= SRB_STATUS_SUCCESS
;
9614 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
9616 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
9618 ForgetBadBlocks(LunExt
);
9620 status
= SRB_STATUS_SUCCESS
;
9623 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
9625 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
9630 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
);
9633 status
= SRB_STATUS_SUCCESS
;
9637 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
9638 AtaCtl
->hdr
.ControlCode
));
9639 status
= SRB_STATUS_INVALID_REQUEST
;
9644 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
9645 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
9646 "SCSIDISK", "-UNIATA-"));
9648 status
= SRB_STATUS_INVALID_REQUEST
;
9653 } // end SRB_FUNCTION_IO_CONTROL
9656 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
9657 // Indicate unsupported command.
9658 status
= SRB_STATUS_INVALID_REQUEST
;
9666 PathId
= Srb
->PathId
;
9667 TargetId
= Srb
->TargetId
;
9670 if (status
!= SRB_STATUS_PENDING
) {
9672 KdPrint2((PRINT_PREFIX
9673 "AtapiStartIo: Srb %#x complete with status %#x\n",
9677 // Set status in SRB.
9678 Srb
->SrbStatus
= (UCHAR
)status
;
9681 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan
, Srb
));
9682 AtapiDmaDBSync(chan
, Srb
);
9684 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan
, Srb
));
9685 UniataRemoveRequest(chan
, Srb
);
9686 // Indicate command complete.
9687 KdPrint2((PRINT_PREFIX
"AtapiStartIo: ScsiPortNotification\n"));
9688 ScsiPortNotification(RequestComplete
,
9692 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataGetCurRequest\n"));
9693 // Remove current Srb & get next one
9694 if((Srb
= UniataGetCurRequest(chan
))) {
9695 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9696 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
9697 // current request is under precessing, thus
9698 // we should do nothing here
9702 KdPrint2((PRINT_PREFIX
"AtapiStartIo: chan %x, Src %x\n", chan
, Srb
));
9707 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
9709 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
9711 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
9712 // Indicate ready for next request.
9713 ScsiPortNotification(NextRequest
,
9717 ScsiPortNotification(NextLuRequest
,
9725 } // end AtapiStartIo__()
9730 UniataInitAtaCommands()
9736 KdPrint2((PRINT_PREFIX
"UniataInitAtaCommands:\n"));
9738 for(i
=0; i
<256; i
++) {
9743 //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
9746 case IDE_COMMAND_READ_DMA48
:
9747 case IDE_COMMAND_READ_DMA_Q48
:
9748 case IDE_COMMAND_READ_STREAM_DMA48
:
9749 case IDE_COMMAND_READ_STREAM48
:
9750 case IDE_COMMAND_WRITE_DMA48
:
9751 case IDE_COMMAND_WRITE_DMA_Q48
:
9752 case IDE_COMMAND_READ_DMA_Q
:
9753 case IDE_COMMAND_READ_DMA
:
9754 case IDE_COMMAND_WRITE_DMA
:
9755 case IDE_COMMAND_WRITE_DMA_Q
:
9756 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9757 case IDE_COMMAND_WRITE_STREAM48
:
9758 case IDE_COMMAND_WRITE_FUA_DMA48
:
9759 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9760 case IDE_COMMAND_READ_LOG_DMA48
:
9761 case IDE_COMMAND_WRITE_LOG_DMA48
:
9762 case IDE_COMMAND_TRUSTED_RCV_DMA
:
9763 case IDE_COMMAND_TRUSTED_SEND_DMA
:
9764 case IDE_COMMAND_DATA_SET_MGMT
:
9765 //KdPrint2((PRINT_PREFIX "DMA "));
9766 flags
|= ATA_CMD_FLAG_DMA
;
9770 case IDE_COMMAND_WRITE_FUA_DMA48
:
9771 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9772 case IDE_COMMAND_WRITE_MUL_FUA48
:
9774 flags
|= ATA_CMD_FLAG_FUA
;
9777 case IDE_COMMAND_READ48
:
9778 case IDE_COMMAND_READ_DMA48
:
9779 case IDE_COMMAND_READ_DMA_Q48
:
9780 case IDE_COMMAND_READ_MUL48
:
9781 case IDE_COMMAND_READ_STREAM_DMA48
:
9782 case IDE_COMMAND_READ_STREAM48
:
9783 case IDE_COMMAND_WRITE48
:
9784 case IDE_COMMAND_WRITE_DMA48
:
9785 case IDE_COMMAND_WRITE_DMA_Q48
:
9786 case IDE_COMMAND_WRITE_MUL48
:
9787 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9788 case IDE_COMMAND_WRITE_STREAM48
:
9789 case IDE_COMMAND_FLUSH_CACHE48
:
9790 case IDE_COMMAND_VERIFY48
:
9792 //KdPrint2((PRINT_PREFIX "48 "));
9793 flags
|= ATA_CMD_FLAG_48
;
9796 case IDE_COMMAND_READ
:
9797 case IDE_COMMAND_READ_MULTIPLE
:
9798 case IDE_COMMAND_READ_DMA
:
9799 case IDE_COMMAND_READ_DMA_Q
:
9800 case IDE_COMMAND_WRITE
:
9801 case IDE_COMMAND_WRITE_MULTIPLE
:
9802 case IDE_COMMAND_WRITE_DMA
:
9803 case IDE_COMMAND_WRITE_DMA_Q
:
9804 case IDE_COMMAND_FLUSH_CACHE
:
9805 case IDE_COMMAND_VERIFY
:
9807 //KdPrint2((PRINT_PREFIX "LBA "));
9808 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
9812 case IDE_COMMAND_READ_NATIVE_SIZE48
:
9813 case IDE_COMMAND_SET_NATIVE_SIZE48
:
9814 // we cannot set LBA flag for these commands to avoid BadBlock handling
9815 //flags |= ATA_CMD_FLAG_LBAIOsupp;
9816 flags
|= ATA_CMD_FLAG_48
;
9818 case IDE_COMMAND_READ_NATIVE_SIZE
:
9819 case IDE_COMMAND_SET_NATIVE_SIZE
:
9821 flags
|= ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_FUA
;
9824 flags
|= ATA_CMD_FLAG_48supp
;
9827 case IDE_COMMAND_READ
:
9828 command
= IDE_COMMAND_READ48
; break;
9829 case IDE_COMMAND_READ_MULTIPLE
:
9830 command
= IDE_COMMAND_READ_MUL48
; break;
9831 case IDE_COMMAND_READ_DMA
:
9832 command
= IDE_COMMAND_READ_DMA48
; break;
9833 case IDE_COMMAND_READ_DMA_Q
:
9834 command
= IDE_COMMAND_READ_DMA_Q48
; break;
9835 case IDE_COMMAND_WRITE
:
9836 command
= IDE_COMMAND_WRITE48
; break;
9837 case IDE_COMMAND_WRITE_MULTIPLE
:
9838 command
= IDE_COMMAND_WRITE_MUL48
; break;
9839 case IDE_COMMAND_WRITE_DMA
:
9840 command
= IDE_COMMAND_WRITE_DMA48
; break;
9841 case IDE_COMMAND_WRITE_DMA_Q
:
9842 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
9843 case IDE_COMMAND_FLUSH_CACHE
:
9844 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
9845 // case IDE_COMMAND_READ_NATIVE_SIZE:
9846 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
9847 case IDE_COMMAND_SET_NATIVE_SIZE
:
9848 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
9849 case IDE_COMMAND_VERIFY
:
9850 command
= IDE_COMMAND_VERIFY48
; break;
9852 //KdPrint2((PRINT_PREFIX "!28->48 "));
9853 flags
&= ~ATA_CMD_FLAG_48supp
;
9857 case IDE_COMMAND_READ
:
9858 case IDE_COMMAND_READ_MULTIPLE
:
9859 case IDE_COMMAND_READ_DMA48
:
9860 case IDE_COMMAND_READ_DMA_Q48
:
9861 case IDE_COMMAND_READ_STREAM_DMA48
:
9862 case IDE_COMMAND_READ_STREAM48
:
9863 case IDE_COMMAND_READ_DMA_Q
:
9864 case IDE_COMMAND_READ_DMA
:
9865 case IDE_COMMAND_READ_LOG_DMA48
:
9866 case IDE_COMMAND_TRUSTED_RCV_DMA
:
9867 case IDE_COMMAND_IDENTIFY
:
9868 case IDE_COMMAND_ATAPI_IDENTIFY
:
9869 //KdPrint2((PRINT_PREFIX "RD "));
9870 flags
|= ATA_CMD_FLAG_In
;
9872 case IDE_COMMAND_WRITE
:
9873 case IDE_COMMAND_WRITE_MULTIPLE
:
9874 case IDE_COMMAND_WRITE_DMA48
:
9875 case IDE_COMMAND_WRITE_DMA_Q48
:
9876 case IDE_COMMAND_WRITE_DMA
:
9877 case IDE_COMMAND_WRITE_DMA_Q
:
9878 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9879 case IDE_COMMAND_WRITE_STREAM48
:
9880 case IDE_COMMAND_WRITE_FUA_DMA48
:
9881 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9882 //KdPrint2((PRINT_PREFIX "WR "));
9883 flags
|= ATA_CMD_FLAG_Out
;
9887 //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
9888 AtaCommands48
[i
] = command
;
9889 AtaCommandFlags
[i
] = flags
;
9891 } // end UniataInitAtaCommands()
9895 Routine Description:
9897 Installable driver initialization entry point for system.
9905 Status from ScsiPortInitialize()
9912 IN PVOID DriverObject
,
9916 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
9919 ULONG statusToReturn
, newStatus
;
9920 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
9921 BOOLEAN ReEnter
= FALSE
;
9923 #ifndef USE_REACTOS_DDK
9927 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
9928 BOOLEAN PrimaryClaimed
= FALSE
;
9929 BOOLEAN SecondaryClaimed
= FALSE
;
9931 LARGE_INTEGER t0
, t1
;
9934 KdPrint2((PRINT_PREFIX
"%s", (PCCHAR
)ver_string
));
9935 //a = (WCHAR)strlen(ver_string);
9937 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
9939 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
9942 if(!SavedDriverObject
) {
9943 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
9944 #ifdef USE_REACTOS_DDK
9945 KdPrint(("UniATA Init: OS should be ReactOS\n"));
9950 // we are here for the 1st time
9951 // init CrossNT and get OS version
9952 if(!NT_SUCCESS(status
= CrNtInit(SavedDriverObject
, RegistryPath
))) {
9953 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status
));
9954 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
9957 #endif // USE_REACTOS_DDK
9958 KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion
, MinorVersion
, BuildNumber
, KeNumberProcessors
));
9960 KeQuerySystemTime(&t0
);
9962 KeQuerySystemTime(&t1
);
9963 } while(t0
.QuadPart
== t1
.QuadPart
);
9967 KeQuerySystemTime(&t1
);
9969 } while(t0
.QuadPart
== t1
.QuadPart
);
9970 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
9971 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
9973 KdPrint(("UniATA Init: ReEnter\n"));
9977 // (re)read bad block list
9978 InitBadBlocks(NULL
);
9981 // init ATA command translation table
9982 UniataInitAtaCommands();
9983 // get registry path to settings
9984 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
9985 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
9986 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
9987 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
9988 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
9989 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
9992 if(WinVer_Id() >= WinVer_2k
) {
9993 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
9994 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
9995 WinVer_WDM_Model
= TRUE
;
9997 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
9998 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
9999 WinVer_WDM_Model
= TRUE
;
10003 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
10004 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
10006 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
10009 statusToReturn
= 0xffffffff;
10011 // Zero out structure.
10012 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
10014 // Set size of hwInitializationData.
10015 hwInitializationData
.comm
.HwInitializationDataSize
=
10016 sizeof(hwInitializationData
.comm
) +
10017 // sizeof(hwInitializationData.nt4) +
10018 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
10019 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
10021 // Set entry points.
10022 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
10023 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
10024 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
10025 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
10027 // Specify size of extensions.
10028 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
10029 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
10030 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
10032 // Indicate PIO device.
10033 hwInitializationData
.comm
.MapBuffers
= TRUE
;
10034 // Set PnP-specific API
10035 if(WinVer_Id() > WinVer_NT
) {
10036 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
10037 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
10038 KdPrint(("set AtapiAdapterControl() ptr\n"));
10039 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
10042 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE enum supported BusMaster Devices\n"));
10046 g_opt_VirtualMachine
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualMachineType", g_opt_VirtualMachine
);
10047 if(g_opt_VirtualMachine
> VM_MAX_KNOWN
) {
10048 g_opt_VirtualMachine
= 0;
10050 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualBox", (g_opt_VirtualMachine
== VM_VBOX
))) {
10051 g_opt_VirtualMachine
= VM_VBOX
;
10053 // Pre-scan PCI bus, also check if we are under VM
10054 UniataEnumBusMasterController(DriverObject
, Argument2
);
10056 switch(g_opt_VirtualMachine
) {
10058 KdPrint2((PRINT_PREFIX
"adjust options for VirtualBox\n"));
10059 // adjust options for VirtualBox
10060 g_opt_WaitBusyCount
= 20000;
10061 g_opt_WaitBusyDelay
= 150;
10062 g_opt_WaitDrqDelay
= 100;
10063 g_opt_WaitBusyLongCount
= 20000;
10064 g_opt_MaxIsrWait
= 200;
10065 g_opt_AtapiSendDisableIntr
= 0;
10066 g_opt_AtapiDmaRawRead
= FALSE
;
10071 KdPrint2((PRINT_PREFIX
"old slow machine, adjust timings\n"));
10072 // old slow machine, adjust timings
10073 g_opt_WaitBusyCount
= 20000;
10074 g_opt_WaitBusyDelay
= 150;
10075 g_opt_WaitDrqDelay
= 100;
10076 g_opt_WaitBusyLongCount
= 20000;
10077 g_opt_MaxIsrWait
= 200;
10080 g_opt_WaitBusyCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyCount", g_opt_WaitBusyCount
); // 200 vs 20000
10081 g_opt_WaitBusyDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyDelay", g_opt_WaitBusyDelay
); // 10 vs 150
10082 g_opt_WaitDrqDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitDrqDelay", g_opt_WaitDrqDelay
); // 10 vs 100
10083 g_opt_WaitBusyLongCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongCount", g_opt_WaitBusyLongCount
); // 2000 vs 20000
10084 g_opt_WaitBusyLongDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongDelay", g_opt_WaitBusyLongDelay
); // 250 vs 250
10085 g_opt_AtapiSendDisableIntr
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr
); // 1 vs 0
10086 g_opt_AtapiDmaRawRead
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiDmaRawRead", g_opt_AtapiDmaRawRead
); // 1 vs 0
10087 g_opt_MaxIsrWait
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"MaxIsrWait", g_opt_MaxIsrWait
); // 40 vs xxx
10090 // Look for legacy ISA-bridged PCI IDE controller (onboard)
10091 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
10092 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
10093 for (i
=0; i
<BMListLen
; i
++) {
10095 if(!BMList
[i
].MasterDev
) {
10096 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
10099 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10103 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
10104 if(BMList
[i
].ChanInitOk
& 0x03) {
10105 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
10107 newStatus
= STATUS_SUCCESS
;
10111 //BMList[i].AltInitMasterDev = (UCHAR)0xff;
10113 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
10114 PrimaryClaimed
= TRUE
;
10115 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
10116 SecondaryClaimed
= TRUE
;
10118 if(!WinVer_WDM_Model
&& !PrimaryClaimed
&& !SecondaryClaimed
&&
10119 !(BMList
[i
].ChanInitOk
& 0x80)) {
10120 newStatus
= UniataClaimLegacyPCIIDE(i
);
10121 if(newStatus
!= STATUS_SUCCESS
) {
10122 KdPrint2((PRINT_PREFIX
"Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
10127 if(g_opt_Verbose
) {
10128 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
10132 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
10134 for(c
=0; c
<2; c
++) {
10136 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10140 if(PrimaryClaimed
) {
10141 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
10146 if(SecondaryClaimed
) {
10147 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
10152 if((WinVer_Id() < WinVer_2k
)) {
10153 // do not even try if already claimed
10155 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
10158 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
10161 if(!WinVer_WDM_Model
) {
10162 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10164 // in WDM model things are different....
10165 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
10166 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
10168 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10169 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10171 if(!WinVer_WDM_Model
) {
10172 BMList
[i
].channel
= (UCHAR
)c
;
10175 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
10176 newStatus
= ScsiPortInitialize(DriverObject
,
10178 &hwInitializationData
.comm
,
10179 (PVOID
)(i
| (alt
? 0x80000000 : 0)));
10180 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10181 if (newStatus
< statusToReturn
) {
10182 statusToReturn
= newStatus
;
10184 if (newStatus
== STATUS_SUCCESS
) {
10185 if(WinVer_Id() < WinVer_2k
) {
10186 // This should be done in HwInitialize under w2k+ to ensure that
10187 // channel is actually initialized
10188 BMList
[i
].ChanInitOk
|= 0x01 << c
;
10190 if(BMList
[i
].ChanInitOk
& (0x01 << c
)) {
10191 KdPrint2((PRINT_PREFIX
"HwInit passed\n"));
10195 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
10196 c = 1; // this will break our for()
10197 BMList[i].ChanInitOk |= 0x01 << c;
10202 /* if(WinVer_Id() >= WinVer_2k) {
10203 // the following didn't work under higher OSes,
10204 // until we move setting of FLAGS to HwInit
10205 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
10208 if(BMList
[i
].ChanInitOk
& 0x03) {
10209 // Under NT we receive status immediately, so
10210 // we can omit alternative init method if STATUS_SUCCESS returned.
10211 // Under w2k+ we relay on flags, set in HwInitialize.
10212 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
10215 if(WinVer_Id() >= WinVer_2k
) {
10216 // try AltInit if HwInit was not called immediately under w2k+
10217 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10219 // if (WinVer_Id() == WinVer_NT) and some error occured
10220 // try alternative init method
10221 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10224 if(g_opt_Verbose
) {
10225 if(BMList
[i
].ChanInitOk
& 0x03) {
10226 _PrintNtConsole(" OK\n");
10228 _PrintNtConsole(" failed\n");
10234 /* KeBugCheckEx(0xc000000e,
10235 (i << 16) | BMList[0].ChanInitOk,
10237 newStatus, statusToReturn);*/
10239 // Look for PCI IDE controller
10240 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
10241 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
10242 for (; i
<BMListLen
; i
++) {
10244 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", 0)) {
10247 /* if(BMList[i].MasterDev)
10249 if(g_opt_Verbose
) {
10250 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
10251 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
10252 BMList
[i
].busNumber
,
10253 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
10254 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
10257 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10258 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10259 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
10261 hwInitializationData
.comm
.VendorId
= (PVOID
)BMList
[i
].VendorId
;
10262 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
10263 hwInitializationData
.comm
.DeviceId
= (PVOID
)BMList
[i
].DeviceId
;
10264 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
10266 BMList
[i
].channel
= 0/*(UCHAR)c*/;
10268 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
10269 hwInitializationData
.comm
.VendorId
,
10270 hwInitializationData
.comm
.DeviceId
));
10271 newStatus
= ScsiPortInitialize(DriverObject
,
10273 &hwInitializationData
.comm
,
10275 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10276 if(newStatus
== (ULONG
)STATUS_DEVICE_DOES_NOT_EXIST
&& BMList
[i
].NeedAltInit
) {
10277 // Note: this is actually a BUG in scsiport.sys
10278 // It stops scanning PCI bus when reaches empty PCI Function inside Slot
10279 // However, this PCI Slot may have higher non-empty Functions
10280 // UniATA will perform all staff instead of ScsiPort under NT,
10281 // but for ReactOS it is better to patch ScsiPort.
10282 KdPrint2((PRINT_PREFIX
"STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
10283 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10284 newStatus
= ScsiPortInitialize(DriverObject
,
10286 &hwInitializationData
.comm
,
10287 (PVOID
)(i
| 0x80000000));
10288 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x (2)\n", newStatus
));
10290 if (newStatus
< statusToReturn
)
10291 statusToReturn
= newStatus
;
10293 if(g_opt_Verbose
) {
10294 if(newStatus
== STATUS_SUCCESS
) {
10295 _PrintNtConsole(" OK\n");
10297 _PrintNtConsole(" failed\n");
10303 /* KeBugCheckEx(0xc000000e,
10306 newStatus, statusToReturn);*/
10310 hwInitializationData
.comm
.VendorId
= 0;
10311 hwInitializationData
.comm
.VendorIdLength
= 0;
10312 hwInitializationData
.comm
.DeviceId
= 0;
10313 hwInitializationData
.comm
.DeviceIdLength
= 0;
10316 hwInitializationData
.comm
.SrbExtensionSize
= //FIELD_OFFSET(ATA_REQ, ata);
10318 KdPrint2((PRINT_PREFIX
"using AtaReq sz %x\n", hwInitializationData
.comm
.SrbExtensionSize
));
10321 // The adapter count is used by the find adapter routine to track how
10322 // which adapter addresses have been tested.
10324 // Indicate 2 access ranges and reset FindAdapter.
10325 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
10326 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindController
;
10328 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
10329 // Indicate ISA bustype.
10330 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10333 // Call initialization for ISA bustype.
10334 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
10335 newStatus
= ScsiPortInitialize(DriverObject
,
10337 &hwInitializationData
.comm
,
10339 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10340 if (newStatus
< statusToReturn
)
10341 statusToReturn
= newStatus
;
10343 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
10345 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
10346 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
10349 newStatus
= ScsiPortInitialize(DriverObject
,
10351 &hwInitializationData
.comm
,
10353 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10354 if (newStatus
< statusToReturn
)
10355 statusToReturn
= newStatus
;
10357 InDriverEntry
= FALSE
;
10359 KdPrint2((PRINT_PREFIX
"\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn
));
10361 return statusToReturn
;
10363 } // end DriverEntry()
10366 PSCSI_REQUEST_BLOCK
10368 BuildMechanismStatusSrb(
10369 IN PVOID HwDeviceExtension
,
10370 IN PSCSI_REQUEST_BLOCK Srb
10373 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10374 PSCSI_REQUEST_BLOCK srb
;
10376 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10378 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10380 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10382 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10383 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10384 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10385 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10387 // Set flags to disable synchronous negociation.
10388 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10390 // Set timeout to 4 seconds.
10391 srb
->TimeOutValue
= 4;
10393 srb
->CdbLength
= 6;
10394 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
10395 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10396 srb
->SrbExtension
= AtaReq
;
10398 // Set CDB operation code.
10399 cdb
= (PCDB
)srb
->Cdb
;
10400 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
10401 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10403 KdPrint2((PRINT_PREFIX
" MechanismStatusSrb %#x\n", srb
));
10406 } // end BuildMechanismStatusSrb()
10408 #endif //UNIATA_CORE
10410 PSCSI_REQUEST_BLOCK
10412 BuildRequestSenseSrb (
10413 IN PVOID HwDeviceExtension
,
10414 IN PSCSI_REQUEST_BLOCK Srb
10417 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10418 PSCSI_REQUEST_BLOCK srb
;
10420 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10422 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10424 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10426 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10427 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10428 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10429 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10431 // Set flags to disable synchronous negociation.
10432 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10434 // Set timeout to 2 seconds.
10435 srb
->TimeOutValue
= 4;
10437 srb
->CdbLength
= 6;
10438 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
10439 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
10440 srb
->SrbExtension
= AtaReq
;
10442 // Set CDB operation code.
10443 cdb
= (PCDB
)srb
->Cdb
;
10444 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
10445 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
10447 KdPrint2((PRINT_PREFIX
" RequestSenseSrb %#x\n", srb
));
10450 } // end BuildRequestSenseSrb()
10452 #ifndef UNIATA_CORE
10456 AtapiRegCheckDevLunValue(
10457 IN PVOID HwDeviceExtension
,
10458 IN PCWCH NamePrefix
,
10466 ULONG val
= Default
;
10468 val
= AtapiRegCheckParameterValue(
10469 HwDeviceExtension
, NamePrefix
, Name
, val
);
10471 if(chan
!= CHAN_NOT_SPECIFIED
) {
10472 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
10473 val
= AtapiRegCheckParameterValue(
10474 HwDeviceExtension
, namex
, Name
, val
);
10475 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
10476 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
10477 val
= AtapiRegCheckParameterValue(
10478 HwDeviceExtension
, namex
, Name
, val
);
10482 } // end AtapiRegCheckDevLunValue()
10495 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
10514 swprintf(Buffer
+j
, L
"%2.2x", a
);
10522 } // end EncodeVendorStr()
10526 AtapiRegCheckDevValue(
10527 IN PVOID HwDeviceExtension
,
10534 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10535 // WCHAR name0[11];
10536 // WCHAR name1[11+4+5];
10537 // WCHAR name2[11+4+4+10];
10538 // WCHAR name3[11+4+4+5+20];
10539 // WCHAR name3[11+4+4+5+20+1];
10548 IN ULONG SlotNumber
;
10550 ULONG val
= Default
;
10552 KdPrint(( " Parameter %ws\n", Name
));
10554 if(deviceExtension
) {
10555 VendorID
= deviceExtension
->DevID
& 0xffff;
10556 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
10557 SlotNumber
= deviceExtension
->slotNumber
;
10561 SlotNumber
= 0xffffffff;
10564 val
= AtapiRegCheckDevLunValue(
10565 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
10567 if(deviceExtension
) {
10568 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
10570 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
10571 swprintf(namex
, L
"Parameters%s", namev
);
10572 val
= AtapiRegCheckDevLunValue(
10573 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10576 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
10577 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
10578 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
10580 swprintf(namex
, L
"Parameters%s", namev
);
10581 val
= AtapiRegCheckDevLunValue(
10582 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10584 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
10585 val
= AtapiRegCheckDevLunValue(
10586 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10588 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
10589 val
= AtapiRegCheckDevLunValue(
10590 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10592 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
10594 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
10595 swprintf(namex
, L
"Parameters%s", namev
);
10596 val
= AtapiRegCheckDevLunValue(
10597 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10599 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
10600 swprintf(namex
, L
"Parameters%s", namev
);
10601 val
= AtapiRegCheckDevLunValue(
10602 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10605 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
10607 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
10608 swprintf(namex
, L
"Parameters%s", namev
);
10609 val
= AtapiRegCheckDevLunValue(
10610 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10612 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
10613 swprintf(namex
, L
"Parameters%s", namev
);
10614 val
= AtapiRegCheckDevLunValue(
10615 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10620 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
10623 } // end AtapiRegCheckDevValue()
10626 The user must specify that Xxx is to run on the platform
10627 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
10628 Services\UniATA\Xxx:REG_DWORD:Zzz.
10630 The user can override the global setting to enable or disable Xxx on a
10631 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
10632 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
10634 If this registry value does not exist or contains the value zero then
10635 the timer to check for media change does not run.
10639 RegistryPath - pointer to the unicode string inside
10640 ...\CurrentControlSet\Services\UniATA
10641 DeviceNumber - The number of the HBA device object
10643 Returns: Registry Key value
10647 AtapiRegCheckParameterValue(
10648 IN PVOID HwDeviceExtension
,
10649 IN PCWSTR PathSuffix
,
10654 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
10656 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10658 LONG zero
= Default
;
10660 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
10663 LONG doRun
= Default
;
10665 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
10667 UNICODE_STRING paramPath
;
10669 // <SavedRegPath>\<PathSuffix> -> <Name>
10670 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
10671 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
10673 paramPath
.Length
= 0;
10674 paramPath
.MaximumLength
= (USHORT
)(RegistryPath
->Length
+
10675 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
));
10676 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
10677 if(!paramPath
.Buffer
) {
10678 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
10682 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
10683 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
10684 RtlAppendUnicodeToString(¶mPath
, L
"\\");
10685 RtlAppendUnicodeToString(¶mPath
, REGRTL_STR_PTYPE PathSuffix
);
10687 // Check for the Xxx value.
10688 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
10690 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
10691 parameters
[0].Name
= REGRTL_STR_PTYPE Name
;
10692 parameters
[0].EntryContext
= &doRun
;
10693 parameters
[0].DefaultType
= REG_DWORD
;
10694 parameters
[0].DefaultData
= &zero
;
10695 parameters
[0].DefaultLength
= sizeof(ULONG
);
10697 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
10698 paramPath
.Buffer
, parameters
, NULL
, NULL
);
10699 if(NT_SUCCESS(status
)) {
10700 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix
, Name
, doRun
));
10703 ExFreePool(paramPath
.Buffer
);
10705 if(!NT_SUCCESS(status
)) {
10711 #undef ITEMS_TO_QUERY
10713 } // end AtapiRegCheckParameterValue()
10716 SCSI_ADAPTER_CONTROL_STATUS
10718 AtapiAdapterControl(
10719 IN PVOID HwDeviceExtension
,
10720 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
10721 IN PVOID Parameters
10724 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10725 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
10726 ULONG numberChannels
= deviceExtension
->NumberChannels
;
10730 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
10732 switch(ControlType
) {
10733 case ScsiQuerySupportedControlTypes
: {
10734 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
10735 TRUE
, // ScsiQuerySupportedControlTypes
10736 TRUE
, // ScsiStopAdapter
10737 TRUE
, // ScsiRestartAdapter
10738 FALSE
, // ScsiSetBootConfig
10739 FALSE
// ScsiSetRunningConfig
10742 ULONG lim
= ScsiAdapterControlMax
;
10745 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
10747 if(pControlTypeList
->MaxControlType
< lim
) {
10748 lim
= pControlTypeList
->MaxControlType
;
10751 for(i
= 0; i
< lim
; i
++) {
10752 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
10758 case ScsiStopAdapter
: {
10760 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
10761 // Shut down all interrupts on the adapter. They'll get re-enabled
10762 // by the initialization routines.
10763 for (c
= 0; c
< numberChannels
; c
++) {
10764 AtapiResetController(deviceExtension
, c
);
10765 AtapiDisableInterrupts(deviceExtension
, c
);
10767 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
10768 // we must never get here for non-PCI
10769 /*status =*/ UniataDisconnectIntr2(HwDeviceExtension
);
10770 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
10774 case ScsiRestartAdapter
: {
10776 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
10777 // Enable all the interrupts on the adapter while port driver call
10778 // for power up an HBA that was shut down for power management
10780 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
10781 status
= UniataConnectIntr2(HwDeviceExtension
);
10782 if(NT_SUCCESS(status
)) {
10783 for (c
= 0; c
< numberChannels
; c
++) {
10784 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
10785 FindDevices(HwDeviceExtension
, 0, c
);
10786 AtapiEnableInterrupts(deviceExtension
, c
);
10787 AtapiHwInitialize__(deviceExtension
, c
);
10789 if(deviceExtension
->Isr2DevObj
) {
10790 // we must never get here for non-PCI
10791 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
10799 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
10800 return ScsiAdapterControlUnsuccessful
;
10804 return ScsiAdapterControlSuccess
;
10805 } // end AtapiAdapterControl()
10807 #endif //UNIATA_CORE
10817 #define DEBUG_MSG_BUFFER_SIZE 512
10828 UCHAR dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
];
10829 // UNICODE_STRING msgBuff;
10831 va_start(ap
, DebugMessage
);
10833 /*len =*/ _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], DEBUG_MSG_BUFFER_SIZE
-1, DebugMessage
, ap
);
10835 dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
-1] = 0;
10837 //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro
10838 HalDisplayString(dbg_print_tmp_buff
);
10841 if(g_LogToDisplay
> 1) {
10842 AtapiStallExecution(g_LogToDisplay
*1000);
10848 } // end PrintNtConsole()