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;
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
, statusByte2
);
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
, statusByte2
);
1440 SelectDrive(chan
, DeviceNumber
);
1442 GetBaseStatus(chan
, statusByte2
);
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
;
4539 BOOLEAN DmaTransfer
= FALSE
;
4541 ULONG TimerValue
= 1000;
4542 ULONG TotalTimerValue
= 0;
4543 #ifdef UNIATA_USE_XXableInterrupts
4544 BOOLEAN InDpc
= (KeGetCurrentIrql() == DISPATCH_LEVEL
);
4546 BOOLEAN InDpc
= (chan
->DpcState
!= DPC_STATE_ISR
);
4547 #endif // UNIATA_USE_XXableInterrupts
4548 BOOLEAN UseDpc
= deviceExtension
->UseDpc
;
4549 // BOOLEAN RestoreUseDpc = FALSE;
4550 BOOLEAN DataOverrun
= FALSE
;
4551 BOOLEAN NoStartIo
= TRUE
;
4553 KdPrint2((PRINT_PREFIX
"AtapiInterrupt:\n"));
4555 KdPrint2((PRINT_PREFIX
" InDpc = TRUE\n"));
4556 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
4562 UCHAR OldReqState
= REQ_STATE_NONE
;
4564 PHW_LU_EXTENSION LunExt
;
4567 Channel
= (UCHAR
)(deviceExtension
->Channel
+ lChannel
);
4569 KdPrint2((PRINT_PREFIX
" cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension
->DevIndex
, Channel
, KeGetCurrentIrql(), c
));
4571 if((chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) ||
4572 (AtaReq
&& (AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
)) ||
4573 (deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
4575 KdPrint2((PRINT_PREFIX
" DmaTransfer = TRUE\n"));
4579 PathId
= srb
->PathId
;
4580 TargetId
= srb
->TargetId
;
4586 goto enqueue_next_req
;
4589 //ldev = GET_LDEV2(PathId, TargetId, Lun);
4590 DeviceNumber
= (UCHAR
)(TargetId
);
4591 LunExt
= chan
->lun
[DeviceNumber
];
4592 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
4593 KdPrint2((PRINT_PREFIX
" dev_type %s\n", atapiDev
? "ATAPI" : "IDE"));
4595 // check if we are in ISR DPC
4597 KdPrint2((PRINT_PREFIX
" InDpc -> CTRFLAGS_INTR_DISABLED\n"));
4598 goto ServiceInterrupt
;
4602 dma_status
= GetDmaStatus(deviceExtension
, lChannel
);
4605 if (!(chan
->ExpectingInterrupt
)) {
4607 KdPrint2((PRINT_PREFIX
" Unexpected interrupt for this channel.\n"));
4611 // change request state
4613 OldReqState
= AtaReq
->ReqState
;
4614 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4615 KdPrint2((PRINT_PREFIX
" OldReqState = %x\n", OldReqState
));
4618 // We don't want using DPC for fast operations, like
4619 // DMA completion, sending CDB, short ATAPI transfers, etc.
4621 // We MUST use DPC, because of interprocessor synchronization
4622 // on multiprocessor platforms
4625 goto ServiceInterrupt
;
4627 switch(OldReqState
) {
4628 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR
:
4629 KdPrint3((PRINT_PREFIX
" EXPECTING_CMD_INTR\n"));
4630 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR
:
4631 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
:
4632 case REQ_STATE_DPC_WAIT_BUSY0
:
4633 case REQ_STATE_DPC_WAIT_BUSY1
:
4634 KdPrint2((PRINT_PREFIX
" continue service interrupt\n"));
4635 goto ServiceInterrupt
;
4636 case REQ_STATE_ATAPI_DO_NOTHING_INTR
:
4637 KdPrint2((PRINT_PREFIX
" do nothing on interrupt\n"));
4641 if(!DmaTransfer
&& !atapiDev
) {
4642 KdPrint2((PRINT_PREFIX
" service PIO HDD\n"));
4649 goto ServiceInterrupt
;
4651 #ifdef UNIATA_USE_XXableInterrupts
4653 KdPrint2((PRINT_PREFIX
" Unexpected InDpc\n"));
4655 // shall never get here
4660 KdPrint2((PRINT_PREFIX
" this is direct DPC call on DRQL\n"));
4662 AtaReq
->ReqState
= REQ_STATE_DPC_INTR_REQ
;
4663 KdPrint2((PRINT_PREFIX
" ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
4665 KdPrint2((PRINT_PREFIX
" DPC without AtaReq!!!\n"));
4668 KdPrint2((PRINT_PREFIX
"call service interrupt\n"));
4669 goto ServiceInterrupt
;
4670 #endif // UNIATA_USE_XXableInterrupts
4675 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
4676 // We always get here when are called from timer callback, which is invoked on DRQL.
4677 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
4679 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: start DPC init...\n"));
4680 // disable interrupts for this channel,
4681 // but avoid recursion and double-disable
4682 if(OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4683 UniataExpectChannelInterrupt(chan
, FALSE
);
4684 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4687 chan
->ChannelCtrlFlags
|= CTRFLAGS_DPC_REQ
;
4689 #ifdef UNIATA_USE_XXableInterrupts
4690 // Will lower IRQL to DISPATCH_LEVEL
4691 ScsiPortNotification(CallEnableInterrupts
, HwDeviceExtension
,
4692 /*c ?*/ AtapiInterruptDpc
/*_1 : AtapiInterruptDpc_0*/);
4693 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DPC inited\n"));
4695 // Will raise IRQL to DIRQL
4696 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4699 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
4700 #endif // UNIATA_USE_XXableInterrupts
4705 AtaReq
->ReqState
= REQ_STATE_PROCESSING_INTR
;
4707 if(!InDpc
&& OldReqState
!= REQ_STATE_DPC_WAIT_BUSY1
) {
4708 // we must block interrupts from this channel
4709 // If device generate new interrupt before we get to DPC,
4710 // ISR will assume, that it is NOT our interrupt
4711 AtapiDisableInterrupts(deviceExtension
, lChannel
);
4712 // We should not clean ExpectingInterrupt flag on channel, since it is used in DPC
4714 // Will raise IRQL to DIRQL
4715 AtapiQueueTimerDpc(HwDeviceExtension
, c
,
4719 #endif //UNIATA_CORE
4723 if(AtaReq
&& InDpc
) {
4724 switch(AtaReq
->ReqState
) {
4725 case REQ_STATE_DPC_WAIT_DRQ0
:
4727 case REQ_STATE_DPC_WAIT_BUSY
:
4729 case REQ_STATE_DPC_WAIT_DRQ
:
4731 case REQ_STATE_DPC_WAIT_DRQ_ERR
:
4733 case REQ_STATE_DPC_WAIT_BUSY0
:
4734 case REQ_STATE_DPC_WAIT_BUSY1
:
4735 // continue normal execution
4741 #endif //UNIATA_CORE
4743 // make additional delay for old devices (if we are not in DPC)
4744 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
4748 !(deviceExtension->HwFlags & UNIATA_SATA)
4750 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
4751 AtapiStallExecution(10);
4755 /* clear interrupt and get status */
4756 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4757 UniataAhciEndTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, srb
);
4758 statusByte
= (UCHAR
)(AtaReq
->ahci
.in_status
& IDE_STATUS_MASK
);
4760 if(chan
->AhciLastIS
& ~(ATA_AHCI_P_IX_DHR
| ATA_AHCI_P_IX_PS
| ATA_AHCI_P_IX_DS
| ATA_AHCI_P_IX_SDB
)) {
4761 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
)));
4762 if(chan
->AhciLastIS
& ~ATA_AHCI_P_IX_OF
) {
4763 //KdPrint3((PRINT_PREFIX "Err mask (%#x)\n", chan->AhciLastIS & ~ATA_AHCI_P_IX_OF));
4764 // We have some other error except Overflow
4765 // Just signal ERROR, operation will be aborted in ERROR branch.
4766 statusByte
|= IDE_STATUS_ERROR
;
4768 // We have only Overflow. Abort operation and continue
4770 UniataDumpAhciPortRegs(chan
);
4772 if(!UniataAhciAbortOperation(chan
)) {
4773 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
4776 UniataDumpAhciPortRegs(chan
);
4778 UniataAhciWaitCommandReady(chan
, 10);
4783 GetBaseStatus(chan
, statusByte
);
4786 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte
));
4788 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Entered with status (%#x)\n", statusByte
));
4792 KdPrint2((PRINT_PREFIX
" operate like in DPC\n"));
4798 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4799 KdPrint3((PRINT_PREFIX
" AHCI branch (IDE)\n"));
4801 if (statusByte
& IDE_STATUS_BUSY
) {
4802 if (deviceExtension
->DriverMustPoll
) {
4803 // Crashdump is polling and we got caught with busy asserted.
4804 // Just go away, and we will be polled again shortly.
4805 KdPrint2((PRINT_PREFIX
" Hit BUSY while polling during crashdump.\n"));
4806 goto ReturnEnableIntr
;
4809 // Ensure BUSY is non-asserted.
4810 // make a very small idle before falling to DPC
4811 k
= (InDpc
&& UseDpc
) ? 1000 : 2;
4813 for (i
= 0; i
< k
; i
++) {
4815 GetBaseStatus(chan
, statusByte
);
4816 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4819 AtapiStallExecution(10);
4822 if (!InDpc
&& UseDpc
&& i
== 2) {
4824 KdPrint2((PRINT_PREFIX
" BUSY on entry. Status %#x, Base IO %#x\n", statusByte
));
4827 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4832 AtapiStallExecution(TimerValue
);
4833 goto ServiceInterrupt
;
4834 #endif //UNIATA_CORE
4836 if (InDpc
&& i
== k
) {
4837 // reset the controller.
4838 KdPrint2((PRINT_PREFIX
4839 " Resetting due to BUSY on entry - %#x.\n",
4841 goto IntrPrepareResetController
;
4846 if(!LunExt
->IdentifyData
.MajorRevision
&&
4849 !(deviceExtension
->HwFlags
& UNIATA_SATA
)
4851 //KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n"));
4852 //AtapiStallExecution(10);
4854 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4855 KdPrint3((PRINT_PREFIX
" AHCI branch (ATAPI)\n"));
4857 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
4858 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
4861 if (statusByte
& IDE_STATUS_BUSY
) {
4862 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
4865 // This is just workaround
4866 // We should DISABLE interrupts before entering WAIT state
4867 UniataExpectChannelInterrupt(chan, TRUE);
4868 #endif //UNIATA_CORE
4870 KdPrint3((PRINT_PREFIX
" BUSY on ATAPI device, waiting %d us\n", LunExt
->AtapiReadyWaitDelay
));
4872 if(LunExt
->AtapiReadyWaitDelay
&& (LunExt
->AtapiReadyWaitDelay
> g_opt_MaxIsrWait
) && !InDpc
&& UseDpc
) {
4873 TimerValue
= LunExt
->AtapiReadyWaitDelay
;
4874 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC (0)\n"));
4875 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4878 #endif //UNIATA_CORE
4881 GetBaseStatus(chan
, statusByte
);
4882 KdPrint3((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
4883 KdPrint3((PRINT_PREFIX
" Error reg (%#x)\n",
4884 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Error
)));
4885 if (!(statusByte
& IDE_STATUS_BUSY
)) {
4886 KdPrint2((PRINT_PREFIX
" expecting intr + cleared BUSY\n"));
4889 TotalTimerValue
+= TimerValue
;
4891 KdPrint3((PRINT_PREFIX
" too long wait -> DPC\n"));
4893 KdPrint2((PRINT_PREFIX
" too long wait: ISR -> DPC\n"));
4895 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY0
;
4897 KdPrint2((PRINT_PREFIX
" too long wait: DPC -> DPC\n"));
4899 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY1
;
4903 if(!LunExt
->AtapiReadyWaitDelay
) {
4904 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
4908 #endif //UNIATA_CORE
4911 AtapiStallExecution(TimerValue
);
4914 if(!LunExt
->AtapiReadyWaitDelay
) {
4915 LunExt
->AtapiReadyWaitDelay
= TotalTimerValue
*2/3;
4916 KdPrint2((PRINT_PREFIX
" store AtapiReadyWaitDelay: %d\n", LunExt
->AtapiReadyWaitDelay
));
4918 if (statusByte
& IDE_STATUS_BUSY
) {
4919 KdPrint3((PRINT_PREFIX
" expecting intr + BUSY (2), try DPC wait\n"));
4925 if(AtaReq
&& DmaTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_AHCI
)) {
4926 switch(OldReqState
) {
4927 case REQ_STATE_EARLY_INTR
:
4928 case REQ_STATE_DPC_WAIT_BUSY0
:
4930 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_ACTIVE
) {
4931 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DMA still active\n"));
4932 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
4939 // Check for error conditions.
4940 if ((statusByte
& IDE_STATUS_ERROR
) ||
4941 (dma_status
& BM_STATUS_ERR
)) {
4943 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
4944 error
= AtaReq
->ahci
.in_error
;
4947 UniataDumpAhciPortRegs(chan
);
4949 if(!UniataAhciAbortOperation(chan
)) {
4950 KdPrint2((PRINT_PREFIX
"need UniataAhciReset\n"));
4952 // clear interrupts again
4953 UniataAhciWaitCommandReady(chan
, 10);
4955 UniataDumpAhciPortRegs(chan
);
4957 UniataAhciStatus(HwDeviceExtension
, lChannel
, DEVNUM_NOT_SPECIFIED
);
4959 UniataDumpAhciPortRegs(chan
);
4962 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
4964 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Error %#x\n", error
));
4966 if(error & IDE_STATUS_CORRECTED_ERROR) {
4967 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
4968 statusByte &= ~IDE_STATUS_ERROR;
4973 KdPrint2((PRINT_PREFIX
" Bad Lba %#I64x\n", AtaReq
->lba
));
4975 KdPrint2((PRINT_PREFIX
" Bad Lba unknown\n"));
4980 KdPrint2((PRINT_PREFIX
" wait 100 ready after IDE error\n"));
4981 AtapiStallExecution(100);
4983 KdPrint2((PRINT_PREFIX
" wait 10 ready after ATAPI error\n"));
4984 AtapiStallExecution(10);
4988 KdPrint3((PRINT_PREFIX
" Intr on DRQ %x\n",
4989 LunExt
->DeviceFlags
& DFLAGS_INT_DRQ
));
4991 for (k
= atapiDev
? 0 : 200; k
; k
--) {
4992 GetBaseStatus(chan
, statusByte
);
4993 if (!(statusByte
& IDE_STATUS_DRQ
)) {
4994 AtapiStallExecution(50);
5001 /* if this is a UDMA CRC error, reinject request */
5004 if(AtaReq
->retry
< MAX_RETRIES
) {
5005 #ifdef IO_STATISTICS
5006 chan
->lun
[DeviceNumber
]->ModeErrorCount
[AtaReq
->retry
]++;
5007 #endif //IO_STATISTICS
5009 (error & IDE_ERROR_ICRC)*/) {
5010 if(AtaReq
->retry
< MAX_RETRIES
) {
5012 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5013 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5014 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5015 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5019 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5022 KdPrint2((PRINT_PREFIX
"Errors in PIO mode\n"));
5026 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5027 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason
));
5029 if(DmaTransfer
&& (chan
->lun
[DeviceNumber
]->TransferMode
> ATA_UDMA2
) &&
5030 ((error
>> 4) == SCSI_SENSE_HARDWARE_ERROR
)) {
5031 if(AtaReq
->retry
< MAX_RETRIES
) {
5033 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5034 AtaReq
->Flags
|= REQ_FLAG_FORCE_DOWNRATE
;
5035 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5036 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
5040 if(!(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
)) {
5043 KdPrint3((PRINT_PREFIX
"Errors in PIO mode\n"));
5047 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error\n"));
5048 if (srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
5049 // Fail this request.
5050 status
= SRB_STATUS_ERROR
;
5051 goto CompleteRequest
;
5053 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n"));
5056 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE_LBA48
) {
5057 KdPrint2((PRINT_PREFIX
"DMA doesn't work right with LBA48\n"));
5058 deviceExtension
->HbaCtrlFlags
|= HBAFLAGS_DMA_DISABLED_LBA48
;
5060 if(AtaReq
->Flags
& REQ_FLAG_FORCE_DOWNRATE
) {
5061 #ifdef IO_STATISTICS
5062 KdPrint2((PRINT_PREFIX
"Some higher mode doesn't work right :((\n"));
5063 KdPrint2((PRINT_PREFIX
"Recovery stats[%d]: %d vs %d\n",
5065 LunExt
->RecoverCount
[AtaReq
->retry
],
5066 LunExt
->BlockIoCount
5068 LunExt
->RecoverCount
[AtaReq
->retry
]++;
5069 if(LunExt
->RecoverCount
[AtaReq
->retry
] >= chan
->lun
[DeviceNumber
]->BlockIoCount
/3 ||
5070 (deviceExtension
->HwFlags
& UNIATA_NO80CHK
)
5073 if(deviceExtension
->HwFlags
& UNIATA_NO80CHK
) {
5074 #endif //IO_STATISTICS
5075 KdPrint2((PRINT_PREFIX
"Limit transfer rate to %x\n", LunExt
->TransferMode
));
5076 LunExt
->LimitedTransferMode
=
5077 LunExt
->TransferMode
;
5080 #ifdef IO_STATISTICS
5081 if(AtaReq
->bcount
) {
5082 // we need stats for Read/Write operations
5083 LunExt
->BlockIoCount
++;
5086 #endif //IO_STATISTICS
5090 // check reason for this interrupt.
5093 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ATAPI branch\n"));
5096 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
5097 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: iReason %x\n", interruptReason
));
5099 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5101 wordsThisInterrupt
= DEV_BSIZE
/2;
5109 // simulate DRQ for DMA transfers
5110 statusByte
|= IDE_STATUS_DRQ
;
5112 if (statusByte
& IDE_STATUS_DRQ
) {
5115 wordsThisInterrupt
= DEV_BSIZE
/2*512;
5117 if (LunExt
->MaximumBlockXfer
) {
5118 wordsThisInterrupt
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
5121 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5123 interruptReason
= ATAPI_IR_IO_toHost
;
5125 } else if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5126 interruptReason
= ATAPI_IR_IO_toDev
;
5129 status
= SRB_STATUS_ERROR
;
5130 goto CompleteRequest
;
5133 } else if (statusByte
& IDE_STATUS_BUSY
) {
5135 //AtapiEnableInterrupts(deviceExtension, lChannel);
5136 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
5141 if (AtaReq
->WordsLeft
) {
5143 // Funky behaviour seen with PCI IDE (not all, just one).
5145 // The ISR hits with DRQ low, but comes up later.
5146 for (k
= 0; k
< 5000; k
++) {
5147 GetBaseStatus(chan
, statusByte
);
5148 if (statusByte
& IDE_STATUS_DRQ
) {
5153 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ0
;
5155 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq0)\n"));
5159 AtapiStallExecution(TimerValue
);
5160 goto ServiceInterrupt
;
5161 #endif //UNIATA_CORE
5163 AtapiStallExecution(100);
5166 // reset the controller.
5167 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
5169 IntrPrepareResetController
:
5170 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
);
5171 goto ReturnEnableIntr
;
5174 interruptReason
= (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ? ATAPI_IR_IO_toHost
: ATAPI_IR_IO_toDev
;
5178 // Command complete - verify, write, or the SMART enable/disable.
5179 // Also get_media_status
5180 interruptReason
= ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
;
5185 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason
, statusByte
));
5186 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
5187 KdPrint2((PRINT_PREFIX
" AHCI path, WordsTransfered %x, WordsLeft %x\n", AtaReq
->WordsTransfered
, AtaReq
->WordsLeft
));
5188 /* if(chan->AhciLastIS & ATA_AHCI_P_IX_OF) {
5189 //status = SRB_STATUS_DATA_OVERRUN;
5192 status = SRB_STATUS_SUCCESS;
5194 if(AtaReq
->WordsTransfered
>= AtaReq
->WordsLeft
) {
5195 AtaReq
->WordsLeft
= 0;
5197 AtaReq
->WordsLeft
-= AtaReq
->WordsTransfered
;
5199 //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
5200 // status = SRB_STATUS_DATA_OVERRUN;
5202 status
= SRB_STATUS_SUCCESS
;
5203 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5204 goto CompleteRequest
;
5206 if (interruptReason
== ATAPI_IR_COD_Cmd
&& (statusByte
& IDE_STATUS_DRQ
)) {
5207 // Write the packet.
5208 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Writing Atapi packet.\n"));
5209 // Send CDB to device.
5210 WriteBuffer(chan
, (PUSHORT
)srb
->Cdb
,
5211 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
5213 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5215 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
5216 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: AtapiDmaStart().\n"));
5217 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, srb
);
5220 goto ReturnEnableIntr
;
5222 } else if (interruptReason
== ATAPI_IR_IO_toDev
&& (statusByte
& IDE_STATUS_DRQ
)) {
5227 // Pick up bytes to transfer and convert to words.
5229 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
);
5232 (USHORT
)AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8;
5234 // Covert bytes to words.
5236 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get W wordCount %#x\n", wordCount
));
5238 if (wordCount
!= AtaReq
->WordsLeft
) {
5239 KdPrint2((PRINT_PREFIX
5240 "AtapiInterrupt: %d words requested; %d words xferred\n",
5245 // Verify this makes sense.
5246 if (wordCount
> AtaReq
->WordsLeft
) {
5247 wordCount
= AtaReq
->WordsLeft
;
5248 KdPrint2((PRINT_PREFIX
5249 "AtapiInterrupt: Write underrun\n"));
5255 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
5256 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5257 // Transfer only words requested.
5258 wordCount
= AtaReq
->WordsLeft
;
5260 // Transfer next block.
5261 wordCount
= wordsThisInterrupt
;
5266 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5267 //ASSERT(AtaReq->WordsLeft == wordCount);
5268 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5269 KdPrint2((PRINT_PREFIX
5270 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5271 if(AtaReq
->WordsLeft
> wordCount
) {
5272 AtaReq
->WordsLeft
-= wordCount
;
5273 AtaReq
->WordsTransfered
+= wordCount
;
5274 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5275 goto ReturnEnableIntr
;
5277 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5279 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5280 AtaReq
->WordsLeft
= 0;
5281 status
= SRB_STATUS_SUCCESS
;
5282 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5283 goto CompleteRequest
;
5286 // Ensure that this is a write command.
5287 if (srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
5289 KdPrint2((PRINT_PREFIX
5290 "AtapiInterrupt: Write interrupt\n"));
5292 statusByte
= WaitOnBusy(chan
);
5294 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
5299 UniataGetPioTiming(LunExt
));
5303 (PULONG
)(AtaReq
->DataBuffer
),
5305 UniataGetPioTiming(LunExt
));
5309 KdPrint3((PRINT_PREFIX
5310 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5314 // Fail this request.
5315 status
= SRB_STATUS_ERROR
;
5316 goto CompleteRequest
;
5318 // Advance data buffer pointer and bytes left.
5319 AtaReq
->DataBuffer
+= wordCount
;
5320 AtaReq
->WordsLeft
-= wordCount
;
5321 AtaReq
->WordsTransfered
+= wordCount
;
5324 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5327 goto ReturnEnableIntr
;
5329 } else if (interruptReason
== ATAPI_IR_IO_toHost
&& (statusByte
& IDE_STATUS_DRQ
)) {
5334 // Pick up bytes to transfer and convert to words.
5336 AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountLow
) |
5337 (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8);
5339 // Convert bytes to words.
5341 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: get R wordCount %#x\n", wordCount
));
5343 if (wordCount
!= AtaReq
->WordsLeft
) {
5344 KdPrint2((PRINT_PREFIX
5345 "AtapiInterrupt: %d words requested; %d words xferred\n",
5350 // Verify this makes sense.
5351 if (wordCount
> AtaReq
->WordsLeft
) {
5352 wordCount
= AtaReq
->WordsLeft
;
5358 // Check if words left is at least 256.
5359 if (AtaReq
->WordsLeft
< wordsThisInterrupt
) {
5360 // Transfer only words requested.
5361 wordCount
= AtaReq
->WordsLeft
;
5363 // Transfer next block.
5364 wordCount
= wordsThisInterrupt
;
5369 (chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
)) {
5370 if(AtaReq
->ReqState
== REQ_STATE_ATAPI_EXPECTING_DATA_INTR2
) {
5371 KdPrint2((PRINT_PREFIX
5372 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq
->WordsLeft
, wordCount
));
5373 if(AtaReq
->WordsLeft
> wordCount
) {
5374 AtaReq
->WordsLeft
-= wordCount
;
5375 AtaReq
->WordsTransfered
+= wordCount
;
5376 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5377 goto ReturnEnableIntr
;
5379 dma_status
= AtapiDmaDone(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, lChannel
, NULL
/*srb*/);
5381 //ASSERT(AtaReq->WordsLeft == wordCount);
5382 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5383 AtaReq
->WordsLeft
= 0;
5384 status
= SRB_STATUS_SUCCESS
;
5385 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
5386 goto CompleteRequest
;
5388 // Ensure that this is a read command.
5389 if (srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5392 "AtapiInterrupt: Read interrupt\n"));*/
5394 statusByte
= WaitOnBusy(chan
);
5396 if (atapiDev
|| !(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
) /*!deviceExtension->DWordIO*/) {
5397 KdPrint2((PRINT_PREFIX
5398 "IdeIntr: Read %#x words\n", wordCount
));
5403 UniataGetPioTiming(LunExt
));
5404 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)-1) ));
5405 //KdDump(AtaReq->DataBuffer, wordCount*2);
5406 if(srb
&& atapiDev
&& srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
5407 KdDump(AtaReq
->DataBuffer
, wordCount
*2);
5410 GetBaseStatus(chan
, statusByte
);
5411 KdPrint2((PRINT_PREFIX
" status re-check %#x\n", statusByte
));
5414 KdPrint2((PRINT_PREFIX
" DataOverrun\n"));
5415 AtapiSuckPort2(chan
);
5416 GetBaseStatus(chan
, statusByte
);
5419 if(statusByte
& IDE_STATUS_BUSY
) {
5420 for (i
= 0; i
< 2; i
++) {
5421 AtapiStallExecution(10);
5422 GetBaseStatus(chan
, statusByte
);
5423 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5430 KdPrint2((PRINT_PREFIX
5431 "IdeIntr: Read %#x Dwords\n", wordCount
/2));
5434 (PULONG
)(AtaReq
->DataBuffer
),
5436 UniataGetPioTiming(LunExt
));
5440 KdPrint3((PRINT_PREFIX
5441 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5445 // Fail this request.
5446 status
= SRB_STATUS_ERROR
;
5447 goto CompleteRequest
;
5450 // Advance data buffer pointer and bytes left.
5451 AtaReq
->DataBuffer
+= wordCount
;
5452 AtaReq
->WordsLeft
-= wordCount
;
5453 AtaReq
->WordsTransfered
+= wordCount
;
5455 // Check for read command complete.
5456 if (AtaReq
->WordsLeft
== 0) {
5458 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
5461 // Work around to make many atapi devices return correct sector size
5462 // of 2048. Also certain devices will have sector count == 0x00, check
5464 if ((srb
->Cdb
[0] == SCSIOP_READ_CAPACITY
) &&
5465 (LunExt
->IdentifyData
.DeviceType
== ATAPI_TYPE_CDROM
)) {
5467 AtaReq
->DataBuffer
-= wordCount
;
5468 if (AtaReq
->DataBuffer
[0] == 0x00) {
5470 *((ULONG
*) &(AtaReq
->DataBuffer
[0])) = 0xFFFFFF7F;
5474 *((ULONG
*) &(AtaReq
->DataBuffer
[2])) = 0x00080000;
5475 AtaReq
->DataBuffer
+= wordCount
;
5478 GetStatus(chan
, statusByte
);
5479 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5480 // Assume command is completed if BUSY is cleared
5481 // and all data read
5482 // Optionally, we may receive COMPLETE interrupt later and
5483 // treat it as unexpected
5484 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete ? status %x\n", statusByte
));
5486 status
= SRB_STATUS_SUCCESS
;
5487 goto CompleteRequest
;
5493 // Completion for IDE drives.
5494 if (AtaReq->WordsLeft) {
5495 status = SRB_STATUS_DATA_OVERRUN;
5497 status = SRB_STATUS_SUCCESS;
5500 goto CompleteRequest;
5502 status
= SRB_STATUS_SUCCESS
;
5503 goto CompleteRequest
;
5508 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
5509 GetStatus(chan
, statusByte
);
5510 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5511 // Assume command is completed if BUSY is cleared
5512 // even if NOT all data read
5513 // Optionally, we may receive COMPLETE interrupt later and
5514 // treat it as unexpected
5515 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: early complete + underrun ? status %x\n", statusByte
));
5517 status
= SRB_STATUS_SUCCESS
;
5518 goto CompleteRequest
;
5523 goto ReturnEnableIntr
;
5525 } else if (interruptReason
== (ATAPI_IR_IO_toHost
| ATAPI_IR_COD_Cmd
) && !(statusByte
& IDE_STATUS_DRQ
)) {
5527 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: interruptReason = CompleteRequest\n"));
5528 // Command complete.
5530 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
5531 AtaReq
->WordsTransfered
= AtaReq
->WordsLeft
;
5532 AtaReq
->WordsLeft
= 0;
5534 //if (AtaReq->WordsLeft) {
5535 // status = SRB_STATUS_DATA_OVERRUN;
5537 status
= SRB_STATUS_SUCCESS
;
5540 #ifdef UNIATA_DUMP_ATAPI
5542 srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5546 PCHAR ModeSelectData
;
5548 PSCSI_REQUEST_BLOCK Srb
= srb
;
5550 Cdb
= (PCDB
)(Srb
->Cdb
);
5551 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
5552 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
5553 CdbDataLen
= Srb
->DataTransferLength
;
5555 if(CdbDataLen
> 0x1000) {
5556 CdbDataLen
= 0x1000;
5560 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
5561 KdPrint2(("P:T:D=%d:%d:%d\n",
5565 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand
));
5568 if(ScsiCommand
== SCSIOP_MODE_SENSE
) {
5569 KdPrint(("ModeSense 6\n"));
5570 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5571 ModeSelectData
= CdbData
+4;
5572 KdDump(CdbData
, CdbDataLen
);
5574 if(ScsiCommand
== SCSIOP_MODE_SENSE10
) {
5575 KdPrint(("ModeSense 10\n"));
5576 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
5577 ModeSelectData
= CdbData
+8;
5578 KdDump(CdbData
, CdbDataLen
);
5580 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5581 KdPrint(("Read buffer from device:\n"));
5582 KdDump(CdbData
, CdbDataLen
);
5587 #endif //UNIATA_DUMP_ATAPI
5591 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: CompleteRequest, srbstatus %x\n", status
));
5592 // Check and see if we are processing our secret (mechanism status/request sense) srb
5594 if(AtaReq
->WordsLeft
&& (status
== SRB_STATUS_SUCCESS
)) {
5595 KdPrint2((PRINT_PREFIX
"WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq
->WordsLeft
));
5596 status
= SRB_STATUS_DATA_OVERRUN
;
5599 if (AtaReq
->OriginalSrb
) {
5603 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: OriginalSrb != NULL\n"));
5604 if (srb
->Cdb
[0] == SCSIOP_MECHANISM_STATUS
) {
5606 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status
));
5607 if (status
== SRB_STATUS_SUCCESS
) {
5609 AtapiHwInitializeChanger (HwDeviceExtension
,
5611 (PMECHANICAL_STATUS_INFORMATION_HEADER
) srb
->DataBuffer
);
5613 // Get ready to issue the original srb
5614 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5615 AtaReq
->OriginalSrb
= NULL
;
5618 // failed! Get the sense key and maybe try again
5619 srb
= AtaReq
->Srb
= BuildRequestSenseSrb (
5621 AtaReq
->OriginalSrb
);
5624 // do not enable interrupts in DPC, do not waste time, do it now!
5625 if(UseDpc && chan->DisableIntr) {
5626 AtapiEnableInterrupts(HwDeviceExtension, c);
5628 RestoreUseDpc = TRUE;
5631 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
5633 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
5635 if (srbStatus
== SRB_STATUS_PENDING
) {
5636 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
5637 goto ReturnEnableIntr
;
5641 // restore state on error
5643 AtapiDisableInterrupts(HwDeviceExtension, c);
5647 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
5649 PSENSE_DATA senseData
= (PSENSE_DATA
) srb
->DataBuffer
;
5651 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: ATAPI command status %#x\n", status
));
5652 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5653 // Check to see if we at least get mininum number of bytes
5654 if ((srb
->DataTransferLength
- AtaReq
->WordsLeft
) >
5655 (FIELD_OFFSET (SENSE_DATA
, AdditionalSenseLength
) + sizeof(senseData
->AdditionalSenseLength
))) {
5656 status
= SRB_STATUS_SUCCESS
;
5660 if (status
== SRB_STATUS_SUCCESS
) {
5662 if ((senseData
->SenseKey
!= SCSI_SENSE_ILLEGAL_REQUEST
) &&
5663 chan
->MechStatusRetryCount
) {
5665 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: MechStatusRetryCount %#x\n", chan
->MechStatusRetryCount
));
5666 // The sense key doesn't say the last request is illegal, so try again
5667 chan
->MechStatusRetryCount
--;
5668 srb
= AtaReq
->Srb
= BuildMechanismStatusSrb (
5670 AtaReq
->OriginalSrb
);
5673 // last request was illegal. No point trying again.
5674 // Do-nothing call ?
5675 AtapiHwInitializeChanger (HwDeviceExtension
,
5677 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
5679 // Get ready to issue the original srb
5680 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5681 AtaReq
->OriginalSrb
= NULL
;
5683 #endif //UNIATA_CORE
5685 // do not enable interrupts in DPC, do not waste time, do it now!
5686 if(UseDpc && chan->DisableIntr) {
5687 AtapiEnableInterrupts(HwDeviceExtension, c);
5689 RestoreUseDpc = TRUE;
5692 srbStatus
= AtapiSendCommand(HwDeviceExtension
, srb
, CMD_ACTION_ALL
);
5694 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan
->ExpectingInterrupt
));
5696 if (srbStatus
== SRB_STATUS_PENDING
) {
5697 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
5698 goto ReturnEnableIntr
;
5702 // restore state on error
5704 AtapiDisableInterrupts(HwDeviceExtension, c);
5710 // If we get here, it means AtapiSendCommand() has failed
5711 // Can't recover. Pretend the original srb has failed and complete it.
5713 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. complete OriginalSrb\n"));
5715 if (AtaReq
->OriginalSrb
) {
5716 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
5717 // Do-nothing call ?
5718 AtapiHwInitializeChanger (HwDeviceExtension
,
5720 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
5721 srb
= AtaReq
->Srb
= AtaReq
->OriginalSrb
;
5722 AtaReq
->OriginalSrb
= NULL
;
5725 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan
->ExpectingInterrupt
));
5727 // fake an error and read no data
5728 status
= SRB_STATUS_ERROR
;
5729 srb
->ScsiStatus
= 0;
5730 AtaReq
->DataBuffer
= (PUSHORT
)(srb
->DataBuffer
);
5731 AtaReq
->WordsLeft
= srb
->DataTransferLength
;
5734 } else if (status
== SRB_STATUS_ERROR
) {
5736 // Map error to specific SRB status and handle request sense.
5737 KdPrint3((PRINT_PREFIX
"AtapiInterrupt: Error. Begin mapping...\n"));
5738 status
= MapError(deviceExtension
,
5743 } else if(!DmaTransfer
) {
5745 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion\n"));
5746 // Command complete.
5748 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO completion, wait BUSY\n"));
5749 // Wait for busy to drop.
5750 for (i
= 0; i
< 5*30; i
++) {
5751 GetBaseStatus(chan
, statusByte
);
5752 if (!(statusByte
& IDE_STATUS_BUSY
)) {
5757 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_BUSY
;
5759 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (busy)\n"));
5763 AtapiStallExecution(TimerValue
);
5764 goto ServiceInterrupt
;
5765 #endif //UNIATA_CORE
5767 AtapiStallExecution(100);
5772 // reset the controller.
5773 KdPrint2((PRINT_PREFIX
5774 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
5776 goto IntrPrepareResetController
;
5778 // Check to see if DRQ is still up.
5779 if(statusByte
& IDE_STATUS_DRQ
) {
5780 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: DRQ...\n"));
5782 if(srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
5783 KdPrint2((PRINT_PREFIX
"srb %x data in\n", srb
));
5785 KdPrint2((PRINT_PREFIX
"srb %x data out\n", srb
));
5788 KdPrint2((PRINT_PREFIX
"srb NULL\n"));
5791 KdPrint2((PRINT_PREFIX
"AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq
, AtaReq
->WordsLeft
));
5793 KdPrint2((PRINT_PREFIX
"AtaReq NULL\n"));
5795 if(AtaReq
&& AtaReq
->WordsLeft
/*&&
5796 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
5797 KdPrint2((PRINT_PREFIX
"DRQ+AtaReq->WordsLeft -> next portion\n"));
5801 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
5802 //if ((statusByte & IDE_STATUS_DRQ)) {}
5803 if((statusByte
& IDE_STATUS_DRQ
) &&
5804 (LunExt
->DeviceFlags
& (DFLAGS_ATAPI_DEVICE
| DFLAGS_TAPE_DEVICE
| DFLAGS_LBA_ENABLED
)) ) {
5807 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: PIO_wait_DRQ\n"));
5808 for (i
= 0; i
< 200; i
++) {
5809 GetBaseStatus(chan
, statusByte
);
5810 if (!(statusByte
& IDE_STATUS_DRQ
)) {
5815 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: go to DPC (drq)\n"));
5816 AtaReq
->ReqState
= REQ_STATE_DPC_WAIT_DRQ
;
5821 AtapiStallExecution(TimerValue
);
5822 goto ServiceInterrupt
;
5823 #endif //UNIATA_CORE
5825 AtapiStallExecution(100);
5829 // reset the controller.
5830 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
5832 goto IntrPrepareResetController
;
5836 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
5837 AtaReq
->DataBuffer
, (srb
? srb
->DataBuffer
: (void*)(-1)), srb
->DataTransferLength
));
5838 //KdDump(srb->DataBuffer, srb->DataTransferLength);
5840 if(!AtapiDmaPioSync(HwDeviceExtension
, srb
, (PUCHAR
)(srb
->DataBuffer
), srb
->DataTransferLength
)) {
5841 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
5845 // Clear interrupt expecting flag.
5846 UniataExpectChannelInterrupt(chan
, FALSE
);
5847 // clear this flag now, it can be set again in sub-calls
5848 InterlockedExchange(&(chan
->CheckIntr
),
5851 // Sanity check that there is a current request.
5853 // Set status in SRB.
5854 srb
->SrbStatus
= (UCHAR
)status
;
5856 // Check for underflow.
5857 if(AtaReq
->WordsLeft
) {
5859 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq
->WordsLeft
));
5860 // Subtract out residual words and update if filemark hit,
5861 // setmark hit , end of data, end of media...
5862 if (!(LunExt
->DeviceFlags
& DFLAGS_TAPE_DEVICE
)) {
5863 if (status
== SRB_STATUS_DATA_OVERRUN
) {
5864 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5866 srb
->DataTransferLength
= 0;
5869 srb
->DataTransferLength
-= AtaReq
->WordsLeft
*2;
5872 if(status
== SRB_STATUS_SUCCESS
) {
5873 //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) {
5874 // // This should be set in UniataAhciEndTransaction() for AHCI
5875 // AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
5878 AtaReq
->WordsTransfered
*2 < AtaReq
->TransferLength
) {
5879 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
5880 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5881 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
5882 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_NEXT
;
5885 KdPrint2((PRINT_PREFIX
" Transfered %x, full size %x\n",
5886 AtaReq
->WordsTransfered
*2, AtaReq
->TransferLength
));
5890 if (srb
->Function
!= SRB_FUNCTION_IO_CONTROL
) {
5893 // Indicate command complete.
5895 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete\n"));
5898 if (status
== SRB_STATUS_SUCCESS
&&
5899 srb
->SenseInfoBuffer
&&
5900 srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
5902 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)srb
->SenseInfoBuffer
;
5904 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: set AutoSense\n"));
5905 senseBuffer
->ErrorCode
= 0;
5906 senseBuffer
->Valid
= 1;
5907 senseBuffer
->AdditionalSenseLength
= 0xb;
5908 senseBuffer
->SenseKey
= 0;
5909 senseBuffer
->AdditionalSenseCode
= 0;
5910 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
5912 srb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
5914 AtapiDmaDBSync(chan
, srb
);
5915 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove srb %#x, status %x\n", srb
, status
));
5916 UniataRemoveRequest(chan
, srb
);
5917 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestComplete, srb %#x\n", srb
));
5918 ScsiPortNotification(RequestComplete
,
5924 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: IOCTL completion\n"));
5926 if (status
!= SRB_STATUS_SUCCESS
) {
5927 error
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
5928 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: error %#x\n", error
));
5931 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
5933 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
5934 // Build the SMART status block depending upon the completion status.
5935 cmdOutParameters
->cBufferSize
= wordCount
;
5936 cmdOutParameters
->DriverStatus
.bDriverError
= (error
) ? SMART_IDE_ERROR
: 0;
5937 cmdOutParameters
->DriverStatus
.bIDEError
= error
;
5939 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
5941 if (chan
->SmartCommand
== RETURN_SMART_STATUS
) {
5942 PIDEREGS_EX regs
= (PIDEREGS_EX
)&(cmdOutParameters
->bBuffer
);
5945 UniataSnapAtaRegs(chan
, 0, regs
);
5947 regs
->bCommandReg
= SMART_CMD
;
5948 regs
->bFeaturesReg
= RETURN_SMART_STATUS
;
5950 cmdOutParameters
->cBufferSize
= 8;
5952 chan
->SmartCommand
= 0; // cleanup after execution
5954 // Indicate command complete.
5955 goto IntrCompleteReq
;
5960 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: No SRB!\n"));
5965 for (i
= 0; i
< 5; i
++) {
5966 GetBaseStatus(chan
, statusByte
);
5967 if(!(statusByte
& IDE_STATUS_BUSY
)) {
5968 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RDP + cleared BUSY\n"));
5972 if (statusByte
& IDE_STATUS_DSC
) {
5973 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Clear RDP\n"));
5977 AtapiStallExecution(50);
5980 // RDP can be cleared since previous check
5982 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: RequestTimerCall 2000\n"));
5988 AtapiStallExecution(TimerValue
);
5989 goto ServiceInterrupt
;
5990 #endif //UNIATA_CORE
5993 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
5996 srb
= UniataGetCurRequest(chan
);
6001 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: NextRequest, srb=%#x\n",srb
));
6003 ScsiPortNotification(NextRequest
,
6007 ScsiPortNotification(NextLuRequest
,
6012 // in simplex mode next command must NOT be sent here
6013 if(!deviceExtension
->simplexOnly
) {
6014 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6017 // Try to get SRB fron any non-empty queue (later)
6018 if(deviceExtension
->simplexOnly
) {
6021 #endif //UNIATA_CORE
6023 goto ReturnEnableIntr
;
6027 // Unexpected int. Catch it
6028 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
6032 if(OldReqState
== REQ_STATE_DPC_WAIT_BUSY0
&&
6033 AtaReq
->WordsLeft
== 0) {
6034 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: pending WAIT_BUSY0. Complete.\n"));
6035 status
= SRB_STATUS_SUCCESS
;
6036 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6037 goto CompleteRequest
;
6043 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: ReturnEnableIntr\n",srb
));
6044 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6045 deviceExtension
->ExpectingInterrupt
= TRUE
;
6047 if(CrNtInterlockedExchangeAdd(&(chan
->DisableIntr
), 0)) {
6048 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
6049 #ifdef UNIATA_USE_XXableInterrupts
6050 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
6051 chan
->ChannelCtrlFlags
|= CTRFLAGS_ENABLE_INTR_REQ
;
6052 // must be called on DISPATCH_LEVEL
6053 ScsiPortNotification(CallDisableInterrupts
, HwDeviceExtension
,
6054 AtapiEnableInterrupts__
);
6056 AtapiEnableInterrupts(HwDeviceExtension
, c
);
6057 InterlockedExchange(&(chan
->CheckIntr
),
6059 // Will raise IRQL to DIRQL
6061 AtapiQueueTimerDpc(HwDeviceExtension
, lChannel
,
6062 AtapiEnableInterrupts__
,
6064 #endif // UNIATA_CORE
6065 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: Timer DPC inited\n"));
6066 #endif // UNIATA_USE_XXableInterrupts
6070 InterlockedExchange(&(chan
->CheckIntr
), CHECK_INTR_IDLE
);
6071 // in simplex mode next command must be sent here if
6073 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc
, NoStartIo
));
6076 if(!UseDpc
&& /*deviceExtension->simplexOnly &&*/ !NoStartIo
) {
6077 chan
= UniataGetNextChannel(chan
);
6079 srb
= UniataGetCurRequest(chan
);
6083 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: run srb %x\n", srb
));
6085 AtapiStartIo__(HwDeviceExtension
, srb
, FALSE
);
6088 #endif //UNIATA_CORE
6091 } // end AtapiInterrupt__()
6097 Routine Description:
6099 This routine handles SMART enable, disable, read attributes and threshold commands.
6103 HwDeviceExtension - HBA miniport driver's adapter data storage
6104 Srb - IO request packet
6113 IdeSendSmartCommand(
6114 IN PVOID HwDeviceExtension
,
6115 IN PSCSI_REQUEST_BLOCK Srb
,
6116 IN ULONG targetId
// assume it is always valid
6119 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6120 ULONG c
; // = GET_CHANNEL(Srb); may be invalid
6121 PHW_CHANNEL chan
; // = &(deviceExtension->chan[c]);
6122 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6123 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6124 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
6125 PIDEREGS regs
= &cmdInParameters
.irDriveRegs
;
6130 if (regs
->bCommandReg
!= SMART_CMD
) {
6131 KdPrint2((PRINT_PREFIX
6132 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
6133 return SRB_STATUS_INVALID_REQUEST
;
6136 c
= targetId
/ deviceExtension
->NumberLuns
;
6137 DeviceNumber
= targetId
% deviceExtension
->NumberLuns
;
6138 KdPrint2((PRINT_PREFIX
" c %d, dev %d\n", c
, DeviceNumber
));
6140 chan
= &(deviceExtension
->chan
[c
]);
6142 chan
->SmartCommand
= regs
->bFeaturesReg
;
6144 // Determine which of the commands to carry out.
6145 switch(regs
->bFeaturesReg
) {
6146 case READ_ATTRIBUTES
:
6147 case READ_THRESHOLDS
:
6148 case READ_LOG_SECTOR
:
6149 case WRITE_LOG_SECTOR
:
6151 if(Srb
->DataTransferLength
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1) {
6152 KdPrint2((PRINT_PREFIX
6153 "IdeSendSmartCommand: wrong buffer size\n"));
6154 return SRB_STATUS_DATA_OVERRUN
;
6157 statusByte
= WaitOnBusy(chan
);
6159 if (statusByte
& IDE_STATUS_BUSY
) {
6160 KdPrint2((PRINT_PREFIX
6161 "IdeSendSmartCommand: Returning BUSY status\n"));
6162 return SRB_STATUS_BUSY
;
6165 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6166 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) + READ_ATTRIBUTE_BUFFER_SIZE
- 1);
6168 // Set data buffer pointer and words left.
6169 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6170 AtaReq
->WordsLeft
= READ_ATTRIBUTE_BUFFER_SIZE
/ 2;
6172 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6174 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6176 regs
->bSectorNumberReg
,
6177 regs
->bSectorCountReg
,
6181 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6182 // Wait for interrupt.
6183 return SRB_STATUS_PENDING
;
6185 return SRB_STATUS_ERROR
;
6189 case RETURN_SMART_STATUS
:
6190 case ENABLE_DISABLE_AUTOSAVE
:
6191 case EXECUTE_OFFLINE_DIAGS
:
6192 case SAVE_ATTRIBUTE_VALUES
:
6195 statusByte
= WaitOnBusy(chan
);
6197 if (statusByte
& IDE_STATUS_BUSY
) {
6198 KdPrint2((PRINT_PREFIX
6199 "IdeSendSmartCommand: Returning BUSY status\n"));
6200 return SRB_STATUS_BUSY
;
6203 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6204 RtlZeroMemory(cmdOutParameters
, sizeof(SENDCMDOUTPARAMS
) - 1);
6206 // Set data buffer pointer and indicate no data transfer.
6207 AtaReq
->DataBuffer
= (PUSHORT
)cmdOutParameters
->bBuffer
;
6208 AtaReq
->WordsLeft
= 0;
6210 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, c
,
6212 (USHORT
)(regs
->bCylLowReg
) | (((USHORT
)(regs
->bCylHighReg
)) << 8),
6214 regs
->bSectorNumberReg
,
6215 regs
->bSectorCountReg
,
6219 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6220 // Wait for interrupt.
6221 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6222 return SRB_STATUS_PENDING
;
6224 return SRB_STATUS_ERROR
;
6225 } // end switch(regs->bFeaturesReg)
6227 return SRB_STATUS_INVALID_REQUEST
;
6229 } // end IdeSendSmartCommand()
6231 #endif //UNIATA_CORE
6235 UniAtaCalculateLBARegs(
6236 PHW_LU_EXTENSION LunExt
,
6237 ULONGLONG startingSector
,
6241 UCHAR drvSelect
,sectorNumber
;
6245 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6246 if(LunExt
->LimitedTransferMode
>= ATA_DMA
) {
6247 if(LunExt
->DeviceExtension
) {
6248 (*max_bcount
) = LunExt
->DeviceExtension
->MaximumDmaTransferLength
/ DEV_BSIZE
;
6251 return startingSector
;
6253 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6254 LunExt
->IdentifyData
.NumberOfHeads
;
6256 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: 0-sized\n"));
6260 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
;
6262 cylinder
= (USHORT
)(startingSector
/ tmp
);
6263 drvSelect
= (UCHAR
)((startingSector
% tmp
) / LunExt
->IdentifyData
.SectorsPerTrack
);
6264 sectorNumber
= (UCHAR
)(startingSector
% LunExt
->IdentifyData
.SectorsPerTrack
) + 1;
6265 (*max_bcount
) = LunExt
->IdentifyData
.SectorsPerTrack
- sectorNumber
+ 1;
6266 KdPrint2((PRINT_PREFIX
"UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
6267 cylinder
, drvSelect
, sectorNumber
, (*max_bcount
)));
6271 return (ULONG
)(sectorNumber
&0xff) | (((ULONG
)cylinder
&0xffff)<<8) | (((ULONG
)drvSelect
&0xf)<<24);
6272 } // end UniAtaCalculateLBARegs()
6276 UniAtaCalculateLBARegsBack(
6277 PHW_LU_EXTENSION LunExt
,
6281 ULONG drvSelect
,sectorNumber
;
6285 if(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
6288 tmp
= LunExt
->IdentifyData
.SectorsPerTrack
*
6289 LunExt
->IdentifyData
.NumberOfHeads
;
6291 cylinder
= (USHORT
)((lba
>> 8) & 0xffff);
6292 drvSelect
= (UCHAR
)((lba
>> 24) & 0xf);
6293 sectorNumber
= (UCHAR
)(lba
& 0xff);
6295 lba
= sectorNumber
-1 +
6296 (drvSelect
*LunExt
->IdentifyData
.SectorsPerTrack
) +
6300 } // end UniAtaCalculateLBARegsBack()
6305 Routine Description:
6307 This routine handles IDE read and writes.
6311 HwDeviceExtension - HBA miniport driver's adapter data storage
6312 Srb - IO request packet
6322 IN PVOID HwDeviceExtension
,
6323 IN PSCSI_REQUEST_BLOCK Srb
,
6327 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6328 UCHAR lChannel
= GET_CHANNEL(Srb
);
6329 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6330 PHW_LU_EXTENSION LunExt
;
6331 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6332 //ULONG ldev = GET_LDEV(Srb);
6333 UCHAR DeviceNumber
= GET_CDEV(Srb
);;
6334 ULONGLONG startingSector
=0;
6336 ULONG wordCount
= 0;
6337 UCHAR statusByte
,statusByte2
;
6340 BOOLEAN use_dma
= FALSE
;
6343 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6344 LunExt
= chan
->lun
[DeviceNumber
];
6346 if((CmdAction
& CMD_ACTION_PREPARE
) &&
6347 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
6349 if(LunExt
->opt_ReadOnly
&&
6350 (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) {
6351 if(LunExt
->opt_ReadOnly
== 1) {
6352 KdPrint2((PRINT_PREFIX
"Abort WRITE (Soft R/O)\n"));
6353 return SRB_STATUS_ERROR
;
6355 KdPrint2((PRINT_PREFIX
"Ignore WRITE (Soft R/O)\n"));
6356 return SRB_STATUS_SUCCESS
;
6360 // Set data buffer pointer and words left.
6361 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6363 if(AtaReq
->WordsTransfered
) {
6364 AtaReq
->DataBuffer
= ((PUSHORT
)(Srb
->DataBuffer
)) + AtaReq
->WordsTransfered
;
6365 startingSector
= (UniAtaCalculateLBARegsBack(LunExt
, AtaReq
->lba
)) /* latest lba */ + AtaReq
->bcount
/* previous bcount */;
6366 AtaReq
->bcount
= (AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2 + DEV_BSIZE
-1) / DEV_BSIZE
;
6367 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Chained REQ): Starting sector %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
6369 AtaReq
->TransferLength
/2,
6370 AtaReq
->WordsTransfered
,
6373 AtaReq
->DataBuffer
= (PUSHORT
)(Srb
->DataBuffer
);
6374 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
6375 // Set up 1st block.
6376 switch(Srb
->Cdb
[0]) {
6379 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6380 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6383 case SCSIOP_WRITE12
:
6384 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
6385 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6388 case SCSIOP_WRITE16
:
6389 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6390 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6393 KdPrint2((PRINT_PREFIX
"IdeReadWrite (Orig REQ): Starting sector %I64x, OrigWordsRequested %#x, DevSize %#x\n",
6395 AtaReq
->TransferLength
/2,
6398 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6401 AtaReq
->bcount
= min(AtaReq
->bcount
, max_bcount
);
6403 AtaReq
->WordsLeft
= min(AtaReq
->TransferLength
- AtaReq
->WordsTransfered
*2,
6404 AtaReq
->bcount
* DEV_BSIZE
) / 2;
6406 KdPrint2((PRINT_PREFIX
"IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n",
6413 // assume best case here
6414 // we cannot reinit Dma until previous request is completed
6415 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6416 UniataAhciSetupCmdPtr(AtaReq
);
6417 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6418 (PUCHAR
)(AtaReq
->DataBuffer
),
6419 AtaReq
->bcount
* DEV_BSIZE
)) {
6420 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !DMA\n"));
6421 return SRB_STATUS_ERROR
;
6424 if ((LunExt
->LimitedTransferMode
>= ATA_DMA
)) {
6426 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6427 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
6428 (PUCHAR
)(AtaReq
->DataBuffer
),
6429 AtaReq
->bcount
* DEV_BSIZE
)) {
6434 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6435 KdPrint2((PRINT_PREFIX
"IdeReadWrite: setup AHCI FIS\n"));
6436 RtlZeroMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
), sizeof(AtaReq
->ahci_cmd0
.cfis
));
6438 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
6439 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
6440 (AtaReq
->Flags
& REQ_FLAG_READ
) ? IDE_COMMAND_READ_DMA
: IDE_COMMAND_WRITE_DMA
,
6442 (USHORT
)(AtaReq
->bcount
),
6444 /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/
6448 KdPrint3((PRINT_PREFIX
"IdeReadWrite: AHCI !FIS\n"));
6449 return SRB_STATUS_ERROR
;
6452 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0, (AtaReq
->Flags
& REQ_FLAG_READ
) ? 0 : ATA_AHCI_CMD_WRITE
, fis_size
, DeviceNumber
);
6453 KdPrint2((PRINT_PREFIX
"IdeReadWrite ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
6456 AtaReq
->ReqState
= REQ_STATE_READY_TO_TRANSFER
;
6458 } else { // exec_only
6459 KdPrint2((PRINT_PREFIX
"IdeReadWrite (ExecOnly): \n"));
6462 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
6466 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
6468 return SRB_STATUS_PENDING
;
6471 // if this is queued request, reinit DMA and check
6472 // if DMA mode is still available
6473 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
6474 if (/*EnableDma &&*/
6475 (LunExt
->TransferMode
>= ATA_DMA
)) {
6478 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6482 // Check if write request.
6483 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6485 // Prepare read command.
6487 cmd
= IDE_COMMAND_READ_DMA
;
6489 if(LunExt
->MaximumBlockXfer
) {
6490 cmd
= IDE_COMMAND_READ_MULTIPLE
;
6492 cmd
= IDE_COMMAND_READ
;
6496 // Prepare write command.
6498 wordCount
= AtaReq
->bcount
*DEV_BSIZE
/2;
6499 cmd
= IDE_COMMAND_WRITE_DMA
;
6501 if (LunExt
->MaximumBlockXfer
) {
6502 wordCount
= DEV_BSIZE
/2 * LunExt
->MaximumBlockXfer
;
6504 if (AtaReq
->WordsLeft
< wordCount
) {
6505 // Transfer only words requested.
6506 wordCount
= AtaReq
->WordsLeft
;
6508 cmd
= IDE_COMMAND_WRITE_MULTIPLE
;
6511 wordCount
= DEV_BSIZE
/2;
6512 cmd
= IDE_COMMAND_WRITE
;
6517 KdPrint2((PRINT_PREFIX
"IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba
, ((Srb
->DataTransferLength
+ 0x1FF) / 0x200),
6518 ((wordCount
*2 + DEV_BSIZE
-1) / DEV_BSIZE
)));
6520 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
6522 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
6525 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
6526 // AHCI doesn't distinguish DMA and PIO
6527 //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
6528 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
6529 UniataExpectChannelInterrupt(chan
, TRUE
); // device may interrupt
6530 InterlockedExchange(&(chan
->CheckIntr
),
6532 return SRB_STATUS_PENDING
;
6535 if ((Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) ||
6537 statusByte2
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
6539 (USHORT
)(AtaReq
->bcount
),
6540 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6542 if(statusByte2
!= IDE_STATUS_WRONG
) {
6543 GetStatus(chan
, statusByte2
);
6545 if(statusByte2
& IDE_STATUS_ERROR
) {
6546 statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
6547 KdPrint2((PRINT_PREFIX
"IdeReadWrite: status %#x, error %#x\n", statusByte2
, statusByte
));
6548 return SRB_STATUS_ERROR
;
6551 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
6553 return SRB_STATUS_PENDING
;
6556 statusByte
= AtaCommand48(deviceExtension
, DeviceNumber
, lChannel
,
6558 (USHORT
)(AtaReq
->bcount
),
6559 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6562 if (!(statusByte
& IDE_STATUS_DRQ
) ||
6563 statusByte
== IDE_STATUS_WRONG
) {
6565 if(statusByte
== IDE_STATUS_WRONG
) {
6566 KdPrint2((PRINT_PREFIX
6567 "IdeReadWrite: error sending command (%#x)\n",
6570 KdPrint2((PRINT_PREFIX
6571 "IdeReadWrite: DRQ never asserted (%#x)\n",
6575 AtaReq
->WordsLeft
= 0;
6577 // Clear interrupt expecting flag.
6578 UniataExpectChannelInterrupt(chan
, FALSE
);
6579 InterlockedExchange(&(chan
->CheckIntr
),
6582 // Clear current SRB.
6583 UniataRemoveRequest(chan
, Srb
);
6585 return (statusByte
== IDE_STATUS_WRONG
) ? SRB_STATUS_ERROR
: SRB_STATUS_TIMEOUT
;
6588 UniataExpectChannelInterrupt(chan
, TRUE
);
6589 InterlockedExchange(&(chan
->CheckIntr
),
6592 // Write next DEV_BSIZE/2*N words.
6593 if (!(LunExt
->DeviceFlags
& DFLAGS_DWORDIO_ENABLED
)) {
6594 KdPrint2((PRINT_PREFIX
6595 "IdeReadWrite: Write %#x words\n", wordCount
));
6600 UniataGetPioTiming(LunExt
));
6604 KdPrint2((PRINT_PREFIX
6605 "IdeReadWrite: Write %#x Dwords\n", wordCount
/2));
6608 (PULONG
)(AtaReq
->DataBuffer
),
6610 UniataGetPioTiming(LunExt
));
6613 // Adjust buffer address and words left count.
6614 AtaReq
->WordsLeft
-= wordCount
;
6615 AtaReq
->DataBuffer
+= wordCount
;
6617 // Wait for interrupt.
6618 return SRB_STATUS_PENDING
;
6620 } // end IdeReadWrite()
6626 Routine Description:
6627 This routine handles IDE Verify.
6630 HwDeviceExtension - HBA miniport driver's adapter data storage
6631 Srb - IO request packet
6640 IN PVOID HwDeviceExtension
,
6641 IN PSCSI_REQUEST_BLOCK Srb
6644 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6645 UCHAR lChannel
= GET_CHANNEL(Srb
);
6646 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6647 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6648 PHW_LU_EXTENSION LunExt
;
6649 //ULONG ldev = GET_LDEV(Srb);
6650 ULONG DeviceNumber
= GET_CDEV(Srb
);
6652 ULONGLONG startingSector
=0;
6655 ULONGLONG endSector
;
6656 ULONG sectorCount
=0;
6659 LunExt
= chan
->lun
[DeviceNumber
];
6660 // Drive has these number sectors.
6661 if(!(sectors
= (ULONG
)(LunExt
->NumOfSectors
))) {
6662 sectors
= LunExt
->IdentifyData
.SectorsPerTrack
*
6663 LunExt
->IdentifyData
.NumberOfHeads
*
6664 LunExt
->IdentifyData
.NumberOfCylinders
;
6667 KdPrint2((PRINT_PREFIX
6668 "IdeVerify: Total sectors %#x\n",
6671 // Get starting sector number from CDB.
6672 switch(Srb
->Cdb
[0]) {
6674 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6675 MOV_SWP_DW2DD(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6677 case SCSIOP_VERIFY12
:
6678 MOV_DD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.LBA
);
6679 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6681 case SCSIOP_VERIFY16
:
6682 MOV_QD_SWP(startingSector
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6683 MOV_DD_SWP(sectorCount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6687 KdPrint2((PRINT_PREFIX
6688 "IdeVerify: Starting sector %#I64x. Number of blocks %#x\n",
6692 endSector
= startingSector
+ sectorCount
;
6694 KdPrint2((PRINT_PREFIX
6695 "IdeVerify: Ending sector %#I64x\n",
6698 if (endSector
> sectors
) {
6700 // Too big, round down.
6701 KdPrint2((PRINT_PREFIX
6702 "IdeVerify: Truncating request to %#x blocks\n",
6703 sectors
- startingSector
- 1));
6705 sectorCount
= (ULONG
)(sectors
- startingSector
- 1);
6709 // Set up sector count register. Round up to next block.
6710 if (sectorCount
> 0xFF) {
6711 sectorCount
= (USHORT
)0xFF;
6715 // Set data buffer pointer and words left.
6716 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
6717 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
6719 // Indicate expecting an interrupt.
6720 InterlockedExchange(&(chan
->CheckIntr
),
6723 lba
= UniAtaCalculateLBARegs(LunExt
, startingSector
, &max_bcount
);
6725 statusByte
= AtaCommand48(deviceExtension
, LunExt
->Lun
, GET_CHANNEL(Srb
),
6726 IDE_COMMAND_VERIFY
, lba
,
6727 (USHORT
)sectorCount
,
6730 if(!(statusByte
& IDE_STATUS_ERROR
)) {
6731 // Wait for interrupt.
6732 return SRB_STATUS_PENDING
;
6734 return SRB_STATUS_ERROR
;
6736 } // end IdeVerify()
6738 #endif //UNIATA_CORE
6742 Routine Description:
6743 Send ATAPI packet command to device.
6746 HwDeviceExtension - HBA miniport driver's adapter data storage
6747 Srb - IO request packet
6755 IN PVOID HwDeviceExtension
,
6756 IN PSCSI_REQUEST_BLOCK Srb
,
6760 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
6761 UCHAR lChannel
= GET_CHANNEL(Srb
);
6762 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
6763 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
6764 PHW_LU_EXTENSION LunExt
;
6765 //ULONG ldev = GET_LDEV(Srb);
6766 ULONG DeviceNumber
= GET_CDEV(Srb
);
6768 UCHAR statusByte
,statusByte0
,byteCountLow
,byteCountHigh
;
6769 BOOLEAN use_dma
= FALSE
;
6770 BOOLEAN dma_reinited
= FALSE
;
6771 BOOLEAN retried
= FALSE
;
6775 LunExt
= chan
->lun
[DeviceNumber
];
6777 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: req state %#x, Action %x\n", AtaReq
->ReqState
, CmdAction
));
6778 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
6779 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
6782 #ifdef UNIATA_DUMP_ATAPI
6783 if(CmdAction
& CMD_ACTION_PREPARE
) {
6787 PCHAR ModeSelectData
;
6790 Cdb
= (PCDB
)(Srb
->Cdb
);
6791 ScsiCommand
= Cdb
->CDB6
.OperationCode
;
6792 CdbData
= (PCHAR
)(Srb
->DataBuffer
);
6793 CdbDataLen
= Srb
->DataTransferLength
;
6795 if(CdbDataLen
> 0x1000) {
6796 CdbDataLen
= 0x1000;
6800 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
6801 KdPrint2(("P:T:D=%d:%d:%d\n",
6805 KdPrint(("SCSI Command %2.2x\n", ScsiCommand
));
6808 if(ScsiCommand
== SCSIOP_WRITE_CD
) {
6809 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
6810 Cdb
->WRITE_CD
.LBA
[0],
6811 Cdb
->WRITE_CD
.LBA
[1],
6812 Cdb
->WRITE_CD
.LBA
[2],
6813 Cdb
->WRITE_CD
.LBA
[3]
6816 if(ScsiCommand
== SCSIOP_WRITE12
) {
6817 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
6818 Cdb
->CDB12READWRITE
.LBA
[0],
6819 Cdb
->CDB12READWRITE
.LBA
[1],
6820 Cdb
->CDB12READWRITE
.LBA
[2],
6821 Cdb
->CDB12READWRITE
.LBA
[3]
6824 if(ScsiCommand
== SCSIOP_WRITE16
) {
6825 KdPrint(("Write16, LBA %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
6826 Cdb
->CDB16READWRITE
.LBA
[0],
6827 Cdb
->CDB16READWRITE
.LBA
[1],
6828 Cdb
->CDB16READWRITE
.LBA
[2],
6829 Cdb
->CDB16READWRITE
.LBA
[3],
6830 Cdb
->CDB16READWRITE
.LBA
[4],
6831 Cdb
->CDB16READWRITE
.LBA
[5],
6832 Cdb
->CDB16READWRITE
.LBA
[6],
6833 Cdb
->CDB16READWRITE
.LBA
[7]
6836 if(ScsiCommand
== SCSIOP_MODE_SELECT
) {
6837 KdPrint(("ModeSelect 6\n"));
6838 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6839 ModeSelectData
= CdbData
+4;
6840 KdDump(CdbData
, CdbDataLen
);
6842 if(ScsiCommand
== SCSIOP_MODE_SELECT10
) {
6843 KdPrint(("ModeSelect 10\n"));
6844 PMODE_PARAMETER_HEADER ParamHdr
= (PMODE_PARAMETER_HEADER
)CdbData
;
6845 ModeSelectData
= CdbData
+8;
6846 KdDump(CdbData
, CdbDataLen
);
6848 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
6849 KdPrint(("Send buffer to device:\n"));
6850 KdDump(CdbData
, CdbDataLen
);
6855 #endif //UNIATA_DUMP_ATAPI
6858 if(CmdAction
== CMD_ACTION_PREPARE
) {
6859 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb
->Cdb
)));
6861 switch (Srb
->Cdb
[0]) {
6862 case SCSIOP_RECEIVE
:
6867 case SCSIOP_WRITE12
:
6869 case SCSIOP_WRITE16
:
6873 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY\n"));
6874 return SRB_STATUS_BUSY
;
6877 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6878 !AtaReq
->OriginalSrb
) {
6879 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
6880 return SRB_STATUS_BUSY
;
6885 // We need to know how many platters our atapi cd-rom device might have.
6886 // Before anyone tries to send a srb to our target for the first time,
6887 // we must "secretly" send down a separate mechanism status srb in order to
6888 // initialize our device extension changer data. That's how we know how
6889 // many platters our target has.
6891 if (!(LunExt
->DeviceFlags
& DFLAGS_CHANGER_INITED
) &&
6892 !AtaReq
->OriginalSrb
) {
6896 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: BuildMechanismStatusSrb()\n"));
6897 // Set this flag now. If the device hangs on the mech. status
6898 // command, we will not have the chance to set it.
6899 LunExt
->DeviceFlags
|= DFLAGS_CHANGER_INITED
;
6901 chan
->MechStatusRetryCount
= 3;
6902 AtaReq
->OriginalSrb
= Srb
;
6903 AtaReq
->Srb
= BuildMechanismStatusSrb (
6907 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AtapiSendCommand recursive\n"));
6908 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
6909 if (srbStatus
== SRB_STATUS_PENDING
) {
6910 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
6914 // failed! Get the sense key and maybe try again
6915 AtaReq
->Srb
= BuildRequestSenseSrb ( HwDeviceExtension
,
6916 AtaReq
->OriginalSrb
);
6918 srbStatus
= AtapiSendCommand(HwDeviceExtension
, AtaReq
->Srb
, CMD_ACTION_ALL
);
6920 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan
->ExpectingInterrupt
));
6922 if (srbStatus
== SRB_STATUS_PENDING
) {
6923 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n"));
6927 // failed again ? should not get here
6929 AtaReq
->Srb
= AtaReq
->OriginalSrb
;
6930 AtaReq
->OriginalSrb
= NULL
;
6932 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiHwInitializeChanger()\n"));
6933 // Do-nothing call ?
6934 AtapiHwInitializeChanger (HwDeviceExtension
, Srb
,
6935 (PMECHANICAL_STATUS_INFORMATION_HEADER
) NULL
);
6939 #endif //UNIATA_CORE
6941 if((CmdAction
& CMD_ACTION_PREPARE
) &&
6942 (AtaReq
->ReqState
!= REQ_STATE_READY_TO_TRANSFER
)) {
6944 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb
->Cdb
[0], &(Srb
->Cdb
)));
6946 if(!LunExt
->IdentifyData
.AtapiCmdSize
&&
6947 (Srb
->CdbLength
> 12)) {
6948 KdPrint2((PRINT_PREFIX
"Cdb16 not supported\n"));
6949 return SRB_STATUS_INVALID_REQUEST
;
6952 // Set data buffer pointer and words left.
6953 AtaReq
->DataBuffer
= (PUSHORT
)Srb
->DataBuffer
;
6954 AtaReq
->WordsLeft
= Srb
->DataTransferLength
/ 2;
6955 AtaReq
->TransferLength
= Srb
->DataTransferLength
;
6956 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
6957 // reset this to force PRD init. May be already setup by recursive SRB
6958 AtaReq
->dma_entries
= 0;
6960 // check if reorderable
6961 switch(Srb
->Cdb
[0]) {
6963 case SCSIOP_WRITE16
:
6965 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.NumOfBlocks
);
6966 MOV_QD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB16READWRITE
.LBA
);
6970 case SCSIOP_WRITE12
:
6972 MOV_DD_SWP(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB12READWRITE
.NumOfBlocks
);
6978 MOV_SWP_DW2DD(AtaReq
->bcount
, ((PCDB
)Srb
->Cdb
)->CDB10
.TransferBlocks
);
6980 MOV_DD_SWP(AtaReq
->lba
, ((PCDB
)Srb
->Cdb
)->CDB10
.LBA
);
6982 AtaReq
->Flags
|= REQ_FLAG_REORDERABLE_CMD
;
6983 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6984 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
6985 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
6986 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ?
6987 REQ_FLAG_WRITE
: REQ_FLAG_READ
;
6990 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
6991 if(!AtaReq
->TransferLength
) {
6992 KdPrint((" assume 0-transfer\n"));
6994 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
6995 KdPrint((" assume OUT\n"));
6996 AtaReq
->Flags
|= REQ_FLAG_WRITE
;
6998 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
6999 KdPrint((" assume IN\n"));
7000 AtaReq
->Flags
|= REQ_FLAG_READ
;
7005 // check if DMA read/write
7006 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7007 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: force use dma (ahci)\n"));
7011 /* if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) {
7012 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n"));
7016 if(Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) {
7017 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
7019 if(AtaReq
->TransferLength
) {
7021 switch(Srb
->Cdb
[0]) {
7023 case SCSIOP_WRITE12
:
7024 case SCSIOP_WRITE16
:
7026 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
)
7029 case SCSIOP_RECEIVE
:
7034 if(deviceExtension
->opt_AtapiDmaReadWrite
) {
7036 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7037 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7040 if(AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7041 (PUCHAR
)(AtaReq
->DataBuffer
),
7042 Srb
->DataTransferLength
7043 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
7045 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7050 case SCSIOP_READ_CD
:
7051 if(deviceExtension
->opt_AtapiDmaRawRead
)
7052 goto call_dma_setup
;
7056 if(deviceExtension
->opt_AtapiDmaControlCmd
) {
7057 if(Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
7062 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_RO
) {
7063 KdPrint2((PRINT_PREFIX
"dma RO\n"));
7075 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7076 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (ahci)\n"));
7079 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7080 (PUCHAR
)(AtaReq
->DataBuffer
),
7081 Srb
->DataTransferLength
)) {
7082 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma\n"));
7085 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma\n"));
7089 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer, no DMA setup\n"));
7093 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7095 UniataAhciSetupCmdPtr(AtaReq
);
7097 if(!Srb
->DataTransferLength
) {
7098 KdPrint2((PRINT_PREFIX
"zero-transfer\n"));
7101 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
7102 (PUCHAR
)(AtaReq
->DataBuffer
),
7103 Srb
->DataTransferLength
)) {
7104 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no AHCI dma!\n"));
7105 return SRB_STATUS_ERROR
;
7108 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7110 FeatureReg
|= ATA_F_DMA
;
7111 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7112 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7113 FeatureReg
|= ATA_F_DMAREAD
;
7117 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: setup AHCI FIS\n"));
7118 // this is done in UniataAhciSetupFIS_H2D()
7119 //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
7120 RtlCopyMemory(&(AtaReq
->ahci
.ahci_cmd_ptr
->acmd
), Srb
->Cdb
, Srb
->CdbLength
);
7122 fis_size
= UniataAhciSetupFIS_H2D(deviceExtension
, DeviceNumber
, lChannel
,
7123 &(AtaReq
->ahci
.ahci_cmd_ptr
->cfis
[0]),
7124 IDE_COMMAND_ATAPI_PACKET
/* command */,
7126 (Srb
->DataTransferLength
>= 0x10000) ? (USHORT
)(0xffff) : (USHORT
)(Srb
->DataTransferLength
),
7127 FeatureReg
/* feature */
7131 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: AHCI !FIS\n"));
7132 return SRB_STATUS_ERROR
;
7135 AtaReq
->ahci
.io_cmd_flags
= UniAtaAhciAdjustIoFlags(0,
7136 ((Srb
->DataTransferLength
&& (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
)) ? ATA_AHCI_CMD_WRITE
: 0) |
7137 (ATA_AHCI_CMD_ATAPI
| ATA_AHCI_CMD_PREFETCH
),
7138 fis_size
, DeviceNumber
);
7140 KdPrint2((PRINT_PREFIX
"AtapiSendCommand ahci io flags %x: \n", AtaReq
->ahci
.io_cmd_flags
));
7144 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7145 // if this is queued request, reinit DMA and check
7146 // if DMA mode is still available
7147 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() (1)\n"));
7148 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7149 if (/*EnableDma &&*/
7150 (LunExt
->TransferMode
>= ATA_DMA
)) {
7151 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use dma (2)\n"));
7154 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7155 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: no dma (2)\n"));
7158 dma_reinited
= TRUE
;
7162 if(!(CmdAction
& CMD_ACTION_EXEC
)) {
7163 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
7164 return SRB_STATUS_PENDING
;
7166 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma
, Srb
->Cdb
[0]));
7167 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7168 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7171 if((Srb
->Cdb
[0] == SCSIOP_REQUEST_SENSE
) && !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7172 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
7174 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7175 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7176 } if(AtaReq
->TransferLength
) {
7178 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit()\n"));
7179 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7180 if (/*EnableDma &&*/
7181 (LunExt
->TransferMode
>= ATA_DMA
)) {
7184 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7189 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: zero transfer\n"));
7191 AtaReq
->Flags
&= ~REQ_FLAG_DMA_OPERATION
;
7192 if(!deviceExtension
->opt_AtapiDmaZeroTransfer
&& !(deviceExtension
->HwFlags
& UNIATA_SATA
)) {
7193 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
7194 AtapiDmaReinit(deviceExtension
, LunExt
, AtaReq
);
7197 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: use_dma=%d\n", use_dma
));
7198 if(AtaReq
->Flags
& REQ_FLAG_DMA_OPERATION
) {
7199 KdPrint2((PRINT_PREFIX
" REQ_FLAG_DMA_OPERATION\n"));
7202 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: CMD_ACTION_EXEC\n"));
7204 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
7205 &(Srb
->Cdb
), Srb
->Cdb
[0], Srb
->TargetId
, Srb
->Lun
));
7207 // Make sure command is to ATAPI device.
7208 flags
= LunExt
->DeviceFlags
;
7209 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7210 if((Srb
->Lun
) > (LunExt
->DiscsPresent
- 1)) {
7212 // Indicate no device found at this address.
7213 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7214 return SRB_STATUS_SELECTION_TIMEOUT
;
7216 } else if(Srb
->Lun
> 0) {
7217 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7218 return SRB_STATUS_SELECTION_TIMEOUT
;
7221 if(!(flags
& DFLAGS_ATAPI_DEVICE
)) {
7222 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7223 return SRB_STATUS_SELECTION_TIMEOUT
;
7226 // Select device 0 or 1. Or more for PM
7227 SelectDrive(chan
, DeviceNumber
);
7229 // Verify that controller is ready for next command.
7230 GetStatus(chan
, statusByte
);
7231 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status %#x\n", statusByte
));
7233 if(statusByte
== IDE_STATUS_WRONG
) {
7234 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: bad status 0xff on entry\n"));
7237 if(statusByte
& IDE_STATUS_BUSY
) {
7238 if(statusByte
& IDE_STATUS_DSC
) {
7239 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte
));
7241 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte
));
7242 // We have to make reset here, since we are expecting device to be available
7243 //return SRB_STATUS_BUSY; // this cause queue freeze
7247 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7249 // Check if command list is free
7250 CI
= UniataAhciReadChannelPort4(chan
, IDX_AHCI_P_CI
);
7252 // controller is busy, however we expect it to be free
7253 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI
));
7257 if(statusByte
& IDE_STATUS_ERROR
) {
7258 if (Srb
->Cdb
[0] != SCSIOP_REQUEST_SENSE
) {
7260 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on entry: (%#x)\n", statusByte
));
7261 // Read the error reg. to clear it and fail this request.
7262 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7263 return MapError(deviceExtension
, Srb
);
7265 KdPrint2((PRINT_PREFIX
" continue with SCSIOP_REQUEST_SENSE\n", statusByte
));
7268 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
7269 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
7270 if((!(statusByte
& IDE_STATUS_DSC
)) &&
7271 (flags
& (DFLAGS_TAPE_DEVICE
| DFLAGS_ATAPI_DEVICE
)) && chan
->RDP
) {
7273 AtapiStallExecution(200);
7274 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte
));
7275 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
7276 return SRB_STATUS_PENDING
;
7279 if(IS_RDP(Srb
->Cdb
[0])) {
7281 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb
->Cdb
[0]));
7285 if(statusByte
& IDE_STATUS_DRQ
) {
7287 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
7289 // Try to drain the data that one preliminary device thinks that it has
7290 // to transfer. Hopefully this random assertion of DRQ will not be present
7291 // in production devices.
7292 statusByte
= AtapiSuckPort2(chan
);
7294 for (i = 0; i < 0x10000; i++) {
7295 GetStatus(chan, statusByte);
7296 if(statusByte & IDE_STATUS_DRQ) {
7297 AtapiReadPort2(chan, IDX_IO1_i_Data);
7303 if (statusByte
& IDE_STATUS_DRQ
) {
7305 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte
));
7307 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7309 AtapiSoftReset(chan
, DeviceNumber
);
7311 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Issued soft reset to Atapi device. \n"));
7312 // Re-initialize Atapi device.
7313 CheckDevice(HwDeviceExtension
, GET_CHANNEL(Srb
), DeviceNumber
, TRUE
);
7315 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
7316 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
7318 // Inform the port driver that the bus has been reset.
7319 ScsiPortNotification(ResetDetected
, HwDeviceExtension
, 0);
7320 // Clean up device extension fields that AtapiStartIo won't.
7321 UniataExpectChannelInterrupt(chan
, FALSE
);
7323 InterlockedExchange(&(deviceExtension
->chan
[GET_CHANNEL(Srb
)].CheckIntr
),
7326 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7328 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7329 return SRB_STATUS_BUS_RESET;
7332 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: retry after reset.\n"));
7336 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: selection timeout.\n"));
7337 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7338 return SRB_STATUS_SELECTION_TIMEOUT
;
7342 if(flags
& (DFLAGS_SANYO_ATAPI_CHANGER
| DFLAGS_ATAPI_CHANGER
)) {
7343 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
7344 Srb
->Cdb
[1] &= ~0xE0;
7345 if((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
) && (flags
& DFLAGS_SANYO_ATAPI_CHANGER
)) {
7346 // Torisan changer. TUR's are overloaded to be platter switches.
7347 Srb
->Cdb
[7] = Srb
->Lun
;
7354 chan
->ChannelCtrlFlags
|= CTRFLAGS_DMA_OPERATION
;
7356 chan
->ChannelCtrlFlags
&= ~CTRFLAGS_DMA_OPERATION
;
7359 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
7360 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: AHCI, begin transaction\n"));
7361 //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
7362 UniataExpectChannelInterrupt(chan
, TRUE
);
7363 UniataAhciBeginTransaction(HwDeviceExtension
, lChannel
, DeviceNumber
, Srb
);
7364 return SRB_STATUS_PENDING
;
7367 statusByte
= WaitOnBusy(chan
);
7368 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Entry Status (%#x)\n",
7372 FeatureReg
|= ATA_F_DMA
;
7373 if(LunExt
->IdentifyData
.AtapiDMA
.DMADirRequired
&&
7374 (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
)) {
7375 FeatureReg
|= ATA_F_DMAREAD
;
7379 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, FeatureReg
);
7381 // Write transfer byte count to registers.
7382 byteCountLow
= (UCHAR
)(Srb
->DataTransferLength
& 0xFF);
7383 byteCountHigh
= (UCHAR
)(Srb
->DataTransferLength
>> 8);
7385 if (Srb
->DataTransferLength
>= 0x10000) {
7386 byteCountLow
= byteCountHigh
= 0xFF;
7389 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountLow
, byteCountLow
);
7390 AtapiWritePort1(chan
, IDX_ATAPI_IO1_o_ByteCountHigh
, byteCountHigh
);
7392 if (flags
& DFLAGS_INT_DRQ
) {
7394 // This device interrupts when ready to receive the packet.
7396 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
7399 UniataExpectChannelInterrupt(chan
, TRUE
);
7400 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_CMD_INTR
;
7401 InterlockedExchange(&(chan
->CheckIntr
),
7404 // Write ATAPI packet command.
7405 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7407 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
7408 return SRB_STATUS_PENDING
;
7412 // This device quickly sets DRQ when ready to receive the packet.
7414 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
7417 UniataExpectChannelInterrupt(chan
, TRUE
);
7418 AtaReq
->ReqState
= REQ_STATE_ATAPI_DO_NOTHING_INTR
;
7419 InterlockedExchange(&(chan
->CheckIntr
),
7422 if(g_opt_AtapiSendDisableIntr
) {
7423 AtapiDisableInterrupts(deviceExtension
, lChannel
);
7425 // remember status. Later we may check if error appeared after cmd packet
7426 statusByte0
= statusByte
;
7428 // Write ATAPI packet command.
7429 AtapiWritePort1(chan
, IDX_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
7433 statusByte
= WaitForDrq(chan
);
7435 // Need to read status register and clear interrupt (if any)
7436 GetBaseStatus(chan
, statusByte
);
7438 if (!(statusByte
& IDE_STATUS_DRQ
)) {
7440 if(g_opt_AtapiSendDisableIntr
) {
7441 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7443 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte
));
7444 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7445 return SRB_STATUS_ERROR
;
7448 GetStatus(chan
, statusByte
);
7449 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: status (%#x)\n", statusByte
));
7451 // Send CDB to device.
7452 statusByte
= WaitOnBaseBusy(chan
);
7454 // Indicate expecting an interrupt and wait for it.
7455 UniataExpectChannelInterrupt(chan
, TRUE
);
7456 InterlockedExchange(&(chan
->CheckIntr
),
7458 AtaReq
->ReqState
= REQ_STATE_ATAPI_EXPECTING_DATA_INTR
;
7460 GetBaseStatus(chan
, statusByte
);
7462 if(g_opt_AtapiSendDisableIntr
) {
7463 AtapiEnableInterrupts(deviceExtension
, lChannel
);
7468 LunExt
->IdentifyData
.AtapiCmdSize
? 8 : 6,
7471 GetStatus(chan
, statusByte
);
7472 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: cmd status (%#x)\n", statusByte
));
7474 // When we operate in DMA mode, we should not start transfer when there is an error on entry
7475 // Interrupt may never come in such case.
7476 if(statusByte
& IDE_STATUS_ERROR
) {
7477 UCHAR interruptReason
;
7479 GetBaseStatus(chan
, statusByte
);
7480 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: Error on cmd: (%#x)\n", statusByte
));
7482 interruptReason
= (AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_InterruptReason
) & ATAPI_IR_Mask
);
7483 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: iReason %x\n", interruptReason
));
7485 // TODO: we should check interruptReason and decide what to do now
7487 // Read the error reg. to clear it and fail this request.
7488 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
7489 return MapError(deviceExtension
, Srb
);
7491 /* if(statusByte & IDE_STATUS_DSC) {
7492 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DSC on cmd: (%#x)\n", statusByte));
7493 // Read the error reg. to clear it and fail this request.
7494 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7495 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte));
7496 if(statusByte >> 4) {
7497 GetBaseStatus(chan, statusByte);
7498 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7499 return MapError(deviceExtension, Srb);
7503 if(chan
->ChannelCtrlFlags
& CTRFLAGS_DMA_OPERATION
) {
7504 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
7507 KdPrint3((PRINT_PREFIX
"AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan
->ExpectingInterrupt
));
7509 KdPrint2((PRINT_PREFIX
"AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
7510 return SRB_STATUS_PENDING
;
7512 } // end AtapiSendCommand()
7519 Routine Description:
7520 Program ATA registers for IDE disk transfer.
7523 HwDeviceExtension - ATAPI driver storage.
7524 Srb - System request block.
7527 SRB status (pending if all goes well).
7532 ULONG check_point
= 0;
7533 #define SetCheckPoint(cp) { check_point = (cp) ; }
7535 #define SetCheckPoint(cp)
7541 IN PVOID HwDeviceExtension
,
7542 IN PSCSI_REQUEST_BLOCK Srb
,
7547 KdPrint2((PRINT_PREFIX
"** Ide: Command: entryway\n"));
7550 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
7555 PHW_LU_EXTENSION LunExt
;
7559 UCHAR statusByte
,errorByte
;
7560 ULONG status
= SRB_STATUS_INVALID_REQUEST
;
7563 PMODE_PARAMETER_HEADER modeData
;
7570 //ULONG __ebp__ = 0;
7572 SetCheckPoint(0x20);
7573 KdPrint2((PRINT_PREFIX
"** Ide: Command:\n\n"));
7578 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
7579 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
7580 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
7581 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
7582 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
7584 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
7585 Srb->SrbExtension));
7586 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
7589 SetCheckPoint(0x30);
7590 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
7592 KdPrint2((PRINT_PREFIX
"** Ide: Command &AtaReq %#x\n",
7594 KdPrint2((PRINT_PREFIX
"** Ide: Command AtaReq %#x\n",
7596 KdPrint2((PRINT_PREFIX
"** --- **\n"));
7598 lChannel
= GET_CHANNEL(Srb
);
7599 chan
= &(deviceExtension
->chan
[lChannel
]);
7600 //ldev = GET_LDEV(Srb);
7601 DeviceNumber
= GET_CDEV(Srb
);
7602 LunExt
= chan
->lun
[DeviceNumber
];
7604 SetCheckPoint(0x40);
7605 if(AtaReq
->ReqState
< REQ_STATE_PREPARE_TO_TRANSFER
)
7606 AtaReq
->ReqState
= REQ_STATE_PREPARE_TO_TRANSFER
;
7608 cdb
= (PCDB
)(Srb
->Cdb
);
7610 if(CmdAction
== CMD_ACTION_PREPARE
) {
7611 switch (Srb
->Cdb
[0]) {
7612 case SCSIOP_SERVICE_ACTION16
:
7613 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
7616 goto default_no_prep
;
7619 case SCSIOP_INQUIRY
: // now it requires device access
7621 case SCSIOP_READ_CAPACITY
:
7625 case SCSIOP_WRITE12
:
7627 case SCSIOP_WRITE16
:
7628 case SCSIOP_REQUEST_SENSE
:
7630 KdPrint2((PRINT_PREFIX
"** Ide: Command continue prep\n"));
7636 KdPrint2((PRINT_PREFIX
"** Ide: Command break prep\n"));
7637 return SRB_STATUS_BUSY
;
7641 SetCheckPoint(0x100 | Srb
->Cdb
[0]);
7642 switch (Srb
->Cdb
[0]) {
7643 case SCSIOP_INQUIRY
:
7645 KdPrint2((PRINT_PREFIX
7646 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
7647 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7648 // Filter out wrong TIDs.
7649 if ((Srb
->Lun
!= 0) ||
7650 (Srb
->PathId
>= deviceExtension
->NumberChannels
) ||
7651 (Srb
->TargetId
>= deviceExtension
->NumberLuns
)) {
7653 KdPrint2((PRINT_PREFIX
7654 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
7655 // Indicate no device found at this address.
7656 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7661 KdPrint2((PRINT_PREFIX
7662 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
7663 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
7664 PIDENTIFY_DATA2 identifyData
= &(LunExt
->IdentifyData
);
7666 if (!(chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
7668 if(!CheckDevice(HwDeviceExtension
, lChannel
, DeviceNumber
, FALSE
)) {
7669 KdPrint2((PRINT_PREFIX
7670 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
7671 // Indicate no device found at this address.
7673 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7677 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, DeviceNumber
)) {
7678 KdPrint2((PRINT_PREFIX
7679 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
7680 // Indicate no device found at this address.
7681 UniataForgetDevice(chan
->lun
[DeviceNumber
]);
7683 status
= SRB_STATUS_SELECTION_TIMEOUT
;
7688 // Zero INQUIRY data structure.
7689 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
7691 // Standard IDE interface only supports disks.
7692 inquiryData
->DeviceType
= DIRECT_ACCESS_DEVICE
;
7694 // Set the removable bit, if applicable.
7695 if (LunExt
->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
7696 KdPrint2((PRINT_PREFIX
7697 "RemovableMedia\n"));
7698 inquiryData
->RemovableMedia
= 1;
7700 // Set the Relative Addressing (LBA) bit, if applicable.
7701 if (LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) {
7702 inquiryData
->RelativeAddressing
= 1;
7703 KdPrint2((PRINT_PREFIX
7704 "RelativeAddressing\n"));
7706 // Set the CommandQueue bit
7707 inquiryData
->CommandQueue
= 1;
7709 // Fill in vendor identification fields.
7710 for (i
= 0; i
< 24; i
+= 2) {
7711 MOV_DW_SWP(inquiryData
->DeviceIdentificationString
[i
], ((PUCHAR
)identifyData
->ModelNumber
)[i
]);
7714 // Initialize unused portion of product id.
7715 for (i = 0; i < 4; i++) {
7716 inquiryData->ProductId[12+i] = ' ';
7719 // Move firmware revision from IDENTIFY data to
7720 // product revision in INQUIRY data.
7721 for (i
= 0; i
< 4; i
+= 2) {
7722 MOV_DW_SWP(inquiryData
->ProductRevisionLevel
[i
], ((PUCHAR
)identifyData
->FirmwareRevision
)[i
]);
7725 status
= SRB_STATUS_SUCCESS
;
7730 case SCSIOP_REPORT_LUNS
: {
7733 PREPORT_LUNS_INFO_HDR LunInfo
;
7735 KdPrint2((PRINT_PREFIX
7736 "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
7737 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7739 MOV_DD_SWP(alen
, cdb
->REPORT_LUNS
.AllocationLength
);
7746 LunInfo
= (PREPORT_LUNS_INFO_HDR
)(Srb
->DataBuffer
);
7747 RtlZeroMemory(LunInfo
, 16);
7749 MOV_DD_SWP( LunInfo
->ListLength
, alen
);
7750 Srb
->DataTransferLength
= 16;
7751 status
= SRB_STATUS_SUCCESS
;
7755 case SCSIOP_MODE_SENSE
:
7757 KdPrint2((PRINT_PREFIX
7758 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
7759 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7761 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_POWER_CONDITION
) {
7762 PMODE_POWER_CONDITION_PAGE modeData
;
7764 KdPrint2((PRINT_PREFIX
"MODE_PAGE_POWER_CONDITION\n"));
7765 modeData
= (PMODE_POWER_CONDITION_PAGE
)(Srb
->DataBuffer
);
7766 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_POWER_CONDITION_PAGE
)) {
7767 status
= SRB_STATUS_DATA_OVERRUN
;
7769 RtlZeroMemory(modeData
, sizeof(MODE_POWER_CONDITION_PAGE
));
7770 modeData
->PageCode
= MODE_PAGE_POWER_CONDITION
;
7771 modeData
->PageLength
= sizeof(MODE_PAGE_POWER_CONDITION
)-sizeof(MODE_PARAMETER_HEADER
);
7772 modeData
->Byte3
.Fields
.Idle
= LunExt
->PowerState
<= StartStop_Power_Idle
;
7773 modeData
->Byte3
.Fields
.Standby
= LunExt
->PowerState
== StartStop_Power_Standby
;
7774 Srb
->DataTransferLength
= sizeof(MODE_POWER_CONDITION_PAGE
);
7775 status
= SRB_STATUS_SUCCESS
;
7778 if(cdb
->MODE_SENSE
.PageCode
== MODE_PAGE_CACHING
) {
7779 PMODE_CACHING_PAGE modeData
;
7781 KdPrint2((PRINT_PREFIX
"MODE_PAGE_CACHING\n"));
7782 modeData
= (PMODE_CACHING_PAGE
)(Srb
->DataBuffer
);
7783 if(cdb
->MODE_SENSE
.AllocationLength
< sizeof(MODE_CACHING_PAGE
)) {
7784 status
= SRB_STATUS_DATA_OVERRUN
;
7786 RtlZeroMemory(modeData
, sizeof(MODE_CACHING_PAGE
));
7787 modeData
->PageCode
= MODE_PAGE_CACHING
;
7788 modeData
->PageLength
= sizeof(MODE_CACHING_PAGE
)-sizeof(MODE_PARAMETER_HEADER
);
7789 modeData
->ReadDisableCache
= (LunExt
->DeviceFlags
& DFLAGS_RCACHE_ENABLED
) ? 0 : 1;
7790 modeData
->WriteCacheEnable
= (LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) ? 1 : 0;
7791 Srb
->DataTransferLength
= sizeof(MODE_CACHING_PAGE
);
7792 status
= SRB_STATUS_SUCCESS
;
7795 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
7797 // This is used to determine if the media is write-protected.
7798 // Since IDE does not support mode sense then we will modify just the portion we need
7799 // so the higher level driver can determine if media is protected.
7801 //SelectDrive(chan, DeviceNumber);
7802 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7803 //statusByte = WaitOnBusy(chan);
7804 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
7806 if (!(statusByte
& IDE_STATUS_ERROR
)) {
7808 // no error occured return success, media is not protected
7809 UniataExpectChannelInterrupt(chan
, FALSE
);
7810 InterlockedExchange(&(chan
->CheckIntr
),
7812 status
= SRB_STATUS_SUCCESS
;
7816 // error occured, handle it locally, clear interrupt
7817 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7819 GetBaseStatus(chan
, statusByte
);
7820 UniataExpectChannelInterrupt(chan
, FALSE
);
7821 InterlockedExchange(&(chan
->CheckIntr
),
7823 status
= SRB_STATUS_SUCCESS
;
7825 if (errorByte
& IDE_ERROR_DATA_ERROR
) {
7827 //media is write-protected, set bit in mode sense buffer
7828 modeData
= (PMODE_PARAMETER_HEADER
)Srb
->DataBuffer
;
7830 Srb
->DataTransferLength
= sizeof(MODE_PARAMETER_HEADER
);
7831 modeData
->DeviceSpecificParameter
|= MODE_DSP_WRITE_PROTECT
;
7834 status
= SRB_STATUS_SUCCESS
;
7836 status
= SRB_STATUS_INVALID_REQUEST
;
7840 case SCSIOP_TEST_UNIT_READY
:
7842 KdPrint2((PRINT_PREFIX
7843 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
7844 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7845 if (chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
7847 // Select device 0 or 1.
7848 //SelectDrive(chan, DeviceNumber);
7849 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7850 // Wait for busy. If media has not changed, return success
7851 //statusByte = WaitOnBusy(chan);
7852 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_GET_MEDIA_STATUS
, 0, 0, 0, 0, 0, ATA_WAIT_READY
);
7854 if (!(statusByte
& IDE_STATUS_ERROR
)){
7855 UniataExpectChannelInterrupt(chan
, FALSE
);
7856 InterlockedExchange(&(chan
->CheckIntr
),
7858 status
= SRB_STATUS_SUCCESS
;
7860 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
7861 if (errorByte
== IDE_ERROR_DATA_ERROR
){
7863 // Special case: If current media is write-protected,
7864 // the 0xDA command will always fail since the write-protect bit
7865 // is sticky,so we can ignore this error
7866 GetBaseStatus(chan
, statusByte
);
7867 UniataExpectChannelInterrupt(chan
, FALSE
);
7868 InterlockedExchange(&(chan
->CheckIntr
),
7870 status
= SRB_STATUS_SUCCESS
;
7874 // Request sense buffer to be build
7875 UniataExpectChannelInterrupt(chan
, TRUE
);
7876 InterlockedExchange(&(chan
->CheckIntr
),
7878 status
= SRB_STATUS_PENDING
;
7882 status
= SRB_STATUS_SUCCESS
;
7887 case SCSIOP_READ_CAPACITY
:
7889 KdPrint2((PRINT_PREFIX
7890 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7891 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7892 // Claim 512 byte blocks (big-endian).
7893 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7895 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY_DATA
));
7896 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
7898 // Calculate last sector.
7899 if(!(i
= (ULONG
)LunExt
->NumOfSectors
)) {
7900 i
= LunExt
->IdentifyData
.SectorsPerTrack
*
7901 LunExt
->IdentifyData
.NumberOfHeads
*
7902 LunExt
->IdentifyData
.NumberOfCylinders
;
7906 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
7907 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
7908 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
7910 MOV_DD_SWP( ((PREAD_CAPACITY_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, i
);
7912 KdPrint2((PRINT_PREFIX
7913 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
7915 LunExt
->IdentifyData
.SectorsPerTrack
,
7916 LunExt
->IdentifyData
.NumberOfHeads
,
7917 LunExt
->IdentifyData
.NumberOfCylinders
));
7920 status
= SRB_STATUS_SUCCESS
;
7923 case SCSIOP_SERVICE_ACTION16
:
7925 if( cdb
->SERVICE_ACTION16
.ServiceAction
==SCSIOP_SA_READ_CAPACITY16
) {
7926 KdPrint2((PRINT_PREFIX
7927 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7928 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7929 // Claim 512 byte blocks (big-endian).
7930 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7932 RtlZeroMemory(Srb
->DataBuffer
, sizeof(READ_CAPACITY16_DATA
));
7933 MOV_DD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->BytesPerBlock
, i
);
7935 // Calculate last sector.
7936 if(!(lba
= LunExt
->NumOfSectors
)) {
7937 lba
= LunExt
->IdentifyData
.SectorsPerTrack
*
7938 LunExt
->IdentifyData
.NumberOfHeads
*
7939 LunExt
->IdentifyData
.NumberOfCylinders
;
7942 MOV_QD_SWP( ((PREAD_CAPACITY16_DATA
)Srb
->DataBuffer
)->LogicalBlockAddress
, lba
);
7944 KdPrint2((PRINT_PREFIX
7945 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n",
7947 LunExt
->IdentifyData
.SectorsPerTrack
,
7948 LunExt
->IdentifyData
.NumberOfHeads
,
7949 LunExt
->IdentifyData
.NumberOfCylinders
));
7951 status
= SRB_STATUS_SUCCESS
;
7958 case SCSIOP_VERIFY12
:
7959 case SCSIOP_VERIFY16
:
7961 KdPrint2((PRINT_PREFIX
7962 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
7963 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7964 status
= IdeVerify(HwDeviceExtension
,Srb
);
7971 case SCSIOP_WRITE12
:
7973 case SCSIOP_WRITE16
:
7975 KdPrint2((PRINT_PREFIX
7976 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
7977 (Srb
->Cdb
[0] == SCSIOP_WRITE
) ? "WRITE" : "READ",
7978 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7979 AtaReq
->Flags
&= ~REQ_FLAG_RW_MASK
;
7980 AtaReq
->Flags
|= (Srb
->Cdb
[0] == SCSIOP_WRITE
||
7981 Srb
->Cdb
[0] == SCSIOP_WRITE12
||
7982 Srb
->Cdb
[0] == SCSIOP_WRITE16
) ? REQ_FLAG_WRITE
: REQ_FLAG_READ
;
7983 status
= IdeReadWrite(HwDeviceExtension
,
7987 case SCSIOP_START_STOP_UNIT
:
7989 KdPrint2((PRINT_PREFIX
7990 "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
7991 cdb
->START_STOP
.Immediate
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
7992 //Determine what type of operation we should perform
7996 if(cdb
->START_STOP
.FL
||
7997 cdb
->START_STOP
.FormatLayerNumber
||
7998 cdb
->START_STOP
.Reserved2
||
7999 cdb
->START_STOP
.Reserved2_2
||
8000 cdb
->START_STOP
.Reserved3
||
8005 if (cdb
->START_STOP
.PowerConditions
) {
8006 KdPrint2((PRINT_PREFIX
"START_STOP Power %d\n", cdb
->START_STOP
.PowerConditions
));
8007 switch(cdb
->START_STOP
.PowerConditions
) {
8008 case StartStop_Power_Idle
:
8009 command
= IDE_COMMAND_IDLE_IMMED
;
8011 case StartStop_Power_Standby
:
8012 command
= IDE_COMMAND_STANDBY_IMMED
;
8014 case StartStop_Power_Sleep
:
8015 // TODO: we should save power state in order to know
8016 // that RESET sould be issued to revert device into
8019 command
= IDE_COMMAND_SLEEP
;
8024 LunExt
->PowerState
= cdb
->START_STOP
.PowerConditions
;
8026 if (cdb
->START_STOP
.LoadEject
== 1) {
8027 KdPrint2((PRINT_PREFIX
"START_STOP eject\n"));
8029 // first select device 0 or 1.
8030 //SelectDrive(chan, DeviceNumber);
8031 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
8032 command
= IDE_COMMAND_MEDIA_EJECT
;
8034 if (cdb
->START_STOP
.Start
== 0) {
8035 KdPrint2((PRINT_PREFIX
"START_STOP standby\n"));
8036 command
= IDE_COMMAND_STANDBY_IMMED
;
8038 // TODO: we may need to perform hard reset (after sleep) or
8039 // issue IDE_COMMAND_IDLE_IMMED in order to activate device
8040 KdPrint2((PRINT_PREFIX
"START_STOP activate\n"));
8042 if(LunExt
->PowerState
== StartStop_Power_Sleep
) {
8043 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
8044 status
= SRB_STATUS_SUCCESS
;
8047 if(LunExt
->PowerState
> StartStop_Power_Idle
) {
8048 KdPrint2((PRINT_PREFIX
" issue IDLE\n"));
8049 command
= IDE_COMMAND_IDLE_IMMED
;
8051 KdPrint2((PRINT_PREFIX
" do nothing\n"));
8052 status
= SRB_STATUS_SUCCESS
;
8057 statusByte
= WaitOnBaseBusy(chan
);
8058 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, command
, 0, 0, 0, 0, 0,
8059 cdb
->START_STOP
.Immediate
? ATA_IMMEDIATE
: ATA_WAIT_READY
);
8060 status
= (statusByte
& IDE_STATUS_ERROR
) ? SRB_STATUS_ERROR
: SRB_STATUS_SUCCESS
;
8061 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
8065 KdPrint2((PRINT_PREFIX
"START_STOP invalid\n"));
8066 if (Srb
->SenseInfoBuffer
) {
8068 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8070 senseBuffer
->ErrorCode
= 0x70;
8071 senseBuffer
->Valid
= 1;
8072 senseBuffer
->AdditionalSenseLength
= 0xb;
8073 senseBuffer
->SenseKey
= SCSI_SENSE_ILLEGAL_REQUEST
;
8074 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_INVALID_CDB
;
8075 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8077 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8078 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8080 status
= SRB_STATUS_ERROR
;
8084 case SCSIOP_MEDIUM_REMOVAL
:
8086 cdb
= (PCDB
)Srb
->Cdb
;
8088 if(LunExt
->IdentifyData
.Removable
) {
8089 statusByte
= WaitOnBaseBusy(chan
);
8091 //SelectDrive(chan, DeviceNumber);
8092 if (cdb
->MEDIA_REMOVAL
.Prevent
== TRUE
) {
8093 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
8094 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_LOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8096 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
8097 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
, IDE_COMMAND_DOOR_UNLOCK
, 0, 0, 0, 0, 0, ATA_IMMEDIATE
);
8099 status
= SRB_STATUS_SUCCESS
;
8101 status
= SRB_STATUS_INVALID_REQUEST
;
8106 // Note: I don't implement this, because NTFS driver too often issues this command
8107 // It causes awful performance degrade. However, if somebody wants, I will implement
8108 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
8109 case SCSIOP_FLUSH_BUFFER
:
8110 case SCSIOP_SYNCHRONIZE_CACHE
:
8112 SelectDrive(chan
, DeviceNumber
);
8113 AtapiWritePort1(chan
, IDX_IO1_o_Command
,IDE_COMMAND_FLUSH_CACHE
);
8114 status
= SRB_STATUS_SUCCESS
;
8115 // status = SRB_STATUS_PENDING;
8116 statusByte
= WaitOnBusy(chan
);
8120 case SCSIOP_REQUEST_SENSE
:
8121 // this function makes sense buffers to report the results
8122 // of the original GET_MEDIA_STATUS command
8124 KdPrint2((PRINT_PREFIX
8125 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8126 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8127 if (LunExt
->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
) {
8128 status
= IdeBuildSenseBuffer(HwDeviceExtension
,Srb
);
8131 status
= SRB_STATUS_INVALID_REQUEST
;
8135 case SCSIOP_ATA_PASSTHROUGH
:
8138 BOOLEAN use_dma
= FALSE
;
8141 regs
= (PIDEREGS_EX
) &(Srb
->Cdb
[2]);
8143 if(chan
->DeviceExtension
->HwFlags
& UNIATA_SATA
) {
8144 //lChannel = Srb->TargetId >> 1;
8146 DeviceNumber
= max(DeviceNumber
, 1);
8147 regs
->bDriveHeadReg
&= 0x0f;
8148 regs
->bDriveHeadReg
|= (UCHAR
) (((DeviceNumber
& 0x1) << 4) | 0xA0);
8151 if((regs
->bOpFlags
& 1) == 0) { // execute ATA command
8153 KdPrint2((PRINT_PREFIX
8154 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
8155 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8157 if((regs
->bOpFlags
& UNIATA_SPTI_EX_SPEC_TO
) == UNIATA_SPTI_EX_SPEC_TO
) {
8158 to_lim
= Srb
->TimeOutValue
;
8160 if(Srb
->TimeOutValue
<= 2) {
8161 to_lim
= Srb
->TimeOutValue
*900;
8163 to_lim
= (Srb
->TimeOutValue
*999) - 500;
8167 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8169 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
8171 statusByte
= UniataAhciSendPIOCommandDirect(
8180 if(statusByte
== IDE_STATUS_WRONG
) {
8181 goto passthrough_err
;
8183 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8184 UniataAhciAbortOperation(chan
);
8185 goto passthrough_err
;
8187 goto passthrough_done
;
8191 if((AtaCommandFlags
[regs
->bCommandReg
] & ATA_CMD_FLAG_DMA
) || (regs
->bOpFlags
& UNIATA_SPTI_EX_USE_DMA
)) {
8192 if((chan
->lun
[DeviceNumber
]->LimitedTransferMode
>= ATA_DMA
)) {
8194 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
8195 if(!AtapiDmaSetup(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
,
8196 (PUCHAR
)(Srb
->DataBuffer
),
8197 ((Srb
->DataTransferLength
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)))) {
8203 AtapiWritePort1(chan
, IDX_IO1_o_DriveSelect
, regs
->bDriveHeadReg
);
8204 AtapiStallExecution(10);
8206 if((regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
) == 0) { // execute ATA command
8207 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8208 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8209 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8210 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8211 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8213 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesRegH
);
8214 AtapiWritePort1(chan
, IDX_IO1_o_Feature
, regs
->bFeaturesReg
);
8215 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountRegH
);
8216 AtapiWritePort1(chan
, IDX_IO1_o_BlockCount
, regs
->bSectorCountReg
);
8217 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberRegH
);
8218 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, regs
->bSectorNumberReg
);
8219 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowRegH
);
8220 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, regs
->bCylLowReg
);
8221 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighRegH
);
8222 AtapiWritePort1(chan
, IDX_IO1_o_CylinderHigh
, regs
->bCylHighReg
);
8224 AtapiWritePort1(chan
, IDX_IO1_o_Command
, regs
->bCommandReg
);
8227 GetBaseStatus(chan
, statusByte
);
8228 if(statusByte
& IDE_STATUS_ERROR
) {
8229 goto passthrough_err
;
8231 AtapiDmaStart(HwDeviceExtension
, DeviceNumber
, lChannel
, Srb
);
8234 ScsiPortStallExecution(1); // wait for busy to be set
8236 for(i
=0; i
<to_lim
;i
+=2) { // 2 msec from WaitOnBaseBusy()
8237 statusByte
= WaitOnBaseBusy(chan
); // wait for busy to be clear, up to 2 msec
8238 GetBaseStatus(chan
, statusByte
);
8239 if(statusByte
& IDE_STATUS_ERROR
) {
8242 if(!(statusByte
& IDE_STATUS_BUSY
)) {
8247 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
8249 AtapiResetController__(HwDeviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8250 goto passthrough_err
;
8254 AtapiCheckInterrupt__(deviceExtension
, (UCHAR
)lChannel
);
8256 AtapiDmaDone(deviceExtension
, DeviceNumber
, lChannel
, NULL
);
8257 GetBaseStatus(chan
, statusByte
);
8259 if(statusByte
& (IDE_STATUS_BUSY
| IDE_STATUS_ERROR
)) {
8260 AtapiSuckPort2(chan
);
8262 if (Srb
->SenseInfoBuffer
) {
8264 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->SenseInfoBuffer
;
8266 senseBuffer
->ErrorCode
= 0x70;
8267 senseBuffer
->Valid
= 1;
8268 senseBuffer
->AdditionalSenseLength
= 0xb;
8269 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
8270 senseBuffer
->AdditionalSenseCode
= 0;
8271 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8273 Srb
->SrbStatus
= SRB_STATUS_AUTOSENSE_VALID
;
8274 Srb
->ScsiStatus
= SCSISTAT_CHECK_CONDITION
;
8276 status
= SRB_STATUS_ERROR
;
8280 if (statusByte
& IDE_STATUS_DRQ
) {
8281 if (Srb
->SrbFlags
& SRB_FLAGS_DATA_IN
) {
8283 (PUSHORT
) Srb
->DataBuffer
,
8284 Srb
->DataTransferLength
/ 2,
8286 } else if (Srb
->SrbFlags
& SRB_FLAGS_DATA_OUT
) {
8288 (PUSHORT
) Srb
->DataBuffer
,
8289 Srb
->DataTransferLength
/ 2,
8294 status
= SRB_STATUS_SUCCESS
;
8297 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8299 } else { // read task register
8302 regs
= (PIDEREGS_EX
) Srb
->DataBuffer
;
8304 KdPrint2((PRINT_PREFIX
8305 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
8306 Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8308 if((Srb
->DataTransferLength
>= sizeof(IDEREGS_EX
)) &&
8309 (regs
->bOpFlags
& ATA_FLAGS_48BIT_COMMAND
)) {
8312 if(Srb
->DataTransferLength
>= sizeof(IDEREGS
)) {
8315 KdPrint2((PRINT_PREFIX
" buffer too small \n"));
8316 status
= SRB_STATUS_DATA_OVERRUN
;
8319 RtlZeroMemory(regs
, use48
? sizeof(IDEREGS_EX
) : sizeof(IDEREGS
));
8320 regs
->bOpFlags
= use48
? ATA_FLAGS_48BIT_COMMAND
: 0;
8321 UniataSnapAtaRegs(chan
, 0, regs
);
8323 status
= SRB_STATUS_SUCCESS
;
8330 KdPrint2((PRINT_PREFIX
8331 "IdeSendCommand: Unsupported command %#x\n",
8334 status
= SRB_STATUS_INVALID_REQUEST
;
8338 if(status
== SRB_STATUS_PENDING
) {
8339 KdPrint2((PRINT_PREFIX
"IdeSendCommand: SRB_STATUS_PENDING\n"));
8340 if(CmdAction
& CMD_ACTION_EXEC
) {
8341 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
8342 AtaReq
->ReqState
= REQ_STATE_EXPECTING_INTR
;
8345 KdPrint2((PRINT_PREFIX
"IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
8346 AtaReq
->ReqState
= REQ_STATE_TRANSFER_COMPLETE
;
8351 } // end IdeSendCommand()
8356 Routine Description:
8357 Enables disables media status notification
8360 HwDeviceExtension - ATAPI driver storage.
8367 IN PVOID HwDeviceExtension
,
8369 IN ULONG DeviceNumber
8372 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8374 UCHAR statusByte
,errorByte
;
8376 chan
= &(deviceExtension
->chan
[lChannel
]);
8377 SelectDrive(chan
, DeviceNumber
);
8379 if (EnableMSN
== TRUE
){
8381 // If supported enable Media Status Notification support
8382 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
)) {
8385 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8386 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8387 0, ATA_C_F_ENAB_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8389 if (statusByte
& IDE_STATUS_ERROR
) {
8390 // Read the error register.
8391 errorByte
= AtapiReadPort1(chan
, IDX_IO1_i_Error
);
8393 KdPrint2((PRINT_PREFIX
8394 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
8398 chan
->lun
[DeviceNumber
]->DeviceFlags
|= DFLAGS_MEDIA_STATUS_ENABLED
;
8399 KdPrint2((PRINT_PREFIX
"IdeMediaStatus: Media Status Notification Supported\n"));
8400 chan
->ReturningMediaStatus
= 0;
8405 } else { // end if EnableMSN == TRUE
8407 // disable if previously enabled
8408 if ((chan
->lun
[DeviceNumber
]->DeviceFlags
& DFLAGS_MEDIA_STATUS_ENABLED
)) {
8410 statusByte
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8411 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8412 0, ATA_C_F_DIS_MEDIASTAT
, ATA_WAIT_BASE_READY
);
8413 chan
->lun
[DeviceNumber
]->DeviceFlags
&= ~DFLAGS_MEDIA_STATUS_ENABLED
;
8420 } // end IdeMediaStatus()
8425 Routine Description:
8427 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
8428 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
8431 HwDeviceExtension - ATAPI driver storage.
8432 Srb - System request block.
8436 SRB status (ALWAYS SUCCESS).
8441 IdeBuildSenseBuffer(
8442 IN PVOID HwDeviceExtension
,
8443 IN PSCSI_REQUEST_BLOCK Srb
8446 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8448 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)Srb
->DataBuffer
;
8449 UCHAR ReturningMediaStatus
= deviceExtension
->chan
[GET_CHANNEL(Srb
)].ReturningMediaStatus
;
8453 if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE
) {
8455 senseBuffer
->ErrorCode
= 0x70;
8456 senseBuffer
->Valid
= 1;
8457 senseBuffer
->AdditionalSenseLength
= 0xb;
8458 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8459 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8460 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8461 } else if(ReturningMediaStatus
& IDE_ERROR_MEDIA_CHANGE_REQ
) {
8463 senseBuffer
->ErrorCode
= 0x70;
8464 senseBuffer
->Valid
= 1;
8465 senseBuffer
->AdditionalSenseLength
= 0xb;
8466 senseBuffer
->SenseKey
= SCSI_SENSE_UNIT_ATTENTION
;
8467 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_MEDIUM_CHANGED
;
8468 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8469 } else if(ReturningMediaStatus
& IDE_ERROR_END_OF_MEDIA
) {
8471 senseBuffer
->ErrorCode
= 0x70;
8472 senseBuffer
->Valid
= 1;
8473 senseBuffer
->AdditionalSenseLength
= 0xb;
8474 senseBuffer
->SenseKey
= SCSI_SENSE_NOT_READY
;
8475 senseBuffer
->AdditionalSenseCode
= SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
;
8476 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8477 } else if(ReturningMediaStatus
& IDE_ERROR_DATA_ERROR
) {
8479 senseBuffer
->ErrorCode
= 0x70;
8480 senseBuffer
->Valid
= 1;
8481 senseBuffer
->AdditionalSenseLength
= 0xb;
8482 senseBuffer
->SenseKey
= SCSI_SENSE_DATA_PROTECT
;
8483 senseBuffer
->AdditionalSenseCode
= 0;
8484 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8486 return SRB_STATUS_SUCCESS
;
8488 return SRB_STATUS_ERROR
;
8490 }// End of IdeBuildSenseBuffer
8494 UniataUserDeviceReset(
8495 PHW_DEVICE_EXTENSION deviceExtension
,
8496 PHW_LU_EXTENSION LunExt
,
8501 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8502 if ((LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) &&
8503 (LunExt
->PowerState
!= StartStop_Power_Sleep
)) {
8504 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset ATAPI\n"));
8505 AtapiSoftReset(&(deviceExtension
->chan
[lChannel
]), LunExt
->Lun
);
8507 KdPrint2((PRINT_PREFIX
"UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
8508 AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_NONE
);
8509 for(i
=0; i
<deviceExtension
->NumberLuns
; i
++) {
8510 deviceExtension
->chan
[lChannel
].lun
[i
]->DeviceFlags
|= DFLAGS_REINIT_DMA
;
8513 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
8514 AtapiEnableInterrupts(deviceExtension
, lChannel
);
8516 } // end UniataUserDeviceReset()
8521 PHW_DEVICE_EXTENSION deviceExtension
,
8526 BOOLEAN PostReq
= FALSE
;
8528 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: TopLevel, qd=%x\n", chan
->queue_depth
));
8529 if(chan
->queue_depth
> 0) {
8532 ((Srb
->Cdb
[0] == SCSIOP_TEST_UNIT_READY
)/* ||
8533 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
8534 KdPrint2((PRINT_PREFIX
"spec: SCSIOP_TEST_UNIT_READY\n"));
8536 status
= SRB_STATUS_BUSY
;
8545 if(deviceExtension
->simplexOnly
&& deviceExtension
->queue_depth
> 0) {
8549 KdPrint3((PRINT_PREFIX
"UniataNeedQueueing: qd=%x\n", chan
->queue_depth
));
8552 } // end UniataNeedQueueing()
8556 Routine Description:
8558 This routine is called from the SCSI port driver synchronized
8559 with the kernel to start an IO request.
8564 HwDeviceExtension - HBA miniport driver's adapter data storage
8565 Srb - IO request packet
8575 IN PVOID HwDeviceExtension
,
8576 IN PSCSI_REQUEST_BLOCK Srb
8579 return AtapiStartIo__(HwDeviceExtension
, Srb
, TRUE
);
8580 } // end AtapiStartIo()
8585 IN PVOID HwDeviceExtension
,
8586 IN PSCSI_REQUEST_BLOCK Srb
,
8590 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
8593 PHW_LU_EXTENSION LunExt
;
8601 PSCSI_REQUEST_BLOCK tmpSrb
;
8602 BOOLEAN PostReq
= FALSE
;
8604 BOOLEAN commPort
= FALSE
;
8606 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
8607 if(deviceExtension
->Isr2DevObj
&& !BMList
[deviceExtension
->DevIndex
].Isr2Enable
) {
8608 KdPrint2((PRINT_PREFIX
"Isr2Enable -> 1\n"));
8609 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
8611 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
8613 /* KeBugCheckEx(0xc000000e,
8614 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8616 TopLevel, 0x80000001);
8618 if(TopLevel
&& Srb
&& Srb
->SrbExtension
) {
8619 KdPrint2((PRINT_PREFIX
"TopLevel\n"));
8620 //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
8621 UniAtaClearAtaReq(Srb
->SrbExtension
);
8624 do { // fetch all queued commands for the channel (if valid)
8626 lChannel
= GET_CHANNEL(Srb
);
8627 //ldev = GET_LDEV(Srb);
8630 DeviceNumber
= GET_CDEV(Srb
);
8633 //ASSERT(deviceExtension);
8636 KdPrint2((PRINT_PREFIX
8637 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8638 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
));
8639 KdPrint2((PRINT_PREFIX
" VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension
->DevID
, deviceExtension
->RevID
));
8641 if(lChannel
== deviceExtension
->NumberChannels
&&
8642 !Srb
->Lun
&& !Srb
->TargetId
&&
8643 ((Srb
->Function
== SRB_FUNCTION_IO_CONTROL
) ||
8644 (Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
&& Srb
->Cdb
[0] == SCSIOP_INQUIRY
))
8646 // This is our virtual device
8647 KdPrint2((PRINT_PREFIX
8648 "AtapiStartIo: Communication port\n"));
8649 if(Srb
->Function
== SRB_FUNCTION_EXECUTE_SCSI
) {
8651 if(Srb
->DataTransferLength
< sizeof(PINQUIRYDATA
)) {
8652 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Buffer too small: %#x < %#x\n", Srb
->DataTransferLength
,
8653 sizeof(PINQUIRYDATA
) ));
8655 status
= SRB_STATUS_DATA_OVERRUN
;
8659 PINQUIRYDATA inquiryData
= (PINQUIRYDATA
)(Srb
->DataBuffer
);
8661 KdPrint2((PRINT_PREFIX
8663 // Zero INQUIRY data structure.
8664 RtlZeroMemory((PCHAR
)(Srb
->DataBuffer
), Srb
->DataTransferLength
);
8666 inquiryData
->DeviceType
= COMMUNICATION_DEVICE
;
8668 // Fill in vendor identification fields.
8669 RtlCopyMemory(&inquiryData
->VendorId
, &uniata_comm_name
, 28);
8671 status
= SRB_STATUS_SUCCESS
;
8675 /* Pass IOCTL request down */
8677 if(lChannel
>= deviceExtension
->NumberChannels
||
8678 Srb
->TargetId
/*DeviceNumber*/ >= deviceExtension
->NumberLuns
||
8681 if(lChannel
>= deviceExtension
->NumberChannels
) {
8686 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8687 KdPrint3((PRINT_PREFIX
8688 "AtapiStartIo: SRB rejected\n"));
8689 // Indicate no device found at this address.
8690 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
8691 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8695 if((deviceExtension
->HwFlags
& UNIATA_AHCI
) &&
8696 !UniataAhciChanImplemented(deviceExtension
, lChannel
)) {
8701 chan
= &(deviceExtension
->chan
[lChannel
]);
8702 LunExt
= chan
->lun
[DeviceNumber
];
8706 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
8712 if(!commPort
&& !LunExt
) {
8714 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
8717 deviceExtension
->NumberChannels
);
8718 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
8719 lChannel
, GET_CDEV(Srb
), deviceExtension
->chan
[0].lun
[0]);
8720 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8721 Srb
->Function
, Srb
->PathId
, Srb
->Lun
, Srb
->TargetId
);
8725 for(i=0; i<1000; i++) {
8726 AtapiStallExecution(3*1000);
8733 // Determine which function.
8734 switch (Srb
->Function
) {
8736 case SRB_FUNCTION_EXECUTE_SCSI
:
8738 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8739 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
8740 // let passthrough go
8742 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
8746 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8747 KdPrint2((PRINT_PREFIX
8748 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
8749 // Indicate no device found at this address.
8750 KdPrint2((PRINT_PREFIX
"SRB_STATUS_SELECTION_TIMEOUT\n"));
8751 status
= SRB_STATUS_SELECTION_TIMEOUT
;
8756 KdPrint2((PRINT_PREFIX
8757 " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb
, &(Srb
->Cdb
), Srb
->SrbExtension
, Srb
->Cdb
[0]));
8761 if(Srb->DataTransferLength) {
8763 a = ((PUCHAR)(Srb->DataBuffer))[0];
8766 } __except(EXCEPTION_EXECUTE_HANDLER) {
8767 KdPrint3((PRINT_PREFIX
8768 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
8769 // Indicate no device found at this address.
8770 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
8771 status = SRB_STATUS_ERROR;
8772 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
8777 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
8781 KdPrint3((PRINT_PREFIX
"Non-empty queue\n"));
8783 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)) {
8784 KdPrint3((PRINT_PREFIX
"Try ATAPI prepare\n"));
8786 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
8788 KdPrint2((PRINT_PREFIX
"Try IDE prepare\n"));
8789 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_PREPARE
);
8791 /*KeBugCheckEx(0xc000000e,
8792 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8794 status, 0x80000001);*/
8795 if(status
== SRB_STATUS_BUSY
)
8796 status
= SRB_STATUS_PENDING
;
8797 // Insert requests AFTER they have been initialized on
8798 // CMD_ACTION_PREPARE stage
8799 // we should not check TopLevel here (it is always TRUE)
8800 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8801 UniataQueueRequest(chan
, Srb
);
8803 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
8807 // Send command to device.
8808 KdPrint2((PRINT_PREFIX
"Send to device %x\n", Srb
->Cdb
[0]));
8810 KdPrint2((PRINT_PREFIX
"TopLevel (2), srb %#x\n", Srb
));
8811 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
8812 KdPrint2((PRINT_PREFIX
"TopLevel (3), AtaReq %#x\n", AtaReq
));
8813 //ASSERT(!AtaReq->Flags);
8814 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8815 UniataQueueRequest(chan
, Srb
);
8816 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
8817 //ASSERT(!AtaReq->Flags);
8818 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
8819 //ASSERT(!AtaReq->Flags);
8823 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8827 if(Srb
->Cdb
[0] == SCSIOP_INQUIRY
) {
8828 if(UniataAnybodyHome(deviceExtension
, chan
->lChannel
, DeviceNumber
)) {
8829 if(!CheckDevice(HwDeviceExtension
, chan
->lChannel
, DeviceNumber
, TRUE
)) {
8833 if(!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8837 if(Srb
->Cdb
[0] == SCSIOP_ATA_PASSTHROUGH
) {
8846 (Srb
->Cdb
[0] != SCSIOP_ATA_PASSTHROUGH
)/* &&
8847 (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
8848 KdPrint3((PRINT_PREFIX
"Try ATAPI send %x\n", Srb
->Cdb
[0]));
8849 status
= AtapiSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
8851 KdPrint2((PRINT_PREFIX
"Try IDE send\n"));
8856 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
8863 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
8865 status
= IdeSendCommand(HwDeviceExtension
, Srb
, CMD_ACTION_ALL
);
8867 /* KeBugCheckEx(0xc000000e,
8868 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8870 status, 0x80000002);*/
8878 case SRB_FUNCTION_ABORT_COMMAND
:
8880 tmpSrb
= ScsiPortGetSrb(HwDeviceExtension
, Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
,
8882 // Verify that SRB to abort is still outstanding.
8883 if((tmpSrb
!= Srb
->NextSrb
) ||
8884 !chan
->queue_depth
) {
8886 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB to abort already completed\n"));
8888 // Complete abort SRB.
8889 status
= SRB_STATUS_ABORT_FAILED
;
8893 AtaReq
= (PATA_REQ
)(tmpSrb
->SrbExtension
);
8894 if(AtaReq
->ReqState
> REQ_STATE_READY_TO_TRANSFER
) {
8895 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_CURRENT
)) {
8896 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Abort command failed\n"));
8897 // Log reset failure.
8898 KdPrint3((PRINT_PREFIX
8899 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
8900 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
8902 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
8903 status
= SRB_STATUS_ERROR
;
8906 status
= SRB_STATUS_SUCCESS
;
8909 KdPrint2((PRINT_PREFIX
"AtapiInterrupt: remove aborted srb %#x\n", tmpSrb
));
8910 if (tmpSrb
->SenseInfoBuffer
&&
8911 tmpSrb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
)) {
8913 PSENSE_DATA senseBuffer
= (PSENSE_DATA
)tmpSrb
->SenseInfoBuffer
;
8915 senseBuffer
->ErrorCode
= 0;
8916 senseBuffer
->Valid
= 1;
8917 senseBuffer
->AdditionalSenseLength
= 0xb;
8918 senseBuffer
->SenseKey
= SCSI_SENSE_ABORTED_COMMAND
;
8919 senseBuffer
->AdditionalSenseCode
= 0;
8920 senseBuffer
->AdditionalSenseCodeQualifier
= 0;
8922 tmpSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
8924 AtapiDmaDBSync(chan
, tmpSrb
);
8925 UniataRemoveRequest(chan
, tmpSrb
);
8926 // Indicate command complete.
8927 ScsiPortNotification(RequestComplete
,
8930 status
= SRB_STATUS_SUCCESS
;
8934 // Abort function indicates that a request timed out.
8935 // Call reset routine. Card will only be reset if
8936 // status indicates something is wrong.
8937 // Fall through to reset code.
8939 case SRB_FUNCTION_RESET_DEVICE
:
8940 case SRB_FUNCTION_RESET_LOGICAL_UNIT
:
8942 // Reset single device.
8943 // For now we support only Lun=0
8945 // Note: reset is immediate command, it cannot be queued since it is usually used to
8946 // revert not-responding device to operational state
8947 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device request received\n"));
8948 UniataUserDeviceReset(deviceExtension
, LunExt
, lChannel
);
8949 status
= SRB_STATUS_SUCCESS
;
8952 case SRB_FUNCTION_RESET_BUS
:
8954 // Reset Atapi and SCSI bus.
8956 // Note: reset is immediate command, it cannot be queued since it is usually used to
8957 // revert not- responding device to operational state
8958 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus request received\n"));
8959 if (!AtapiResetController__(deviceExtension
, lChannel
, RESET_COMPLETE_ALL
)) {
8960 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset bus failed\n"));
8961 // Log reset failure.
8962 KdPrint3((PRINT_PREFIX
8963 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
8964 HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8
8966 ScsiPortLogError(HwDeviceExtension
, NULL
, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR
, 5 << 8);
8967 status
= SRB_STATUS_ERROR
;
8970 status
= SRB_STATUS_SUCCESS
;
8975 case SRB_FUNCTION_SHUTDOWN
:
8977 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown\n"));
8978 if(!LunExt
|| !(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
8979 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - no such device\n"));
8982 // FLUSH ATAPI device - do nothing
8983 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - ATAPI device\n"));
8985 // FLUSH IDE/ATA device
8986 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Shutdown - IDE device\n"));
8987 AtapiDisableInterrupts(deviceExtension
, lChannel
);
8988 status
= AtaCommand(deviceExtension
, DeviceNumber
, GET_CHANNEL(Srb
),
8989 IDE_COMMAND_FLUSH_CACHE
, 0, 0, 0, 0, 0, ATA_WAIT_IDLE
);
8990 // If supported & allowed, reset write cacheing
8991 if(LunExt
->DeviceFlags
& DFLAGS_WCACHE_ENABLED
) {
8993 // Disable write cache
8994 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
8995 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
8996 0, ATA_C_F_DIS_WCACHE
, ATA_WAIT_BASE_READY
);
8997 // Check for errors.
8998 if (status
& IDE_STATUS_ERROR
) {
8999 KdPrint2((PRINT_PREFIX
9000 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
9003 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9005 // Re-enable write cache
9006 status
= AtaCommand(deviceExtension
, DeviceNumber
, lChannel
,
9007 IDE_COMMAND_SET_FEATURES
, 0, 0, 0,
9008 0, ATA_C_F_ENAB_WCACHE
, ATA_WAIT_BASE_READY
);
9009 // Check for errors.
9010 if (status
& IDE_STATUS_ERROR
) {
9011 KdPrint2((PRINT_PREFIX
9012 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
9014 LunExt
->DeviceFlags
&= ~DFLAGS_WCACHE_ENABLED
;
9016 LunExt
->DeviceFlags
|= DFLAGS_WCACHE_ENABLED
;
9020 AtapiEnableInterrupts(deviceExtension
, lChannel
);
9022 status
= SRB_STATUS_SUCCESS
;
9026 case SRB_FUNCTION_FLUSH
:
9028 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Flush (do nothing)\n"));
9029 status
= SRB_STATUS_SUCCESS
;
9032 case SRB_FUNCTION_IO_CONTROL
: {
9036 KdPrint2((PRINT_PREFIX
"AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
9038 len
= Srb
->DataTransferLength
;
9040 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"SCSIDISK",sizeof("SCSIDISK")-1)) {
9042 ULONG targetId
= (ULONG
)(-1);
9044 if(len
< sizeof(SRB_IO_CONTROL
)) {
9045 goto wrong_buffer_size
;
9048 // extract bogus bus address
9049 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9050 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9051 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9053 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(GETVERSIONINPARAMS
)) {
9054 goto wrong_buffer_size
;
9057 targetId
= versionParameters
->bIDEDeviceMap
;
9058 KdPrint2((PRINT_PREFIX
"targetId (smart ver) %d\n", targetId
));
9060 case IOCTL_SCSI_MINIPORT_IDENTIFY
:
9061 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
:
9062 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
:
9063 case IOCTL_SCSI_MINIPORT_ENABLE_SMART
:
9064 case IOCTL_SCSI_MINIPORT_DISABLE_SMART
:
9065 case IOCTL_SCSI_MINIPORT_RETURN_STATUS
:
9066 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
:
9067 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
:
9068 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
:
9069 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE
:
9070 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG
:
9071 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG
:
9073 PSENDCMDINPARAMS cmdInParameters
= (PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9075 if(len
< sizeof(SRB_IO_CONTROL
)+sizeof(SENDCMDINPARAMS
) - 1) {
9076 goto wrong_buffer_size
;
9079 targetId
= cmdInParameters
->bDriveNumber
;
9080 KdPrint2((PRINT_PREFIX
"targetId (smart/ident) %d\n", targetId
));
9084 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9085 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
));
9086 status
= SRB_STATUS_INVALID_REQUEST
;
9090 // adjust (if necessary) bus address
9091 if(targetId
!= (ULONG
)(-1)) {
9093 // This is done because of how the IOCTL_SCSI_MINIPORT
9094 // determines 'targetid's'. Disk.sys places the real target id value
9095 // in the DeviceMap field. Once we do some parameter checking, the value passed
9096 // back to the application will be determined.
9098 if (deviceExtension
->NumberChannels
== 1) {
9099 // do this for legacy controllers and legacy callers
9100 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call\n"));
9101 DeviceNumber
= (targetId
& 0x01);
9105 // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
9106 // due to DISK.SYS design bug, we have invalid SCSI address in SRB
9107 KdPrint2((PRINT_PREFIX
"AtapiStartIo: legacy call (2)\n"));
9108 if(deviceExtension
->HwFlags
& UNIATA_AHCI
) {
9109 lChannel
= (UCHAR
)targetId
/ 2;
9112 lChannel
= (UCHAR
)(targetId
/ 2);
9113 DeviceNumber
= targetId
& 0x01;
9116 // otherwise assume lChannel and DeviceNumber from Srb are ok
9118 if(lChannel
>= deviceExtension
->NumberChannels
||
9119 DeviceNumber
>= deviceExtension
->NumberLuns
) {
9120 KdPrint2((PRINT_PREFIX
9121 "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
9123 // Indicate no device found at this address.
9126 targetId
= lChannel
*deviceExtension
->NumberLuns
+DeviceNumber
;
9127 chan
= &(deviceExtension
->chan
[lChannel
]);
9128 LunExt
= chan
->lun
[DeviceNumber
];
9132 atapiDev
= (LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) ? TRUE
: FALSE
;
9134 if (!(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
)) {
9139 switch (((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->ControlCode
) {
9140 case IOCTL_SCSI_MINIPORT_SMART_VERSION
: {
9142 PGETVERSIONINPARAMS versionParameters
= (PGETVERSIONINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9143 UCHAR deviceNumberMap
;
9145 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
9147 // Version and revision per SMART 1.03
9149 versionParameters
->bVersion
= 1;
9150 versionParameters
->bRevision
= 1;
9151 versionParameters
->bReserved
= 0;
9153 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
9154 versionParameters
->fCapabilities
= (CAP_ATA_ID_CMD
| CAP_ATAPI_ID_CMD
| CAP_SMART_CMD
);
9157 goto invalid_request
;
9160 // NOTE: This will only set the bit
9161 // corresponding to this drive's target id.
9162 // The bit mask is as follows:
9168 if(chan
->DeviceExtension
->HwFlags
& UNIATA_AHCI
) {
9169 deviceNumberMap
= 1 << lChannel
;
9172 if (deviceExtension
->NumberChannels
== 1) {
9173 if (chan
->PrimaryAddress
) {
9174 deviceNumberMap
= 1 << DeviceNumber
;
9176 deviceNumberMap
= 4 << DeviceNumber
;
9179 deviceNumberMap
= 1 << (DeviceNumber
+lChannel
*2);
9182 versionParameters
->bIDEDeviceMap
= deviceNumberMap
;
9184 status
= SRB_STATUS_SUCCESS
;
9188 case IOCTL_SCSI_MINIPORT_IDENTIFY
: {
9190 PSENDCMDOUTPARAMS cmdOutParameters
= (PSENDCMDOUTPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9191 SENDCMDINPARAMS cmdInParameters
= *(PSENDCMDINPARAMS
)(((PUCHAR
)Srb
->DataBuffer
) + sizeof(SRB_IO_CONTROL
));
9193 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
9194 // Extract the target.
9195 KdPrint2((PRINT_PREFIX
"targetId %d\n", targetId
));
9197 switch(cmdInParameters
.irDriveRegs
.bCommandReg
) {
9200 KdPrint2((PRINT_PREFIX
"Error: ID_CMD for ATAPI\n"));
9201 goto invalid_request
;
9207 (cmdInParameters
.irDriveRegs
.bCommandReg
== ATAPI_ID_CMD
)) {
9208 KdPrint2((PRINT_PREFIX
"Error: ATAPI_ID_CMD for non-ATAPI\n"));
9209 goto invalid_request
;
9212 len
= min(len
, sizeof(SENDCMDOUTPARAMS
) - 1 + IDENTIFY_BUFFER_SIZE
);
9213 // Zero the output buffer
9214 RtlZeroMemory(cmdOutParameters
, len
);
9215 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
9216 ((PUCHAR)cmdOutParameters)[i] = 0;
9219 // Build status block.
9220 cmdOutParameters
->cBufferSize
= min(IDENTIFY_BUFFER_SIZE
, len
- sizeof(SENDCMDOUTPARAMS
) + 1);
9221 cmdOutParameters
->DriverStatus
.bDriverError
= 0;
9222 cmdOutParameters
->DriverStatus
.bIDEError
= 0;
9224 // Extract the identify data from the device extension.
9225 ScsiPortMoveMemory (cmdOutParameters
->bBuffer
, &(LunExt
->IdentifyData
),
9226 cmdOutParameters
->cBufferSize
);
9228 if((cmdOutParameters
->cBufferSize
== IDENTIFY_BUFFER_SIZE
) &&
9229 (LunExt
->IdentifyData
.ChecksumValid
== ATA_ChecksumValid
)) {
9230 // adjust checksum if it is possible
9234 for(i
=0; i
< IDENTIFY_BUFFER_SIZE
-1; i
++) {
9235 csum
+= (CHAR
)(cmdOutParameters
->bBuffer
[i
]);
9237 cmdOutParameters
->bBuffer
[i
] = -csum
;
9238 KdPrint2((PRINT_PREFIX
"AtapiStartIo: adjust checksum %d\n"));
9240 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
9242 status
= SRB_STATUS_SUCCESS
;
9246 KdPrint2((PRINT_PREFIX
"AtapiStartIo: not supported ID code %x\n",
9247 cmdInParameters
.irDriveRegs
.bCommandReg
));
9248 status
= SRB_STATUS_INVALID_REQUEST
;
9254 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9255 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9256 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9257 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9258 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9259 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9260 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9261 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9264 // *all* IOCTLs here are SMART
9266 KdPrint2((PRINT_PREFIX
9267 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
9270 goto invalid_request
;
9273 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9275 if(PostReq
|| TopLevel
) {
9276 UniataQueueRequest(chan
, Srb
);
9277 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9278 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9283 KdPrint2((PRINT_PREFIX
"Non-empty queue (SMART)\n"));
9284 status
= SRB_STATUS_PENDING
;
9286 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9289 status
= IdeSendSmartCommand(HwDeviceExtension
, Srb
, targetId
);
9293 // we should not get here, checked above
9295 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9296 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9297 status = SRB_STATUS_INVALID_REQUEST;
9302 if(!AtapiStringCmp( (PCHAR
)(((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
),"-UNIATA-", sizeof("-UNIATA-")-1)) {
9304 PUNIATA_CTL AtaCtl
= (PUNIATA_CTL
)(Srb
->DataBuffer
);
9305 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
9306 ULONG DeviceNumber
= AtaCtl
->addr
.TargetId
;
9310 pos
= FIELD_OFFSET(UNIATA_CTL
, RawData
);
9311 //chan = &(deviceExtension->chan[lChannel]);
9313 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9314 FIELD_OFFSET(UNIATA_CTL
, RawData
) ));
9315 goto wrong_buffer_size
;
9318 if(AtaCtl
->addr
.Lun
||
9319 AtaCtl
->addr
.TargetId
>= deviceExtension
->NumberLuns
||
9320 AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
) {
9328 lChannel
= AtaCtl
->addr
.PathId
;
9329 chan
= &(deviceExtension
->chan
[lChannel
]);
9330 LunExt
= chan
->lun
[DeviceNumber
];
9333 KdPrint2((PRINT_PREFIX
"AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl
->hdr
.ControlCode
, DeviceNumber
));
9335 /* check for valid LUN */
9336 switch (AtaCtl
->hdr
.ControlCode
) {
9337 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9338 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
:
9339 // this would be BUS reset
9341 (AtaCtl
->addr
.PathId
>= deviceExtension
->NumberChannels
||
9342 AtaCtl
->addr
.TargetId
!= 0xff ||
9343 AtaCtl
->addr
.Lun
!= 0
9345 if(AtaCtl
->hdr
.ControlCode
== IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
&&
9346 DeviceNumber
< deviceExtension
->NumberLuns
) { // AtaCtl->addr.TargetId != 0xff
9347 lChannel
= AtaCtl
->addr
.PathId
;
9348 chan
= &(deviceExtension
->chan
[lChannel
]);
9349 LunExt
= chan
->lun
[DeviceNumber
];
9352 goto handle_bad_ldev
;
9355 lChannel
= AtaCtl
->addr
.PathId
;
9356 chan
= &(deviceExtension
->chan
[lChannel
]);
9359 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
:
9360 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9361 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
:
9362 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9363 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
9366 KdPrint2((PRINT_PREFIX
9367 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
9368 // Indicate no device found at this address.
9373 /* check if queueing is necessary */
9374 switch (AtaCtl
->hdr
.ControlCode
) {
9375 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
:
9376 if(!LunExt
->nBadBlocks
) {
9379 goto uata_ctl_queue
;
9380 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
:
9381 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9382 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9383 pos
+sizeof(AtaCtl
->SetMode
) ));
9384 goto wrong_buffer_size
;
9386 if(!AtaCtl
->SetMode
.ApplyImmediately
) {
9389 goto uata_ctl_queue
;
9390 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9391 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
9393 KdPrint2((PRINT_PREFIX
"put to queue (UNIATA)\n"));
9394 PostReq
= UniataNeedQueueing(deviceExtension
, chan
, TopLevel
);
9396 if(PostReq
|| TopLevel
) {
9397 UniataQueueRequest(chan
, Srb
);
9398 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9399 AtaReq
->ReqState
= REQ_STATE_QUEUED
;
9402 KdPrint2((PRINT_PREFIX
"Non-empty queue (UNIATA)\n"));
9403 status
= SRB_STATUS_PENDING
;
9405 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Already have %d request(s)!\n", chan
->queue_depth
));
9408 } // end switch (AtaCtl->hdr.ControlCode)
9410 /* process request */
9411 switch (AtaCtl
->hdr
.ControlCode
) {
9412 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES
:
9414 KdPrint2((PRINT_PREFIX
"AtapiStartIo: rescan bus\n"));
9416 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9417 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9418 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9419 goto wrong_buffer_size
;
9421 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
) {
9422 KdPrint2((PRINT_PREFIX
"AtapiStartIo: unhide from further detection\n"));
9423 if(AtaCtl
->addr
.TargetId
!= 0xff) {
9424 LunExt
->DeviceFlags
&= ~DFLAGS_HIDDEN
;
9429 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9430 AtapiStallExecution(1000 * 1000);
9433 FindDevices(HwDeviceExtension
,
9434 ((AtaCtl
->addr
.TargetId
== 0xff) && (AtaCtl
->FindDelDev
.Flags
& UNIATA_ADD_FLAGS_UNHIDE
))
9435 ? UNIATA_FIND_DEV_UNHIDE
: 0,
9436 AtaCtl
->addr
.PathId
);
9437 status
= SRB_STATUS_SUCCESS
;
9441 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE
: {
9443 KdPrint2((PRINT_PREFIX
"AtapiStartIo: remove %#x:%#x\n", AtaCtl
->addr
.PathId
, AtaCtl
->addr
.TargetId
));
9445 if(len
< pos
+sizeof(AtaCtl
->FindDelDev
)) {
9446 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9447 pos
+sizeof(AtaCtl
->FindDelDev
) ));
9448 goto wrong_buffer_size
;
9450 LunExt
->DeviceFlags
= 0;
9451 if(AtaCtl
->FindDelDev
.Flags
& UNIATA_REMOVE_FLAGS_HIDE
) {
9452 KdPrint2((PRINT_PREFIX
"AtapiStartIo: hide from further detection\n"));
9453 //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
9454 UniataForgetDevice(LunExt
);
9457 for(i
=0; i
<AtaCtl
->FindDelDev
.WaitForPhysicalLink
&& i
<30; i
++) {
9458 AtapiStallExecution(1000 * 1000);
9461 status
= SRB_STATUS_SUCCESS
;
9464 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE
: {
9466 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Set transfer mode\n"));
9468 if(len
< pos
+sizeof(AtaCtl
->SetMode
)) {
9469 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9470 pos
+sizeof(AtaCtl
->SetMode
) ));
9471 goto wrong_buffer_size
;
9473 if(AtaCtl
->SetMode
.OrigMode
!= IOMODE_NOT_SPECIFIED
) {
9474 LunExt
->OrigTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.OrigMode
);
9476 if(AtaCtl
->SetMode
.MaxMode
!= IOMODE_NOT_SPECIFIED
) {
9477 LunExt
->LimitedTransferMode
= (UCHAR
)(AtaCtl
->SetMode
.MaxMode
);
9478 if(LunExt
->LimitedTransferMode
>
9479 LunExt
->OrigTransferMode
) {
9480 // check for incorrect value
9481 LunExt
->LimitedTransferMode
=
9482 LunExt
->OrigTransferMode
;
9485 LunExt
->TransferMode
= min(LunExt
->LimitedTransferMode
, LunExt
->OrigTransferMode
);
9487 LunExt
->DeviceFlags
|= DFLAGS_REINIT_DMA
; // force PIO/DMA reinit
9488 if(AtaCtl
->SetMode
.ApplyImmediately
) {
9489 AtapiDmaInit__(deviceExtension
, LunExt
);
9491 /* LunExt->TransferMode =
9492 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
9493 status
= SRB_STATUS_SUCCESS
;
9496 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE
: {
9498 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get transfer mode\n"));
9500 if(len
< pos
+sizeof(AtaCtl
->GetMode
)) {
9501 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9502 pos
+sizeof(AtaCtl
->GetMode
) ));
9503 goto wrong_buffer_size
;
9505 AtaCtl
->GetMode
.OrigMode
= LunExt
->OrigTransferMode
;
9506 AtaCtl
->GetMode
.MaxMode
= LunExt
->LimitedTransferMode
;
9507 AtaCtl
->GetMode
.CurrentMode
= LunExt
->TransferMode
;
9508 AtaCtl
->GetMode
.PhyMode
= LunExt
->PhyTransferMode
;
9510 status
= SRB_STATUS_SUCCESS
;
9513 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION
: {
9515 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get version\n"));
9517 if(len
< pos
+sizeof(AtaCtl
->Version
)) {
9518 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9519 pos
+sizeof(AtaCtl
->Version
) ));
9520 goto wrong_buffer_size
;
9522 AtaCtl
->Version
.Length
= sizeof(GETDRVVERSION
);
9523 AtaCtl
->Version
.VersionMj
= UNIATA_VER_MJ
;
9524 AtaCtl
->Version
.VersionMn
= UNIATA_VER_MN
;
9525 AtaCtl
->Version
.SubVerMj
= UNIATA_VER_SUB_MJ
;
9526 AtaCtl
->Version
.SubVerMn
= UNIATA_VER_SUB_MN
;
9528 status
= SRB_STATUS_SUCCESS
;
9531 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO
: {
9533 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Get adapter info\n"));
9535 if(len
< pos
+sizeof(AtaCtl
->AdapterInfo
)) {
9536 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len
,
9537 pos
+sizeof(AtaCtl
->AdapterInfo
) ));
9538 goto wrong_buffer_size
;
9540 AtaCtl
->AdapterInfo
.HeaderLength
= sizeof(ADAPTERINFO
);
9542 AtaCtl
->AdapterInfo
.DevID
= deviceExtension
->DevID
;
9543 AtaCtl
->AdapterInfo
.RevID
= deviceExtension
->RevID
;
9544 AtaCtl
->AdapterInfo
.slotNumber
= deviceExtension
->slotNumber
;
9545 AtaCtl
->AdapterInfo
.SystemIoBusNumber
= deviceExtension
->SystemIoBusNumber
;
9546 AtaCtl
->AdapterInfo
.DevIndex
= deviceExtension
->DevIndex
;
9547 AtaCtl
->AdapterInfo
.Channel
= deviceExtension
->Channel
;
9548 AtaCtl
->AdapterInfo
.HbaCtrlFlags
= deviceExtension
->HbaCtrlFlags
;
9549 AtaCtl
->AdapterInfo
.simplexOnly
= deviceExtension
->simplexOnly
;
9550 AtaCtl
->AdapterInfo
.MemIo
= FALSE
;/*deviceExtension->MemIo;*/
9551 AtaCtl
->AdapterInfo
.UnknownDev
= deviceExtension
->UnknownDev
;
9552 AtaCtl
->AdapterInfo
.MasterDev
= deviceExtension
->MasterDev
;
9553 AtaCtl
->AdapterInfo
.MaxTransferMode
= deviceExtension
->MaxTransferMode
;
9554 AtaCtl
->AdapterInfo
.HwFlags
= deviceExtension
->HwFlags
;
9555 AtaCtl
->AdapterInfo
.OrigAdapterInterfaceType
= deviceExtension
->OrigAdapterInterfaceType
;
9556 AtaCtl
->AdapterInfo
.BusInterruptLevel
= deviceExtension
->BusInterruptLevel
;
9557 AtaCtl
->AdapterInfo
.InterruptMode
= deviceExtension
->InterruptMode
;
9558 AtaCtl
->AdapterInfo
.BusInterruptVector
= deviceExtension
->BusInterruptVector
;
9559 AtaCtl
->AdapterInfo
.NumberChannels
= deviceExtension
->NumberChannels
;
9560 AtaCtl
->AdapterInfo
.NumberLuns
= (UCHAR
)deviceExtension
->NumberLuns
;
9561 AtaCtl
->AdapterInfo
.AdapterInterfaceType
= deviceExtension
->AdapterInterfaceType
;
9562 if(deviceExtension
->FullDevName
) {
9563 strncpy(AtaCtl
->AdapterInfo
.DeviceName
, deviceExtension
->FullDevName
, 64);
9565 AtaCtl
->AdapterInfo
.ChanInfoValid
= FALSE
;
9566 AtaCtl
->AdapterInfo
.LunInfoValid
= FALSE
;
9567 AtaCtl
->AdapterInfo
.ChanHeaderLengthValid
= TRUE
;
9569 pos
+= AtaCtl
->AdapterInfo
.HeaderLength
;
9572 RtlZeroMemory(((PCHAR
)AtaCtl
)+pos
,
9575 if(len
>= pos
+AtaCtl
->AdapterInfo
.NumberChannels
*sizeof(CHANINFO
)) {
9576 PCHANINFO ChanInfo
= (PCHANINFO
)( ((PCHAR
)AtaCtl
)+pos
);
9577 PHW_CHANNEL cur_chan
;
9578 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Fill channel info\n"));
9579 for(i
=0;i
<AtaCtl
->AdapterInfo
.NumberChannels
;i
++) {
9580 KdPrint2((PRINT_PREFIX
"chan[%d] %x\n", i
, cur_chan
));
9581 cur_chan
= &(deviceExtension
->chan
[i
]);
9582 ChanInfo
->MaxTransferMode
= cur_chan
->MaxTransferMode
;
9583 ChanInfo
->ChannelCtrlFlags
= cur_chan
->ChannelCtrlFlags
;
9584 RtlCopyMemory(&(ChanInfo
->QueueStat
), &(cur_chan
->QueueStat
), sizeof(ChanInfo
->QueueStat
));
9585 ChanInfo
->ReorderCount
= cur_chan
->ReorderCount
;
9586 ChanInfo
->IntersectCount
= cur_chan
->IntersectCount
;
9587 ChanInfo
->TryReorderCount
= cur_chan
->TryReorderCount
;
9588 ChanInfo
->TryReorderHeadCount
= cur_chan
->TryReorderHeadCount
;
9589 ChanInfo
->TryReorderTailCount
= cur_chan
->TryReorderTailCount
;
9590 //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
9593 AtaCtl
->AdapterInfo
.ChanInfoValid
= TRUE
;
9594 AtaCtl
->AdapterInfo
.ChanHeaderLength
= sizeof(*ChanInfo
);
9597 status
= SRB_STATUS_SUCCESS
;
9600 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB
: {
9602 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Forget BB list\n"));
9604 ForgetBadBlocks(LunExt
);
9606 status
= SRB_STATUS_SUCCESS
;
9609 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE
: {
9611 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Reset device\n"));
9616 UniataUserDeviceReset(deviceExtension
, LunExt
, AtaCtl
->addr
.PathId
);
9619 status
= SRB_STATUS_SUCCESS
;
9623 KdPrint2((PRINT_PREFIX
"AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
9624 AtaCtl
->hdr
.ControlCode
));
9625 status
= SRB_STATUS_INVALID_REQUEST
;
9630 KdPrint2((PRINT_PREFIX
"AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
9631 ((PSRB_IO_CONTROL
)(Srb
->DataBuffer
))->Signature
,
9632 "SCSIDISK", "-UNIATA-"));
9634 status
= SRB_STATUS_INVALID_REQUEST
;
9639 } // end SRB_FUNCTION_IO_CONTROL
9642 KdPrint2((PRINT_PREFIX
"AtapiStartIo: Unknown IOCTL\n"));
9643 // Indicate unsupported command.
9644 status
= SRB_STATUS_INVALID_REQUEST
;
9652 PathId
= Srb
->PathId
;
9653 TargetId
= Srb
->TargetId
;
9656 if (status
!= SRB_STATUS_PENDING
) {
9658 KdPrint2((PRINT_PREFIX
9659 "AtapiStartIo: Srb %#x complete with status %#x\n",
9663 // Set status in SRB.
9664 Srb
->SrbStatus
= (UCHAR
)status
;
9667 KdPrint2((PRINT_PREFIX
"AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan
, Srb
));
9668 AtapiDmaDBSync(chan
, Srb
);
9670 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan
, Srb
));
9671 UniataRemoveRequest(chan
, Srb
);
9672 // Indicate command complete.
9673 KdPrint2((PRINT_PREFIX
"AtapiStartIo: ScsiPortNotification\n"));
9674 ScsiPortNotification(RequestComplete
,
9678 KdPrint2((PRINT_PREFIX
"AtapiStartIo: UniataGetCurRequest\n"));
9679 // Remove current Srb & get next one
9680 if((Srb
= UniataGetCurRequest(chan
))) {
9681 AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
9682 if(AtaReq
->ReqState
> REQ_STATE_QUEUED
) {
9683 // current request is under precessing, thus
9684 // we should do nothing here
9688 KdPrint2((PRINT_PREFIX
"AtapiStartIo: chan %x, Src %x\n", chan
, Srb
));
9693 KdPrint2((PRINT_PREFIX
"AtapiStartIo: next Srb %x\n", Srb
));
9695 } while (Srb
&& (status
!= SRB_STATUS_PENDING
));
9697 KdPrint2((PRINT_PREFIX
"AtapiStartIo: query PORT for next request\n"));
9698 // Indicate ready for next request.
9699 ScsiPortNotification(NextRequest
,
9703 ScsiPortNotification(NextLuRequest
,
9711 } // end AtapiStartIo__()
9716 UniataInitAtaCommands()
9722 KdPrint2((PRINT_PREFIX
"UniataInitAtaCommands:\n"));
9724 for(i
=0; i
<256; i
++) {
9729 //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
9732 case IDE_COMMAND_READ_DMA48
:
9733 case IDE_COMMAND_READ_DMA_Q48
:
9734 case IDE_COMMAND_READ_STREAM_DMA48
:
9735 case IDE_COMMAND_READ_STREAM48
:
9736 case IDE_COMMAND_WRITE_DMA48
:
9737 case IDE_COMMAND_WRITE_DMA_Q48
:
9738 case IDE_COMMAND_READ_DMA_Q
:
9739 case IDE_COMMAND_READ_DMA
:
9740 case IDE_COMMAND_WRITE_DMA
:
9741 case IDE_COMMAND_WRITE_DMA_Q
:
9742 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9743 case IDE_COMMAND_WRITE_STREAM48
:
9744 case IDE_COMMAND_WRITE_FUA_DMA48
:
9745 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9746 case IDE_COMMAND_READ_LOG_DMA48
:
9747 case IDE_COMMAND_WRITE_LOG_DMA48
:
9748 case IDE_COMMAND_TRUSTED_RCV_DMA
:
9749 case IDE_COMMAND_TRUSTED_SEND_DMA
:
9750 case IDE_COMMAND_DATA_SET_MGMT
:
9751 //KdPrint2((PRINT_PREFIX "DMA "));
9752 flags
|= ATA_CMD_FLAG_DMA
;
9756 case IDE_COMMAND_WRITE_FUA_DMA48
:
9757 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9758 case IDE_COMMAND_WRITE_MUL_FUA48
:
9760 flags
|= ATA_CMD_FLAG_FUA
;
9763 case IDE_COMMAND_READ48
:
9764 case IDE_COMMAND_READ_DMA48
:
9765 case IDE_COMMAND_READ_DMA_Q48
:
9766 case IDE_COMMAND_READ_MUL48
:
9767 case IDE_COMMAND_READ_STREAM_DMA48
:
9768 case IDE_COMMAND_READ_STREAM48
:
9769 case IDE_COMMAND_WRITE48
:
9770 case IDE_COMMAND_WRITE_DMA48
:
9771 case IDE_COMMAND_WRITE_DMA_Q48
:
9772 case IDE_COMMAND_WRITE_MUL48
:
9773 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9774 case IDE_COMMAND_WRITE_STREAM48
:
9775 case IDE_COMMAND_FLUSH_CACHE48
:
9776 case IDE_COMMAND_VERIFY48
:
9778 //KdPrint2((PRINT_PREFIX "48 "));
9779 flags
|= ATA_CMD_FLAG_48
;
9782 case IDE_COMMAND_READ
:
9783 case IDE_COMMAND_READ_MULTIPLE
:
9784 case IDE_COMMAND_READ_DMA
:
9785 case IDE_COMMAND_READ_DMA_Q
:
9786 case IDE_COMMAND_WRITE
:
9787 case IDE_COMMAND_WRITE_MULTIPLE
:
9788 case IDE_COMMAND_WRITE_DMA
:
9789 case IDE_COMMAND_WRITE_DMA_Q
:
9790 case IDE_COMMAND_FLUSH_CACHE
:
9791 case IDE_COMMAND_VERIFY
:
9793 //KdPrint2((PRINT_PREFIX "LBA "));
9794 flags
|= ATA_CMD_FLAG_LBAIOsupp
;
9798 case IDE_COMMAND_READ_NATIVE_SIZE48
:
9799 case IDE_COMMAND_SET_NATIVE_SIZE48
:
9800 // we cannot set LBA flag for these commands to avoid BadBlock handling
9801 //flags |= ATA_CMD_FLAG_LBAIOsupp;
9802 flags
|= ATA_CMD_FLAG_48
;
9804 case IDE_COMMAND_READ_NATIVE_SIZE
:
9805 case IDE_COMMAND_SET_NATIVE_SIZE
:
9807 flags
|= ATA_CMD_FLAG_LBAIOsupp
| ATA_CMD_FLAG_FUA
;
9810 flags
|= ATA_CMD_FLAG_48supp
;
9813 case IDE_COMMAND_READ
:
9814 command
= IDE_COMMAND_READ48
; break;
9815 case IDE_COMMAND_READ_MULTIPLE
:
9816 command
= IDE_COMMAND_READ_MUL48
; break;
9817 case IDE_COMMAND_READ_DMA
:
9818 command
= IDE_COMMAND_READ_DMA48
; break;
9819 case IDE_COMMAND_READ_DMA_Q
:
9820 command
= IDE_COMMAND_READ_DMA_Q48
; break;
9821 case IDE_COMMAND_WRITE
:
9822 command
= IDE_COMMAND_WRITE48
; break;
9823 case IDE_COMMAND_WRITE_MULTIPLE
:
9824 command
= IDE_COMMAND_WRITE_MUL48
; break;
9825 case IDE_COMMAND_WRITE_DMA
:
9826 command
= IDE_COMMAND_WRITE_DMA48
; break;
9827 case IDE_COMMAND_WRITE_DMA_Q
:
9828 command
= IDE_COMMAND_WRITE_DMA_Q48
; break;
9829 case IDE_COMMAND_FLUSH_CACHE
:
9830 command
= IDE_COMMAND_FLUSH_CACHE48
; break;
9831 // case IDE_COMMAND_READ_NATIVE_SIZE:
9832 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
9833 case IDE_COMMAND_SET_NATIVE_SIZE
:
9834 command
= IDE_COMMAND_SET_NATIVE_SIZE48
; break;
9835 case IDE_COMMAND_VERIFY
:
9836 command
= IDE_COMMAND_VERIFY48
; break;
9838 //KdPrint2((PRINT_PREFIX "!28->48 "));
9839 flags
&= ~ATA_CMD_FLAG_48supp
;
9843 case IDE_COMMAND_READ
:
9844 case IDE_COMMAND_READ_MULTIPLE
:
9845 case IDE_COMMAND_READ_DMA48
:
9846 case IDE_COMMAND_READ_DMA_Q48
:
9847 case IDE_COMMAND_READ_STREAM_DMA48
:
9848 case IDE_COMMAND_READ_STREAM48
:
9849 case IDE_COMMAND_READ_DMA_Q
:
9850 case IDE_COMMAND_READ_DMA
:
9851 case IDE_COMMAND_READ_LOG_DMA48
:
9852 case IDE_COMMAND_TRUSTED_RCV_DMA
:
9853 case IDE_COMMAND_IDENTIFY
:
9854 case IDE_COMMAND_ATAPI_IDENTIFY
:
9855 //KdPrint2((PRINT_PREFIX "RD "));
9856 flags
|= ATA_CMD_FLAG_In
;
9858 case IDE_COMMAND_WRITE
:
9859 case IDE_COMMAND_WRITE_MULTIPLE
:
9860 case IDE_COMMAND_WRITE_DMA48
:
9861 case IDE_COMMAND_WRITE_DMA_Q48
:
9862 case IDE_COMMAND_WRITE_DMA
:
9863 case IDE_COMMAND_WRITE_DMA_Q
:
9864 case IDE_COMMAND_WRITE_STREAM_DMA48
:
9865 case IDE_COMMAND_WRITE_STREAM48
:
9866 case IDE_COMMAND_WRITE_FUA_DMA48
:
9867 case IDE_COMMAND_WRITE_FUA_DMA_Q48
:
9868 //KdPrint2((PRINT_PREFIX "WR "));
9869 flags
|= ATA_CMD_FLAG_Out
;
9873 //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
9874 AtaCommands48
[i
] = command
;
9875 AtaCommandFlags
[i
] = flags
;
9877 } // end UniataInitAtaCommands()
9881 Routine Description:
9883 Installable driver initialization entry point for system.
9891 Status from ScsiPortInitialize()
9898 IN PVOID DriverObject
,
9902 HW_INITIALIZATION_DATA_COMMON hwInitializationData
;
9905 ULONG statusToReturn
, newStatus
;
9906 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
9907 BOOLEAN ReEnter
= FALSE
;
9909 #ifndef USE_REACTOS_DDK
9913 PCONFIGURATION_INFORMATION GlobalConfig
= IoGetConfigurationInformation();
9914 BOOLEAN PrimaryClaimed
= FALSE
;
9915 BOOLEAN SecondaryClaimed
= FALSE
;
9917 LARGE_INTEGER t0
, t1
;
9920 KdPrint2((PRINT_PREFIX
"%s", (PCCHAR
)ver_string
));
9921 a
= (WCHAR
)strlen(ver_string
);
9923 g_opt_Verbose
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PrintLogo", 0);
9925 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR
"\n");
9928 if(!SavedDriverObject
) {
9929 SavedDriverObject
= (PDRIVER_OBJECT
)DriverObject
;
9930 #ifdef USE_REACTOS_DDK
9931 KdPrint(("UniATA Init: OS should be ReactOS\n"));
9936 // we are here for the 1st time
9937 // init CrossNT and get OS version
9938 if(!NT_SUCCESS(status
= CrNtInit(SavedDriverObject
, RegistryPath
))) {
9939 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status
));
9940 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
9943 #endif // USE_REACTOS_DDK
9944 KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion
, MinorVersion
, BuildNumber
, KeNumberProcessors
));
9946 KeQuerySystemTime(&t0
);
9948 KeQuerySystemTime(&t1
);
9949 } while(t0
.QuadPart
== t1
.QuadPart
);
9953 KeQuerySystemTime(&t1
);
9955 } while(t0
.QuadPart
== t1
.QuadPart
);
9956 g_PerfDt
= (ULONG
)((t1
.QuadPart
- t0
.QuadPart
)/10);
9957 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt
, g_Perf
));
9959 KdPrint(("UniATA Init: ReEnter\n"));
9963 // (re)read bad block list
9964 InitBadBlocks(NULL
);
9967 // init ATA command translation table
9968 UniataInitAtaCommands();
9969 // get registry path to settings
9970 RtlCopyMemory(&SavedRegPath
, RegistryPath
, sizeof(UNICODE_STRING
));
9971 SavedRegPath
.Buffer
= (PWCHAR
)&SavedRegPathBuffer
;
9972 SavedRegPath
.Length
= min(RegistryPath
->Length
, 255*sizeof(WCHAR
));
9973 SavedRegPath
.MaximumLength
= 255*sizeof(WCHAR
);
9974 RtlCopyMemory(SavedRegPath
.Buffer
, RegistryPath
->Buffer
, SavedRegPath
.Length
);
9975 SavedRegPath
.Buffer
[SavedRegPath
.Length
/sizeof(WCHAR
)] = 0;
9978 if(WinVer_Id() >= WinVer_2k
) {
9979 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"1", 0)) {
9980 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
9981 WinVer_WDM_Model
= TRUE
;
9983 if(AtapiRegCheckParameterValue(NULL
, L
"Paramaters\\PnpInterface", L
"5", 0)) {
9984 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
9985 WinVer_WDM_Model
= TRUE
;
9989 SkipRaids
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"SkipRaids", 1);
9990 ForceSimplex
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"ForceSimplex", 0);
9992 g_LogToDisplay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"LogToDisplay", 0);
9995 statusToReturn
= 0xffffffff;
9997 // Zero out structure.
9998 RtlZeroMemory(((PCHAR
)&hwInitializationData
), sizeof(hwInitializationData
));
10000 // Set size of hwInitializationData.
10001 hwInitializationData
.comm
.HwInitializationDataSize
=
10002 sizeof(hwInitializationData
.comm
) +
10003 // sizeof(hwInitializationData.nt4) +
10004 ((WinVer_Id() <= WinVer_NT
) ? 0 : sizeof(hwInitializationData
.w2k
));
10005 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData
.comm
.HwInitializationDataSize
));
10007 // Set entry points.
10008 hwInitializationData
.comm
.HwInitialize
= (PHW_INITIALIZE
)AtapiHwInitialize
;
10009 hwInitializationData
.comm
.HwResetBus
= (PHW_RESET_BUS
)AtapiResetController
;
10010 hwInitializationData
.comm
.HwStartIo
= (PHW_STARTIO
)AtapiStartIo
;
10011 hwInitializationData
.comm
.HwInterrupt
= (PHW_INTERRUPT
)AtapiInterrupt
;
10013 // Specify size of extensions.
10014 hwInitializationData
.comm
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
10015 hwInitializationData
.comm
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
10016 hwInitializationData
.comm
.SrbExtensionSize
= sizeof(ATA_REQ
);
10018 // Indicate PIO device.
10019 hwInitializationData
.comm
.MapBuffers
= TRUE
;
10020 // Set PnP-specific API
10021 if(WinVer_Id() > WinVer_NT
) {
10022 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
10023 hwInitializationData
.comm
.NeedPhysicalAddresses
= TRUE
;
10024 KdPrint(("set AtapiAdapterControl() ptr\n"));
10025 hwInitializationData
.w2k
.HwAdapterControl
= (PHW_ADAPTER_CONTROL
)AtapiAdapterControl
;
10028 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE enum supported BusMaster Devices\n"));
10032 g_opt_VirtualMachine
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualMachineType", g_opt_VirtualMachine
);
10033 if(g_opt_VirtualMachine
> VM_MAX_KNOWN
) {
10034 g_opt_VirtualMachine
= 0;
10036 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"VirtualBox", (g_opt_VirtualMachine
== VM_VBOX
))) {
10037 g_opt_VirtualMachine
= VM_VBOX
;
10039 // Pre-scan PCI bus, also check if we are under VM
10040 UniataEnumBusMasterController(DriverObject
, Argument2
);
10042 switch(g_opt_VirtualMachine
) {
10044 KdPrint2((PRINT_PREFIX
"adjust options for VirtualBox\n"));
10045 // adjust options for VirtualBox
10046 g_opt_WaitBusyCount
= 20000;
10047 g_opt_WaitBusyDelay
= 150;
10048 g_opt_WaitDrqDelay
= 100;
10049 g_opt_WaitBusyLongCount
= 20000;
10050 g_opt_MaxIsrWait
= 200;
10051 g_opt_AtapiSendDisableIntr
= 0;
10052 g_opt_AtapiDmaRawRead
= FALSE
;
10057 KdPrint2((PRINT_PREFIX
"old slow machine, adjust timings\n"));
10058 // old slow machine, adjust timings
10059 g_opt_WaitBusyCount
= 20000;
10060 g_opt_WaitBusyDelay
= 150;
10061 g_opt_WaitDrqDelay
= 100;
10062 g_opt_WaitBusyLongCount
= 20000;
10063 g_opt_MaxIsrWait
= 200;
10066 g_opt_WaitBusyCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyCount", g_opt_WaitBusyCount
); // 200 vs 20000
10067 g_opt_WaitBusyDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyDelay", g_opt_WaitBusyDelay
); // 10 vs 150
10068 g_opt_WaitDrqDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitDrqDelay", g_opt_WaitDrqDelay
); // 10 vs 100
10069 g_opt_WaitBusyLongCount
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongCount", g_opt_WaitBusyLongCount
); // 2000 vs 20000
10070 g_opt_WaitBusyLongDelay
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"WaitBusyLongDelay", g_opt_WaitBusyLongDelay
); // 250 vs 250
10071 g_opt_AtapiSendDisableIntr
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr
); // 1 vs 0
10072 g_opt_AtapiDmaRawRead
= (BOOLEAN
)AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"AtapiDmaRawRead", g_opt_AtapiDmaRawRead
); // 1 vs 0
10073 g_opt_MaxIsrWait
= AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"MaxIsrWait", g_opt_MaxIsrWait
); // 40 vs xxx
10076 // Look for legacy ISA-bridged PCI IDE controller (onboard)
10077 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
10078 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: BMListLen %d\n", BMListLen
));
10079 for (i
=0; i
<BMListLen
; i
++) {
10081 if(!BMList
[i
].MasterDev
) {
10082 KdPrint2((PRINT_PREFIX
"!BMList[i].MasterDev\n"));
10085 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10089 KdPrint2((PRINT_PREFIX
"ReEnter, skip it\n"));
10090 if(BMList
[i
].ChanInitOk
& 0x03) {
10091 KdPrint2((PRINT_PREFIX
"Already initialized, skip it\n"));
10093 newStatus
= STATUS_SUCCESS
;
10097 //BMList[i].AltInitMasterDev = (UCHAR)0xff;
10099 if(GlobalConfig
->AtDiskPrimaryAddressClaimed
)
10100 PrimaryClaimed
= TRUE
;
10101 if(GlobalConfig
->AtDiskSecondaryAddressClaimed
)
10102 SecondaryClaimed
= TRUE
;
10104 if(!WinVer_WDM_Model
&& !PrimaryClaimed
&& !SecondaryClaimed
&&
10105 !(BMList
[i
].ChanInitOk
& 0x80)) {
10106 newStatus
= UniataClaimLegacyPCIIDE(i
);
10107 if(newStatus
!= STATUS_SUCCESS
) {
10108 KdPrint2((PRINT_PREFIX
"Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
10113 if(g_opt_Verbose
) {
10114 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
10118 for(alt
= 0; alt
< (ULONG
)(WinVer_WDM_Model
? 1 : 2) ; alt
++) {
10120 for(c
=0; c
<2; c
++) {
10122 if(AtapiRegCheckDevValue(NULL
, c
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsaCompatiblePci", 0)) {
10126 if(PrimaryClaimed
) {
10127 KdPrint2((PRINT_PREFIX
"Primary already claimed\n"));
10132 if(SecondaryClaimed
) {
10133 KdPrint2((PRINT_PREFIX
"Secondary already claimed\n"));
10138 if((WinVer_Id() < WinVer_2k
)) {
10139 // do not even try if already claimed
10141 GlobalConfig
->AtDiskPrimaryAddressClaimed
= FALSE
;
10144 GlobalConfig
->AtDiskSecondaryAddressClaimed
= FALSE
;
10147 if(!WinVer_WDM_Model
) {
10148 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10150 // in WDM model things are different....
10151 hwInitializationData
.comm
.HwFindAdapter
= (c
== 0) ?
10152 UniataFindCompatBusMasterController1
: UniataFindCompatBusMasterController2
;
10154 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10155 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10157 if(!WinVer_WDM_Model
) {
10158 BMList
[i
].channel
= (UCHAR
)c
;
10161 KdPrint2((PRINT_PREFIX
"Try init channel %d, method %d\n", c
, alt
));
10162 newStatus
= ScsiPortInitialize(DriverObject
,
10164 &hwInitializationData
.comm
,
10165 (PVOID
)(i
| (alt
? 0x80000000 : 0)));
10166 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10167 if (newStatus
< statusToReturn
) {
10168 statusToReturn
= newStatus
;
10170 if (newStatus
== STATUS_SUCCESS
) {
10171 if(WinVer_Id() < WinVer_2k
) {
10172 // This should be done in HwInitialize under w2k+ to ensure that
10173 // channel is actually initialized
10174 BMList
[i
].ChanInitOk
|= 0x01 << c
;
10176 if(BMList
[i
].ChanInitOk
& (0x01 << c
)) {
10177 KdPrint2((PRINT_PREFIX
"HwInit passed\n"));
10181 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
10182 c = 1; // this will break our for()
10183 BMList[i].ChanInitOk |= 0x01 << c;
10188 /* if(WinVer_Id() >= WinVer_2k) {
10189 // the following didn't work under higher OSes,
10190 // until we move setting of FLAGS to HwInit
10191 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
10194 if(BMList
[i
].ChanInitOk
& 0x03) {
10195 // Under NT we receive status immediately, so
10196 // we can omit alternative init method if STATUS_SUCCESS returned.
10197 // Under w2k+ we relay on flags, set in HwInitialize.
10198 KdPrint2((PRINT_PREFIX
"Ok, no more retries required\n"));
10201 if(WinVer_Id() >= WinVer_2k
) {
10202 // try AltInit if HwInit was not called immediately under w2k+
10203 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10205 // if (WinVer_Id() == WinVer_NT) and some error occured
10206 // try alternative init method
10207 KdPrint2((PRINT_PREFIX
"make still one attempt w2k+\n"));
10210 if(g_opt_Verbose
) {
10211 if(BMList
[i
].ChanInitOk
& 0x03) {
10212 _PrintNtConsole(" OK\n");
10214 _PrintNtConsole(" failed\n");
10220 /* KeBugCheckEx(0xc000000e,
10221 (i << 16) | BMList[0].ChanInitOk,
10223 newStatus, statusToReturn);*/
10225 // Look for PCI IDE controller
10226 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for PCI IDE controller\n"));
10227 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: i %d, BMListLen %d\n", i
, BMListLen
));
10228 for (; i
<BMListLen
; i
++) {
10230 if(AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreNativePci", 0)) {
10233 /* if(BMList[i].MasterDev)
10235 if(g_opt_Verbose
) {
10236 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
10237 BMList
[i
].VendorId
, BMList
[i
].DeviceId
,
10238 BMList
[i
].busNumber
,
10239 BMList
[i
].slotNumber
% PCI_MAX_FUNCTION
,
10240 (BMList
[i
].slotNumber
/ PCI_MAX_FUNCTION
) % PCI_MAX_DEVICES
);
10243 hwInitializationData
.comm
.HwFindAdapter
= UniataFindBusMasterController
;
10244 hwInitializationData
.comm
.NumberOfAccessRanges
= 6;
10245 hwInitializationData
.comm
.AdapterInterfaceType
= PCIBus
;
10247 hwInitializationData
.comm
.VendorId
= (PVOID
)BMList
[i
].VendorId
;
10248 hwInitializationData
.comm
.VendorIdLength
= (USHORT
) BMList
[i
].VendorIdLength
;
10249 hwInitializationData
.comm
.DeviceId
= (PVOID
)BMList
[i
].DeviceId
;
10250 hwInitializationData
.comm
.DeviceIdLength
= (USHORT
) BMList
[i
].DeviceIdLength
;
10252 BMList
[i
].channel
= 0/*(UCHAR)c*/;
10254 KdPrint2((PRINT_PREFIX
"Try init %4.4s %4.4s \n",
10255 hwInitializationData
.comm
.VendorId
,
10256 hwInitializationData
.comm
.DeviceId
));
10257 newStatus
= ScsiPortInitialize(DriverObject
,
10259 &hwInitializationData
.comm
,
10261 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10262 if(newStatus
== (ULONG
)STATUS_DEVICE_DOES_NOT_EXIST
&& BMList
[i
].NeedAltInit
) {
10263 // Note: this is actually a BUG in scsiport.sys
10264 // It stops scanning PCI bus when reaches empty PCI Function inside Slot
10265 // However, this PCI Slot may have higher non-empty Functions
10266 // UniATA will perform all staff instead of ScsiPort under NT,
10267 // but for ReactOS it is better to patch ScsiPort.
10268 KdPrint2((PRINT_PREFIX
"STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
10269 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10270 newStatus
= ScsiPortInitialize(DriverObject
,
10272 &hwInitializationData
.comm
,
10273 (PVOID
)(i
| 0x80000000));
10274 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x (2)\n", newStatus
));
10276 if (newStatus
< statusToReturn
)
10277 statusToReturn
= newStatus
;
10279 if(g_opt_Verbose
) {
10280 if(newStatus
== STATUS_SUCCESS
) {
10281 _PrintNtConsole(" OK\n");
10283 _PrintNtConsole(" failed\n");
10289 /* KeBugCheckEx(0xc000000e,
10292 newStatus, statusToReturn);*/
10296 hwInitializationData
.comm
.VendorId
= 0;
10297 hwInitializationData
.comm
.VendorIdLength
= 0;
10298 hwInitializationData
.comm
.DeviceId
= 0;
10299 hwInitializationData
.comm
.DeviceIdLength
= 0;
10302 hwInitializationData
.comm
.SrbExtensionSize
= //FIELD_OFFSET(ATA_REQ, ata);
10304 KdPrint2((PRINT_PREFIX
"using AtaReq sz %x\n", hwInitializationData
.comm
.SrbExtensionSize
));
10307 // The adapter count is used by the find adapter routine to track how
10308 // which adapter addresses have been tested.
10310 // Indicate 2 access ranges and reset FindAdapter.
10311 hwInitializationData
.comm
.NumberOfAccessRanges
= 2;
10312 hwInitializationData
.comm
.HwFindAdapter
= AtapiFindController
;
10314 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreIsa", 0)) {
10315 // Indicate ISA bustype.
10316 hwInitializationData
.comm
.AdapterInterfaceType
= Isa
;
10319 // Call initialization for ISA bustype.
10320 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for ISA Controllers\n"));
10321 newStatus
= ScsiPortInitialize(DriverObject
,
10323 &hwInitializationData
.comm
,
10325 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10326 if (newStatus
< statusToReturn
)
10327 statusToReturn
= newStatus
;
10329 if(!AtapiRegCheckDevValue(NULL
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"IgnoreMca", 0)) {
10331 KdPrint2((PRINT_PREFIX
"\n\nATAPI IDE: Look for MCA Controllers\n"));
10332 hwInitializationData
.comm
.AdapterInterfaceType
= MicroChannel
;
10335 newStatus
= ScsiPortInitialize(DriverObject
,
10337 &hwInitializationData
.comm
,
10339 KdPrint2((PRINT_PREFIX
"ScsiPortInitialize Status %#x\n", newStatus
));
10340 if (newStatus
< statusToReturn
)
10341 statusToReturn
= newStatus
;
10343 InDriverEntry
= FALSE
;
10345 KdPrint2((PRINT_PREFIX
"\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn
));
10347 return statusToReturn
;
10349 } // end DriverEntry()
10352 PSCSI_REQUEST_BLOCK
10354 BuildMechanismStatusSrb(
10355 IN PVOID HwDeviceExtension
,
10356 IN PSCSI_REQUEST_BLOCK Srb
10359 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10360 PSCSI_REQUEST_BLOCK srb
;
10362 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10364 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10366 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10368 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10369 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10370 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10371 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10373 // Set flags to disable synchronous negociation.
10374 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10376 // Set timeout to 4 seconds.
10377 srb
->TimeOutValue
= 4;
10379 srb
->CdbLength
= 6;
10380 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusData
);
10381 srb
->DataTransferLength
= sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10382 srb
->SrbExtension
= AtaReq
;
10384 // Set CDB operation code.
10385 cdb
= (PCDB
)srb
->Cdb
;
10386 cdb
->MECH_STATUS
.OperationCode
= SCSIOP_MECHANISM_STATUS
;
10387 cdb
->MECH_STATUS
.AllocationLength
[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER
);
10389 KdPrint2((PRINT_PREFIX
" MechanismStatusSrb %#x\n", srb
));
10392 } // end BuildMechanismStatusSrb()
10394 #endif //UNIATA_CORE
10396 PSCSI_REQUEST_BLOCK
10398 BuildRequestSenseSrb (
10399 IN PVOID HwDeviceExtension
,
10400 IN PSCSI_REQUEST_BLOCK Srb
10403 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10404 PSCSI_REQUEST_BLOCK srb
;
10406 PATA_REQ AtaReq
= (PATA_REQ
)(Srb
->SrbExtension
);
10408 srb
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].InternalSrb
);
10410 RtlZeroMemory((PCHAR
) srb
, sizeof(SCSI_REQUEST_BLOCK
));
10412 srb
->PathId
= (UCHAR
)(Srb
->PathId
);
10413 srb
->TargetId
= (UCHAR
)(Srb
->TargetId
);
10414 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
10415 srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
10417 // Set flags to disable synchronous negociation.
10418 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
10420 // Set timeout to 2 seconds.
10421 srb
->TimeOutValue
= 4;
10423 srb
->CdbLength
= 6;
10424 srb
->DataBuffer
= &(deviceExtension
->chan
[GET_CHANNEL(Srb
)].MechStatusSense
);
10425 srb
->DataTransferLength
= sizeof(SENSE_DATA
);
10426 srb
->SrbExtension
= AtaReq
;
10428 // Set CDB operation code.
10429 cdb
= (PCDB
)srb
->Cdb
;
10430 cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
10431 cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
10433 KdPrint2((PRINT_PREFIX
" RequestSenseSrb %#x\n", srb
));
10436 } // end BuildRequestSenseSrb()
10438 #ifndef UNIATA_CORE
10442 AtapiRegCheckDevLunValue(
10443 IN PVOID HwDeviceExtension
,
10444 IN PCWCH NamePrefix
,
10452 ULONG val
= Default
;
10454 val
= AtapiRegCheckParameterValue(
10455 HwDeviceExtension
, NamePrefix
, Name
, val
);
10457 if(chan
!= CHAN_NOT_SPECIFIED
) {
10458 swprintf(namex
, L
"%s\\Chan_%1.1d", NamePrefix
, chan
);
10459 val
= AtapiRegCheckParameterValue(
10460 HwDeviceExtension
, namex
, Name
, val
);
10461 if(dev
!= DEVNUM_NOT_SPECIFIED
) {
10462 swprintf(namex
, L
"%s\\Chan_%1.1d\\%s", NamePrefix
, chan
, (dev
& 0x01) ? L
"Lun_1" : L
"Lun_0");
10463 val
= AtapiRegCheckParameterValue(
10464 HwDeviceExtension
, namex
, Name
, val
);
10468 } // end AtapiRegCheckDevLunValue()
10481 for(i
=0, j
=0; i
<Length
; i
++, j
++) {
10500 swprintf(Buffer
+j
, L
"%2.2x", a
);
10508 } // end EncodeVendorStr()
10512 AtapiRegCheckDevValue(
10513 IN PVOID HwDeviceExtension
,
10520 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10521 // WCHAR name0[11];
10522 // WCHAR name1[11+4+5];
10523 // WCHAR name2[11+4+4+10];
10524 // WCHAR name3[11+4+4+5+20];
10525 // WCHAR name3[11+4+4+5+20+1];
10534 IN ULONG SlotNumber
;
10536 ULONG val
= Default
;
10538 KdPrint(( " Parameter %ws\n", Name
));
10540 if(deviceExtension
) {
10541 VendorID
= deviceExtension
->DevID
& 0xffff;
10542 DeviceID
= (deviceExtension
->DevID
>> 16) & 0xffff;
10543 SlotNumber
= deviceExtension
->slotNumber
;
10547 SlotNumber
= 0xffffffff;
10550 val
= AtapiRegCheckDevLunValue(
10551 HwDeviceExtension
, L
"Parameters", chan
, dev
, Name
, val
);
10553 if(deviceExtension
) {
10554 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
10556 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
);
10557 swprintf(namex
, L
"Parameters%s", namev
);
10558 val
= AtapiRegCheckDevLunValue(
10559 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10562 swprintf(namev
, L
"\\Ven_%4.4x", VendorID
);
10563 swprintf(named
, L
"\\Dev_%4.4x", DeviceID
);
10564 swprintf(names
, L
"\\Slot_%8.8x", SlotNumber
);
10566 swprintf(namex
, L
"Parameters%s", namev
);
10567 val
= AtapiRegCheckDevLunValue(
10568 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10570 swprintf(namex
, L
"Parameters%s%s", namev
, named
);
10571 val
= AtapiRegCheckDevLunValue(
10572 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10574 swprintf(namex
, L
"Parameters%s%s%s", namev
, named
, names
);
10575 val
= AtapiRegCheckDevLunValue(
10576 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10578 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
10580 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
);
10581 swprintf(namex
, L
"Parameters%s", namev
);
10582 val
= AtapiRegCheckDevLunValue(
10583 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10585 swprintf(namev
, L
"\\ISA_%d", deviceExtension
->DevIndex
);
10586 swprintf(namex
, L
"Parameters%s", namev
);
10587 val
= AtapiRegCheckDevLunValue(
10588 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10591 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
10593 swprintf(namev
, L
"\\IDE_%d", deviceExtension
->DevIndex
+BMListLen
+IsaCount
);
10594 swprintf(namex
, L
"Parameters%s", namev
);
10595 val
= AtapiRegCheckDevLunValue(
10596 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10598 swprintf(namev
, L
"\\MCA_%d", deviceExtension
->DevIndex
);
10599 swprintf(namex
, L
"Parameters%s", namev
);
10600 val
= AtapiRegCheckDevLunValue(
10601 HwDeviceExtension
, namex
, chan
, dev
, Name
, val
);
10606 KdPrint(( " Parameter %ws = %#x\n", Name
, val
));
10609 } // end AtapiRegCheckDevValue()
10612 The user must specify that Xxx is to run on the platform
10613 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
10614 Services\UniATA\Xxx:REG_DWORD:Zzz.
10616 The user can override the global setting to enable or disable Xxx on a
10617 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
10618 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
10620 If this registry value does not exist or contains the value zero then
10621 the timer to check for media change does not run.
10625 RegistryPath - pointer to the unicode string inside
10626 ...\CurrentControlSet\Services\UniATA
10627 DeviceNumber - The number of the HBA device object
10629 Returns: Registry Key value
10633 AtapiRegCheckParameterValue(
10634 IN PVOID HwDeviceExtension
,
10635 IN PCWSTR PathSuffix
,
10640 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
10642 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10644 LONG zero
= Default
;
10646 RTL_QUERY_REGISTRY_TABLE parameters
[ITEMS_TO_QUERY
];
10649 LONG doRun
= Default
;
10651 PUNICODE_STRING RegistryPath
= &SavedRegPath
;
10653 UNICODE_STRING paramPath
;
10655 // <SavedRegPath>\<PathSuffix> -> <Name>
10656 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
10657 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
10659 paramPath
.Length
= 0;
10660 paramPath
.MaximumLength
= RegistryPath
->Length
+
10661 (wcslen(PathSuffix
)+2)*sizeof(WCHAR
);
10662 paramPath
.Buffer
= (PWCHAR
)ExAllocatePool(NonPagedPool
, paramPath
.MaximumLength
);
10663 if(!paramPath
.Buffer
) {
10664 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
10668 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
10669 RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
10670 RtlAppendUnicodeToString(¶mPath
, L
"\\");
10671 RtlAppendUnicodeToString(¶mPath
, REGRTL_STR_PTYPE PathSuffix
);
10673 // Check for the Xxx value.
10674 RtlZeroMemory(parameters
, (sizeof(RTL_QUERY_REGISTRY_TABLE
)*ITEMS_TO_QUERY
));
10676 parameters
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
10677 parameters
[0].Name
= REGRTL_STR_PTYPE Name
;
10678 parameters
[0].EntryContext
= &doRun
;
10679 parameters
[0].DefaultType
= REG_DWORD
;
10680 parameters
[0].DefaultData
= &zero
;
10681 parameters
[0].DefaultLength
= sizeof(ULONG
);
10683 status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
/*| RTL_REGISTRY_OPTIONAL*/,
10684 paramPath
.Buffer
, parameters
, NULL
, NULL
);
10685 if(NT_SUCCESS(status
)) {
10686 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix
, Name
, doRun
));
10689 ExFreePool(paramPath
.Buffer
);
10691 if(!NT_SUCCESS(status
)) {
10697 #undef ITEMS_TO_QUERY
10699 } // end AtapiRegCheckParameterValue()
10702 SCSI_ADAPTER_CONTROL_STATUS
10704 AtapiAdapterControl(
10705 IN PVOID HwDeviceExtension
,
10706 IN SCSI_ADAPTER_CONTROL_TYPE ControlType
,
10707 IN PVOID Parameters
10710 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10711 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList
;
10712 ULONG numberChannels
= deviceExtension
->NumberChannels
;
10716 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType
));
10718 switch(ControlType
) {
10719 case ScsiQuerySupportedControlTypes
: {
10720 BOOLEAN supportedTypes
[ScsiAdapterControlMax
] = {
10721 TRUE
, // ScsiQuerySupportedControlTypes
10722 TRUE
, // ScsiStopAdapter
10723 TRUE
, // ScsiRestartAdapter
10724 FALSE
, // ScsiSetBootConfig
10725 FALSE
// ScsiSetRunningConfig
10728 ULONG lim
= ScsiAdapterControlMax
;
10731 pControlTypeList
= (PSCSI_SUPPORTED_CONTROL_TYPE_LIST
) Parameters
;
10733 if(pControlTypeList
->MaxControlType
< lim
) {
10734 lim
= pControlTypeList
->MaxControlType
;
10737 for(i
= 0; i
< lim
; i
++) {
10738 pControlTypeList
->SupportedTypeList
[i
] = supportedTypes
[i
];
10744 case ScsiStopAdapter
: {
10746 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
10747 // Shut down all interrupts on the adapter. They'll get re-enabled
10748 // by the initialization routines.
10749 for (c
= 0; c
< numberChannels
; c
++) {
10750 AtapiResetController(deviceExtension
, c
);
10751 AtapiDisableInterrupts(deviceExtension
, c
);
10753 if(deviceExtension
->AdapterInterfaceType
== PCIBus
) {
10754 // we must never get here for non-PCI
10755 status
= UniataDisconnectIntr2(HwDeviceExtension
);
10756 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= FALSE
;
10760 case ScsiRestartAdapter
: {
10762 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
10763 // Enable all the interrupts on the adapter while port driver call
10764 // for power up an HBA that was shut down for power management
10766 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
10767 status
= UniataConnectIntr2(HwDeviceExtension
);
10768 for (c
= 0; c
< numberChannels
; c
++) {
10769 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, c
);
10770 FindDevices(HwDeviceExtension
, 0, c
);
10771 AtapiEnableInterrupts(deviceExtension
, c
);
10772 AtapiHwInitialize__(deviceExtension
, c
);
10774 if(deviceExtension
->Isr2DevObj
) {
10775 // we must never get here for non-PCI
10776 BMList
[deviceExtension
->DevIndex
].Isr2Enable
= TRUE
;
10783 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
10784 return ScsiAdapterControlUnsuccessful
;
10788 return ScsiAdapterControlSuccess
;
10789 } // end AtapiAdapterControl()
10791 #endif //UNIATA_CORE
10801 #define DEBUG_MSG_BUFFER_SIZE 512
10812 UCHAR dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
];
10813 // UNICODE_STRING msgBuff;
10815 va_start(ap
, DebugMessage
);
10817 len
= _vsnprintf((PCHAR
)&dbg_print_tmp_buff
[0], DEBUG_MSG_BUFFER_SIZE
-1, DebugMessage
, ap
);
10819 dbg_print_tmp_buff
[DEBUG_MSG_BUFFER_SIZE
-1] = 0;
10821 //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro
10822 HalDisplayString(dbg_print_tmp_buff
);
10825 if(g_LogToDisplay
> 1) {
10826 AtapiStallExecution(g_LogToDisplay
*1000);
10832 } // end PrintNtConsole()